diff options
author | Kentoku SHIBA <kentokushiba@gmail.com> | 2015-02-17 13:34:27 +0900 |
---|---|---|
committer | Kentoku SHIBA <kentokushiba@gmail.com> | 2015-02-17 13:34:27 +0900 |
commit | f5dabd7acaaaf21019a59a641e090a7dfdaefae5 (patch) | |
tree | 1e8bc0ad46144127cbabe23cac945244b3cfbefc | |
parent | 162446a6219ca77e35b4b05c71a9c3dd650d719a (diff) | |
download | mariadb-git-f5dabd7acaaaf21019a59a641e090a7dfdaefae5.tar.gz |
Update Mroonga to the latest version on 2015-02-17T13:34:27+0900
416 files changed, 46168 insertions, 7028 deletions
diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt index faad871fa95..ff72953bfac 100644 --- a/storage/mroonga/CMakeLists.txt +++ b/storage/mroonga/CMakeLists.txt @@ -1,6 +1,6 @@ # -*- indent-tabs-mode: nil -*- # -# Copyright(C) 2012-2014 Kouhei Sutou <kou@clear-code.com> +# Copyright(C) 2012-2015 Kouhei Sutou <kou@clear-code.com> # Copyright(C) 2013 Kentoku SHIBA # # This library is free software; you can redistribute it and/or @@ -75,6 +75,28 @@ file(READ ${MRN_SOURCE_DIR}/version_in_hex MRN_VERSION_IN_HEX) file(READ ${MRN_SOURCE_DIR}/plugin_version MRN_PLUGIN_VERSION) if(MRN_GROONGA_BUNDLED) + option(MRN_GROONGA_EMBED + "Embed libgroonga" + ON) + if(MRN_GROONGA_EMBED) + set(GRN_EMBED ON) + endif() + + set(MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR + "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql") + option(MRN_GROONGA_NORMALIZER_MYSQL_EMBED + "Embed groonga-normalizer-mysql Groonga plugin" + ON) + if(EXISTS ${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR}) + set(GROONGA_NORMALIZER_MYSQL_FOUND ON) + else() + set(GROONGA_NORMALIZER_MYSQL_FOUND OFF) + set(MRN_GROONGA_NORMALIZER_MYSQL_EMBED OFF) + endif() + if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED) + set(GROONGA_NORMALIZER_MYSQL_EMBED ON) + endif() + add_subdirectory("${MRN_BUNDLED_GROONGA_RELATIVE_DIR}") else() file(READ ${MRN_SOURCE_DIR}/required_groonga_version REQUIRED_GROONGA_VERSION) @@ -98,15 +120,21 @@ set(MRN_C_COMPILE_FLAGS "") set(MRN_CXX_COMPILE_FLAGS "") macro(mrn_check_cflag flag) - check_c_compiler_flag(${flag} "HAVE_C_${flag}") - if(HAVE_C_${flag}) + string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag}) + string(TOUPPER "${temporary_variable_name}" temporary_variable_name) + set(temporary_variable_name "CFLAG${temporary_variable_name}") + check_c_compiler_flag(${flag} ${temporary_variable_name}) + if(${temporary_variable_name}) set(MRN_C_COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS} ${flag}") endif() endmacro() macro(mrn_check_cxxflag flag) - check_cxx_compiler_flag(${flag} "HAVE_CXX_${flag}") - if(HAVE_CXX_${flag}) + string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag}) + string(TOUPPER "${temporary_variable_name}" temporary_variable_name) + set(temporary_variable_name "CXXFLAG${temporary_variable_name}") + check_cxx_compiler_flag(${flag} ${temporary_variable_name}) + if(${temporary_variable_name}) set(MRN_CXX_COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS} ${flag}") endif() endmacro() @@ -122,7 +150,7 @@ else() set(MRN_RELATIVE_DIR_PREFIX "") endif() -read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am MROONGA_SOURCES) +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am MRN_SOURCES) read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/lib/libmrn_no_mysql_sources.am LIBMRN_NO_MYSQL_SOURCES) string(REGEX REPLACE "([^;]+)" "${MRN_RELATIVE_DIR_PREFIX}lib/\\1" @@ -157,11 +185,18 @@ else() set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/regex") endif() +if(EXISTS "${MYSQL_SOURCE_DIR}/extra/rapidjson") + set(MYSQL_RAPIDJSON_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/extra/rapidjson/include") +else() + set(MYSQL_RAPIDJSON_INCLUDE_DIR) +endif() + set(MYSQL_INCLUDE_DIRS "${MYSQL_BUILD_DIR}/include" "${MYSQL_SOURCE_DIR}/sql" "${MYSQL_SOURCE_DIR}/include" "${MYSQL_REGEX_INCLUDE_DIR}" + "${MYSQL_RAPIDJSON_INCLUDE_DIR}" "${MYSQL_SOURCE_DIR}") if(MRN_BUNDLED) @@ -190,6 +225,12 @@ else() set_mysql_config_value("--version" MYSQL_VERSION) endif() +if(${MYSQL_VERSION} VERSION_LESS "5.5.0") + message(FATAL_ERROR + "Mroonga doesn't support MySQL < 5.5.0: <${MYSQL_VERSION}>") + return() +endif() + if(${MYSQL_VERSION} VERSION_GREATER "10.0.0" AND ${MYSQL_VERSION} VERSION_LESS "10.0.9") message(FATAL_ERROR @@ -201,10 +242,14 @@ if(MRN_GROONGA_BUNDLED) set(GROONGA_INCLUDE_DIRS "${MRN_BUNDLED_GROONGA_DIR}/include") set(GROONGA_LIBRARY_DIRS "${MRN_BUNDLED_GROONGA_DIR}/lib") set(GROONGA_LIBRARIES "libgroonga") - if(EXISTS "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql") - set(GROONGA_NORMALIZER_MYSQL_FOUND TRUE) - else() - set(GROONGA_NORMALIZER_MYSQL_FOUND FALSE) + + set(MRN_LIBRARY_DIRS ${GROONGA_LIBRARY_DIRS}) + set(MRN_LIBRARIES ${GROONGA_LIBRARIES}) + if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED) + set(MRN_LIBRARY_DIRS + ${MRN_LIBRARY_DIRS} + "${MRN_BUNDLED_GROONGA_NORMALIZER_MYSQL_DIR}/normalizers") + set(MRN_LIBRARIES ${MRN_LIBRARIES} mysql_normalizer) endif() else() include(FindPkgConfig) @@ -213,12 +258,6 @@ else() "groonga-normalizer-mysql >= ${REQUIRED_GROONGA_NORMALIZER_MYSQL_VERSION}") endif() -if(GROONGA_NORMALIZER_MYSQL_FOUND AND MRN_GROONGA_BUNDLED) - read_file_list(${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql_sources.am MRN_GRN_NORMALIZER_MYSQL_SOURCES) - string(REGEX REPLACE "([^;]+)" "${MRN_BUNDLED_GROONGA_DIR}/vendor/plugins/groonga-normalizer-mysql/normalizers/\\1" - MRN_GRN_NORMALIZER_MYSQL_SOURCES "${MRN_GRN_NORMALIZER_MYSQL_SOURCES}") -endif() - include_directories( "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}" @@ -235,28 +274,22 @@ else() "${MYSQL_SERVICES_LIB_DIR}") endif() link_directories( - ${GROONGA_LIBRARY_DIRS} + ${MRN_LIBRARY_DIRS} ${MYSQL_LIBRARY_DIRS}) +set(MRN_ALL_SOURCES + ${MRN_SOURCES} + ${MRN_UDF_SOURCES} + ${LIBMRN_NO_MYSQL_SOURCES} + ${LIBMRN_NEED_MYSQL_SOURCES}) + if(MRN_BUNDLED) - if(GROONGA_NORMALIZER_MYSQL_FOUND AND MRN_GROONGA_BUNDLED) - mysql_add_plugin(mroonga - "${MROONGA_SOURCES};${MRN_UDF_SOURCES};${MRN_GRN_NORMALIZER_MYSQL_SOURCES};${LIBMRN_NEED_MYSQL_SOURCES};${LIBMRN_NO_MYSQL_SOURCES}" - STORAGE_ENGINE MODULE_ONLY - LINK_LIBRARIES ${GROONGA_LIBRARIES}) - else() - mysql_add_plugin(mroonga - "${MROONGA_SOURCES};${MRN_UDF_SOURCES};${LIBMRN_NEED_MYSQL_SOURCES};${LIBMRN_NO_MYSQL_SOURCES}" - STORAGE_ENGINE MODULE_ONLY - LINK_LIBRARIES ${GROONGA_LIBRARIES}) - endif() - else() + mysql_add_plugin(mroonga + ${MRN_ALL_SOURCES} + STORAGE_ENGINE MODULE_ONLY + LINK_LIBRARIES ${MRN_LIBRARIES}) else() - add_library(mroonga MODULE - ${MROONGA_SOURCES} - ${MRN_UDF_SOURCES} - ${LIBMRN_NO_MYSQL_SOURCES} - ${LIBMRN_NEED_MYSQL_SOURCES}) + add_library(mroonga MODULE ${MRN_ALL_SOURCES}) set(MYSQL_LIBRARIES "mysqlservices") target_link_libraries(mroonga ${GROONGA_LIBRARIES} ${MYSQL_LIBRARIES}) @@ -303,14 +336,14 @@ else() mrn_check_cxxflag("-fno-rtti") mrn_check_cxxflag("-felide-constructors") endif() - set_source_files_properties(${MROONGA_SOURCES} PROPERTIES + set_source_files_properties(${MRN_SOURCES} PROPERTIES COMPILE_FLAGS "${MYSQL_CFLAGS} ${MRN_CXX_COMPILE_FLAGS}") set_source_files_properties(${LIBMRN_NEED_MYSQL_SOURCES} PROPERTIES COMPILE_FLAGS "${MYSQL_CFLAGS} ${MRN_CXX_COMPILE_FLAGS}") set_source_files_properties(${MRN_UDF_SOURCES} PROPERTIES - COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS}") + COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS}") set_source_files_properties(${LIBMRN_NO_MYSQL_SOURCES} PROPERTIES - COMPILE_FLAGS "${MRN_C_COMPILE_FLAGS}") + COMPILE_FLAGS "${MRN_CXX_COMPILE_FLAGS}") set_property(TARGET mroonga APPEND PROPERTY COMPILE_DEFINITIONS "MYSQL_DYNAMIC_PLUGIN") set_target_properties(mroonga PROPERTIES @@ -321,19 +354,20 @@ else() endif() if(GROONGA_NORMALIZER_MYSQL_FOUND) - set(WITH_GROONGA_NORMALIZER_MYSQL 1) - ADD_DEFINITIONS(-DWITH_GROONGA_NORMALIZER_MYSQL=1) - if(MRN_GROONGA_BUNDLED) - ADD_DEFINITIONS(-DGROONGA_NORMALIZER_MYSQL_PLUGIN_IS_BUNDLED_STATIC=1) + set_property(TARGET mroonga APPEND PROPERTY + COMPILE_DEFINITIONS "WITH_GROONGA_NORMALIZER_MYSQL=1") + if(MRN_GROONGA_NORMALIZER_MYSQL_EMBED) + set_property(TARGET mroonga APPEND PROPERTY + COMPILE_DEFINITIONS "MRN_GROONGA_NORMALIZER_MYSQL_EMBED") else() - set(GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME \"normalizers/mysql\") set_property(TARGET mroonga APPEND PROPERTY COMPILE_DEFINITIONS "GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME=\"normalizers/mysql\"") endif() endif() set(MRN_DEFAULT_PARSER "TokenBigram" CACHE STRING "The default fulltext parser") -ADD_DEFINITIONS(-DMRN_PARSER_DEFAULT="${MRN_DEFAULT_PARSER}") +set_property(TARGET mroonga APPEND PROPERTY + COMPILE_DEFINITIONS "MRN_PARSER_DEFAULT=\"${MRN_DEFAULT_PARSER}\"") configure_file( "${PROJECT_SOURCE_DIR}/mrn_version.h.in" diff --git a/storage/mroonga/Makefile.am b/storage/mroonga/Makefile.am index 32fc88ad061..733347eb2c2 100644 --- a/storage/mroonga/Makefile.am +++ b/storage/mroonga/Makefile.am @@ -67,8 +67,6 @@ update-latest-release: misc misc/update-latest-release.rb \ $(PACKAGE) $(OLD_RELEASE) $(OLD_RELEASE_DATE) \ $(VERSION) $(NEW_RELEASE_DATE) \ - packages/rpm/fedora/mysql-mroonga.spec.in \ - packages/rpm/fedora/mariadb-mroonga.spec.in \ packages/rpm/centos/mariadb-mroonga.spec.in \ packages/rpm/centos/mysql55-mroonga.spec.in \ packages/rpm/centos/mysql56-community-mroonga.spec.in \ diff --git a/storage/mroonga/appveyor.yml b/storage/mroonga/appveyor.yml new file mode 100644 index 00000000000..a048d7d02e1 --- /dev/null +++ b/storage/mroonga/appveyor.yml @@ -0,0 +1,51 @@ +version: "{build}" +clone_depth: 10 +install: + - cd .. + - choco install curl 7zip.commandline + - curl -O http://mirror.jmu.edu/pub/mariadb/mariadb-10.0.16/source/mariadb-10.0.16.tar.gz + - 7z x mariadb-10.0.16.tar.gz + - 7z x mariadb-10.0.16.tar > nul + - cd mariadb-10.0.16 + - rmdir /S /Q storage\mroonga\ + - move ..\mroonga storage\mroonga + - git clone --quiet --depth 1 https://github.com/groonga/groonga.git ..\groonga + - rmdir /S /Q ..\groonga\test\ + - mkdir storage\mroonga\vendor + - move ..\groonga storage\mroonga\vendor\groonga + - git clone --quiet --depth 1 https://github.com/groonga/groonga-normalizer-mysql.git storage\mroonga\vendor\groonga\vendor\plugins\groonga-normalizer-mysql +build_script: + - "echo # > win\\packaging\\CMakeLists.txt" + - cmake . -G "Visual Studio 12 Win64" + -DCMAKE_BUILD_TYPE=Debug + -DWITHOUT_ARCHIVE=ON + -DWITHOUT_BLACKHOLE=ON + -DWITHOUT_CASSANDRA=ON + -DWITHOUT_CONNECT=ON + -DWITHOUT_CSV=ON + -DWITHOUT_EXAMPLE=ON + -DWITHOUT_FEDERATED=ON + -DWITHOUT_FEDERATEDX=ON + -DWITHOUT_HEAP=ON + -DWITHOUT_INNOBASE=ON + -DWITHOUT_MYISAM=ON + -DWITHOUT_MYISAMMRG=ON + -DWITHOUT_OQGRAPH=ON + -DWITHOUT_PERFSCHEMA=OFF + -DWITHOUT_SEQUENCE=ON + -DWITHOUT_SPHINX=ON + -DWITHOUT_SPIDER=ON + -DWITHOUT_TEST_SQL_DISCOVERY=ON + -DWITHOUT_TOKUDB=ON + -DWITHOUT_XTRADB=ON + -DWITH_UNIT_TESTS=OFF + - cmake --build . --config Debug + +notifications: + - provider: Email + to: + - groonga-mysql-commit@lists.sourceforge.jp + - kou@clear-code.com + on_build_status_changed: true + +test: off diff --git a/storage/mroonga/configure.ac b/storage/mroonga/configure.ac index 48312a44c8c..6d8fa0fe31d 100644 --- a/storage/mroonga/configure.ac +++ b/storage/mroonga/configure.ac @@ -174,6 +174,10 @@ AC_DEFUN([CONFIG_OPTION_MYSQL],[ MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_build_dir/include" MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/sql" MYSQL_INCLUDES="$MYSQL_INCLUDES -I$ac_mysql_source_dir/include" + if test -d "$ac_mysql_source_dir/extra/rapidjson"; then + mysql_rapidjson_include_dir="$ac_mysql_source_dir/extra/rapidjson/include" + MYSQL_INCLUDES="$MYSQL_INCLUDES -I$mysql_rapidjson_include_dir" + fi if test -d "$ac_mysql_source_dir/pcre"; then mysql_regex_include_dir="$ac_mysql_source_dir/pcre" else @@ -461,7 +465,6 @@ AC_CONFIG_FILES([ packages/Makefile packages/rpm/Makefile packages/rpm/centos/Makefile - packages/rpm/fedora/Makefile packages/yum/Makefile packages/apt/Makefile packages/source/Makefile @@ -486,8 +489,6 @@ AC_OUTPUT([ packages/rpm/centos/mysql55-mroonga.spec packages/rpm/centos/mysql56-community-mroonga.spec packages/rpm/centos/mariadb-mroonga.spec - packages/rpm/fedora/mysql-mroonga.spec - packages/rpm/fedora/mariadb-mroonga.spec packages/yum/env.sh data/install.sql ]) diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 8b9a08b59dc..3ff89d02e03 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -2,7 +2,7 @@ /* Copyright(C) 2010 Tetsuro IKEDA Copyright(C) 2010-2013 Kentoku SHIBA - Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com> Copyright(C) 2013 Kenji Maruyama <mmmaru777@gmail.com> This library is free software; you can redistribute it and/or @@ -116,23 +116,14 @@ } \ } while (0) #else -# if MYSQL_VERSION_ID >= 50500 -# ifdef DBUG_OFF -# ifndef _WIN32 -extern mysql_mutex_t LOCK_open; -# endif -# endif -static mysql_mutex_t *mrn_LOCK_open; -# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open) -# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open) -# else +# ifdef DBUG_OFF # ifndef _WIN32 -extern pthread_mutex_t LOCK_open; +extern mysql_mutex_t LOCK_open; # endif -static pthread_mutex_t *mrn_LOCK_open; -# define mrn_open_mutex_lock(share) -# define mrn_open_mutex_unlock(share) # endif +static mysql_mutex_t *mrn_LOCK_open; +# define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open) +# define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open) #endif #if MYSQL_VERSION_ID >= 50600 @@ -208,19 +199,44 @@ int grn_atoi(const char *nptr, const char *end, const char **rest); uint grn_atoui(const char *nptr, const char *end, const char **rest); /* global variables */ -static pthread_mutex_t mrn_log_mutex; handlerton *mrn_hton_ptr; HASH mrn_open_tables; -pthread_mutex_t mrn_open_tables_mutex; +mysql_mutex_t mrn_open_tables_mutex; +static PSI_mutex_key mrn_open_tables_mutex_key; HASH mrn_long_term_share; -pthread_mutex_t mrn_long_term_share_mutex; +mysql_mutex_t mrn_long_term_share_mutex; +static PSI_mutex_key mrn_long_term_share_mutex_key; + +HASH mrn_allocated_thds; +mysql_mutex_t mrn_allocated_thds_mutex; +PSI_mutex_key mrn_allocated_thds_mutex_key; + +PSI_mutex_key mrn_share_mutex_key; +PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key; /* internal variables */ static grn_ctx mrn_ctx; +static mysql_mutex_t mrn_log_mutex; +static PSI_mutex_key mrn_log_mutex_key; static grn_obj *mrn_db; static grn_ctx mrn_db_manager_ctx; +static mysql_mutex_t mrn_db_manager_mutex; +static PSI_mutex_key mrn_db_manager_mutex_key; mrn::DatabaseManager *mrn_db_manager = NULL; +static PSI_mutex_info mrn_mutexes[] = +{ + {&mrn_open_tables_mutex_key, "open_tables", PSI_FLAG_GLOBAL}, + {&mrn_long_term_share_mutex_key, "long_term_share", PSI_FLAG_GLOBAL}, + {&mrn_allocated_thds_mutex_key, "allocated_thds", PSI_FLAG_GLOBAL}, + {&mrn_share_mutex_key, "share", 0}, + {&mrn_long_term_share_auto_inc_mutex_key, + "long_term_share::auto_inc", 0}, + {&mrn_log_mutex_key, "log", PSI_FLAG_GLOBAL}, + {&mrn_db_manager_mutex_key, "DatabaseManager", PSI_FLAG_GLOBAL} +}; + + #ifdef WIN32 static inline double round(double x) { @@ -506,6 +522,31 @@ static int mrn_lock_timeout = grn_get_lock_timeout(); static char *mrn_libgroonga_version = const_cast<char *>(grn_get_version()); static char *mrn_version = const_cast<char *>(MRN_VERSION); static char *mrn_vector_column_delimiter = NULL; +static my_bool mrn_libgroonga_support_zlib = FALSE; +static my_bool mrn_libgroonga_support_lz4 = FALSE; +typedef enum { + MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT = (1 << 0), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_QUERY = (1 << 1), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT = (1 << 2), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN = (1 << 3), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE = (1 << 4), + MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT = (1 << 5) +} mrn_boolean_mode_syntax_flag; +static const char *mrn_boolean_mode_sytnax_flag_names[] = { + "DEFAULT", + "SYNTAX_QUERY", + "SYNTAX_SCRIPT", + "ALLOW_COLUMN", + "ALLOW_UPDATE", + "ALLOW_LEADING_NOT", + NullS +}; +static TYPELIB mrn_boolean_mode_syntax_flags_typelib = { + array_elements(mrn_boolean_mode_sytnax_flag_names) - 1, + "", + mrn_boolean_mode_sytnax_flag_names, + NULL +}; typedef enum { MRN_ACTION_ON_ERROR_ERROR, @@ -552,9 +593,6 @@ static grn_logger mrn_logger = { NULL }; -/* global hashes and mutexes */ -HASH mrn_allocated_thds; -pthread_mutex_t mrn_allocated_thds_mutex; static uchar *mrn_allocated_thds_get_key(const uchar *record, size_t *length, my_bool not_used __attribute__ ((unused))) @@ -578,13 +616,21 @@ static struct st_mysql_show_var mrn_status_variables[] = {NullS, NullS, SHOW_LONG} }; -static const char *mrn_log_level_type_names[] = { "NONE", "EMERG", "ALERT", - "CRIT", "ERROR", "WARNING", - "NOTICE", "INFO", "DEBUG", - "DUMP", NullS }; -static TYPELIB mrn_log_level_typelib = -{ - array_elements(mrn_log_level_type_names)-1, +static const char *mrn_log_level_type_names[] = { + "NONE", + "EMERG", + "ALERT", + "CRIT", + "ERROR", + "WARNING", + "NOTICE", + "INFO", + "DEBUG", + "DUMP", + NullS +}; +static TYPELIB mrn_log_level_typelib = { + array_elements(mrn_log_level_type_names) - 1, "mrn_log_level_typelib", mrn_log_level_type_names, NULL @@ -678,7 +724,7 @@ static void mrn_log_file_update(THD *thd, struct st_mysql_sys_var *var, #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR char *old_log_file_name = *old_value_ptr; *old_value_ptr = my_strdup(new_log_file_name, MYF(MY_WME)); - my_free(old_log_file_name, MYF(0)); + my_free(old_log_file_name); #else *old_value_ptr = my_strdup(new_log_file_name, MYF(MY_WME)); #endif @@ -717,7 +763,7 @@ static void mrn_default_parser_update(THD *thd, struct st_mysql_sys_var *var, } #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR - my_free(*old_value_ptr, MYF(0)); + my_free(*old_value_ptr); *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); #else *old_value_ptr = (char *)new_value; @@ -771,7 +817,7 @@ static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var char **old_value_ptr = (char **)var_ptr; #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR - my_free(*old_value_ptr, MYF(0)); + my_free(*old_value_ptr); *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); #else *old_value_ptr = (char *)new_value; @@ -796,7 +842,7 @@ static void mrn_database_path_prefix_update(THD *thd, char **old_value_ptr = (char **)var_ptr; #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR if (*old_value_ptr) - my_free(*old_value_ptr, MYF(0)); + my_free(*old_value_ptr); if (new_value) *old_value_ptr = my_strdup(new_value, MYF(MY_WME)); else @@ -876,6 +922,58 @@ static MYSQL_SYSVAR_STR(version, mrn_version, NULL, MRN_VERSION); +static my_bool grn_check_zlib_support() +{ + bool is_zlib_support = false; + grn_obj grn_support_p; + + GRN_BOOL_INIT(&grn_support_p, 0); + grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZLIB, &grn_support_p); + is_zlib_support = (GRN_BOOL_VALUE(&grn_support_p)); + grn_obj_unlink(&mrn_ctx, &grn_support_p); + + return is_zlib_support; +} + +static my_bool grn_check_lz4_support() +{ + bool is_lz4_support = false; + grn_obj grn_support_p; + + GRN_BOOL_INIT(&grn_support_p, 0); + grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_LZ4, &grn_support_p); + is_lz4_support = (GRN_BOOL_VALUE(&grn_support_p)); + grn_obj_unlink(&mrn_ctx, &grn_support_p); + + return is_lz4_support; +} + +static MYSQL_SYSVAR_BOOL(libgroonga_support_zlib, mrn_libgroonga_support_zlib, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "The status of libgroonga supports zlib", + NULL, + NULL, + grn_check_zlib_support()); + +static MYSQL_SYSVAR_BOOL(libgroonga_support_lz4, mrn_libgroonga_support_lz4, + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, + "The status of libgroonga supports LZ4", + NULL, + NULL, + grn_check_lz4_support()); + +static MYSQL_THDVAR_SET(boolean_mode_syntax_flags, + PLUGIN_VAR_RQCMDARG, + "The flags to custom syntax in BOOLEAN MODE. " + "Available flags: " + "DEFAULT(=SYNTAX_QUERY,ALLOW_LEADING_NOT), " + "SYNTAX_QUERY, SYNTAX_SCRIPT, " + "ALLOW_COLUMN, ALLOW_UPDATE and ALLOW_LEADING_NOT", + NULL, + NULL, + MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT, + &mrn_boolean_mode_syntax_flags_typelib); + static struct st_mysql_sys_var *mrn_system_variables[] = { MYSQL_SYSVAR(log_level), @@ -891,6 +989,9 @@ static struct st_mysql_sys_var *mrn_system_variables[] = MYSQL_SYSVAR(libgroonga_version), MYSQL_SYSVAR(version), MYSQL_SYSVAR(vector_column_delimiter), + MYSQL_SYSVAR(libgroonga_support_zlib), + MYSQL_SYSVAR(libgroonga_support_lz4), + MYSQL_SYSVAR(boolean_mode_syntax_flags), NULL }; @@ -917,7 +1018,7 @@ static ST_FIELD_INFO i_s_mrn_stats_fields_info[] = MYSQL_TYPE_LONG, 0, 0, - "Rows written to groonga", + "Rows written to Groonga", SKIP_OPEN_TABLE }, { @@ -926,7 +1027,7 @@ static ST_FIELD_INFO i_s_mrn_stats_fields_info[] = MYSQL_TYPE_LONG, 0, 0, - "Rows read from groonga", + "Rows read from Groonga", SKIP_OPEN_TABLE } }; @@ -1191,6 +1292,65 @@ static grn_builtin_type mrn_grn_type_from_field(grn_ctx *ctx, Field *field, return type; } +grn_obj_flags mrn_parse_grn_column_create_flags(THD *thd, + grn_ctx *ctx, + const char *flag_names, + uint flag_names_length) +{ + grn_obj_flags flags = 0; + const char *flag_names_end = flag_names + flag_names_length; + + while (flag_names < flag_names_end) { + uint rest_length = flag_names_end - flag_names; + + if (*flag_names == '|' || *flag_names == ' ') { + flag_names += 1; + continue; + } + if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_SCALAR", 13)) { + flags |= GRN_OBJ_COLUMN_SCALAR; + flag_names += 13; + } else if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_VECTOR", 13)) { + flags |= GRN_OBJ_COLUMN_VECTOR; + flag_names += 13; + } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZLIB", 13)) { + if (mrn_libgroonga_support_zlib) { + flags |= GRN_OBJ_COMPRESS_ZLIB; + } else { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, + "COMPRESS_ZLIB"); + } + flag_names += 13; + } else if (rest_length >= 12 && !memcmp(flag_names, "COMPRESS_LZ4", 12)) { + if (mrn_libgroonga_support_lz4) { + flags |= GRN_OBJ_COMPRESS_LZ4; + } else { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, + ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, + "COMPRESS_LZ4"); + } + flag_names += 12; + } else { + char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE]; + snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE, + "%.*s", + static_cast<int>(rest_length), + flag_names); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_MRN_INVALID_COLUMN_FLAG_NUM, + ER_MRN_INVALID_COLUMN_FLAG_STR, + invalid_flag_name, + "COLUMN_SCALAR"); + flags |= GRN_OBJ_COLUMN_SCALAR; + break; + } + } + return flags; +} + #ifdef HAVE_SPATIAL static int mrn_set_geometry(grn_ctx *ctx, grn_obj *buf, const char *wkb, uint wkb_size) @@ -1275,7 +1435,7 @@ static int mrn_init(void *p) hton = (handlerton *)p; hton->state = SHOW_OPTION_YES; hton->create = mrn_handler_create; - hton->flags = HTON_NO_PARTITION; + hton->flags = 0; hton->drop_database = mrn_drop_database; hton->close_connection = mrn_close_connection; hton->flush_logs = mrn_flush_logs; @@ -1294,13 +1454,8 @@ static int mrn_init(void *p) # endif # ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE mrn_LOCK_open = -# if MYSQL_VERSION_ID >= 50500 (mysql_mutex_t *)GetProcAddress(current_module, "?LOCK_open@@3Ust_mysql_mutex@@A"); -# else - (pthread_mutex_t *)GetProcAddress(current_module, - "?LOCK_open@@3U_RTL_CRITICAL_SECTION@@A"); -# endif # endif # ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE mrn_table_share_lock_share = @@ -1321,7 +1476,12 @@ static int mrn_init(void *p) # endif #endif - // init groonga + if (PSI_server) { + const char *category = "mroonga"; + int n_mutexes = array_elements(mrn_mutexes); + PSI_server->register_mutex(category, mrn_mutexes, n_mutexes); + } + if (grn_init() != GRN_SUCCESS) { goto err_grn_init; } @@ -1335,7 +1495,9 @@ static int mrn_init(void *p) if (mrn_change_encoding(ctx, system_charset_info)) goto err_mrn_change_encoding; - if (pthread_mutex_init(&mrn_log_mutex, NULL) != 0) { + if (mysql_mutex_init(mrn_log_mutex_key, + &mrn_log_mutex, + MY_MUTEX_INIT_FAST) != 0) { goto err_log_mutex_init; } @@ -1358,25 +1520,39 @@ static int mrn_init(void *p) grn_ctx_init(&mrn_db_manager_ctx, 0); grn_logger_set(&mrn_db_manager_ctx, &mrn_logger); - mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx); + if (mysql_mutex_init(mrn_db_manager_mutex_key, + &mrn_db_manager_mutex, + MY_MUTEX_INIT_FAST) != 0) { + GRN_LOG(&mrn_db_manager_ctx, GRN_LOG_ERROR, + "failed to initialize mutex for database manager"); + goto err_db_manager_mutex_init; + } + mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx, + &mrn_db_manager_mutex); if (!mrn_db_manager->init()) { goto err_db_manager_init; } - if ((pthread_mutex_init(&mrn_allocated_thds_mutex, NULL) != 0)) { + if ((mysql_mutex_init(mrn_allocated_thds_mutex_key, + &mrn_allocated_thds_mutex, + MY_MUTEX_INIT_FAST) != 0)) { goto err_allocated_thds_mutex_init; } if (my_hash_init(&mrn_allocated_thds, system_charset_info, 32, 0, 0, mrn_allocated_thds_get_key, 0, 0)) { goto error_allocated_thds_hash_init; } - if ((pthread_mutex_init(&mrn_open_tables_mutex, NULL) != 0)) { + if ((mysql_mutex_init(mrn_open_tables_mutex_key, + &mrn_open_tables_mutex, + MY_MUTEX_INIT_FAST) != 0)) { goto err_allocated_open_tables_mutex_init; } if (my_hash_init(&mrn_open_tables, system_charset_info, 32, 0, 0, mrn_open_tables_get_key, 0, 0)) { goto error_allocated_open_tables_hash_init; } - if ((pthread_mutex_init(&mrn_long_term_share_mutex, NULL) != 0)) { + if ((mysql_mutex_init(mrn_long_term_share_mutex_key, + &mrn_long_term_share_mutex, + MY_MUTEX_INIT_FAST) != 0)) { goto error_allocated_long_term_share_mutex_init; } if (my_hash_init(&mrn_long_term_share, system_charset_info, 32, 0, 0, @@ -1391,18 +1567,20 @@ static int mrn_init(void *p) return 0; error_allocated_long_term_share_hash_init: - pthread_mutex_destroy(&mrn_long_term_share_mutex); + mysql_mutex_destroy(&mrn_long_term_share_mutex); error_allocated_long_term_share_mutex_init: my_hash_free(&mrn_open_tables); error_allocated_open_tables_hash_init: - pthread_mutex_destroy(&mrn_open_tables_mutex); + mysql_mutex_destroy(&mrn_open_tables_mutex); err_allocated_open_tables_mutex_init: my_hash_free(&mrn_allocated_thds); error_allocated_thds_hash_init: - pthread_mutex_destroy(&mrn_allocated_thds_mutex); + mysql_mutex_destroy(&mrn_allocated_thds_mutex); err_allocated_thds_mutex_init: err_db_manager_init: delete mrn_db_manager; + mysql_mutex_destroy(&mrn_db_manager_mutex); +err_db_manager_mutex_init: grn_ctx_fin(&mrn_db_manager_ctx); grn_obj_unlink(ctx, mrn_db); err_db_create: @@ -1411,7 +1589,7 @@ err_db_create: mrn_log_file_opened = false; } err_log_file_open: - pthread_mutex_destroy(&mrn_log_mutex); + mysql_mutex_destroy(&mrn_log_mutex); err_log_mutex_init: err_mrn_change_encoding: grn_ctx_fin(ctx); @@ -1450,12 +1628,13 @@ static int mrn_deinit(void *p) } my_hash_free(&mrn_long_term_share); - pthread_mutex_destroy(&mrn_long_term_share_mutex); + mysql_mutex_destroy(&mrn_long_term_share_mutex); my_hash_free(&mrn_open_tables); - pthread_mutex_destroy(&mrn_open_tables_mutex); + mysql_mutex_destroy(&mrn_open_tables_mutex); my_hash_free(&mrn_allocated_thds); - pthread_mutex_destroy(&mrn_allocated_thds_mutex); + mysql_mutex_destroy(&mrn_allocated_thds_mutex); delete mrn_db_manager; + mysql_mutex_destroy(&mrn_db_manager_mutex); grn_ctx_fin(&mrn_db_manager_ctx); grn_obj_unlink(ctx, mrn_db); @@ -1466,7 +1645,7 @@ static int mrn_deinit(void *p) fclose(mrn_log_file); mrn_log_file_opened = false; } - pthread_mutex_destroy(&mrn_log_mutex); + mysql_mutex_destroy(&mrn_log_mutex); return 0; } @@ -1489,6 +1668,18 @@ mrn_declare_plugin(MRN_PLUGIN_NAME) i_s_mrn_stats mrn_declare_plugin_end; +static double mrn_get_score_value(grn_obj *score) +{ + MRN_DBUG_ENTER_FUNCTION(); + double score_value; + if (score->header.domain == GRN_DB_FLOAT) { + score_value = GRN_FLOAT_VALUE(score); + } else { + score_value = (double)GRN_INT32_VALUE(score); + } + DBUG_RETURN(score_value); +} + static void mrn_generic_ft_clear(FT_INFO *handler) { MRN_DBUG_ENTER_FUNCTION(); @@ -1555,7 +1746,7 @@ static float mrn_wrapper_ft_find_relevance(FT_INFO *handler, uchar *record, GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } @@ -1593,7 +1784,7 @@ static float mrn_wrapper_ft_get_relevance(FT_INFO *handler) GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } @@ -1640,7 +1831,7 @@ static float mrn_storage_ft_find_relevance(FT_INFO *handler, uchar *record, GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } DBUG_PRINT("info", ("mroonga: record_id=%d score=%g", @@ -1672,7 +1863,7 @@ static float mrn_storage_ft_get_relevance(FT_INFO *handler) GRN_BULK_REWIND(&(info->score)); grn_obj_get_value(info->ctx, info->score_column, result_record_id, &(info->score)); - score = (float)GRN_INT32_VALUE(&(info->score)); + score = mrn_get_score_value(&(info->score)); } } DBUG_PRINT("info", @@ -1916,7 +2107,6 @@ ha_mroonga::ha_mroonga(handlerton *hton, TABLE_SHARE *share_arg) grn_column_ranges(NULL), grn_index_tables(NULL), grn_index_columns(NULL), - grn_table_is_referenced(false), grn_source_column_geo(NULL), cursor_geo(NULL), @@ -2126,7 +2316,7 @@ uint ha_mroonga::wrapper_max_supported_key_length() const uint ha_mroonga::storage_max_supported_key_length() const { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(HA_MAX_REC_LENGTH); + DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE); } uint ha_mroonga::max_supported_key_length() const @@ -2173,7 +2363,7 @@ uint ha_mroonga::wrapper_max_supported_key_part_length() const uint ha_mroonga::storage_max_supported_key_part_length() const { MRN_DBUG_ENTER_METHOD(); - DBUG_RETURN(HA_MAX_REC_LENGTH); + DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE); } uint ha_mroonga::max_supported_key_part_length() const @@ -2467,7 +2657,7 @@ int ha_mroonga::wrapper_create(const char *name, TABLE *table, share = NULL; if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -2486,7 +2676,7 @@ int ha_mroonga::wrapper_create(const char *name, TABLE *table, if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -2838,9 +3028,9 @@ int ha_mroonga::storage_create(const char *name, TABLE *table, if (key_parts == 1) { grn_obj *normalizer = NULL; if (tmp_share->normalizer) { - normalizer = grn_ctx_get(ctx, - tmp_share->normalizer, - tmp_share->normalizer_length); + normalizer = grn_ctx_get(ctx, + tmp_share->normalizer, + tmp_share->normalizer_length); } else { Field *field = &(key_info.key_part->field[0]); if (should_normalize(field)) { @@ -2902,12 +3092,10 @@ int ha_mroonga::storage_create(const char *name, TABLE *table, grn_obj_flags col_flags = GRN_OBJ_PERSISTENT; if (tmp_share->col_flags[i]) { - // TODO: parse flags - if (strcmp(tmp_share->col_flags[i], "COLUMN_VECTOR") == 0) { - col_flags |= GRN_OBJ_COLUMN_VECTOR; - } else { - col_flags |= GRN_OBJ_COLUMN_SCALAR; - } + col_flags |= mrn_parse_grn_column_create_flags(ha_thd(), + ctx, + tmp_share->col_flags[i], + tmp_share->col_flags_length[i]); } else { col_flags |= GRN_OBJ_COLUMN_SCALAR; } @@ -3448,7 +3636,8 @@ int ha_mroonga::storage_create_indexes(TABLE *table, const char *grn_table_name, } if (error) { while (true) { - if (index_tables[i]) { + if (index_tables[i] && + !(tmp_share->index_table && tmp_share->index_table[i])) { grn_obj_remove(ctx, index_tables[i]); } if (!i) @@ -3574,7 +3763,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) MRN_SET_BASE_TABLE_KEY(this, table); if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -3598,7 +3787,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) MRN_SET_BASE_TABLE_KEY(this, table); if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -3626,7 +3815,7 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint test_if_locked) wrap_handler = NULL; if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -3806,55 +3995,6 @@ int ha_mroonga::storage_open(const char *name, int mode, uint test_if_locked) DBUG_RETURN(0); } -void ha_mroonga::update_grn_table_is_referenced() -{ - MRN_DBUG_ENTER_METHOD(); - - grn_table_is_referenced = false; - - grn_table_cursor *cursor; - int flags = GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING;; - cursor = grn_table_cursor_open(ctx, grn_ctx_db(ctx), - NULL, 0, - NULL, 0, - 0, -1, flags); - if (cursor) { - grn_id id; - grn_id grn_table_id; - - grn_table_id = grn_obj_id(ctx, grn_table); - while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { - grn_obj *object; - grn_id range = GRN_ID_NIL; - - object = grn_ctx_at(ctx, id); - if (!object) { - ctx->rc = GRN_SUCCESS; - continue; - } - - switch (object->header.type) { - case GRN_COLUMN_FIX_SIZE: - case GRN_COLUMN_VAR_SIZE: - range = grn_obj_get_range(ctx, object); - break; - default: - break; - } - grn_obj_unlink(ctx, object); - - if (range == grn_table_id) { - grn_table_is_referenced = true; - break; - } - } - - grn_table_cursor_close(ctx, cursor); - } - - DBUG_VOID_RETURN; -} - int ha_mroonga::open_table(const char *name) { int error; @@ -3881,8 +4021,6 @@ int ha_mroonga::open_table(const char *name) DBUG_RETURN(error); } - update_grn_table_is_referenced(); - DBUG_RETURN(0); } @@ -4104,7 +4242,7 @@ int ha_mroonga::wrapper_close() wrap_handler = NULL; if (wrap_key_info) { - my_free(wrap_key_info, MYF(0)); + my_free(wrap_key_info); wrap_key_info = NULL; } base_key_info = NULL; @@ -4323,7 +4461,6 @@ int ha_mroonga::delete_table(const char *name) } if (!tmp_table_share) { - mrn::PathMapper mapper(name); #ifdef MRN_TABLE_LIST_INIT_REQUIRE_ALIAS table_list.init_one_table(mapper.db_name(), strlen(mapper.db_name()), mapper.mysql_table_name(), @@ -5090,6 +5227,7 @@ int ha_mroonga::storage_write_row(uchar *buf) { MRN_DBUG_ENTER_METHOD(); int error = 0; + bool unique_indexes_are_processed = false; if (is_dry_write()) { DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__)); @@ -5098,7 +5236,6 @@ int ha_mroonga::storage_write_row(uchar *buf) THD *thd = ha_thd(); int i; - uint j; int n_columns = table->s->fields; if (table->next_number_field && buf == table->record[0]) @@ -5156,6 +5293,11 @@ int ha_mroonga::storage_write_row(uchar *buf) } } + if (grn_table->header.type != GRN_TABLE_NO_KEY && pkey_size == 0) { + my_message(ER_ERROR_ON_WRITE, "primary key is empty", MYF(0)); + DBUG_RETURN(ER_ERROR_ON_WRITE); + } + int added; record_id = grn_table_add(ctx, grn_table, pkey, pkey_size, &added); if (ctx->rc) { @@ -5179,6 +5321,7 @@ int ha_mroonga::storage_write_row(uchar *buf) { goto err; } + unique_indexes_are_processed = true; grn_obj colbuf; GRN_VOID_INIT(&colbuf); @@ -5270,13 +5413,16 @@ int ha_mroonga::storage_write_row(uchar *buf) DBUG_RETURN(0); err: - for (j = 0; j < table->s->keys; j++) { - if (j == pkey_nr) { - continue; - } - KEY *key_info = &table->key_info[j]; - if (key_info->flags & HA_NOSAME) { - grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]); + if (unique_indexes_are_processed) { + uint j; + for (j = 0; j < table->s->keys; j++) { + if (j == pkey_nr) { + continue; + } + KEY *key_info = &table->key_info[j]; + if (key_info->flags & HA_NOSAME) { + grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]); + } } } grn_table_delete_by_id(ctx, grn_table, record_id); @@ -5363,6 +5509,7 @@ err: int ha_mroonga::storage_write_row_unique_index(uchar *buf, KEY *key_info, grn_obj *index_table, + grn_obj *index_column, grn_id *key_id) { char *ukey = NULL; @@ -5398,7 +5545,29 @@ int ha_mroonga::storage_write_row_unique_index(uchar *buf, if (!added) { // duplicated error error = HA_ERR_FOUND_DUPP_KEY; - memcpy(dup_ref, key_id, sizeof(grn_id)); + grn_id duplicated_record_id = GRN_ID_NIL; + { + grn_table_cursor *table_cursor; + table_cursor = grn_table_cursor_open(ctx, index_table, + ukey, ukey_size, + ukey, ukey_size, + 0, -1, 0); + if (table_cursor) { + grn_obj *index_cursor; + index_cursor = grn_index_cursor_open(ctx, table_cursor, index_column, + GRN_ID_NIL, GRN_ID_MAX, 0); + if (index_cursor) { + grn_posting *posting; + posting = grn_index_cursor_next(ctx, index_cursor, NULL); + if (posting) { + duplicated_record_id = posting->rid; + } + } + grn_obj_unlink(ctx, index_cursor); + } + grn_table_cursor_close(ctx, table_cursor); + } + memcpy(dup_ref, &duplicated_record_id, sizeof(grn_id)); if (!ignoring_duplicated_key) { GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated id on insert: update unique index: <%.*s>", @@ -5431,9 +5600,14 @@ int ha_mroonga::storage_write_row_unique_indexes(uchar *buf) if (!index_table) { continue; } + grn_obj *index_column = grn_index_columns[i]; + if (!index_column) { + continue; + } if ((error = storage_write_row_unique_index(buf, key_info, - index_table, &key_id[i]))) + index_table, index_column, + &key_id[i]))) { if (error == HA_ERR_FOUND_DUPP_KEY) { @@ -5449,7 +5623,16 @@ err: mrn_change_encoding(ctx, NULL); do { i--; + + if (i == table->s->primary_key) { + continue; + } + KEY *key_info = &table->key_info[i]; + if (!(key_info->flags & HA_NOSAME)) { + continue; + } + if (key_info->flags & HA_NOSAME) { grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]); } @@ -5914,6 +6097,13 @@ int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data) continue; } + grn_obj *index_column = grn_index_columns[i]; + if (!index_column) { + key_id[i] = GRN_ID_NIL; + del_key_id[i] = GRN_ID_NIL; + continue; + } + if ( KEY_N_KEY_PARTS(key_info) == 1 && !bitmap_is_set(table->write_set, @@ -5926,7 +6116,8 @@ int ha_mroonga::storage_update_row_unique_indexes(uchar *new_data) } if ((error = storage_write_row_unique_index(new_data, key_info, - index_table, &key_id[i]))) + index_table, index_column, + &key_id[i]))) { if (error == HA_ERR_FOUND_DUPP_KEY) { @@ -7594,6 +7785,34 @@ bool ha_mroonga::generic_ft_init_ext_parse_pragma_w(struct st_mrn_ft_info *info, DBUG_RETURN(n_weights > 0); } +grn_expr_flags ha_mroonga::expr_flags_in_boolean_mode() +{ + MRN_DBUG_ENTER_METHOD(); + + ulonglong syntax_flags = THDVAR(ha_thd(), boolean_mode_syntax_flags); + grn_expr_flags expression_flags = 0; + if (syntax_flags == MRN_BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT) { + expression_flags = GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT; + } else { + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_SYNTAX_SCRIPT) { + expression_flags |= GRN_EXPR_SYNTAX_SCRIPT; + } else { + expression_flags |= GRN_EXPR_SYNTAX_QUERY; + } + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_COLUMN) { + expression_flags |= GRN_EXPR_ALLOW_COLUMN; + } + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_UPDATE) { + expression_flags |= GRN_EXPR_ALLOW_UPDATE; + } + if (syntax_flags & MRN_BOOLEAN_MODE_SYNTAX_FLAG_ALLOW_LEADING_NOT) { + expression_flags |= GRN_EXPR_ALLOW_LEADING_NOT; + } + } + + DBUG_RETURN(expression_flags); +} + grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode( struct st_mrn_ft_info *info, String *key, @@ -7674,12 +7893,10 @@ grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode( if (!weight_specified) { grn_expr_append_obj(info->ctx, match_columns, index_column, GRN_OP_PUSH, 1); } - grn_expr_flags expression_flags = - GRN_EXPR_SYNTAX_QUERY | GRN_EXPR_ALLOW_LEADING_NOT; rc = grn_expr_parse(info->ctx, expression, keyword, keyword_length, match_columns, GRN_OP_MATCH, default_operator, - expression_flags); + expr_flags_in_boolean_mode()); if (rc) { char error_message[MRN_MESSAGE_BUFFER_SIZE]; snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, @@ -8351,7 +8568,8 @@ int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index) const char *table_name = target_share->index_table[key_index]; snprintf(target_name, GRN_TABLE_MAX_KEY_SIZE, "%s.%s", table_name, key_info[key_index].name); - grn_obj *index_column = grn_ctx_get(ctx, target_name, strlen(target_name)); + target_name_length = strlen(target_name); + grn_obj *index_column = grn_ctx_get(ctx, target_name, target_name_length); if (index_column) { rc = grn_obj_remove(ctx, index_column); } @@ -8366,6 +8584,8 @@ int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index) target_name_length = grn_obj_name(ctx, index_table, target_name, GRN_TABLE_MAX_KEY_SIZE); rc = grn_obj_remove(ctx, index_table); + } else { + target_name_length = 0; } } @@ -8421,6 +8641,7 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info) { MRN_DBUG_ENTER_METHOD(); grn_obj *normalizer = NULL; + bool use_normalizer = true; #if MYSQL_VERSION_ID >= 50500 if (key_info->comment.length > 0) { mrn::ParametersParser parser(key_info->comment.str, @@ -8428,11 +8649,15 @@ grn_obj *ha_mroonga::find_normalizer(KEY *key_info) parser.parse(); const char *normalizer_name = parser["normalizer"]; if (normalizer_name) { - normalizer = grn_ctx_get(ctx, normalizer_name, -1); + if (strcmp(normalizer_name, "none") == 0) { + use_normalizer = false; + } else { + normalizer = grn_ctx_get(ctx, normalizer_name, -1); + } } } #endif - if (!normalizer) { + if (use_normalizer && !normalizer) { Field *field = key_info->key_part[0].field; mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field); normalizer = field_normalizer.find_grn_normalizer(); @@ -9438,9 +9663,9 @@ int ha_mroonga::generic_store_bulk_blob(Field *field, grn_obj *buf) int error = 0; String buffer; Field_blob *blob = (Field_blob *)field; - const char *value = blob->val_str(0, &buffer)->ptr(); + String *value = blob->val_str(0, &buffer); grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0); - GRN_TEXT_SET(ctx, buf, value, blob->get_length()); + GRN_TEXT_SET(ctx, buf, value->ptr(), value->length()); DBUG_RETURN(error); } @@ -9451,8 +9676,9 @@ int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf) #ifdef HAVE_SPATIAL String buffer; Field_geom *geometry = (Field_geom *)field; - const char *wkb = geometry->val_str(0, &buffer)->ptr(); - int len = geometry->get_length(); + String *value = geometry->val_str(0, &buffer); + const char *wkb = value->ptr(); + int len = value->length(); error = mrn_set_geometry(ctx, buf, wkb, len); #endif DBUG_RETURN(error); @@ -9994,7 +10220,7 @@ void ha_mroonga::storage_store_field(Field *field, } } -void ha_mroonga::storage_store_field_column(Field *field, +void ha_mroonga::storage_store_field_column(Field *field, bool is_primary_key, int nth_column, grn_id record_id) { MRN_DBUG_ENTER_METHOD(); @@ -10009,7 +10235,6 @@ void ha_mroonga::storage_store_field_column(Field *field, grn_obj_reinit(ctx, value, range_id, GRN_OBJ_VECTOR); grn_obj_get_value(ctx, column, record_id, value); - // TODO: Check whether reference type or not grn_obj unvectored_value; GRN_TEXT_INIT(&unvectored_value, 0); int n_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id); @@ -10042,7 +10267,15 @@ void ha_mroonga::storage_store_field_column(Field *field, } else { grn_obj_reinit(ctx, value, range_id, 0); grn_obj_get_value(ctx, column, record_id, value); - storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value)); + if (is_primary_key && GRN_BULK_VSIZE(value) == 0) { + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_length; + key_length = grn_table_get_key(ctx, grn_table, record_id, + &key, GRN_TABLE_MAX_KEY_SIZE); + storage_store_field(field, key, key_length); + } else { + storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value)); + } } DBUG_VOID_RETURN; @@ -10056,9 +10289,11 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id) my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]); Field *primary_key_field = NULL; - if (grn_table_is_referenced && table->s->primary_key != MAX_INDEXES) { + if (table->s->primary_key != MAX_INDEXES) { KEY *key_info = &(table->s->key_info[table->s->primary_key]); - primary_key_field = key_info->key_part[0].field; + if (KEY_N_KEY_PARTS(key_info) == 1) { + primary_key_field = key_info->key_part[0].field; + } } int i; @@ -10087,13 +10322,9 @@ void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id) } else if (primary_key_field && strcmp(primary_key_field->field_name, column_name) == 0) { // for primary key column - char key[GRN_TABLE_MAX_KEY_SIZE]; - int key_length; - key_length = grn_table_get_key(ctx, grn_table, record_id, - &key, GRN_TABLE_MAX_KEY_SIZE); - storage_store_field(field, key, key_length); + storage_store_field_column(field, true, i, record_id); } else { - storage_store_field_column(field, i ,record_id); + storage_store_field_column(field, false, i, record_id); } field->move_field_offset(-ptr_diff); } @@ -10770,12 +11001,12 @@ int ha_mroonga::wrapper_reset() MRN_SET_BASE_TABLE_KEY(this, table); #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER if (alter_key_info_buffer) { - my_free(alter_key_info_buffer, MYF(0)); + my_free(alter_key_info_buffer); alter_key_info_buffer = NULL; } #else if (wrap_alter_key_info) { - my_free(wrap_alter_key_info, MYF(0)); + my_free(wrap_alter_key_info); wrap_alter_key_info = NULL; } #endif @@ -11787,7 +12018,7 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info) if (slot_data) { slot_data->alter_create_info = create_info; if (slot_data->alter_connect_string) { - my_free(slot_data->alter_connect_string, MYF(0)); + my_free(slot_data->alter_connect_string); slot_data->alter_connect_string = NULL; } if (create_info->connect_string.str) { @@ -11797,7 +12028,7 @@ void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info) MYF(MY_WME)); } if (slot_data->alter_comment) { - my_free(slot_data->alter_comment, MYF(0)); + my_free(slot_data->alter_comment); slot_data->alter_comment = NULL; } if (create_info->comment.str) { @@ -12184,6 +12415,44 @@ bool ha_mroonga::auto_repair() const DBUG_RETURN(crashed); } +int ha_mroonga::generic_disable_index(int i, KEY *key_info) +{ + MRN_DBUG_ENTER_METHOD(); + + int error = 0; + if (share->index_table[i]) { + char index_column_name[GRN_TABLE_MAX_KEY_SIZE]; + snprintf(index_column_name, GRN_TABLE_MAX_KEY_SIZE - 1, + "%s.%s", share->index_table[i], key_info[i].name); + grn_obj *index_column = grn_ctx_get(ctx, + index_column_name, + strlen(index_column_name)); + if (index_column) { + grn_obj_remove(ctx, index_column); + } + } else { + mrn::PathMapper mapper(share->table_name); + mrn::IndexTableName index_table_name(mapper.table_name(), + key_info[i].name); + grn_obj *index_table = grn_ctx_get(ctx, + index_table_name.c_str(), + index_table_name.length()); + if (index_table) { + grn_obj_remove(ctx, index_table); + } + } + if (ctx->rc == GRN_SUCCESS) { + grn_index_tables[i] = NULL; + grn_index_columns[i] = NULL; + } else { + // TODO: Implement ctx->rc to error converter and use it. + error = ER_ERROR_ON_WRITE; + my_message(error, ctx->errbuf, MYF(0)); + } + + DBUG_RETURN(error); +} + int ha_mroonga::wrapper_disable_indexes(uint mode) { int error = 0; @@ -12212,23 +12481,16 @@ int ha_mroonga::wrapper_disable_indexes(uint mode) } } KEY *key_info = table_share->key_info; - mrn::PathMapper mapper(share->table_name); for (i = 0; i < table_share->keys; i++) { if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) { continue; } - mrn::IndexTableName index_table_name(mapper.table_name(), - key_info[i].name); - grn_obj *index_table = grn_ctx_get(ctx, - index_table_name.c_str(), - index_table_name.length()); - if (index_table) { - grn_obj_remove(ctx, index_table); + int sub_error = generic_disable_index(i, key_info); + if (error != 0 && sub_error != 0) { + error = sub_error; } - grn_index_tables[i] = NULL; - grn_index_columns[i] = NULL; } } else { error = HA_ERR_WRONG_COMMAND; @@ -12239,6 +12501,7 @@ int ha_mroonga::wrapper_disable_indexes(uint mode) int ha_mroonga::storage_disable_indexes(uint mode) { + int error = 0; MRN_DBUG_ENTER_METHOD(); if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) { uint i; @@ -12252,7 +12515,6 @@ int ha_mroonga::storage_disable_indexes(uint mode) } } KEY *key_info = table_share->key_info; - mrn::PathMapper mapper(share->table_name); for (i = 0; i < table_share->keys; i++) { if (i == table->s->primary_key) { continue; @@ -12262,21 +12524,15 @@ int ha_mroonga::storage_disable_indexes(uint mode) continue; } - mrn::IndexTableName index_table_name(mapper.table_name(), - key_info[i].name); - grn_obj *index_table = grn_ctx_get(ctx, - index_table_name.c_str(), - index_table_name.length()); - if (index_table) { - grn_obj_remove(ctx, index_table); + int sub_error = generic_disable_index(i, key_info); + if (error != 0 && sub_error != 0) { + error = sub_error; } - grn_index_tables[i] = NULL; - grn_index_columns[i] = NULL; } } else { DBUG_RETURN(HA_ERR_WRONG_COMMAND); } - DBUG_RETURN(0); + DBUG_RETURN(error); } int ha_mroonga::disable_indexes(uint mode) @@ -12305,7 +12561,7 @@ int ha_mroonga::wrapper_enable_indexes(uint mode) if (share->wrap_key_nr[i] < MAX_KEY) { continue; } - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { break; } } @@ -12334,7 +12590,7 @@ int ha_mroonga::wrapper_enable_indexes(uint mode) } index_tables[i] = NULL; index_columns[i] = NULL; - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { if ( (key_info[i].flags & HA_FULLTEXT) && (error = wrapper_create_index_fulltext(mapper.table_name(), @@ -12394,7 +12650,7 @@ int ha_mroonga::storage_enable_indexes(uint mode) if (i == table->s->primary_key) { continue; } - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { break; } } @@ -12420,7 +12676,7 @@ int ha_mroonga::storage_enable_indexes(uint mode) break; } index_tables[i] = NULL; - if (!grn_index_tables[i]) { + if (!grn_index_columns[i]) { if ((error = storage_create_index(table, mapper.table_name(), grn_table, share, &key_info[i], index_tables, index_columns, i))) @@ -12434,6 +12690,8 @@ int ha_mroonga::storage_enable_indexes(uint mode) mrn_set_bitmap_by_key(table->read_set, &key_info[i]); have_multiple_column_index = true; } + grn_index_tables[i] = index_tables[i]; + grn_index_columns[i] = index_columns[i]; } else { index_columns[i] = NULL; } @@ -12902,6 +13160,7 @@ int ha_mroonga::storage_add_index_multiple_columns(KEY *key_info, if ((error = storage_write_row_unique_index(table->record[0], current_key_info, index_tables[i], + index_columns[i], &key_id))) { if (error == HA_ERR_FOUND_DUPP_KEY) @@ -13308,7 +13567,7 @@ bool ha_mroonga::wrapper_inplace_alter_table( result = true; } mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(result); @@ -13434,6 +13693,12 @@ bool ha_mroonga::storage_inplace_alter_table_index( ha_alter_info->key_count, index_tables, index_columns, false); + if (error == HA_ERR_FOUND_DUPP_UNIQUE) { + my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0), + table_share->table_name); + } else if (error) { + my_message(error, "failed to create multiple column index", MYF(0)); + } for (i = 0; i < n_columns; ++i) { Field *field = altered_table->field[i]; field->move_field_offset(-ptr_diff); @@ -13460,7 +13725,7 @@ bool ha_mroonga::storage_inplace_alter_table_index( have_error = true; } mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); @@ -13532,12 +13797,10 @@ bool ha_mroonga::storage_inplace_alter_table_add_column( grn_obj_flags col_flags = GRN_OBJ_PERSISTENT; if (tmp_share->col_flags[i]) { - // TODO: parse flags - if (strcmp(tmp_share->col_flags[i], "COLUMN_VECTOR") == 0) { - col_flags |= GRN_OBJ_COLUMN_VECTOR; - } else { - col_flags |= GRN_OBJ_COLUMN_SCALAR; - } + col_flags |= mrn_parse_grn_column_create_flags(ha_thd(), + ctx, + tmp_share->col_flags[i], + tmp_share->col_flags_length[i]); } else { col_flags |= GRN_OBJ_COLUMN_SCALAR; } @@ -13570,7 +13833,7 @@ bool ha_mroonga::storage_inplace_alter_table_add_column( grn_obj_unlink(ctx, table_obj); mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); DBUG_RETURN(have_error); } @@ -13752,7 +14015,7 @@ bool ha_mroonga::wrapper_commit_inplace_alter_table( bool result; MRN_DBUG_ENTER_METHOD(); if (!alter_handler_flags) { - my_free(alter_key_info_buffer, MYF(0)); + my_free(alter_key_info_buffer); alter_key_info_buffer = NULL; DBUG_RETURN(false); } @@ -13765,7 +14028,7 @@ bool ha_mroonga::wrapper_commit_inplace_alter_table( MRN_SET_BASE_ALTER_KEY(this, ha_alter_info); MRN_SET_BASE_SHARE_KEY(share, table->s); MRN_SET_BASE_TABLE_KEY(this, table); - my_free(alter_key_info_buffer, MYF(0)); + my_free(alter_key_info_buffer); alter_key_info_buffer = NULL; DBUG_RETURN(result); } @@ -13990,7 +14253,7 @@ int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info, } #endif mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(error); @@ -14104,7 +14367,7 @@ int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info, } #endif mrn_free_share_alloc(tmp_share); - my_free(tmp_share, MYF(0)); + my_free(tmp_share); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns); DBUG_RETURN(error); @@ -15277,7 +15540,7 @@ void ha_mroonga::wrapper_free_foreign_key_create_info(char* str) void ha_mroonga::storage_free_foreign_key_create_info(char* str) { MRN_DBUG_ENTER_METHOD(); - my_free(str, MYF(0)); + my_free(str); DBUG_VOID_RETURN; } #else diff --git a/storage/mroonga/ha_mroonga.hpp b/storage/mroonga/ha_mroonga.hpp index 224abb09732..14dd7960e5d 100644 --- a/storage/mroonga/ha_mroonga.hpp +++ b/storage/mroonga/ha_mroonga.hpp @@ -263,7 +263,6 @@ private: grn_obj **grn_column_ranges; grn_obj **grn_index_tables; grn_obj **grn_index_columns; - bool grn_table_is_referenced; // buffers grn_obj encoded_key_buffer; @@ -641,7 +640,7 @@ private: void storage_store_field_geometry(Field *field, const char *value, uint value_length); void storage_store_field(Field *field, const char *value, uint value_length); - void storage_store_field_column(Field *field, + void storage_store_field_column(Field *field, bool is_primary_key, int nth_column, grn_id record_id); void storage_store_fields(uchar *buf, grn_id record_id); void storage_store_fields_for_prep_update(const uchar *old_data, @@ -742,7 +741,6 @@ private: int wrapper_open(const char *name, int mode, uint test_if_locked); int wrapper_open_indexes(const char *name); int storage_open(const char *name, int mode, uint test_if_locked); - void update_grn_table_is_referenced(); int open_table(const char *name); int storage_open_columns(void); int storage_open_indexes(const char *name); @@ -785,7 +783,9 @@ private: grn_obj *index_column); int storage_write_row_multiple_column_indexes(uchar *buf, grn_id record_id); int storage_write_row_unique_index(uchar *buf, - KEY *key_info, grn_obj *index_table, + KEY *key_info, + grn_obj *index_table, + grn_obj *index_column, grn_id *key_id); int storage_write_row_unique_indexes(uchar *buf); int wrapper_get_record_id(uchar *data, grn_id *record_id, const char *context); @@ -904,6 +904,7 @@ private: grn_obj *match_columns, uint *consumed_keyword_length, grn_obj *tmp_objects); + grn_expr_flags expr_flags_in_boolean_mode(); grn_rc generic_ft_init_ext_prepare_expression_in_boolean_mode( struct st_mrn_ft_info *info, String *key, @@ -1029,6 +1030,7 @@ private: bool storage_is_crashed() const; bool wrapper_auto_repair(int error) const; bool storage_auto_repair(int error) const; + int generic_disable_index(int i, KEY *key_info); int wrapper_disable_indexes(uint mode); int storage_disable_indexes(uint mode); int wrapper_enable_indexes(uint mode); diff --git a/storage/mroonga/lib/mrn_database_manager.cpp b/storage/mroonga/lib/mrn_database_manager.cpp index 52ec78fccc0..365f47337fa 100644 --- a/storage/mroonga/lib/mrn_database_manager.cpp +++ b/storage/mroonga/lib/mrn_database_manager.cpp @@ -26,6 +26,8 @@ #include "mrn_lock.hpp" #include "mrn_path_mapper.hpp" +#include <groonga/plugin.h> + // for debug #define MRN_CLASS_NAME "mrn::DatabaseManager" @@ -38,19 +40,19 @@ # define MRN_MKDIR(pathname, mode) mkdir((pathname), (mode)) #endif +extern "C" { + grn_rc GRN_PLUGIN_IMPL_NAME_TAGGED(init, normalizers_mysql)(grn_ctx *ctx); + grn_rc GRN_PLUGIN_IMPL_NAME_TAGGED(register, normalizers_mysql)(grn_ctx *ctx); +} + namespace mrn { - DatabaseManager::DatabaseManager(grn_ctx *ctx) + DatabaseManager::DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex) : ctx_(ctx), cache_(NULL), - mutex_(), - mutex_initialized_(false) { + mutex_(mutex) { } DatabaseManager::~DatabaseManager(void) { - if (mutex_initialized_) { - pthread_mutex_destroy(&mutex_); - } - if (cache_) { void *db_address; GRN_HASH_EACH(ctx_, cache_, id, NULL, 0, &db_address, { @@ -75,13 +77,6 @@ namespace mrn { DBUG_RETURN(false); } - if (pthread_mutex_init(&mutex_, NULL) != 0) { - GRN_LOG(ctx_, GRN_LOG_ERROR, - "failed to initialize mutex for opened database cache hash table"); - DBUG_RETURN(false); - } - - mutex_initialized_ = true; DBUG_RETURN(true); } @@ -92,7 +87,7 @@ namespace mrn { *db = NULL; mrn::PathMapper mapper(path); - mrn::Lock lock(&mutex_); + mrn::Lock lock(mutex_); error = mrn::encoding::set(ctx_, system_charset_info); if (error) { @@ -145,7 +140,7 @@ namespace mrn { MRN_DBUG_ENTER_METHOD(); mrn::PathMapper mapper(path); - mrn::Lock lock(&mutex_); + mrn::Lock lock(mutex_); grn_id id; void *db_address; @@ -171,7 +166,7 @@ namespace mrn { MRN_DBUG_ENTER_METHOD(); mrn::PathMapper mapper(path); - mrn::Lock lock(&mutex_); + mrn::Lock lock(mutex_); grn_id id; void *db_address; @@ -211,7 +206,7 @@ namespace mrn { int error = 0; - mrn::Lock lock(&mutex_); + mrn::Lock lock(mutex_); grn_hash_cursor *cursor; cursor = grn_hash_cursor_open(ctx_, cache_, @@ -323,15 +318,12 @@ namespace mrn { if (mysql_normalizer) { grn_obj_unlink(ctx_, mysql_normalizer); } else { -#ifdef GROONGA_NORMALIZER_MYSQL_PLUGIN_IS_BUNDLED_STATIC - char ref_path[FN_REFLEN + 1], *tmp; - tmp = strmov(ref_path, opt_plugin_dir); - tmp = strmov(tmp, "/ha_mroonga"); - strcpy(tmp, SO_EXT); - grn_plugin_register_by_path(ctx_, ref_path); -#else +# ifdef MRN_GROONGA_NORMALIZER_MYSQL_EMBED + GRN_PLUGIN_IMPL_NAME_TAGGED(init, normalizers_mysql)(ctx_); + GRN_PLUGIN_IMPL_NAME_TAGGED(register, normalizers_mysql)(ctx_); +# else grn_plugin_register(ctx_, GROONGA_NORMALIZER_MYSQL_PLUGIN_NAME); -#endif +# endif } } #endif diff --git a/storage/mroonga/lib/mrn_database_manager.hpp b/storage/mroonga/lib/mrn_database_manager.hpp index 46bce7ab1a5..76c76dab6d5 100644 --- a/storage/mroonga/lib/mrn_database_manager.hpp +++ b/storage/mroonga/lib/mrn_database_manager.hpp @@ -27,7 +27,7 @@ namespace mrn { class DatabaseManager { public: - DatabaseManager(grn_ctx *ctx); + DatabaseManager(grn_ctx *ctx, mysql_mutex_t *mutex); ~DatabaseManager(void); bool init(void); int open(const char *path, grn_obj **db); @@ -38,8 +38,7 @@ namespace mrn { private: grn_ctx *ctx_; grn_hash *cache_; - pthread_mutex_t mutex_; - bool mutex_initialized_; + mysql_mutex_t *mutex_; void mkdir_p(const char *directory); void ensure_database_directory(void); diff --git a/storage/mroonga/lib/mrn_lock.cpp b/storage/mroonga/lib/mrn_lock.cpp index 94f8a4774af..3340149b237 100644 --- a/storage/mroonga/lib/mrn_lock.cpp +++ b/storage/mroonga/lib/mrn_lock.cpp @@ -20,12 +20,12 @@ #include "mrn_lock.hpp" namespace mrn { - Lock::Lock(pthread_mutex_t *mutex) + Lock::Lock(mysql_mutex_t *mutex) : mutex_(mutex) { - pthread_mutex_lock(mutex_); + mysql_mutex_lock(mutex_); } Lock::~Lock() { - pthread_mutex_unlock(mutex_); + mysql_mutex_unlock(mutex_); } } diff --git a/storage/mroonga/lib/mrn_lock.hpp b/storage/mroonga/lib/mrn_lock.hpp index 31dd7b3e53b..08e47b39c58 100644 --- a/storage/mroonga/lib/mrn_lock.hpp +++ b/storage/mroonga/lib/mrn_lock.hpp @@ -26,10 +26,10 @@ namespace mrn { class Lock { public: - Lock(pthread_mutex_t *mutex); + Lock(mysql_mutex_t *mutex); ~Lock(); private: - pthread_mutex_t *mutex_; + mysql_mutex_t *mutex_; }; } diff --git a/storage/mroonga/lib/mrn_parameters_parser.cpp b/storage/mroonga/lib/mrn_parameters_parser.cpp index 9a05097e548..3edf910ee91 100644 --- a/storage/mroonga/lib/mrn_parameters_parser.cpp +++ b/storage/mroonga/lib/mrn_parameters_parser.cpp @@ -35,10 +35,10 @@ namespace mrn { }; ~Parameter() { if (key_) { - my_free(key_, MYF(0)); + my_free(key_); } if (value_) { - my_free(value_, MYF(0)); + my_free(value_); } }; }; diff --git a/storage/mroonga/lib/mrn_path_mapper.cpp b/storage/mroonga/lib/mrn_path_mapper.cpp index ee5432f16bb..796101a10d1 100644 --- a/storage/mroonga/lib/mrn_path_mapper.cpp +++ b/storage/mroonga/lib/mrn_path_mapper.cpp @@ -2,7 +2,7 @@ /* Copyright(C) 2010 Tetsuro IKEDA Copyright(C) 2011-2013 Kentoku SHIBA - Copyright(C) 2011-2012 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2011-2015 Kouhei Sutou <kou@clear-code.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -184,6 +184,9 @@ namespace mrn { int i = len, j = 0; for (; mysql_path_[--i] != FN_LIBCHAR ;) {} for (; i < len ;) { + if (len - i - 1 >= 3 && strncmp(mysql_path_ + i + 1, "#P#", 3) == 0) { + break; + } mysql_table_name_[j++] = mysql_path_[++i]; } mysql_table_name_[j] = '\0'; diff --git a/storage/mroonga/mrn_err.h b/storage/mroonga/mrn_err.h index c2ca885407a..bfaf2d44fa8 100644 --- a/storage/mroonga/mrn_err.h +++ b/storage/mroonga/mrn_err.h @@ -28,5 +28,11 @@ #define ER_MRN_ERROR_FROM_GROONGA_STR "Error from Groonga [%s]" #define ER_MRN_INVALID_NULL_VALUE_NUM 16505 #define ER_MRN_INVALID_NULL_VALUE_STR "NULL value can't be used for %s" +#define ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM 16506 +#define ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR \ + "The column flag '%-.64s' is unsupported. It is ignored" +#define ER_MRN_INVALID_COLUMN_FLAG_NUM 16507 +#define ER_MRN_INVALID_COLUMN_FLAG_STR \ + "The column flag '%-.64s' is invalid. '%-64s' is used instead" #endif /* MRN_ERR_H_ */ diff --git a/storage/mroonga/mrn_mysql_compat.h b/storage/mroonga/mrn_mysql_compat.h index 7312dd70827..61b4ddd67a2 100644 --- a/storage/mroonga/mrn_mysql_compat.h +++ b/storage/mroonga/mrn_mysql_compat.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2011-2014 Kouhei Sutou <kou@clear-code.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -22,15 +22,6 @@ #include "mrn_mysql.h" -#if MYSQL_VERSION_ID >= 50500 -# define my_free(PTR, FLAG) my_free(PTR) -#endif - -#if MYSQL_VERSION_ID < 50500 -# define mysql_mutex_lock(mutex) pthread_mutex_lock(mutex) -# define mysql_mutex_unlock(mutex) pthread_mutex_unlock(mutex) -#endif - #if MYSQL_VERSION_ID >= 50604 # define MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 # define MRN_HAVE_MYSQL_TYPE_DATETIME2 diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp index fd406ac2dcf..4fec67b423d 100644 --- a/storage/mroonga/mrn_table.cpp +++ b/storage/mroonga/mrn_table.cpp @@ -61,14 +61,16 @@ extern "C" { #endif extern HASH mrn_open_tables; -extern pthread_mutex_t mrn_open_tables_mutex; +extern mysql_mutex_t mrn_open_tables_mutex; extern HASH mrn_long_term_share; -extern pthread_mutex_t mrn_long_term_share_mutex; +extern mysql_mutex_t mrn_long_term_share_mutex; extern char *mrn_default_parser; extern char *mrn_default_wrapper_engine; extern handlerton *mrn_hton_ptr; extern HASH mrn_allocated_thds; -extern pthread_mutex_t mrn_allocated_thds_mutex; +extern mysql_mutex_t mrn_allocated_thds_mutex; +extern PSI_mutex_key mrn_share_mutex_key; +extern PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key; static char *mrn_get_string_between_quote(const char *ptr) { @@ -424,7 +426,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table) } } - my_free(params_string, MYF(0)); + my_free(params_string); params_string = NULL; } } @@ -455,7 +457,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table) !strncasecmp(share->engine, MRN_GROONGA_STR, MRN_GROONGA_LEN) ) ) { - my_free(share->engine, MYF(0)); + my_free(share->engine); share->engine = NULL; share->engine_length = 0; } else { @@ -474,7 +476,7 @@ int mrn_parse_table_param(MRN_SHARE *share, TABLE *table) error: if (params_string) - my_free(params_string, MYF(0)); + my_free(params_string); DBUG_RETURN(error); } @@ -500,7 +502,7 @@ int mrn_add_index_param(MRN_SHARE *share, KEY *key_info, int i) if (key_info->comment.length == 0) { if (share->key_parser[i]) { - my_free(share->key_parser[i], MYF(0)); + my_free(share->key_parser[i]); } if ( !(share->key_parser[i] = my_strdup(mrn_default_parser, MYF(MY_WME))) @@ -574,12 +576,12 @@ int mrn_add_index_param(MRN_SHARE *share, KEY *key_info, int i) } if (param_string) - my_free(param_string, MYF(0)); + my_free(param_string); DBUG_RETURN(0); error: if (param_string) - my_free(param_string, MYF(0)); + my_free(param_string); #if MYSQL_VERSION_ID >= 50500 error_alloc_param_string: #endif @@ -677,12 +679,12 @@ int mrn_add_column_param(MRN_SHARE *share, Field *field, int i) } if (param_string) - my_free(param_string, MYF(0)); + my_free(param_string); DBUG_RETURN(0); error: if (param_string) - my_free(param_string, MYF(0)); + my_free(param_string); error_alloc_param_string: DBUG_RETURN(error); } @@ -714,26 +716,26 @@ int mrn_free_share_alloc( uint i; MRN_DBUG_ENTER_FUNCTION(); if (share->engine) - my_free(share->engine, MYF(0)); + my_free(share->engine); if (share->default_tokenizer) - my_free(share->default_tokenizer, MYF(0)); + my_free(share->default_tokenizer); if (share->normalizer) - my_free(share->normalizer, MYF(0)); + my_free(share->normalizer); if (share->token_filters) - my_free(share->token_filters, MYF(0)); + my_free(share->token_filters); for (i = 0; i < share->table_share->keys; i++) { if (share->index_table && share->index_table[i]) - my_free(share->index_table[i], MYF(0)); + my_free(share->index_table[i]); if (share->key_parser[i]) - my_free(share->key_parser[i], MYF(0)); + my_free(share->key_parser[i]); } for (i = 0; i < share->table_share->fields; i++) { if (share->col_flags && share->col_flags[i]) - my_free(share->col_flags[i], MYF(0)); + my_free(share->col_flags[i]); if (share->col_type && share->col_type[i]) - my_free(share->col_type[i], MYF(0)); + my_free(share->col_type[i]); } DBUG_RETURN(0); } @@ -745,8 +747,8 @@ void mrn_free_long_term_share(MRN_LONG_TERM_SHARE *long_term_share) mrn::Lock lock(&mrn_long_term_share_mutex); my_hash_delete(&mrn_long_term_share, (uchar*) long_term_share); } - pthread_mutex_destroy(&long_term_share->auto_inc_mutex); - my_free(long_term_share, MYF(0)); + mysql_mutex_destroy(&long_term_share->auto_inc_mutex); + my_free(long_term_share); DBUG_VOID_RETURN; } @@ -775,8 +777,9 @@ MRN_LONG_TERM_SHARE *mrn_get_long_term_share(const char *table_name, long_term_share->table_name = tmp_name; long_term_share->table_name_length = table_name_length; memcpy(long_term_share->table_name, table_name, table_name_length); - if (pthread_mutex_init(&long_term_share->auto_inc_mutex, - MY_MUTEX_INIT_FAST)) + if (mysql_mutex_init(mrn_long_term_share_auto_inc_mutex_key, + &long_term_share->auto_inc_mutex, + MY_MUTEX_INIT_FAST) != 0) { *error = HA_ERR_OUT_OF_MEM; goto error_init_auto_inc_mutex; @@ -790,9 +793,9 @@ MRN_LONG_TERM_SHARE *mrn_get_long_term_share(const char *table_name, DBUG_RETURN(long_term_share); error_hash_insert: - pthread_mutex_destroy(&long_term_share->auto_inc_mutex); + mysql_mutex_destroy(&long_term_share->auto_inc_mutex); error_init_auto_inc_mutex: - my_free(long_term_share, MYF(0)); + my_free(long_term_share); error_alloc_long_term_share: DBUG_RETURN(NULL); } @@ -912,7 +915,9 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error) share->wrap_table_share = wrap_table_share; } - if (pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST)) + if (mysql_mutex_init(mrn_share_mutex_key, + &share->mutex, + MY_MUTEX_INIT_FAST) != 0) { *error = HA_ERR_OUT_OF_MEM; goto error_init_mutex; @@ -934,11 +939,11 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error) error_hash_insert: error_get_long_term_share: - pthread_mutex_destroy(&share->mutex); + mysql_mutex_destroy(&share->mutex); error_init_mutex: error_parse_table_param: mrn_free_share_alloc(share); - my_free(share, MYF(0)); + my_free(share); error_alloc_share: DBUG_RETURN(NULL); } @@ -954,7 +959,7 @@ int mrn_free_share(MRN_SHARE *share) plugin_unlock(NULL, share->plugin); mrn_free_share_alloc(share); thr_lock_delete(&share->lock); - pthread_mutex_destroy(&share->mutex); + mysql_mutex_destroy(&share->mutex); if (share->wrapper_mode) { #ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE mysql_mutex_destroy(&(share->wrap_table_share->LOCK_share)); @@ -963,7 +968,7 @@ int mrn_free_share(MRN_SHARE *share) mysql_mutex_destroy(&(share->wrap_table_share->LOCK_ha_data)); #endif } - my_free(share, MYF(0)); + my_free(share); } DBUG_RETURN(0); } @@ -1025,9 +1030,9 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path } share->tmp_table = INTERNAL_TMP_TABLE; // TODO: is this right? share->path.str = (char *) path; - share->path.length = strlen(path); - share->normalized_path.str = share->path.str; - share->normalized_path.length = share->path.length; + share->path.length = strlen(share->path.str); + share->normalized_path.str = my_strdup(path, MYF(MY_WME)); + share->normalized_path.length = strlen(share->normalized_path.str); if (open_table_def(thd, share, GTS_TABLE)) { *error = ER_CANT_OPEN_FILE; @@ -1039,7 +1044,9 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path void mrn_free_tmp_table_share(TABLE_SHARE *tmp_table_share) { MRN_DBUG_ENTER_FUNCTION(); + char *normalized_path = tmp_table_share->normalized_path.str; free_table_share(tmp_table_share); + my_free(normalized_path); DBUG_VOID_RETURN; } @@ -1131,11 +1138,11 @@ void mrn_clear_alter_share(THD *thd) slot_data->alter_create_info = NULL; slot_data->disable_keys_create_info = NULL; if (slot_data->alter_connect_string) { - my_free(slot_data->alter_connect_string, MYF(0)); + my_free(slot_data->alter_connect_string); slot_data->alter_connect_string = NULL; } if (slot_data->alter_comment) { - my_free(slot_data->alter_comment, MYF(0)); + my_free(slot_data->alter_comment); slot_data->alter_comment = NULL; } } diff --git a/storage/mroonga/mrn_table.hpp b/storage/mroonga/mrn_table.hpp index 813e69e1023..9118455b53d 100644 --- a/storage/mroonga/mrn_table.hpp +++ b/storage/mroonga/mrn_table.hpp @@ -33,7 +33,7 @@ typedef struct st_mroonga_long_term_share uint table_name_length; // for auto_increment (storage mode only) - pthread_mutex_t auto_inc_mutex; + mysql_mutex_t auto_inc_mutex; bool auto_inc_inited; ulonglong auto_inc_value; } MRN_LONG_TERM_SHARE; @@ -43,7 +43,7 @@ typedef struct st_mroonga_share char *table_name; uint table_name_length; uint use_count; - pthread_mutex_t mutex; + mysql_mutex_t mutex; THR_LOCK lock; TABLE_SHARE *table_share; TABLE_SHARE *wrap_table_share; diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc new file mode 100644 index 00000000000..1c74cbffc46 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_lz4.inc @@ -0,0 +1,20 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--disable_query_log +let $libgroonga_support_lz4 = + `SELECT @@mroonga_libgroonga_support_lz4;`; +--enable_query_log diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc new file mode 100644 index 00000000000..5ab5fcd2fb8 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/check_libgroonga_support_zlib.inc @@ -0,0 +1,20 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--disable_query_log +let $libgroonga_support_zlib = + `SELECT @@mroonga_libgroonga_support_zlib;`; +--enable_query_log diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc new file mode 100644 index 00000000000..e67f826b0ce --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_lz4.inc @@ -0,0 +1,22 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/check_libgroonga_support_lz4.inc + +if (!$libgroonga_support_lz4) { + --source ../../include/mroonga/have_mroonga_deinit.inc + skip "This test is for libgroonga supports lz4"; +} diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc new file mode 100644 index 00000000000..9f5196f742b --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/support_libgroonga_zlib.inc @@ -0,0 +1,22 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/check_libgroonga_support_zlib.inc + +if (!$libgroonga_support_zlib) { + --source ../../include/mroonga/have_mroonga_deinit.inc + skip "This test is for libgroonga supports zlib"; +} diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc new file mode 100644 index 00000000000..80874a7a50b --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_lz4.inc @@ -0,0 +1,22 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/check_libgroonga_support_lz4.inc + +if ($libgroonga_support_lz4) { + --source ../../include/mroonga/have_mroonga_deinit.inc + skip "This test is for libgroonga doesn't support lz4"; +} diff --git a/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc new file mode 100644 index 00000000000..d6c3f6dbeda --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/include/mroonga/unsupport_libgroonga_zlib.inc @@ -0,0 +1,22 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/check_libgroonga_support_zlib.inc + +if ($libgroonga_support_zlib) { + --source ../../include/mroonga/have_mroonga_deinit.inc + skip "This test is for libgroonga doesn't support zlib"; +} diff --git a/storage/mroonga/mysql-test/mroonga/storage/disabled.def b/storage/mroonga/mysql-test/mroonga/storage/disabled.def index 3f546dad2a4..6866adc1e35 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/disabled.def +++ b/storage/mroonga/mysql-test/mroonga/storage/disabled.def @@ -6,4 +6,5 @@ create_table_token_filters_index_comment_one_token_filter : Bundled Mroonga does create_table_token_filters_table_comment_multiple_token_filters : Bundled Mroonga does not support token filter yet. create_table_token_filters_table_comment_one_token_filter : Bundled Mroonga does not support token filter yet. foreign_key_create : Bundled Mroonga does not support this test yet. +partition_insert : Bundled Mroonga does not support this test yet. diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result new file mode 100644 index 00000000000..8ab7ef22aca --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_add_index_unique_multiple_column_duplicated.result @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS ids; +CREATE TABLE ids ( +id1 INT, +id2 INT +) DEFAULT CHARSET=utf8mb4; +INSERT INTO ids (id1, id2) values (1, 2), (1, 2); +ALTER TABLE ids ADD UNIQUE INDEX (id1, id2); +ERROR 23000: Can't write, because of unique constraint, to table 'ids' +SHOW CREATE TABLE ids; +Table Create Table +ids CREATE TABLE `ids` ( + `id1` int(11) DEFAULT NULL, + `id2` int(11) DEFAULT NULL +) ENGINE=Mroonga DEFAULT CHARSET=utf8mb4 +SELECT * FROM ids; +id1 id2 +1 2 +1 2 +DROP TABLE ids; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result new file mode 100644 index 00000000000..7e5b1530d33 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_disable_keys_fulltext_table.result @@ -0,0 +1,27 @@ +SET NAMES utf8; +CREATE TABLE terms ( +term varchar(256) NOT NULL PRIMARY KEY +) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"' + DEFAULT CHARSET=utf8; +CREATE TABLE memos ( +id int PRIMARY KEY, +content text NOT NULL, +FULLTEXT INDEX content_index (content) COMMENT 'table "terms"' +) DEFAULT CHARSET=utf8; +SELECT mroonga_command("dump"); +mroonga_command("dump") +table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto +column_create terms term COLUMN_SCALAR ShortText +table_create memos TABLE_PAT_KEY Int32 +column_create memos content COLUMN_SCALAR LongText +column_create memos id COLUMN_SCALAR Int32 +column_create terms content_index COLUMN_INDEX|WITH_POSITION memos content +ALTER TABLE memos DISABLE KEYS; +SELECT mroonga_command("dump"); +mroonga_command("dump") +table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto +column_create terms term COLUMN_SCALAR ShortText +table_create memos TABLE_PAT_KEY Int32 +column_create memos content COLUMN_SCALAR LongText +column_create memos id COLUMN_SCALAR Int32 +DROP TABLE memos; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result new file mode 100644 index 00000000000..74c4867fab4 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/alter_table_enable_keys_fulltext_table.result @@ -0,0 +1,28 @@ +SET NAMES utf8; +CREATE TABLE terms ( +term varchar(256) NOT NULL PRIMARY KEY +) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"' + DEFAULT CHARSET=utf8; +CREATE TABLE memos ( +id int PRIMARY KEY, +content text NOT NULL, +FULLTEXT INDEX content_index (content) COMMENT 'table "terms"' +) DEFAULT CHARSET=utf8; +ALTER TABLE memos DISABLE KEYS; +SELECT mroonga_command("dump"); +mroonga_command("dump") +table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto +column_create terms term COLUMN_SCALAR ShortText +table_create memos TABLE_PAT_KEY Int32 +column_create memos content COLUMN_SCALAR LongText +column_create memos id COLUMN_SCALAR Int32 +ALTER TABLE memos ENABLE KEYS; +SELECT mroonga_command("dump"); +mroonga_command("dump") +table_create terms TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram --normalizer NormalizerAuto +column_create terms term COLUMN_SCALAR ShortText +table_create memos TABLE_PAT_KEY Int32 +column_create memos content COLUMN_SCALAR LongText +column_create memos id COLUMN_SCALAR Int32 +column_create terms content_index COLUMN_INDEX|WITH_POSITION memos content +DROP TABLE memos; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result index 87c14a98f15..767fe491e99 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_other_table.result @@ -1,42 +1,30 @@ -DROP DATABASE IF EXISTS mroonga; -CREATE DATABASE mroonga; -USE mroonga; -CREATE TABLE tags ( +CREATE TABLE terms ( name VARCHAR(64) PRIMARY KEY ) DEFAULT CHARSET=utf8 -COLLATE=utf8_bin -COMMENT='default_tokenizer "TokenDelimit"'; +COMMENT='default_tokenizer "TokenBigram"'; CREATE TABLE bugs ( id INT UNSIGNED PRIMARY KEY, -tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"', -FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"' +title TEXT, +FULLTEXT INDEX (title) COMMENT 'table "terms"' ) DEFAULT CHARSET=utf8; -INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga"); -SELECT mroonga_command("dump"); -mroonga_command("dump") -table_create tags TABLE_PAT_KEY ShortText --default_tokenizer TokenDelimit -column_create tags name COLUMN_SCALAR ShortText -table_create bugs TABLE_PAT_KEY UInt32 -column_create bugs id COLUMN_SCALAR UInt32 -column_create bugs tags COLUMN_VECTOR tags -column_create tags bugs_tags_index COLUMN_INDEX|WITH_POSITION bugs tags -load --table tags -[ -["_key","name"], -["Linux",""], -["MySQL",""], -["groonga",""] -] -load --table bugs -[ -["_key","id","tags"], -[1,1,["Linux","MySQL","groonga"]] -] -SELECT *, MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE) AS score +INSERT INTO bugs (id, title) VALUES (1, "Mroonga can't build with MySQL X.Y.Z"); +SELECT * FROM terms ORDER BY name; +name +' +. +BUILD +CAN +MROONGA +MYSQL +T +WITH +X +Y +Z +SELECT *, MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score FROM bugs -WHERE MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE); -id tags score -1 Linux MySQL groonga 1 +WHERE MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE); +id title score +1 Mroonga can't build with MySQL X.Y.Z 1 DROP TABLE bugs; -DROP TABLE tags; -DROP DATABASE mroonga; +DROP TABLE terms; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result new file mode 100644 index 00000000000..6ac2e1937fe --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_index_fulltext_vector_other_table.result @@ -0,0 +1,42 @@ +DROP DATABASE IF EXISTS mroonga; +CREATE DATABASE mroonga; +USE mroonga; +CREATE TABLE tags ( +name VARCHAR(64) PRIMARY KEY +) DEFAULT CHARSET=utf8 +COLLATE=utf8_bin +COMMENT='default_tokenizer "TokenDelimit"'; +CREATE TABLE bugs ( +id INT UNSIGNED PRIMARY KEY, +tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"', +FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"' +) DEFAULT CHARSET=utf8; +INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga"); +SELECT mroonga_command("dump"); +mroonga_command("dump") +table_create tags TABLE_PAT_KEY ShortText --default_tokenizer TokenDelimit +column_create tags name COLUMN_SCALAR ShortText +table_create bugs TABLE_PAT_KEY UInt32 +column_create bugs id COLUMN_SCALAR UInt32 +column_create bugs tags COLUMN_VECTOR tags +column_create tags bugs_tags_index COLUMN_INDEX|WITH_POSITION bugs tags +load --table tags +[ +["_key","name"], +["Linux",""], +["MySQL",""], +["groonga",""] +] +load --table bugs +[ +["_key","id","tags"], +[1,1,["Linux","MySQL","groonga"]] +] +SELECT *, MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score +FROM bugs +WHERE MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE); +id tags score +1 Linux MySQL groonga 1 +DROP TABLE bugs; +DROP TABLE tags; +DROP DATABASE mroonga; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result new file mode 100644 index 00000000000..11875e15018 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_lz4.result @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS entries; +CREATE TABLE entries ( +id INT UNSIGNED PRIMARY KEY, +content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"' +) DEFAULT CHARSET=utf8; +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); +SELECT * FROM entries; +id content +1 I found Mroonga that is a MySQL storage engine to use Groonga! +DROP TABLE entries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result new file mode 100644 index 00000000000..5d704e3ebec --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_support_zlib.result @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS entries; +CREATE TABLE entries ( +id INT UNSIGNED PRIMARY KEY, +content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"' +) DEFAULT CHARSET=utf8; +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); +SELECT * FROM entries; +id content +1 I found Mroonga that is a MySQL storage engine to use Groonga! +DROP TABLE entries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result new file mode 100644 index 00000000000..a9a5f55fd7f --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_lz4.result @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS entries; +CREATE TABLE entries ( +id INT UNSIGNED PRIMARY KEY, +content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"' +) DEFAULT CHARSET=utf8; +Warnings: +Warning 16506 The column flag 'COMPRESS_LZ4' is unsupported. It is ignored +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); +SELECT * FROM entries; +id content +1 I found Mroonga that is a MySQL storage engine to use Groonga! +DROP TABLE entries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result new file mode 100644 index 00000000000..068ce58bf74 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_groonga_scalar_unsupport_zlib.result @@ -0,0 +1,12 @@ +DROP TABLE IF EXISTS entries; +CREATE TABLE entries ( +id INT UNSIGNED PRIMARY KEY, +content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"' +) DEFAULT CHARSET=utf8; +Warnings: +Warning 16506 The column flag 'COMPRESS_ZLIB' is unsupported. It is ignored +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); +SELECT * FROM entries; +id content +1 I found Mroonga that is a MySQL storage engine to use Groonga! +DROP TABLE entries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_comment.result index e2d405a1e35..e2d405a1e35 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_comment.result diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.result index 9d12e2d0e39..9d12e2d0e39 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.result diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result new file mode 100644 index 00000000000..52c6f055e88 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_fulltext_index_none.result @@ -0,0 +1,16 @@ +DROP TABLE IF EXISTS diaries; +SET NAMES utf8; +CREATE TABLE diaries ( +day DATE PRIMARY KEY, +content VARCHAR(64) NOT NULL, +FULLTEXT INDEX (content) COMMENT 'normalizer "none"' +) DEFAULT CHARSET=utf8; +INSERT INTO diaries VALUES ("2013-04-23", "Mroonga"); +SELECT * FROM diaries +WHERE MATCH (content) AGAINST ("+Mroonga" IN BOOLEAN MODE); +day content +2013-04-23 Mroonga +SELECT * FROM diaries +WHERE MATCH (content) AGAINST ("+mroonga" IN BOOLEAN MODE); +day content +DROP TABLE diaries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_table_comment.result b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_primary_key_table_comment.result index dbf69362ee7..dbf69362ee7 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_table_comment.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/create_table_normalizer_primary_key_table_comment.result diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result b/storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result new file mode 100644 index 00000000000..1d9d5fbbf51 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/index_unique_search_after_duplicated.result @@ -0,0 +1,18 @@ +DROP TABLE IF EXISTS users; +CREATE TABLE users ( +id int PRIMARY KEY, +name varchar(100) NOT NULL, +UNIQUE KEY (name) +) DEFAULT CHARSET=utf8; +INSERT INTO users VALUES (1, "Alice"); +INSERT INTO users VALUES (2, "Bob"); +INSERT INTO users VALUES (3, "Bob"); +ERROR 23000: Duplicate entry 'Bob' for key 'name' +SELECT * FROM users; +id name +1 Alice +2 Bob +SELECT * FROM users WHERE name = "Bob"; +id name +2 Bob +DROP TABLE users; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result b/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result index 8d3decfa32a..63ecb8c669a 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/information_schema_plugins.result @@ -1,4 +1,4 @@ select PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_TYPE from information_schema.plugins where plugin_name = "Mroonga"; PLUGIN_NAME PLUGIN_VERSION PLUGIN_TYPE -Mroonga 4.6 STORAGE ENGINE +Mroonga 5.0 STORAGE ENGINE diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result b/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result index 288e9e3a2c8..fbec44527f7 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/insert_on_duplicate_key_update_unique_key.result @@ -15,16 +15,19 @@ diaries CREATE TABLE `diaries` ( UNIQUE KEY `day` (`day`) ) ENGINE=Mroonga DEFAULT CHARSET=utf8 INSERT INTO diaries (day, title) -VALUES ("2012-02-14", "clear day") -ON DUPLICATE KEY UPDATE title = "clear day (duplicated)"; +VALUES ("2012-02-14", "clear day1") +ON DUPLICATE KEY UPDATE title = "clear day1 (duplicated)"; INSERT INTO diaries (day, title) -VALUES ("2012-02-14", "rainy day") -ON DUPLICATE KEY UPDATE title = "rainy day (duplicated)"; +VALUES ("2012-02-14", "clear day2") +ON DUPLICATE KEY UPDATE title = "clear day2 (duplicated)"; +INSERT INTO diaries (day, title) +VALUES ("2012-02-14", "clear day3") +ON DUPLICATE KEY UPDATE title = "clear day3 (duplicated)"; INSERT INTO diaries (day, title) VALUES ("2012-02-15", "cloudy day") ON DUPLICATE KEY UPDATE title = "cloudy day (duplicated)"; SELECT * FROM diaries; id day title -1 2012-02-14 rainy day (duplicated) -3 2012-02-15 cloudy day +1 2012-02-14 clear day3 (duplicated) +4 2012-02-15 cloudy day DROP TABLE diaries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result b/storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result new file mode 100644 index 00000000000..ea1e63e39d0 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/partition_insert.result @@ -0,0 +1,42 @@ +DROP TABLE IF EXISTS logs; +SET NAMES UTF8; +CREATE TABLE logs ( +timestamp DATETIME, +message TEXT +) DEFAULT CHARSET=UTF8 +PARTITION BY RANGE (TO_DAYS(timestamp)) ( +PARTITION p201501 VALUES LESS THAN (TO_DAYS('2015-02-01')), +PARTITION p201502 VALUES LESS THAN (TO_DAYS('2015-03-01')), +PARTITION p201503 VALUES LESS THAN (TO_DAYS('2015-04-01')), +PARTITION pfuture VALUES LESS THAN MAXVALUE +); +SHOW CREATE TABLE logs; +Table Create Table +logs CREATE TABLE `logs` ( + `timestamp` datetime DEFAULT NULL, + `message` text +) ENGINE=Mroonga DEFAULT CHARSET=utf8 +/*!50100 PARTITION BY RANGE (TO_DAYS(timestamp)) +(PARTITION p201501 VALUES LESS THAN (735995) ENGINE = Mroonga, + PARTITION p201502 VALUES LESS THAN (736023) ENGINE = Mroonga, + PARTITION p201503 VALUES LESS THAN (736054) ENGINE = Mroonga, + PARTITION pfuture VALUES LESS THAN MAXVALUE ENGINE = Mroonga) */ +INSERT INTO logs VALUES('2015-01-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-01-31 23:59:59', 'Shutdown'); +INSERT INTO logs VALUES('2015-02-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-02-28 23:59:59', 'Shutdown'); +INSERT INTO logs VALUES('2015-03-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-03-31 23:59:59', 'Shutdown'); +INSERT INTO logs VALUES('2015-04-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-04-30 23:59:59', 'Shutdown'); +SELECT * FROM logs ORDER BY timestamp; +timestamp message +2015-01-01 00:00:00 Start +2015-01-31 23:59:59 Shutdown +2015-02-01 00:00:00 Start +2015-02-28 23:59:59 Shutdown +2015-03-01 00:00:00 Start +2015-03-31 23:59:59 Shutdown +2015-04-01 00:00:00 Start +2015-04-30 23:59:59 Shutdown +DROP TABLE logs; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result b/storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result new file mode 100644 index 00000000000..2c6c1cbc7e8 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/replace_without_key.result @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS diaries; +SET NAMES utf8; +CREATE TABLE diaries ( +id varchar(32) NOT NULL PRIMARY KEY, +content text, +FULLTEXT INDEX (content) +) DEFAULT CHARSET=utf8; +REPLACE INTO diaries(content) VALUES("Hello"); +ERROR HY000: primary key is empty +DROP TABLE diaries; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result new file mode 100644 index 00000000000..37826335b02 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_column.result @@ -0,0 +1,18 @@ +SET @mroonga_boolean_mode_syntax_flags_backup = +@@mroonga_boolean_mode_syntax_flags; +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN"; +SET NAMES UTF8; +CREATE TABLE diaries ( +title TEXT, +content TEXT, +FULLTEXT KEY (title), +FULLTEXT KEY (content) +) DEFAULT CHARSET=utf8; +INSERT INTO diaries VALUES("Groonga", "Hello Groonga"); +SELECT * FROM diaries +WHERE MATCH(title) AGAINST("content:@Hello" IN BOOLEAN MODE); +title content +Groonga Hello Groonga +DROP TABLE diaries; +SET mroonga_boolean_mode_syntax_flags = +@mroonga_boolean_mode_syntax_flags_backup; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result new file mode 100644 index 00000000000..d3ccb150eab --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_leading_not.result @@ -0,0 +1,16 @@ +SET @mroonga_boolean_mode_syntax_flags_backup = +@@mroonga_boolean_mode_syntax_flags; +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_LEADING_NOT"; +SET NAMES UTF8; +CREATE TABLE diaries ( +title TEXT, +FULLTEXT KEY (title) +) DEFAULT CHARSET=utf8; +INSERT INTO diaries VALUES("Groonga"); +INSERT INTO diaries VALUES("Mroonga"); +SELECT * FROM diaries WHERE MATCH(title) AGAINST("-Groonga" IN BOOLEAN MODE); +title +Mroonga +DROP TABLE diaries; +SET mroonga_boolean_mode_syntax_flags = +@mroonga_boolean_mode_syntax_flags_backup; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result new file mode 100644 index 00000000000..55cd8742758 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_allow_update.result @@ -0,0 +1,18 @@ +SET @mroonga_boolean_mode_syntax_flags_backup = +@@mroonga_boolean_mode_syntax_flags; +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN,ALLOW_UPDATE"; +SET NAMES UTF8; +CREATE TABLE diaries ( +title TEXT, +content TEXT, +FULLTEXT KEY (title), +FULLTEXT KEY (content) +) DEFAULT CHARSET=utf8; +INSERT INTO diaries VALUES("Groonga", "Hello Groonga"); +SELECT * FROM diaries +WHERE MATCH(title) AGAINST('content:="Hello Mroonga"' IN BOOLEAN MODE); +title content +Groonga Hello Mroonga +DROP TABLE diaries; +SET mroonga_boolean_mode_syntax_flags = +@mroonga_boolean_mode_syntax_flags_backup; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result new file mode 100644 index 00000000000..5736fd52c89 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_query.result @@ -0,0 +1,15 @@ +SET @mroonga_boolean_mode_syntax_flags_backup = +@@mroonga_boolean_mode_syntax_flags; +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY"; +SET NAMES UTF8; +CREATE TABLE diaries ( +title TEXT, +FULLTEXT KEY (title) +) DEFAULT CHARSET=utf8; +INSERT INTO diaries VALUES("Re:Mroonga"); +SELECT * FROM diaries WHERE MATCH(title) AGAINST("Re:Mroonga" IN BOOLEAN MODE); +title +Re:Mroonga +DROP TABLE diaries; +SET mroonga_boolean_mode_syntax_flags = +@mroonga_boolean_mode_syntax_flags_backup; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result new file mode 100644 index 00000000000..e42fa259e4a --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_boolean_mode_syntax_flags_syntax_script.result @@ -0,0 +1,16 @@ +SET @mroonga_boolean_mode_syntax_flags_backup = +@@mroonga_boolean_mode_syntax_flags; +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_SCRIPT"; +SET NAMES UTF8; +CREATE TABLE diaries ( +title TEXT, +FULLTEXT KEY (title) +) DEFAULT CHARSET=utf8; +INSERT INTO diaries VALUES("Re:Mroonga"); +SELECT * FROM diaries +WHERE MATCH(title) AGAINST("title @ 'Re:Mroonga'" IN BOOLEAN MODE); +title +Re:Mroonga +DROP TABLE diaries; +SET mroonga_boolean_mode_syntax_flags = +@mroonga_boolean_mode_syntax_flags_backup; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result index aae83fe2b38..9b99165c047 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_version.result @@ -1,3 +1,3 @@ show variables like 'mroonga_version'; Variable_name Value -mroonga_version 4.06 +mroonga_version 5.00 diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test new file mode 100644 index 00000000000..72e0ebc14a4 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_add_index_unique_multiple_column_duplicated.test @@ -0,0 +1,39 @@ +# Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source include/not_embedded.inc +--source ../../include/mroonga/have_mroonga.inc + +--disable_warnings +DROP TABLE IF EXISTS ids; +--enable_warnings + +CREATE TABLE ids ( + id1 INT, + id2 INT +) DEFAULT CHARSET=utf8mb4; + +INSERT INTO ids (id1, id2) values (1, 2), (1, 2); + +--error ER_DUP_UNIQUE +ALTER TABLE ids ADD UNIQUE INDEX (id1, id2); +SHOW CREATE TABLE ids; + +SELECT * FROM ids; + +DROP TABLE ids; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test new file mode 100644 index 00000000000..7a03224abb9 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_disable_keys_fulltext_table.test @@ -0,0 +1,45 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_query_log +DROP DATABASE test; +CREATE DATABASE test; +USE test; +--enable_query_log + +SET NAMES utf8; +CREATE TABLE terms ( + term varchar(256) NOT NULL PRIMARY KEY +) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"' + DEFAULT CHARSET=utf8; + +CREATE TABLE memos ( + id int PRIMARY KEY, + content text NOT NULL, + FULLTEXT INDEX content_index (content) COMMENT 'table "terms"' +) DEFAULT CHARSET=utf8; + +SELECT mroonga_command("dump"); +ALTER TABLE memos DISABLE KEYS; +SELECT mroonga_command("dump"); + +DROP TABLE memos; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test new file mode 100644 index 00000000000..2e9022128df --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/alter_table_enable_keys_fulltext_table.test @@ -0,0 +1,46 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_query_log +DROP DATABASE test; +CREATE DATABASE test; +USE test; +--enable_query_log + +SET NAMES utf8; +CREATE TABLE terms ( + term varchar(256) NOT NULL PRIMARY KEY +) COMMENT='default_tokenizer "TokenBigram", normalizer "NormalizerAuto"' + DEFAULT CHARSET=utf8; + +CREATE TABLE memos ( + id int PRIMARY KEY, + content text NOT NULL, + FULLTEXT INDEX content_index (content) COMMENT 'table "terms"' +) DEFAULT CHARSET=utf8; + +ALTER TABLE memos DISABLE KEYS; +SELECT mroonga_command("dump"); +ALTER TABLE memos ENABLE KEYS; +SELECT mroonga_command("dump"); + +DROP TABLE memos; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test index 805c744236f..dbaf2fb429f 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_other_table.test @@ -1,4 +1,4 @@ -# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -16,39 +16,27 @@ --source include/not_embedded.inc --source ../../include/mroonga/have_mroonga.inc ---source ../../include/mroonga/load_mroonga_functions.inc ---disable_warnings -DROP DATABASE IF EXISTS mroonga; ---enable_warnings - -CREATE DATABASE mroonga; -USE mroonga; - -CREATE TABLE tags ( +CREATE TABLE terms ( name VARCHAR(64) PRIMARY KEY ) DEFAULT CHARSET=utf8 - COLLATE=utf8_bin - COMMENT='default_tokenizer "TokenDelimit"'; + COMMENT='default_tokenizer "TokenBigram"'; CREATE TABLE bugs ( id INT UNSIGNED PRIMARY KEY, - tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"', - FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"' + title TEXT, + FULLTEXT INDEX (title) COMMENT 'table "terms"' ) DEFAULT CHARSET=utf8; -INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga"); +INSERT INTO bugs (id, title) VALUES (1, "Mroonga can't build with MySQL X.Y.Z"); -SELECT mroonga_command("dump"); +SELECT * FROM terms ORDER BY name; -SELECT *, MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE) AS score +SELECT *, MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score FROM bugs - WHERE MATCH (tags) AGAINST ("MySQL" IN BOOLEAN MODE); + WHERE MATCH (title) AGAINST ("+MySQL" IN BOOLEAN MODE); DROP TABLE bugs; -DROP TABLE tags; - -DROP DATABASE mroonga; +DROP TABLE terms; ---source ../../include/mroonga/unload_mroonga_functions.inc --source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test new file mode 100644 index 00000000000..86ef09cc8bb --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_index_fulltext_vector_other_table.test @@ -0,0 +1,54 @@ +# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source include/not_embedded.inc +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_warnings +DROP DATABASE IF EXISTS mroonga; +--enable_warnings + +CREATE DATABASE mroonga; +USE mroonga; + +CREATE TABLE tags ( + name VARCHAR(64) PRIMARY KEY +) DEFAULT CHARSET=utf8 + COLLATE=utf8_bin + COMMENT='default_tokenizer "TokenDelimit"'; + +CREATE TABLE bugs ( + id INT UNSIGNED PRIMARY KEY, + tags TEXT COMMENT 'flags "COLUMN_VECTOR", type "tags"', + FULLTEXT INDEX bugs_tags_index (tags) COMMENT 'table "tags"' +) DEFAULT CHARSET=utf8; + +INSERT INTO bugs (id, tags) VALUES (1, "Linux MySQL groonga"); + +SELECT mroonga_command("dump"); + +SELECT *, MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE) AS score + FROM bugs + WHERE MATCH (tags) AGAINST ("+MySQL" IN BOOLEAN MODE); + +DROP TABLE bugs; +DROP TABLE tags; + +DROP DATABASE mroonga; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test new file mode 100644 index 00000000000..5de8f951d8f --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_lz4.test @@ -0,0 +1,37 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/support_libgroonga_lz4.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_warnings +DROP TABLE IF EXISTS entries; +--enable_warnings + +CREATE TABLE entries ( + id INT UNSIGNED PRIMARY KEY, + content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"' +) DEFAULT CHARSET=utf8; + +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); + +SELECT * FROM entries; + +DROP TABLE entries; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test new file mode 100644 index 00000000000..3ec14ebef76 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_support_zlib.test @@ -0,0 +1,37 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/support_libgroonga_zlib.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_warnings +DROP TABLE IF EXISTS entries; +--enable_warnings + +CREATE TABLE entries ( + id INT UNSIGNED PRIMARY KEY, + content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"' +) DEFAULT CHARSET=utf8; + +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); + +SELECT * FROM entries; + +DROP TABLE entries; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test new file mode 100644 index 00000000000..324b7ac89f5 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_lz4.test @@ -0,0 +1,37 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/unsupport_libgroonga_lz4.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_warnings +DROP TABLE IF EXISTS entries; +--enable_warnings + +CREATE TABLE entries ( + id INT UNSIGNED PRIMARY KEY, + content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_LZ4"' +) DEFAULT CHARSET=utf8; + +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); + +SELECT * FROM entries; + +DROP TABLE entries; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test new file mode 100644 index 00000000000..10e77e40e3d --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/column_groonga_scalar_unsupport_zlib.test @@ -0,0 +1,37 @@ +# Copyright(C) 2014 Naoya Murakami <naoya@createfield.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/unsupport_libgroonga_zlib.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_warnings +DROP TABLE IF EXISTS entries; +--enable_warnings + +CREATE TABLE entries ( + id INT UNSIGNED PRIMARY KEY, + content TEXT COMMENT 'flags "COLUMN_SCALAR|COMPRESS_ZLIB"' +) DEFAULT CHARSET=utf8; + +INSERT INTO entries (id, content) VALUES (1, "I found Mroonga that is a MySQL storage engine to use Groonga!"); + +SELECT * FROM entries; + +DROP TABLE entries; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_comment.test index 02e2cb9e81a..02e2cb9e81a 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_comment.test diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.test index f28fb5b8695..f28fb5b8695 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_no_utf8_charset_with_utf8_normalizer.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_no_utf8_charset_with_utf8_normalizer.test diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test new file mode 100644 index 00000000000..ae4d4cb9f1b --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_fulltext_index_none.test @@ -0,0 +1,42 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc +--source ../../include/mroonga/load_mroonga_functions.inc + +--disable_warnings +DROP TABLE IF EXISTS diaries; +--enable_warnings + +SET NAMES utf8; + +CREATE TABLE diaries ( + day DATE PRIMARY KEY, + content VARCHAR(64) NOT NULL, + FULLTEXT INDEX (content) COMMENT 'normalizer "none"' +) DEFAULT CHARSET=utf8; + +INSERT INTO diaries VALUES ("2013-04-23", "Mroonga"); + +SELECT * FROM diaries + WHERE MATCH (content) AGAINST ("+Mroonga" IN BOOLEAN MODE); +SELECT * FROM diaries + WHERE MATCH (content) AGAINST ("+mroonga" IN BOOLEAN MODE); + +DROP TABLE diaries; + +--source ../../include/mroonga/unload_mroonga_functions.inc +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_table_comment.test b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_primary_key_table_comment.test index 1da8026f56d..1da8026f56d 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_table_comment.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/create_table_normalizer_primary_key_table_comment.test diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test b/storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test new file mode 100644 index 00000000000..533422ec087 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/index_unique_search_after_duplicated.test @@ -0,0 +1,40 @@ +# Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +--disable_warnings +DROP TABLE IF EXISTS users; +--enable_warnings + +CREATE TABLE users ( + id int PRIMARY KEY, + name varchar(100) NOT NULL, + UNIQUE KEY (name) +) DEFAULT CHARSET=utf8; + +INSERT INTO users VALUES (1, "Alice"); + +INSERT INTO users VALUES (2, "Bob"); +-- error ER_DUP_ENTRY +INSERT INTO users VALUES (3, "Bob"); + +SELECT * FROM users; +SELECT * FROM users WHERE name = "Bob"; + +DROP TABLE users; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test b/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test index 782b7bee9ca..350440515c1 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test +++ b/storage/mroonga/mysql-test/mroonga/storage/t/insert_on_duplicate_key_update_unique_key.test @@ -29,11 +29,14 @@ CREATE TABLE diaries ( SHOW CREATE TABLE diaries; INSERT INTO diaries (day, title) - VALUES ("2012-02-14", "clear day") - ON DUPLICATE KEY UPDATE title = "clear day (duplicated)"; + VALUES ("2012-02-14", "clear day1") + ON DUPLICATE KEY UPDATE title = "clear day1 (duplicated)"; INSERT INTO diaries (day, title) - VALUES ("2012-02-14", "rainy day") - ON DUPLICATE KEY UPDATE title = "rainy day (duplicated)"; + VALUES ("2012-02-14", "clear day2") + ON DUPLICATE KEY UPDATE title = "clear day2 (duplicated)"; +INSERT INTO diaries (day, title) + VALUES ("2012-02-14", "clear day3") + ON DUPLICATE KEY UPDATE title = "clear day3 (duplicated)"; INSERT INTO diaries (day, title) VALUES ("2012-02-15", "cloudy day") ON DUPLICATE KEY UPDATE title = "cloudy day (duplicated)"; diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test b/storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test new file mode 100644 index 00000000000..219c3440d69 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/partition_insert.test @@ -0,0 +1,49 @@ +# Copyright(C) 2015 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +--disable_warnings +DROP TABLE IF EXISTS logs; +--enable_warnings + +SET NAMES UTF8; +CREATE TABLE logs ( + timestamp DATETIME, + message TEXT +) DEFAULT CHARSET=UTF8 + PARTITION BY RANGE (TO_DAYS(timestamp)) ( + PARTITION p201501 VALUES LESS THAN (TO_DAYS('2015-02-01')), + PARTITION p201502 VALUES LESS THAN (TO_DAYS('2015-03-01')), + PARTITION p201503 VALUES LESS THAN (TO_DAYS('2015-04-01')), + PARTITION pfuture VALUES LESS THAN MAXVALUE +); +SHOW CREATE TABLE logs; + +INSERT INTO logs VALUES('2015-01-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-01-31 23:59:59', 'Shutdown'); +INSERT INTO logs VALUES('2015-02-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-02-28 23:59:59', 'Shutdown'); +INSERT INTO logs VALUES('2015-03-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-03-31 23:59:59', 'Shutdown'); +INSERT INTO logs VALUES('2015-04-01 00:00:00', 'Start'); +INSERT INTO logs VALUES('2015-04-30 23:59:59', 'Shutdown'); + +SELECT * FROM logs ORDER BY timestamp; + +DROP TABLE logs; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test b/storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test new file mode 100644 index 00000000000..a38c4953e67 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/replace_without_key.test @@ -0,0 +1,35 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +--disable_warnings +DROP TABLE IF EXISTS diaries; +--enable_warnings + +SET NAMES utf8; +CREATE TABLE diaries ( + id varchar(32) NOT NULL PRIMARY KEY, + content text, + FULLTEXT INDEX (content) +) DEFAULT CHARSET=utf8; + +-- error ER_ERROR_ON_WRITE +REPLACE INTO diaries(content) VALUES("Hello"); + +DROP TABLE diaries; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test new file mode 100644 index 00000000000..11ca867d82c --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_column.test @@ -0,0 +1,43 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +SET @mroonga_boolean_mode_syntax_flags_backup = + @@mroonga_boolean_mode_syntax_flags; + +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN"; + +SET NAMES UTF8; + +CREATE TABLE diaries ( + title TEXT, + content TEXT, + FULLTEXT KEY (title), + FULLTEXT KEY (content) +) DEFAULT CHARSET=utf8; + +INSERT INTO diaries VALUES("Groonga", "Hello Groonga"); + +SELECT * FROM diaries + WHERE MATCH(title) AGAINST("content:@Hello" IN BOOLEAN MODE); + +DROP TABLE diaries; + +SET mroonga_boolean_mode_syntax_flags = + @mroonga_boolean_mode_syntax_flags_backup; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test new file mode 100644 index 00000000000..665682fde6e --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_leading_not.test @@ -0,0 +1,41 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +SET @mroonga_boolean_mode_syntax_flags_backup = + @@mroonga_boolean_mode_syntax_flags; + +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_LEADING_NOT"; + +SET NAMES UTF8; + +CREATE TABLE diaries ( + title TEXT, + FULLTEXT KEY (title) +) DEFAULT CHARSET=utf8; + +INSERT INTO diaries VALUES("Groonga"); +INSERT INTO diaries VALUES("Mroonga"); + +SELECT * FROM diaries WHERE MATCH(title) AGAINST("-Groonga" IN BOOLEAN MODE); + +DROP TABLE diaries; + +SET mroonga_boolean_mode_syntax_flags = + @mroonga_boolean_mode_syntax_flags_backup; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test new file mode 100644 index 00000000000..8a55c0fb0f7 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_allow_update.test @@ -0,0 +1,43 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +SET @mroonga_boolean_mode_syntax_flags_backup = + @@mroonga_boolean_mode_syntax_flags; + +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY,ALLOW_COLUMN,ALLOW_UPDATE"; + +SET NAMES UTF8; + +CREATE TABLE diaries ( + title TEXT, + content TEXT, + FULLTEXT KEY (title), + FULLTEXT KEY (content) +) DEFAULT CHARSET=utf8; + +INSERT INTO diaries VALUES("Groonga", "Hello Groonga"); + +SELECT * FROM diaries + WHERE MATCH(title) AGAINST('content:="Hello Mroonga"' IN BOOLEAN MODE); + +DROP TABLE diaries; + +SET mroonga_boolean_mode_syntax_flags = + @mroonga_boolean_mode_syntax_flags_backup; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test new file mode 100644 index 00000000000..0ff2d8aed43 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_query.test @@ -0,0 +1,40 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +SET @mroonga_boolean_mode_syntax_flags_backup = + @@mroonga_boolean_mode_syntax_flags; + +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_QUERY"; + +SET NAMES UTF8; + +CREATE TABLE diaries ( + title TEXT, + FULLTEXT KEY (title) +) DEFAULT CHARSET=utf8; + +INSERT INTO diaries VALUES("Re:Mroonga"); + +SELECT * FROM diaries WHERE MATCH(title) AGAINST("Re:Mroonga" IN BOOLEAN MODE); + +DROP TABLE diaries; + +SET mroonga_boolean_mode_syntax_flags = + @mroonga_boolean_mode_syntax_flags_backup; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test new file mode 100644 index 00000000000..61d5daa63d9 --- /dev/null +++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_boolean_mode_syntax_flags_syntax_script.test @@ -0,0 +1,41 @@ +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# +# This library 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 2.1 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 + +--source ../../include/mroonga/have_mroonga.inc + +SET @mroonga_boolean_mode_syntax_flags_backup = + @@mroonga_boolean_mode_syntax_flags; + +SET mroonga_boolean_mode_syntax_flags = "SYNTAX_SCRIPT"; + +SET NAMES UTF8; + +CREATE TABLE diaries ( + title TEXT, + FULLTEXT KEY (title) +) DEFAULT CHARSET=utf8; + +INSERT INTO diaries VALUES("Re:Mroonga"); + +SELECT * FROM diaries + WHERE MATCH(title) AGAINST("title @ 'Re:Mroonga'" IN BOOLEAN MODE); + +DROP TABLE diaries; + +SET mroonga_boolean_mode_syntax_flags = + @mroonga_boolean_mode_syntax_flags_backup; + +--source ../../include/mroonga/have_mroonga_deinit.inc diff --git a/storage/mroonga/packages/Makefile.am b/storage/mroonga/packages/Makefile.am new file mode 100644 index 00000000000..fed925c3dfc --- /dev/null +++ b/storage/mroonga/packages/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = \ + apt \ + rpm \ + source \ + ubuntu \ + windows \ + yum diff --git a/storage/mroonga/packages/apt/Makefile.am b/storage/mroonga/packages/apt/Makefile.am new file mode 100644 index 00000000000..26f5609c527 --- /dev/null +++ b/storage/mroonga/packages/apt/Makefile.am @@ -0,0 +1,67 @@ +REPOSITORIES_PATH = repositories +DISTRIBUTIONS = debian +ARCHITECTURES = i386 amd64 +CODE_NAMES = wheezy + +all: + +release: build sign-packages update-repository sign-repository upload + +remove-existing-packages: + for distribution in $(DISTRIBUTIONS); do \ + find $(REPOSITORIES_PATH)/$${distribution}/pool \ + -type f -delete; \ + done + +download: + for distribution in $(DISTRIBUTIONS); do \ + rsync -avz --progress --delete \ + $(RSYNC_PATH)/$${distribution} $(REPOSITORIES_PATH)/; \ + done + +sign-packages: + ./sign-packages.sh '$(GPG_UID)' '$(REPOSITORIES_PATH)/' '$(CODE_NAMES)' + +update-repository: + ./update-repository.sh '$(PACKAGE_NAME)' '$(REPOSITORIES_PATH)/' \ + '$(ARCHITECTURES)' '$(CODE_NAMES)' + +sign-repository: + ./sign-repository.sh '$(GPG_UID)' '$(REPOSITORIES_PATH)/' '$(CODE_NAMES)' + +ensure-rsync-path: + @if test -z "$(RSYNC_PATH)"; then \ + echo "--with-rsync-path configure option must be specified."; \ + false; \ + fi + +upload: ensure-rsync-path + for distribution in $(DISTRIBUTIONS); do \ + (cd $(REPOSITORIES_PATH)/$${distribution}; \ + rsync -avz --progress --delete \ + dists pool $(RSYNC_PATH)/$${distribution}; \ + ); \ + done + +build: build-package-deb + +build-package-deb: prepare-build-package-deb + vagrant destroy --force + for architecture in $(ARCHITECTURES); do \ + for code_name in $(CODE_NAMES); do \ + id=debian-$$code_name-$$architecture; \ + vagrant up $$id || exit 1; \ + vagrant destroy --force $$id; \ + done; \ + done + +prepare-build-package-deb: source env.sh + cp env.sh tmp/ + rm -rf tmp/debian + cp -rp $(srcdir)/../debian tmp/ + +source: tmp/$(PACKAGE)-$(VERSION).tar.gz + +tmp/$(PACKAGE)-$(VERSION).tar.gz: $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz + mkdir -p tmp + cp $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz $@ diff --git a/storage/mroonga/packages/apt/Vagrantfile b/storage/mroonga/packages/apt/Vagrantfile new file mode 100644 index 00000000000..4483412326a --- /dev/null +++ b/storage/mroonga/packages/apt/Vagrantfile @@ -0,0 +1,29 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + vms = [ + { + :id => "debian-wheezy-i386", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8-i386_chef-provisionerless.box", + }, + { + :id => "debian-wheezy-amd64", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box", + }, + ] + + vms.each do |vm| + config.vm.define(vm[:id]) do |node| + node.vm.box = vm[:id] + node.vm.box_url = vm[:box_url] + node.vm.provision(:shell, :path => "build-deb.sh") + node.vm.provider("virtualbox") do |virtual_box| + virtual_box.memory = 768 + end + end + end +end diff --git a/storage/mroonga/packages/apt/build-deb.sh b/storage/mroonga/packages/apt/build-deb.sh new file mode 100755 index 00000000000..7db24068a7c --- /dev/null +++ b/storage/mroonga/packages/apt/build-deb.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +LANG=C + +mysql_server_package=mysql-server + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +. /vagrant/tmp/env.sh + +grep '^deb ' /etc/apt/sources.list | \ + sed -e 's/^deb /deb-src /' > /etc/apt/sources.list.d/base-source.list + +run apt-get update +run apt-get install -y lsb-release + +distribution=$(lsb_release --id --short | tr 'A-Z' 'a-z') +code_name=$(lsb_release --codename --short) +case "${distribution}" in + debian) + component=main + run cat <<EOF > /etc/apt/sources.list.d/groonga.list +deb http://packages.groonga.org/debian/ wheezy main +deb-src http://packages.groonga.org/debian/ wheezy main +EOF + if ! grep --quiet security /etc/apt/sources.list; then + run cat <<EOF > /etc/apt/sources.list.d/security.list +deb http://security.debian.org/ ${code_name}/updates main +deb-src http://security.debian.org/ ${code_name}/updates main +EOF + fi + run apt-get update + run apt-get install -y --allow-unauthenticated groonga-keyring + run apt-get update + ;; + ubuntu) + component=universe + run cat <<EOF > /etc/apt/sources.list.d/security.list +deb http://security.ubuntu.com/ubuntu ${code_name}-security main restricted +deb-src http://security.ubuntu.com/ubuntu ${code_name}-security main restricted +EOF + run sed -e 's/main/universe/' /etc/apt/sources.list > \ + /etc/apt/sources.list.d/universe.list + run apt-get -y install software-properties-common + run add-apt-repository -y universe + run add-apt-repository -y ppa:groonga/ppa + run apt-get update + ;; +esac + +run apt-get install -V -y build-essential devscripts ${DEPENDED_PACKAGES} +run apt-get build-dep -y ${mysql_server_package} + +run mkdir -p build +run cp /vagrant/tmp/${PACKAGE}-${VERSION}.tar.gz \ + build/${PACKAGE}_${VERSION}.orig.tar.gz +run cd build +run tar xfz ${PACKAGE}_${VERSION}.orig.tar.gz +run cd ${PACKAGE}-${VERSION}/ +run cp -rp /vagrant/tmp/debian debian +# export DEB_BUILD_OPTIONS=noopt +MYSQL_PACKAGE_INFO=$(apt-cache show mysql-server | grep Version | sort | tail -1) +MYSQL_PACKAGE_VERSION=${MYSQL_PACKAGE_INFO##Version: } +sed -i "s/MYSQL_VERSION/$MYSQL_PACKAGE_VERSION/" debian/control +run debuild -us -uc +run cd - + +package_initial=$(echo "${PACKAGE}" | sed -e 's/\(.\).*/\1/') +pool_dir="/vagrant/repositories/${distribution}/pool/${code_name}/${component}/${package_initial}/${PACKAGE}" +run mkdir -p "${pool_dir}/" +run cp *.tar.gz *.diff.gz *.dsc *.deb "${pool_dir}/" diff --git a/storage/mroonga/packages/apt/env.sh.in b/storage/mroonga/packages/apt/env.sh.in new file mode 100644 index 00000000000..a44d6b36871 --- /dev/null +++ b/storage/mroonga/packages/apt/env.sh.in @@ -0,0 +1,15 @@ +PACKAGE=@PACKAGE@ +VERSION=@VERSION@ +DEPENDED_PACKAGES=" +debhelper +autotools-dev +libgroonga-dev +pkg-config +libmecab-dev +mecab-utils +libmysqlclient-dev +libmysqld-dev +libssl-dev +groonga-normalizer-mysql +wget +" diff --git a/storage/mroonga/packages/apt/sign-packages.sh b/storage/mroonga/packages/apt/sign-packages.sh new file mode 100755 index 00000000000..11a4aea26db --- /dev/null +++ b/storage/mroonga/packages/apt/sign-packages.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +script_base_dir=`dirname $0` + +if [ $# != 3 ]; then + echo "Usage: $0 GPG_UID DESITINATION CODES" + echo " e.g.: $0 'F10399C0' repositories/ 'lenny unstable hardy karmic'" + exit 1 +fi + +GPG_UID=$1 +DESTINATION=$2 +CODES=$3 + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +for code_name in ${CODES}; do + case ${code_name} in + squeeze|wheezy|jessie|unstable) + distribution=debian + ;; + *) + distribution=ubuntu + ;; + esac + + base_directory=${DESTINATION}${distribution} + debsign -pgpg2 --re-sign -k${GPG_UID} \ + $(find ${base_directory} -name '*.dsc' -or -name '*.changes') & + if [ "${PARALLEL}" != "yes" ]; then + wait + fi +done + +wait diff --git a/storage/mroonga/packages/apt/sign-repository.sh b/storage/mroonga/packages/apt/sign-repository.sh new file mode 100755 index 00000000000..fb0de850d6f --- /dev/null +++ b/storage/mroonga/packages/apt/sign-repository.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +script_base_dir=`dirname $0` + +if [ $# != 3 ]; then + echo "Usage: $0 GPG_UID DESTINATION CODES" + echo " e.g.: $0 'F10399C0' repositories/ 'lenny unstable hardy karmic'" + exit 1 +fi + +GPG_UID=$1 +DESTINATION=$2 +CODES=$3 + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +for code_name in ${CODES}; do + case ${code_name} in + squeeze|wheezy|jessie|unstable) + distribution=debian + ;; + *) + distribution=ubuntu + ;; + esac + + release=${DESTINATION}${distribution}/dists/${code_name}/Release + rm -f ${release}.gpg + gpg2 --sign --detach-sign --armor \ + --local-user ${GPG_UID} \ + --output ${release}.gpg \ + ${release} & + + if [ "${PARALLEL}" != "yes" ]; then + wait + fi +done + +wait diff --git a/storage/mroonga/packages/apt/update-repository.sh b/storage/mroonga/packages/apt/update-repository.sh new file mode 100755 index 00000000000..da1f8cd121c --- /dev/null +++ b/storage/mroonga/packages/apt/update-repository.sh @@ -0,0 +1,130 @@ +#!/bin/sh + +script_base_dir=`dirname $0` + +if [ $# != 4 ]; then + echo "Usage: $0 PROJECT_NAME DESTINATION ARCHITECTURES CODES" + echo " e.g.: $0 mroonga repositories/ 'i386 amd64' 'lenny unstable hardy karmic'" + exit 1 +fi + +PROJECT_NAME=$1 +DESTINATION=$2 +ARCHITECTURES=$3 +CODES=$4 + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +update_repository() +{ + distribution=$1 + code_name=$2 + component=$3 + + rm -rf dists/${code_name} + mkdir -p dists/${code_name}/${component}/binary-i386/ + mkdir -p dists/${code_name}/${component}/binary-amd64/ + mkdir -p dists/${code_name}/${component}/source/ + + cat <<EOF > dists/.htaccess +Options +Indexes +EOF + + cat <<EOF > dists/${code_name}/${component}/binary-i386/Release +Archive: ${code_name} +Component: ${component} +Origin: The ${PROJECT_NAME} project +Label: The ${PROJECT_NAME} project +Architecture: i386 +EOF + + cat <<EOF > dists/${code_name}/${component}/binary-amd64/Release +Archive: ${code_name} +Component: ${component} +Origin: The ${PROJECT_NAME} project +Label: The ${PROJECT_NAME} project +Architecture: amd64 +EOF + + cat <<EOF > dists/${code_name}/${component}/source/Release +Archive: ${code_name} +Component: ${component} +Origin: The ${PROJECT_NAME} project +Label: The ${PROJECT_NAME} project +Architecture: source +EOF + + cat <<EOF > generate-${code_name}.conf +Dir::ArchiveDir "."; +Dir::CacheDir "."; +TreeDefault::Directory "pool/${code_name}/${component}"; +TreeDefault::SrcDirectory "pool/${code_name}/${component}"; +Default::Packages::Extensions ".deb"; +Default::Packages::Compress ". gzip bzip2"; +Default::Sources::Compress ". gzip bzip2"; +Default::Contents::Compress "gzip bzip2"; + +BinDirectory "dists/${code_name}/${component}/binary-i386" { + Packages "dists/${code_name}/${component}/binary-i386/Packages"; + Contents "dists/${code_name}/Contents-i386"; + SrcPackages "dists/${code_name}/${component}/source/Sources"; +}; + +BinDirectory "dists/${code_name}/${component}/binary-amd64" { + Packages "dists/${code_name}/${component}/binary-amd64/Packages"; + Contents "dists/${code_name}/Contents-amd64"; + SrcPackages "dists/${code_name}/${component}/source/Sources"; +}; + +Tree "dists/${code_name}" { + Sections "${component}"; + Architectures "i386 amd64 source"; +}; +EOF + apt-ftparchive generate generate-${code_name}.conf + chmod 644 dists/${code_name}/Contents-* + + rm -f dists/${code_name}/Release* + rm -f *.db + cat <<EOF > release-${code_name}.conf +APT::FTPArchive::Release::Origin "The ${PROJECT_NAME} project"; +APT::FTPArchive::Release::Label "The ${PROJECT_NAME} project"; +APT::FTPArchive::Release::Architectures "i386 amd64"; +APT::FTPArchive::Release::Codename "${code_name}"; +APT::FTPArchive::Release::Suite "${code_name}"; +APT::FTPArchive::Release::Components "${component}"; +APT::FTPArchive::Release::Description "${PACKAGE_NAME} packages"; +EOF + apt-ftparchive -c release-${code_name}.conf \ + release dists/${code_name} > /tmp/Release + mv /tmp/Release dists/${code_name} +} + +for code_name in ${CODES}; do + case ${code_name} in + squeeze|wheezy|jessie|unstable) + distribution=debian + component=main + ;; + *) + distribution=ubuntu + component=universe + ;; + esac + + mkdir -p ${DESTINATION}${distribution} + (cd ${DESTINATION}${distribution} + update_repository $distribution $code_name $component) & + if [ "${PARALLEL}" != "yes" ]; then + wait + fi +done + +wait diff --git a/storage/mroonga/packages/check-utility.sh b/storage/mroonga/packages/check-utility.sh new file mode 100755 index 00000000000..211e231a473 --- /dev/null +++ b/storage/mroonga/packages/check-utility.sh @@ -0,0 +1,665 @@ +#!/bin/sh + +# Usage: check-utility.sh [--install-groonga] +# [--check-install] +# [--check-address] +# [--enable-repository] +# +# CODES="squeeze wheezy unstable lucid natty oneiric precise" +# DISTRIBUTIONS="centos fedora" + +CHROOT_ROOT=/var/lib/chroot +CHECK_ADDRESS=0 +CHECK_INSTALL=0 +CHECK_INSTALL_PACKAGE=mysql-server-mroonga +CHECK_BUILD=0 +CHECK_DEPENDS=0 +CHECK_PROVIDES=0 +ENABLE_REPOSITORY=0 +DISABLE_REPOSITORY=0 +INSTALL_SCRIPT=0 +INSTALL_MROONGA=0 +UNINSTALL_MROONGA=0 + +common_deb_procedure () +{ + for code in $CODES; do + for arch in $DEB_ARCHITECTURES; do + root_dir=$CHROOT_ROOT/$code-$arch + eval $1 $code $arch $root_dir + done + done +} + +common_rpm_procedure () +{ + for dist in $DISTRIBUTIONS; do + case $dist in + "fedora") + DISTRIBUTIONS_VERSION="19" + ;; + "centos") + DISTRIBUTIONS_VERSION="5 6" + ;; + esac + for ver in $DISTRIBUTIONS_VERSION; do + for arch in $RPM_ARCHITECTURES; do + root_dir=$CHROOT_ROOT/$dist-$ver-$arch + eval $1 $dist $arch $ver $root_dir + done + done + done +} + +echo_packages_repository_address () +{ + root_dir=$1 + code=$2 + arch=$3 + address=`grep "packages.groonga.org" $root_dir/etc/hosts | grep -v "#"` + if [ -z "$address" ]; then + echo "$code-$arch: default" + else + echo "$code-$arch: $address" + fi +} + +setup_distributions () +{ + if [ -z "$DISTRIBUTIONS" ]; then + DISTRIBUTIONS="centos fedora" + fi +} + +setup_rpm_architectures () +{ + if [ -z "$RPM_ARCHITECTURES" ]; then + RPM_ARCHITECTURES="i386 x86_64" + fi +} + +setup_codes () +{ + if [ -z "$CODES" ]; then + CODES="squeeze wheezy jessie unstable lucid precise quantal raring" + fi +} +setup_deb_architectures () +{ + if [ -z "$DEB_ARCHITECTURES" ]; then + DEB_ARCHITECTURES="i386 amd64" + fi +} + +check_packages_repository_address () +{ + common_deb_procedure "check_packages_deb_repository_address" + common_rpm_procedure "check_packages_rpm_repository_address" +} + +check_packages_deb_repository_address () +{ + code=$1 + arch=$2 + root_dir=$4 + echo_packages_repository_address "$root_dir" "$code" "$arch" +} + +check_packages_rpm_repository_address () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + echo_packages_repository_address "$root_dir" "$dist-$ver" "$arch" +} + +host_address () +{ + ifconfig_result=`LANG=C /sbin/ifconfig wlan0` + inet_addr=`echo "$ifconfig_result" | grep "inet addr:192"` + address=`echo $inet_addr | ruby -ne '/inet addr:(.+?)\s/ =~ $_ && puts($1)'` + HOST_ADDRESS=$address +} + +check_build_packages () +{ + common_deb_procedure "check_build_deb_packages" + common_rpm_procedure "check_build_rpm_packages" +} + +check_build_deb_packages () +{ + code=$1 + arch=$2 + BASE_VERSION=`cat ../version` + RESULT_SET=`find apt/repositories -name "*$BASE_VERSION*" | grep $code | grep $arch` + if [ -z "$RESULT_SET" ]; then + printf "%8s %5s %s => 0 deb\n" $code $arch $BASE_VERSION + else + PACKAGE_COUNT=`find apt/repositories -name "*$BASE_VERSION*" | grep $code | grep $arch | wc | awk '{print \$1}'` + printf "%8s %5s %s => %2d debs\n" $code $arch $BASE_VERSION $PACKAGE_COUNT + fi +} + +check_build_rpm_packages () +{ + dist=$1 + arch=$2 + ver=$3 + BASE_VERSION=`cat ../version` + FIND_PATH=yum/repositories/$dist/$ver/$arch + RESULT_SET=`find $FIND_PATH -name "*$BASE_VERSION*"` + if [ -z "$RESULT_SET" ]; then + printf "%8s %6s %s => 0 rpm\n" $dist$ver $arch $BASE_VERSION + else + PACKAGE_COUNT=`find $FIND_PATH -name "*$BASE_VERSION*" | wc -l` + printf "%8s %6s %s => %2d rpms\n" $dist$ver $arch $BASE_VERSION $PACKAGE_COUNT + fi +} + +check_depends_packages () +{ + common_deb_procedure "check_depends_deb_packages" + common_rpm_procedure "check_depends_rpm_packages" +} + +check_depends_deb_packages () +{ + code=$1 + arch=$2 + BASE_VERSION=`cat ../version` + FIND_PATH=apt/repositories/*/pool/$code + RESULT_SET=`find $FIND_PATH -name "*$BASE_VERSION*.deb"` + if [ -z "$RESULT_SET" ]; then + printf "%8s %5s %s => 404 deb\n" $code $arch $BASE_VERSION + else + for pkg in $RESULT_SET; do + DEB_NAME=`basename $pkg` + DEPENDS=`dpkg -I $pkg | grep "Depends"` + printf "%8s %5s %s => %s\n" $code $arch $DEB_NAME "$DEPENDS" + done + fi +} + +check_depends_rpm_packages () +{ + dist=$1 + arch=$2 + ver=$3 + BASE_VERSION=`cat ../version` + FIND_PATH=yum/repositories/$dist/$ver/$arch + RESULT_SET=`find $FIND_PATH -name "*$BASE_VERSION*"` + if [ -z "$RESULT_SET" ]; then + printf "%8s %6s %s => 404 rpm\n" $dist$ver $arch $BASE_VERSION + else + for pkg in $RESULT_SET; do + RPM_NAME=`basename $pkg` + DEPENDS=`rpm -qp --requires $pkg | grep -i "mysql" | tr -t '\n' ' '` + printf "%9s %6s %s => %s\n" $dist$ver $arch $RPM_NAME "$DEPENDS" + done + fi +} + +check_provided_mysql_packages () +{ + common_deb_procedure "check_provided_mysql_deb_packages" + common_rpm_procedure "check_provided_mysql_rpm_packages" + for code in $CODES; do + echo $code + cat tmp/$code-amd64-mysql-server.txt + done + for dist in $DISTRIBUTIONS; do + echo $dist + cat tmp/$dist-x86_64-mysql-server.txt + done +} + +check_provided_mysql_deb_packages () +{ + code=$1 + arch=$2 + root_dir=$3 + cat > tmp/check-provided-mysql.sh <<EOF +#!/bin/sh +apt-get update > /dev/null +apt-cache show mysql-server | grep "Version" | head -1 > /tmp/$code-$arch-mysql-server.txt +EOF + if [ -d $root_dir ]; then + CHECK_SCRIPT=check-provided-mysql.sh + echo "copy check script $CHECK_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$CHECK_SCRIPT + cp tmp/$CHECK_SCRIPT $root_dir/tmp + sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$CHECK_SCRIPT + cp $root_dir/tmp/$code-$arch-mysql-server.txt tmp + fi +} + +check_provided_mysql_rpm_packages () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + cat > tmp/check-provided-mysql.sh <<EOF +#!/bin/sh +yum update > /dev/null +yum info mysql-server | grep "Version" > /tmp/$code-$arch-mysql-server.txt +EOF + if [ -d $root_dir ]; then + CHECK_SCRIPT=check-provided-mysql.sh + echo "copy check script $CHECK_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$CHECK_SCRIPT + cp tmp/$CHECK_SCRIPT $root_dir/tmp + sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$CHECK_SCRIPT + cp $root_dir/tmp/$code-$arch-mysql-server.txt tmp + fi +} + +check_installed_mroonga_packages () +{ + common_deb_procedure "check_installed_mroonga_deb_packages" + common_rpm_procedure "check_installed_mroonga_rpm_packages" +} + +check_installed_mroonga_deb_packages () +{ + code=$1 + arch=$2 + root_dir=$3 + cat > tmp/check-deb-mroonga.sh <<EOF +#!/bin/sh +dpkg -l | grep $CHECK_INSTALL_PACKAGE +EOF + if [ -d $root_dir ]; then + CHECK_SCRIPT=check-deb-mroonga.sh + echo "copy check script $CHECK_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$CHECK_SCRIPT + cp tmp/$CHECK_SCRIPT $root_dir/tmp + sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$CHECK_SCRIPT + fi +} + +check_installed_mroonga_rpm_packages () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + cat > tmp/check-rpm-mroonga.sh <<EOF +#!/bin/sh +rpm -qa | grep $CHECK_INSTALL_PACKAGE +EOF + CHECK_SCRIPT=check-rpm-mroonga.sh + if [ -d $root_dir ]; then + echo "copy check script $CHECK_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$CHECK_SCRIPT + cp tmp/$CHECK_SCRIPT $root_dir/tmp + sudo chmod 755 $root_dir/tmp/$CHECK_SCRIPT + sudo chname $code-$ver-$arch chroot $root_dir /tmp/$CHECK_SCRIPT + fi +} + +install_mroonga_packages () +{ + common_deb_procedure "install_mroonga_deb_packages" + common_rpm_procedure "install_mroonga_rpm_packages" +} + +install_mroonga_deb_packages () +{ + code=$1 + arch=$2 + root_dir=$4 + cat > tmp/install-aptitude-mroonga.sh <<EOF +#!/bin/sh +sudo aptitude clean +rm -f /var/lib/apt/lists/packages.groonga.org_* +rm -f /var/lib/apt/lists/partial/packages.groonga.org_* +sudo aptitude update +sudo aptitude -V -D -y --allow-untrusted install groonga-keyring +sudo aptitude update +sudo aptitude -V -D install mysql-server-mroonga +sudo aptitude -V -D install groonga-tokenizer-mecab +EOF + cat > tmp/install-aptget-mroonga.sh <<EOF +#!/bin/sh +sudo apt-get clean +rm -f /var/lib/apt/lists/packages.groonga.org_* +rm -f /var/lib/apt/lists/partial/packages.groonga.org_* +sudo apt-get update +sudo apt-get -y --allow-unauthenticated install groonga-keyring +sudo apt-get update +sudo apt-get -V -y install mysql-server-mroonga +sudo apt-get -V -y install groonga-tokenizer-mecab +EOF + root_dir=$CHROOT_ROOT/$code-$arch + INSTALL_SCRIPT="" + case $code in + squeeze|unstable) + INSTALL_SCRIPT=install-aptitude-mroonga.sh + ;; + *) + INSTALL_SCRIPT=install-aptget-mroonga.sh + ;; + esac + if [ -d $root_dir ]; then + echo "copy install script $INSTALL_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$INSTALL_SCRIPT + cp tmp/$INSTALL_SCRIPT $root_dir/tmp + chmod 755 $root_dir/tmp/$INSTALL_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$INSTALL_SCRIPT + fi +} + +install_mroonga_rpm_packages () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + cat > tmp/install-centos5-mroonga.sh <<EOF +sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-0.noarch.rpm +sudo yum makecache +sudo yum install -y MySQL-server +sudo service mysql start +sudo yum install -y mysql-mroonga +sudo yum install -y groonga-tokenizer-mecab +EOF + cat > tmp/install-centos6-mroonga.sh <<EOF +sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-0.noarch.rpm +sudo yum makecache +sudo yum install -y mysql-server +sudo service mysql start +sudo yum install -y mysql-mroonga +sudo yum install -y groonga-tokenizer-mecab +EOF + cat > tmp/install-fedora-mroonga.sh <<EOF +sudo rpm -ivh http://packages.groonga.org/fedora/groonga-release-1.1.0-0.noarch.rpm +sudo yum makecache +sudo yum install -y mysql-mroonga +sudo yum install -y groonga-tokenizer-mecab +EOF + INSTALL_SCRIPT="" + case "$dist-$ver" in + centos-5) + INSTALL_SCRIPT=install-centos5-mroonga.sh + ;; + centos-6) + INSTALL_SCRIPT=install-centos6-mroonga.sh + ;; + fedora-18) + INSTALL_SCRIPT=install-fedora-mroonga.sh + ;; + *) + ;; + esac + if [ -d $root_dir ]; then + echo "copy install script $INSTALL_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$INSTALL_SCRIPT + cp tmp/$INSTALL_SCRIPT $root_dir/tmp + chmod 755 $root_dir/tmp/$INSTALL_SCRIPT + sudo chname $code-$ver-$arch chroot $root_dir /tmp/$INSTALL_SCRIPT + fi +} + + +uninstall_mroonga_packages () +{ + common_deb_procedure "uninstall_mroonga_deb_packages" + common_rpm_procedure "uninstall_mroonga_rpm_packages" +} + +uninstall_mroonga_deb_packages () +{ + code=$1 + arch=$2 + root_dir=$4 + UNINSTALL_SCRIPT=uninstall-deb-mroonga.sh + cat > $UNINSTALL_SCRIPT <<EOF +#!/bin/sh +sudo apt-get purge mroonga-* mysql-* +EOF + if [ -d $root_dir ]; then + echo "copy uninstall script $UNINSTALL_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$UNINSTALL_SCRIPT + cp $UNINSTALL_SCRIPT $root_dir/tmp + chmod 755 $root_dir/tmp/$UNINSTALL_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$UNINSTALL_SCRIPT + fi +} + +uninstall_mroonga_rpm_packages () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + UNINSTALL_SCRIPT=uninstall-rpm-mroonga.sh + cat > tmp/$UNINSTALL_SCRIPT <<EOF +#!/bin/sh +sudo yum remove mroonga-* mysql-* +EOF + if [ -d $root_dir ]; then + echo "copy install script $UNINSTALL_SCRIPT to $root_dir/tmp" + sudo rm -f $root_dir/tmp/$UNINSTALL_SCRIPT + cp tmp/$UNINSTALL_SCRIPT $root_dir/tmp + chmod 755 $root_dir/tmp/$UNINSTALL_SCRIPT + sudo chname $code-$ver-$arch chroot $root_dir /tmp/$UNINSTALL_SCRIPT + fi +} + + +enable_temporaly_mroonga_repository () +{ + cat > tmp/enable-repository.sh <<EOF +#!/bin/sh + +grep -v "packages.groonga.org" /etc/hosts > /tmp/hosts +echo "$HOST_ADDRESS packages.groonga.org" >> /tmp/hosts +cp -f /tmp/hosts /etc/hosts +EOF + common_deb_procedure "enable_temporaly_mroonga_deb_repository" + common_rpm_procedure "enable_temporaly_mroonga_rpm_repository" + check_packages_repository_address +} + +enable_temporaly_mroonga_deb_repository () +{ + code=$1 + arch=$2 + root_dir=$4 + today=`date '+%Y%m%d.%s'` + if [ -d $root_dir ]; then + sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today + sudo cp tmp/enable-repository.sh $root_dir/tmp + sudo chname $code-$arch chroot $root_dir /tmp/enable-repository.sh + fi +} + +enable_temporaly_mroonga_rpm_repository () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + today=`date '+%Y%m%d.%s'` + if [ -d $root_dir ]; then + sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today + sudo cp tmp/enable-repository.sh $root_dir/tmp + sudo chname $code-$arch chroot $root_dir /tmp/enable-repository.sh + fi +} + +disable_temporaly_mroonga_repository () +{ + cat > tmp/disable-repository.sh <<EOF +#!/bin/sh + +grep -v "packages.groonga.org" /etc/hosts > /tmp/hosts +cp -f /tmp/hosts /etc/hosts +EOF + common_deb_procedure "disable_temporaly_mroonga_deb_repository" + common_rpm_procedure "disable_temporaly_mroonga_rpm_repository" + check_packages_repository_address +} + +disable_temporaly_mroonga_deb_repository () +{ + code=$1 + arch=$2 + root_dir=$4 + DISABLE_SCRIPT=disable-repository.sh + today=`date '+%Y%m%d.%s'` + if [ -d $root_dir ]; then + sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today + cp tmp/$DISABLE_SCRIPT $root_dir/tmp + chmod 755 $root_dir/tmp/$DISABLE_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$DISABLE_SCRIPT + fi + +} + +disable_temporaly_mroonga_rpm_repository () +{ + dist=$1 + arch=$2 + ver=$3 + root_dir=$4 + DISABLE_SCRIPT=disable-repository.sh + today=`date '+%Y%m%d.%s'` + if [ -d $root_dir ]; then + sudo cp $root_dir/etc/hosts $root_dir/etc/hosts.$today + cp tmp/$DISABLE_SCRIPT $root_dir/tmp + chmod 755 $root_dir/tmp/$DISABLE_SCRIPT + sudo chname $code-$arch chroot $root_dir /tmp/$DISABLE_SCRIPT + fi +} + +host_address +echo $HOST_ADDRESS + +while [ $# -ne 0 ]; do + case $1 in + --check-install) + CHECK_INSTALL=1 + shift + if [ ! -z "$1" ]; then + case $1 in + groonga|mroonga|roonga|mecab|mysql) + CHECK_INSTALL_PACKAGE=$1 + ;; + *) + ;; + esac + fi + ;; + --check-address) + CHECK_ADDRESS=1 + shift + ;; + --check-depends) + CHECK_DEPENDS=1 + shift + ;; + --check-provides) + CHECK_PROVIDES=1 + shift + ;; + --check-build) + CHECK_BUILD=1 + shift + ;; + --enable-repository) + ENABLE_REPOSITORY=1 + shift + ;; + --disable-repository) + DISABLE_REPOSITORY=1 + shift + ;; + --install-mroonga) + INSTALL_MROONGA=1 + shift + ;; + --uninstall-mroonga) + UNINSTALL_MROONGA=1 + shift + ;; + --code) + shift + if [ "$1" = "all" ]; then + setup_codes + else + CODES=$1 + fi + shift + ;; + --code-arch) + shift + if [ "$1" = "all" ]; then + setup_deb_architectures + else + DEB_ARCHITECTURES=$1 + fi + shift + ;; + --dist) + shift + if [ "$1" = "all" ]; then + setup_distributions + else + DISTRIBUTIONS=$1 + fi + shift + ;; + --dist-arch) + shift + if [ "$1" = "all" ]; then + setup_rpm_architectures + else + RPM_ARCHITECTURES=$1 + fi + shift + ;; + *) + shift + ;; + esac +done + +mkdir -p tmp +setup_deb_architectures +setup_rpm_architectures + +if [ $CHECK_INSTALL -ne 0 ]; then + check_installed_mroonga_packages +fi +if [ $CHECK_ADDRESS -ne 0 ]; then + check_packages_repository_address +fi +if [ $CHECK_BUILD -ne 0 ]; then + check_build_packages +fi +if [ $CHECK_DEPENDS -ne 0 ]; then + check_depends_packages +fi +if [ $CHECK_PROVIDES -ne 0 ]; then + check_provided_mysql_packages +fi +if [ $ENABLE_REPOSITORY -ne 0 ]; then + enable_temporaly_mroonga_repository +fi +if [ $DISABLE_REPOSITORY -ne 0 ]; then + disable_temporaly_mroonga_repository +fi +if [ $INSTALL_MROONGA -ne 0 ]; then + install_mroonga_packages +fi +if [ $UNINSTALL_MROONGA -ne 0 ]; then + uninstall_mroonga_packages +fi + diff --git a/storage/mroonga/packages/debian/apparmor/mysql-server-mroonga b/storage/mroonga/packages/debian/apparmor/mysql-server-mroonga new file mode 100644 index 00000000000..259f8d1dc0c --- /dev/null +++ b/storage/mroonga/packages/debian/apparmor/mysql-server-mroonga @@ -0,0 +1,5 @@ +/usr/lib/groonga/plugins/ r, +/usr/lib/groonga/plugins/** rm, +/etc/mecabrc r, +/var/lib/mecab/dic/** r, +#include <local/mysql-server-mroonga> diff --git a/storage/mroonga/packages/debian/changelog b/storage/mroonga/packages/debian/changelog new file mode 100644 index 00000000000..6aa6fd58d17 --- /dev/null +++ b/storage/mroonga/packages/debian/changelog @@ -0,0 +1,391 @@ +mroonga (5.00-1) unstable; urgency=low + + * New upstream release. + + -- <hayashi@clear-code.com> Mon, 09 Feb 2015 00:00:00 +0900 + +mroonga (4.10-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 29 Jan 2015 00:00:00 +0900 + +mroonga (4.09-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@cozmixng.org> Mon, 29 Dec 2014 00:00:00 +0900 + +mroonga (4.08-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Nov 2014 00:00:00 +0900 + +mroonga (4.07-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Oct 2014 00:00:00 +0900 + +mroonga (4.06-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Mon, 29 Sep 2014 00:00:00 +0900 + +mroonga (4.05-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Aug 2014 00:00:00 +0900 + +mroonga (4.04-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Tue, 29 Jul 2014 00:00:00 +0900 + +mroonga (4.03-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Thu, 29 May 2014 00:00:00 +0900 + +mroonga (4.02-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 29 Apr 2014 00:00:00 +0900 + +mroonga (4.01-2) unstable; urgency=low + + * Built for mysql-server 5.5.37 + + -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 28 Apr 2014 00:00:00 +0900 + +mroonga (4.01-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Mar 2014 00:00:00 +0900 + +mroonga (4.00-2) unstable; urgency=low + + * Built for mysql-server 5.5.35+dfsg-2 on Debian jessie + * Built for mysql-server 5.5.35+dfsg-2 on Debian sid + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 06 Mar 2014 00:00:00 +0900 + +mroonga (4.00-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 09 Feb 2014 00:00:00 +0900 + +mroonga (3.12-2) unstable; urgency=low + + * Built for mysql-server updates on Ubuntu 12.04,12.10, and 13.10. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 29 Jan 2014 13:12:56 +0900 + +mroonga (3.12-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 29 Jan 2014 00:00:00 +0900 + +mroonga (3.11-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 29 Dec 2013 00:00:00 +0900 + +mroonga (3.10-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Fri, 29 Nov 2013 00:00:00 +0900 + +mroonga (3.09-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Tue, 29 Oct 2013 00:00:00 +0900 + +mroonga (3.08-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 29 Sep 2013 00:00:00 +0900 + +mroonga (3.07-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 29 Aug 2013 00:00:00 +0900 + +mroonga (3.06-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 29 Jul 2013 00:00:00 +0900 + +mroonga (3.05-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Jun 2013 00:00:00 +0900 + +mroonga (3.04-2) unstable; urgency=low + + * Built for mysql-server 5.5.31-0ubuntu0.12.04.2 on Ubuntu 12.04 (precise) + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 13 Jun 2013 00:00:00 +0900 + +mroonga (3.04-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 29 May 2013 00:00:00 +0900 + +mroonga (3.03-2) unstable; urgency=low + + * Built for mysql-server 5.5.31+dfsg-0+wheezy1 on Debian wheezy + * Built for mysql-server 5.5.31+dfsg-1 on Debian unstable + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 16 May 2013 00:00:00 +0900 + +mroonga (3.03-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 29 Apr 2013 00:00:00 +0900 + +mroonga (3.02-2) unstable; urgency=low + + * Built for mysql-server 5.5.29-0ubuntu0.12.04.2 on Ubuntu 12.04 (precise) + + -- HAYASHI Kentaro <hayashi@clear-code.com> Fri, 29 Mar 2013 22:15:39 +0900 + +mroonga (3.02-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Fri, 29 Mar 2013 00:00:00 +0900 + +mroonga (3.01-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 28 Feb 2013 00:00:00 +0900 + +mroonga (3.00-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 09 Feb 2013 00:00:00 +0900 + +mroonga (2.10-2) unstable; urgency=low + + * Built for mysql-server 5.5.29+dfsg-1 on Debian/unstable. + * Built for mysql-server 5.1.67-0ubuntu0.10.04.1 on Ubuntu 10.04(lucid). + * Built for mysql-server 5.1.67-0ubuntu0.11.10.1 on Ubuntu 11.10(oneiric). + * Built for mysql-server 5.5.29-0ubuntu0.12.04.1 on Ubuntu 12.04(precise). + * Built for mysql-server 5.5.29-0ubuntu0.12.10.1 on Ubuntu 12.10(quantal). + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 24 Jan 2013 10:28:16 +0900 + +mroonga (2.10-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Dec 2012 00:00:00 +0900 + +mroonga (2.09-2) unstable; urgency=low + + * Built for mysql-server 5.5.28-0ubuntu0.12.10.2 on Ubuntu 12.10. + Reported by @watanabekiyokaz + + -- HAYASHI Kentaro <hayashi@clear-code.com> Wed, 12 Dec 2012 13:28:00 +0900 + +mroonga (2.09-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Thu, 29 Nov 2012 00:00:00 +0900 + +mroonga (2.08-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Mon, 29 Oct 2012 00:00:00 +0900 + +mroonga (2.07-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sat, 29 Sep 2012 00:00:00 +0900 + +mroonga (2.06-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Aug 2012 00:00:00 +0900 + +mroonga (2.05-1) unstable; urgency=low + + * New upstream release. + + -- HAYASHI Kentaro <hayashi@clear-code.com> Sun, 29 Jul 2012 00:00:00 +0900 + +mroonga (2.04-1) unstable; urgency=low + + * New upstream release. + * Ensure deleting mroonga plugin before install. + Suggested by Kazuhiro Isobe. Thanks!!! + + -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Jun 2012 00:00:00 +0900 + +mroonga (2.03-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 29 May 2012 00:00:00 +0900 + +mroonga (2.02-1) unstable; urgency=low + + * New upstream release. + * Require groonga >= 2.0.2. + + -- Kouhei Sutou <kou@clear-code.com> Sun, 29 Apr 2012 00:00:00 +0900 + +mroonga (2.01-1) unstable; urgency=low + + * New upstream release. + * Ensure plugin is uninstalled by closing all tables use mroonga. + + -- Kouhei Sutou <kou@clear-code.com> Thu, 29 Mar 2012 00:00:00 +0900 + +mroonga (2.00-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Feb 2012 00:00:00 +0900 + +mroonga (1.20-1) unstable; urgency=low + + * New upstream release. + * Add mysql-server-mroonga-compatible package for "groonga" storage engine. + + -- Kouhei Sutou <kou@clear-code.com> Sun, 29 Jan 2012 00:00:00 +0900 + +mroonga (1.11-1) unstable; urgency=low + + * New upstream release. + * Change apparmor configuration file name: + mysql-server-groonga -> mysql-server-mroonga + + -- Kouhei Sutou <kou@clear-code.com> Thu, 29 Dec 2011 00:00:00 +0900 + +mroonga (1.10-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Sat, 29 Oct 2011 00:00:00 +0900 + +groonga-storage-engine (1.0.0-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Thu, 29 Sep 2011 00:00:00 +0900 + +groonga-storage-engine (0.9-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Mon, 29 Aug 2011 00:00:00 +0900 + +groonga-storage-engine (0.8-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Jul 2011 00:00:00 +0900 + +groonga-storage-engine (0.7-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Wed, 29 Jun 2011 00:00:00 +0900 + +groonga-storage-engine (0.6-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Sun, 29 May 2011 00:00:00 +0900 + +groonga-storage-engine (0.5-4) unstable; urgency=low + + * fix a typo. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 30 Mar 2011 01:05:00 +0900 + +groonga-storage-engine (0.5-3) unstable; urgency=low + + * fix AppArmor files. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 30 Mar 2011 00:59:00 +0900 + +groonga-storage-engine (0.5-2) unstable; urgency=low + + * hook script fix. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 30 Mar 2011 00:58:00 +0900 + +groonga-storage-engine (0.5-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 29 Mar 2011 00:00:00 +0900 + +groonga-storage-engine (0.4-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Mon, 29 Nov 2010 00:00:00 +0900 + +groonga-storage-engine (0.3-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Fri, 29 Oct 2010 16:34:04 +0900 + +groonga-storage-engine (0.2-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Sat, 25 Sep 2010 14:52:49 +0900 + +groonga-storage-engine (0.1-4) unstable; urgency=low + + * follow configure option changes. + + -- Kouhei Sutou <kou@cozmixng.org> Fri, 10 Sep 2010 08:45:53 +0900 + +groonga-storage-engine (0.1-3) unstable; urgency=low + + * Use HEAD. + + -- Kouhei Sutou <kou@clear-code.com> Thu, 02 Sep 2010 12:03:46 +0900 + +groonga-storage-engine (0.1-2) unstable; urgency=low + + * Built with groonga 1.0.0. + + -- Kouhei Sutou <kou@cozmixng.org> Mon, 30 Aug 2010 13:26:25 +0900 + +groonga-storage-engine (0.1-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Mon, 23 Aug 2010 13:52:01 +0900 diff --git a/storage/mroonga/packages/debian/compat b/storage/mroonga/packages/debian/compat new file mode 100644 index 00000000000..ec635144f60 --- /dev/null +++ b/storage/mroonga/packages/debian/compat @@ -0,0 +1 @@ +9 diff --git a/storage/mroonga/packages/debian/control.in b/storage/mroonga/packages/debian/control.in new file mode 100644 index 00000000000..d6d03fa9a4e --- /dev/null +++ b/storage/mroonga/packages/debian/control.in @@ -0,0 +1,51 @@ +Source: mroonga +Section: database +Priority: optional +Maintainer: Kouhei Sutou <kou@clear-code.com> +Build-Depends: + debhelper (>= 7.0.50), + autotools-dev, + pkg-config, + libgroonga-dev (>= @REQUIRED_GROONGA_VERSION@), + groonga-normalizer-mysql, + libmysqlclient-dev, + libmysqld-dev, + libssl-dev, + wget, + lsb-release +Standards-Version: 3.9.1 +Homepage: http://mroonga.org/ + +Package: mysql-server-mroonga +Section: database +Architecture: any +Replaces: mysql-server-groonga (<< 1.10-1) +Breaks: mysql-server-groonga (<< 1.10-1) +Depends: + ${misc:Depends}, + ${shlibs:Depends}, + libgroonga0 (>= @REQUIRED_GROONGA_VERSION@), + mysql-server (= MYSQL_VERSION), + groonga-normalizer-mysql +Description: A fast fulltext searchable storage engine for MySQL. + Mroonga is a fast fulltext searchable storage engine for MySQL. + It is based on Groonga, a fast fulltext search engine and column store. + Groonga is good at real time update. + . + This package provides a MySQL storage engine as a shared library. + This provides "mroonga" storage engine. It means you can use + "ENGINE = mroonga" in "CREATE TABLE". + +Package: mysql-server-mroonga-doc +Section: doc +Architecture: all +Replaces: mysql-server-groonga-doc (<< 1.10-1) +Breaks: mysql-server-groonga-doc (<< 1.10-1) +Depends: + ${misc:Depends} +Description: Documentation of Mroonga. + Mroonga is a fast fulltext searchable storage engine for MySQL. + It is based on Groonga, a fast fulltext search engine and column store. + Groonga is good at real time update. + . + This package provides documentation of Mroonga. diff --git a/storage/mroonga/packages/debian/copyright b/storage/mroonga/packages/debian/copyright new file mode 100644 index 00000000000..bb41984e8e4 --- /dev/null +++ b/storage/mroonga/packages/debian/copyright @@ -0,0 +1,27 @@ +This work was packaged for Debian by: + + Kouhei Sutou <kou@clear-code.com> on Thu, 02 Sep 2010 13:51:56 +0900. + +It was downloaded: + + <http://github.com/mroonga/mroonga/downloads> + +Upstream Author(s): + + Tetsuro IKEDA <ikdttr at gmail.com> + Daijiro MORI <morita at razil. jp> + Tasuku SUENAGA <a at razil. jp> + Kouhei Sutou <kou at clear-code. com> + +Copyright: + + Copyright(C) 2009-2010 Tetsuro IKEDA + +License: + + LGPLv2.1 + + See `/usr/share/common-licenses/LGPL-2.1'. + +The Debian packaging is done by Kouhei Sutou <kou@clear-code.com> in 2010, +and put into public domain, anyone can use it for any purpose. diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga-doc.install b/storage/mroonga/packages/debian/mysql-server-mroonga-doc.install new file mode 100644 index 00000000000..ad2e27ef7dd --- /dev/null +++ b/storage/mroonga/packages/debian/mysql-server-mroonga-doc.install @@ -0,0 +1 @@ +usr/share/doc/mysql-server-mroonga-doc/ diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.install b/storage/mroonga/packages/debian/mysql-server-mroonga.install new file mode 100644 index 00000000000..03f64cfedb4 --- /dev/null +++ b/storage/mroonga/packages/debian/mysql-server-mroonga.install @@ -0,0 +1,3 @@ +usr/lib/mysql/plugin/ha_mroonga.so* +usr/share/mroonga/* +debian/apparmor/mysql-server-mroonga etc/apparmor.d/abstractions/ diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.postinst b/storage/mroonga/packages/debian/mysql-server-mroonga.postinst new file mode 100755 index 00000000000..9a3db8784a2 --- /dev/null +++ b/storage/mroonga/packages/debian/mysql-server-mroonga.postinst @@ -0,0 +1,72 @@ +#! /bin/sh + +set -e + +prevver="$2" + +install_plugin() { + cat /usr/share/mroonga/install.sql | \ + mysql --defaults-file=/etc/mysql/debian.cnf || true +} + +install_apparmor() { + mysql_apparmor_profile_name=usr.sbin.mysqld + mysql_apparmor_profile=/etc/apparmor.d/${mysql_apparmor_profile_name} + mysql_local_apparmor_profile=/etc/apparmor.d/local/${mysql_apparmor_profile_name} + apparmor_profile_name=mysql-server-mroonga + include_profile="#include <abstractions/${apparmor_profile_name}>" + local_apparmor_profile=/etc/apparmor.d/local/${apparmor_profile_name} + if test -f "${mysql_local_apparmor_profile}"; then + if ! grep -q "${include_profile}" "${mysql_local_apparmor_profile}"; then + echo >> "${mysql_local_apparmor_profile}" + echo "${include_profile}" >> "${mysql_local_apparmor_profile}" + fi + else + mysql_abstraction_apparmor_profile=/etc/apparmor.d/abstractions/mysql + mysql_plugin_dir=/usr/lib/mysql/plugin + if test -f "${mysql_abstraction_apparmor_profile}" && \ + ! grep -q "${mysql_plugin_dir}" \ + "${mysql_abstraction_apparmor_profile}"; then + # For Lucid. + cat <<EOF >> "${mysql_abstraction_apparmor_profile}" + +# ${apparmor_profile_name}: START +# Added by mysql-server-mroonga. +${mysql_plugin_dir}/ r, +${mysql_plugin_dir}/*.so* mr, +${include_profile} +# ${apparmor_profile_name}: END +EOF + fi + fi + + if ! test -e "$local_apparmor_profile"; then + mkdir -p $(dirname "$local_apparmor_profile") + cat <<EOF > "$local_apparmor_profile" +# Site-specific additions and overrides for ${apparmor_profile_name}. +# For more details, please see /etc/apparmor.d/local/README. +EOF + fi + + if aa-status --enabled 2>/dev/null; then + apparmor_parser -r -T -W "${mysql_apparmor_profile}" || true + fi + + true +} + +case "$1" in + configure) + install_apparmor + install_plugin + ;; + abort-upgrade|abort-deconfigure|abort-remove) + : + ;; + *) + echo "Called with unknown argument $1, bailing out." + exit 1 + ;; +esac + +#DEBHELPER# diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.postrm b/storage/mroonga/packages/debian/mysql-server-mroonga.postrm new file mode 100755 index 00000000000..84d7f1ef4ab --- /dev/null +++ b/storage/mroonga/packages/debian/mysql-server-mroonga.postrm @@ -0,0 +1,38 @@ +#! /bin/sh + +set -e + +if [ "$1" = "purge" ]; then + mysql_apparmor_profile_name=usr.sbin.mysqld + mysql_apparmor_profile=/etc/apparmor.d/${mysql_apparmor_profile_name} + mysql_local_apparmor_profile=/etc/apparmor.d/local/${mysql_apparmor_profile_name} + mysql_abstraction_apparmor_profile=/etc/apparmor.d/abstractions/mysql + apparmor_profile_name=mysql-server-mroonga + if test -f "${mysql_local_apparmor_profile}"; then + include_profile="#include <abstractions/${apparmor_profile_name}>" + if grep -q "${include_profile}" "${mysql_local_apparmor_profile}"; then + sed -i'' -e "s,${include_profile},," \ + "${mysql_local_apparmor_profile}" + fi + else + start_marker_re="^# ${apparmor_profile_name}: START$" + end_marker_re="^# ${apparmor_profile_name}: END$" + if test -f "${mysql_abstraction_apparmor_profile}" && \ + grep -q "${start_marker_re}" \ + "${mysql_abstraction_apparmor_profile}"; then + sed -i'' -e "/${start_marker_re}/,/${end_marker_re}/d" \ + "${mysql_abstraction_apparmor_profile}" + fi + fi + + rm -f "/etc/apparmor.d/local/${apparmor_profile_name}" || true + rmdir /etc/apparmor.d/local 2>/dev/null || true + + if aa-status --enabled 2>/dev/null; then + apparmor_parser -r -T -W "${mysql_apparmor_profile}" || true + fi +fi + +#DEBHELPER# + +exit 0 diff --git a/storage/mroonga/packages/debian/mysql-server-mroonga.prerm b/storage/mroonga/packages/debian/mysql-server-mroonga.prerm new file mode 100755 index 00000000000..7fad990d75f --- /dev/null +++ b/storage/mroonga/packages/debian/mysql-server-mroonga.prerm @@ -0,0 +1,10 @@ +#! /bin/sh + +set -e + +cat /usr/share/mroonga/uninstall.sql | \ + mysql --defaults-file=/etc/mysql/debian.cnf || true + +#DEBHELPER# + +exit 0 diff --git a/storage/mroonga/packages/debian/rules b/storage/mroonga/packages/debian/rules new file mode 100755 index 00000000000..2a397b333e1 --- /dev/null +++ b/storage/mroonga/packages/debian/rules @@ -0,0 +1,39 @@ +#!/usr/bin/make -f +# -*- makefile-gmake -*- +# +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 +# This has to be exported to make some magic below work. +export DH_OPTIONS + +export MYSQL_VERSION := $(shell apt-cache show mysql-server-5.5 | grep Version | head -n 1 | awk '{print $$2}' | awk -F '-' '{print $$1}') + +%: + dh $@ + +override_dh_auto_configure: + path=main/m/mysql-5.5/mysql-5.5_$(MYSQL_VERSION).orig.tar.gz; \ + if [ "$$(lsb_release --id --short)" = "Ubuntu" ]; then \ + base_url=http://archive.ubuntu.com/ubuntu/pool; \ + security_base_url=http://security.ubuntu.com/ubuntu/pool; \ + else \ + base_url=http://ftp.debian.org/debian/pool; \ + security_base_url=http://security.debian.org/pool/updates; \ + fi; \ + wget $${security_base_url}/$${path} || \ + wget $${base_url}/$${path} + tar xf mysql-5.5_$(MYSQL_VERSION).orig.tar.gz + dh_auto_configure -- --with-mysql-source=./mysql-$(MYSQL_VERSION) + +# disable 'make check'. +override_dh_auto_test: + +override_dh_install: + mv debian/tmp/usr/share/doc/mroonga/ \ + debian/tmp/usr/share/doc/mysql-server-mroonga-doc/ + dh_install +# if test -x /usr/bin/dh_apparmor; then \ +# dh_apparmor \ +# -pmysql-server-mroonga \ +# --profile-name=usr.lib.mysql.plugin.ha_mroonga; \ +# fi diff --git a/storage/mroonga/packages/rpm/Makefile.am b/storage/mroonga/packages/rpm/Makefile.am new file mode 100644 index 00000000000..aa1ba3ad9c6 --- /dev/null +++ b/storage/mroonga/packages/rpm/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = \ + centos diff --git a/storage/mroonga/packages/rpm/centos/Makefile.am b/storage/mroonga/packages/rpm/centos/Makefile.am new file mode 100644 index 00000000000..e7b22cfa025 --- /dev/null +++ b/storage/mroonga/packages/rpm/centos/Makefile.am @@ -0,0 +1,9 @@ +EXTRA_DIST = \ + mysql55-mroonga.spec.in \ + mysql56-community-mroonga.spec.in \ + mariadb-mroonga.spec.in + +noinst_DATA = \ + mysql55-mroonga.spec \ + mysql56-community-mroonga.spec \ + mariadb-mroonga.spec diff --git a/storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in b/storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in new file mode 100644 index 00000000000..337eeccb1cf --- /dev/null +++ b/storage/mroonga/packages/rpm/centos/mariadb-mroonga.spec.in @@ -0,0 +1,396 @@ +%define mariadb_epoch_default 1 +%define mariadb_version_default 5.5.41 +%define mariadb_release_default 1 +%define mariadb_dist_default .el7_0 +%define mariadb_download_base_url_default http://vault.centos.org/7.0.1406/updates/Source/SPackages +%define mariadb_spec_file_default mariadb.spec + +%{!?mariadb_epoch:%define mariadb_epoch %{mariadb_epoch_default}} +%{!?mariadb_version:%define mariadb_version %{mariadb_version_default}} +%{!?mariadb_release:%define mariadb_release %{mariadb_release_default}} +%{!?mariadb_dist:%define mariadb_dist %{mariadb_dist_default}} +%{!?mariadb_download_base_url:%define mariadb_download_base_url %{mariadb_download_base_url_default}} +%{!?mariadb_spec_file:%define mariadb_spec_file %{mariadb_spec_file_default}} + +%define mariadb_package_version %{mariadb_epoch}:%{mariadb_version}-%{mariadb_release}%{mariadb_dist} + +%define groonga_required_version @REQUIRED_GROONGA_VERSION@ + +Name: mariadb-mroonga +Version: @VERSION@ +Release: 1%{?dist} +Summary: A fast fulltext searchable storage engine for MariaDB + +Group: Applications/Databases +License: LGPLv2.1 +URL: http://mroonga.org/ +Source0: http://packages.groonga.org/source/mroonga/mroonga-%{version}.tar.gz + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n) +BuildRequires: groonga-devel >= %{groonga_required_version} +BuildRequires: groonga-normalizer-mysql-devel +BuildRequires: wget +BuildRequires: mariadb-devel +Requires: mariadb-server = %{mariadb_package_version} +Requires: mariadb = %{mariadb_package_version} +Requires: groonga-libs >= %{groonga_required_version} +Requires: groonga-normalizer-mysql + +%description +Mroonga is a fast fulltext searchable storage plugin for MariaDB. +It is based on Groonga that is a fast fulltext search engine and +column store. Groonga is good at real-time update. + +%package doc +Summary: Documentation for Mroonga +Group: Documentation +License: LGPLv2.1 + +%description doc +Documentation for Mroonga + + +%prep +%setup -q -n mroonga-%{version} + +mariadb_full_version=%{mariadb_version}-%{mariadb_release}%{mariadb_dist} +srpm=mariadb-${mariadb_full_version}.src.rpm +if [ ! -f ../../SRPMS/$srpm ]; then + wget --continue -O ../../SRPMS/$srpm %{mariadb_download_base_url}/$srpm + rpm -Uvh ../../SRPMS/$srpm + rm ../../SRPMS/$srpm +fi + +%build +mariadb_source=../mariadb-%{mariadb_version} +if [ ! -d ${mariadb_source} ]; then + rpmbuild -bc \ + --define 'runselftest 0' \ + --define 'optflags -O0' \ + ../../SPECS/%{mariadb_spec_file} +fi +%configure \ + --disable-static \ + --with-mysql-source=${mariadb_source} \ + %{?mroonga_configure_options} +make %{?_smp_mflags} + + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT +rm $RPM_BUILD_ROOT%{_libdir}/mysql/plugin/*.la +mv $RPM_BUILD_ROOT%{_datadir}/doc/mroonga/ mysql-mroonga-doc/ + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +if /usr/bin/mysql -u root -e "quit"; then + password_option="" +else + password_option="-p" +fi +current_version=0 +version=$(echo %{groonga_required_version} | sed -e 's/\.//g') +required_version=$(expr $version) +version=$(/usr/bin/mysql -e "SHOW VARIABLES LIKE 'mroonga_libgroonga_version'" | \ + grep mroonga | cut -f 2 | sed -e 's/\.//g') +if [ -n "$version" ]; then + current_version=$(expr $version) +fi +install_sql=%{_datadir}/mroonga/install.sql +uninstall_sql=%{_datadir}/mroonga/uninstall.sql + +if [ "$1" = 2 ] ; then + if [ $current_version -lt $required_version ]; then + command="/usr/bin/mysql -u root $password_option" + echo "run the following command after restarting MySQL server:"; + echo " $command < ${uninstall_sql}" + echo " $command < ${install_sql}" + exit 0 + else + command="/usr/bin/mysql -u root $password_option" + command="${command} < ${uninstall_sql}" + echo $command + eval $command || \ + (echo "run the following command to unregister Mroonga:"; \ + echo " $command") + fi +fi + +command="/usr/bin/mysql -u root $password_option < ${install_sql}" +echo $command +eval $command || \ + (echo "run the following command to register Mroonga:"; \ + echo " $command") + +%preun +uninstall_sql=%{_datadir}/mroonga/uninstall.sql + +if mysql -u root -e "quit"; then + password_option="" +else + password_option="-p" +fi +if [ "$1" = 0 ]; then + command="/usr/bin/mysql -u root $password_option < ${uninstall_sql}" + echo $command + eval $command || \ + (echo "run the following command to unregister Mroonga:"; \ + echo " $command") +fi + +%files +%defattr(-,root,root,-) +%{_libdir}/mysql/plugin/ +%{_datadir}/mroonga/* +%{_datadir}/man/man1/* +%{_datadir}/man/*/man1/* + +%files doc +%defattr(-,root,root,-) +%doc README COPYING +%doc mysql-mroonga-doc/* + +%changelog +* Mon Feb 09 2015 <hayashi@clear-code.com> - 5.00-1 +- new upstream release. + +* Thu Jan 29 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-1 +- new upstream release. + +* Wed Jan 14 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.09-2 +- build against mariadb-5.5.40-2.el7_0. + +* Mon Dec 29 2014 Kouhei Sutou <kou@cozmixng.org> - 4.09-1 +- new upstream release. + +* Sat Nov 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.08-1 +- new upstream release. + +* Wed Oct 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.07-1 +- new upstream release. + +* Mon Sep 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.06-1 +- new upstream release. + +* Fri Aug 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.05-1 +- new upstream release. + +* Thu Aug 14 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-4 +- build MariaDB for libmysqlservices.a. + +* Thu Aug 14 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-3 +- support epoch in MariaDB. + +* Wed Aug 13 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-2 +- build against mariadb-5.5.37-1.el7_0. + +* Sun Aug 10 2014 Kouhei Sutou <kou@clear-code.com> - 4.04-1 +- initial packaging for CentOS 7 based on mysql-mroogna package. + +* Tue Jul 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.04-1 +- new upstream release. + +* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-1 +- new upstream release. + +* Tue Apr 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.02-1 +- new upstream release. + +* Sat Mar 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.01-1 +- new upstream release. + +* Thu Feb 13 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-2 +- use MySQL 5.1.73-3 on CentOS 6. + +* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-1 +- new upstream release. + +* Wed Jan 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 3.12-1 +- new upstream release. + +* Sun Dec 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.11-1 +- new upstream release. + +* Sat Dec 7 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-2 +- use MySQL 5.1.71-1 on CentOS 6. + +* Fri Nov 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-1 +- new upstream release. + +* Tue Oct 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.09-1 +- new upstream release. + +* Sun Sep 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.08-1 +- new upstream release. +- use MySQL 5.6.14-1 on CentOS 5. + +* Wed Sep 4 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.07-2 +- fix a bug that mroonga is removed accidentally on upgrade #1918. + Reported by @ceekz. Thanks!!! + +* Thu Aug 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.07-1 +- new upstream release. +- use MySQL 5.6.13-1 on CentOS 5. + +* Mon Jul 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.06-1 +- new upstream release. +- use MySQL 5.6.12-2 on CentOS 5. + +* Sat Jun 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.05-1 +- new upstream release. +- use MySQL 5.6.12 on CentOS 5. + +* Wed May 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.04-1 +- new upstream release. + +* Fri May 10 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.03-2 +- use MySQL 5.6.11-2 on CentOS 5. see http://bugs.mysql.com/bug.php?id=69027 + Reported by Y.Kentaro. Thanks!!! + +* Mon Apr 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.03-1 +- new upstream release. + +* Fri Mar 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.02-0 +- new upstream release. + +* Thu Feb 28 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.01-0 +- new upstream release. + +* Sat Feb 09 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.00-0 +- new upstream release. +- require groonga 3.0.0 or later + +* Tue Feb 05 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 2.10-2 +- use MySQL 5.1.67-1 on CentOS 6. + Reported by wakisuke.ua. Thanks!!! + +* Sat Dec 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.10-0 +- new upstream release. + +* Mon Dec 10 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.09-1 +- use MySQL 5.1.66-2 on CentOS 6. + Reported by wakisuke.ua. Thanks!!! + +* Thu Nov 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.09-0 +- new upstream release. +- use MySQL 5.5.28 on CentOS 5. +- use MySQL 5.1.66 on CentOS 6. + +* Mon Oct 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.08-0 +- new upstream release. +- add missing "DROP FUNCTION mroonga_snippet". + Reported by @tokuhy. Thanks!!! + +* Sat Sep 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.07-0 +- new upstream release. + +* Wed Aug 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.06-0 +- new upstream release. +- make MySQL spec file name customizable. +- make mroonga configure options customizable. +- add missing mysql-devel BuildRequires. Reported by wing. Thanks!!! +- use MySQL 5.5.27. + +* Sun Jul 29 2012 HAYASHI Kentaro <hayashi@clear-code.com> - 2.05-0 +- new upstream release. +- use MySQL 5.5.25a. + +* Fri Jun 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.04-0 +- new upstream release. +- ensure deleting mroonga plugin before install. + Suggested by Kazuhiro Isobe. Thanks!!! +- use MySQL 5.5.25. + +* Tue May 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.03-0 +- new upstream release. +- use MySQL 5.5.24. +- make mysql_* variables customizable +- require groonga 2.0.3 or later. + +* Sun Apr 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.02-0 +- new upstream release. +- use MySQL 5.5.23. +- require groonga 2.0.2 or later. + +* Thu Mar 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.01-0 +- new upstream release. +- ensure plugin is uninstalled by closing all tables use mroonga. + +* Wed Feb 29 2012 Kouhei Sutou <kou@clear-code.com> - 2.00-0 +- new upstream release. +- always install/uninstall plugin. +- use MySQL 5.1.61 and 5.5.21. +- require groonga 2.0.0 or later. + +* Sun Jan 29 2012 Kouhei Sutou <kou@clear-code.com> - 1.20-0 +- new upstream release. +- require groonga 1.3.0. +- groonga -> mroonga. +- use MySQL 5.5.20. + +* Thu Dec 29 2011 Kouhei Sutou <kou@clear-code.com> - 1.11-0 +- new upstream release. + +* Sat Oct 29 2011 Kouhei Sutou <kou@clear-code.com> - 1.10-0 +- new upstream release. +- groonga storage engine -> mroonga. + +* Thu Sep 29 2011 Kouhei Sutou <kou@clear-code.com> - 1.0.0-0 +- new upstream release. + +* Mon Aug 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.9-0 +- new upstream release. + +* Fri Jul 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.8-0 +- new upstream release. + +* Wed Jun 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.7-0 +- new upstream release. + +* Sun May 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.6-0 +- new upstream release. + +* Tue May 17 2011 Kouhei Sutou <kou@clear-code.com> - 0.5-2 +- use MySQL 5.5.12. + +* Tue Mar 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.5-1 +- new upstream release. + +* Sat Jan 29 2011 Kouhei Sutou <kou@clear-code.com> - 0.4-4 +- do not remove plugin on upgrade. + +* Wed Jan 12 2011 Kouhei Sutou <kou@clear-code.com> - 0.4-3 +- rebuild without debug symbol. + +* Thu Dec 30 2010 Kouhei Sutou <kou@clear-code.com> - 0.4-2 +- use MySQL 5.5.8-1. +- fix SQL literal notation. + +* Mon Nov 29 2010 Kouhei Sutou <kou@clear-code.com> - 0.4-1 +- use the latest MySQL. +- new upstream release. + +* Sun Nov 21 2010 Kouhei Sutou <kou@clear-code.com> - 0.3-2 +- install user define function. + +* Fri Oct 29 2010 Kouhei Sutou <kou@clear-code.com> - 0.3-1 +- new upstream release. + +* Fri Oct 08 2010 Kouhei Sutou <kou@clear-code.com> - 0.2-2 +- specify target MySQL version. +- use %{version}. + +* Wed Sep 29 2010 Kouhei Sutou <kou@clear-code.com> - 0.2-1 +- new upstream release. + +* Sun Sep 12 2010 Kouhei Sutou <kou@clear-code.com> - 0.1-3 +- require MySQL-client-community. + +* Fri Sep 10 2010 Kouhei Sutou <kou@clear-code.com> - 0.1-2 +- use MySQL-devel-community. + +* Fri Sep 03 2010 Kouhei Sutou <kou@clear-code.com> - 0.1-1 +- initial packaging for CentOS. diff --git a/storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in b/storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in new file mode 100644 index 00000000000..f1f5b2f4692 --- /dev/null +++ b/storage/mroonga/packages/rpm/centos/mysql55-mroonga.spec.in @@ -0,0 +1,218 @@ +%{?scl:%scl_package mroonga} +%{!?scl:%global pkg_name %{name}} +%{!?centos_ver:%define centos_ver 5} + +%if %{centos_ver} == 6 +%define mysql_version_default 5.5.41 +%define mysql_release_default 2 +%define mysql_dist_default el6.centos.alt +%define mysql_download_base_url_default http://vault.centos.org/6.6/SCL/Source/SPackages +%define mysql_spec_file_default mysql.spec +%else +%define mysql_version_default 5.5.40 +%define mysql_release_default 2 +%define mysql_dist_default el5 +%define mysql_download_base_url_default http://vault.centos.org/5.11/updates/SRPMS +%define mysql_spec_file_default mysql.spec +%endif + +%{!?mysql_version:%define mysql_version %{mysql_version_default}} +%{!?mysql_release:%define mysql_release %{mysql_release_default}} +%{!?mysql_dist:%define mysql_dist %{mysql_dist_default}} +%{!?mysql_download_base_url:%define mysql_download_base_url %{mysql_download_base_url_default}} +%{!?mysql_spec_file:%define mysql_spec_file %{mysql_spec_file_default}} + +%define groonga_required_version @REQUIRED_GROONGA_VERSION@ + +Name: %{?scl_prefix}mroonga +Version: @VERSION@ +Release: 1%{?dist} +Summary: A fast fulltext searchable storage engine for MySQL + +Group: Applications/Databases +License: LGPLv2.1 +URL: http://mroonga.org/ +Source0: http://packages.groonga.org/source/mroonga/mroonga-%{version}.tar.gz + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n) +BuildRequires: groonga-devel >= %{groonga_required_version} +BuildRequires: groonga-normalizer-mysql-devel +BuildRequires: wget +BuildRequires: which +BuildRequires: mysql55-mysql-devel +BuildRequires: mysql55-build +Requires: mysql55-mysql-server = %{mysql_version}-%{mysql_release}.%{mysql_dist} +Requires: mysql55-mysql = %{mysql_version}-%{mysql_release}.%{mysql_dist} +Requires: groonga-libs >= %{groonga_required_version} +Requires: groonga-normalizer-mysql +%{?scl:Requires: %scl_runtime} + +%description +Mroonga is a fast fulltext searchable storage plugin for MySQL. +It is based on Groonga that is a fast fulltext search engine and +column store. Groonga is good at real-time update. + +%package doc +Summary: Documentation for Mroonga +Group: Documentation +License: LGPLv2.1 + +%description doc +Documentation for Mroonga + + +%prep +%setup -q -n %{pkg_name}-%{version} + +mysql_full_version=%{mysql_version}-%{mysql_release}.%{mysql_dist} +srpm=mysql55-mysql-${mysql_full_version}.src.rpm +if [ ! -f ../../SRPMS/$srpm ]; then + wget --continue -O ../../SRPMS/$srpm %{mysql_download_base_url}/$srpm + rpm -Uvh ../../SRPMS/$srpm +fi + +%build +mysql_source=../mysql-%{mysql_version} +if [ ! -d ${mysql_source} ]; then + specs_dir= + MYSQL_RPMBUILD_TEST=no rpmbuild -bp \ + --define 'runselftest 0' \ + --define 'optflags -O0' \ + ../../SPECS/%{mysql_spec_file} +fi +%configure --disable-static --with-mysql-source=${mysql_source} \ + --disable-fast-mutexes \ + --with-mysql-config=`scl enable mysql55 'which mysql_config'` \ + %{?mroonga_configure_options} +make %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT +rm $RPM_BUILD_ROOT%{_libdir}/mysql/plugin/*.la +mv $RPM_BUILD_ROOT%{_datadir}/doc/mroonga/ mysql-mroonga-doc/ + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +mysql_command=`scl enable mysql55 'which mysql'` +password_option="" +$mysql_command -u root -e "quit" +if [ $? -ne 0 ]; then + password_option="-p" +fi +current_version=0 +version=`echo %{groonga_required_version} | sed -e 's/\.//g'` +required_version=`expr $version` +version=`$mysql_command -e "SHOW VARIABLES LIKE 'mroonga_libgroonga_version'" | \ + grep mroonga | cut -f 2 | sed -e 's/\.//g'` +if [ -n "$version" ]; then + current_version=`expr $version` +fi +install_sql=%{_datadir}/mroonga/install.sql +uninstall_sql=%{_datadir}/mroonga/uninstall.sql + +if [ "$1" = 2 ] ; then + if [ $current_version -lt $required_version ]; then + command="$mysql_command -u root $password_option" + echo "run the following command after restarting MySQL server:"; + echo " $command < ${uninstall_sql}" + echo " $command < ${install_sql}" + exit 0 + else + command="$mysql_command -u root $password_option < ${uninstall_sql}" + echo $command + eval $command || \ + (echo "run the following command to unregister Mroonga:"; \ + echo " $command") + fi +fi +command="$mysql_command -u root $password_option < ${install_sql}" +echo $command +eval $command || \ + (echo "run the following command to register Mroonga:"; \ + echo " $command") + +%preun +uninstall_sql=%{_datadir}/mroonga/uninstall.sql +mysql_command=`scl enable mysql55 'which mysql'` +if $mysql_command -u root -e "quit"; then + password_option="" +else + password_option="-p" +fi +if [ "$1" = 0 ]; then + command="$mysql_command -u root $password_option < ${uninstall_sql}" + echo $command + eval $command || \ + (echo "run the following command to unregister Mroonga:"; \ + echo " $command") +fi + +%files +%defattr(-,root,root,-) +%{_libdir}/mysql/plugin/ +%{_datadir}/mroonga/* +%{_datadir}/man/man1/* +%{_datadir}/man/*/man1/* + +%files doc +%defattr(-,root,root,-) +%doc README COPYING +%doc mysql-mroonga-doc/* + +%changelog +* Mon Feb 09 2015 <hayashi@clear-code.com> - 5.00-1 +- new upstream release. + +* Thu Jan 29 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-1 +- new upstream release. + +* Mon Dec 29 2014 Kouhei Sutou <kou@cozmixng.org> - 4.09-1 +- new upstream release. + +* Sat Nov 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.08-1 +- new upstream release. + +* Wed Oct 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.07-1 +- new upstream release. + +* Mon Sep 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.06-1 +- new upstream release. + +* Fri Aug 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.05-1 +- new upstream release. + +* Tue Jul 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.04-1 +- new upstream release. + +* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-2 +- build against MySQL 5.6.37. Reported by YOSHIDA Mitsuo. Thanks!!! + +* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-1 +- new upstream release. + +* Tue Apr 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.02-1 +- new upstream release. + +* Sat Mar 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.01-1 +- new upstream release. + +* Thu Mar 06 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-2 +- use MySQL 5.5.36 on CentOS 5. + +* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-1 +- new upstream release. + +* Wed Jan 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 3.12-1 +- new upstream release. + +* Sun Dec 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.11-1 +- new upstream release. + +* Fri Nov 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-1 +- new upstream release. + +* Tue Oct 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.09-1 +- initial packaging for MySQL 5.5 on CentOS 5. diff --git a/storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in b/storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in new file mode 100644 index 00000000000..37ae5d41b2f --- /dev/null +++ b/storage/mroonga/packages/rpm/centos/mysql56-community-mroonga.spec.in @@ -0,0 +1,222 @@ +%{!?centos_ver:%define centos_ver 6} + +%if %{centos_ver} == 7 +%define mysql_version_default 5.6.23 +%define mysql_release_default 2 +%define mysql_dist_default el7 +%define mysql_download_base_url_default http://repo.mysql.com/yum/mysql-5.6-community/el/7/SRPMS +%define mysql_spec_file_default mysql.spec +%else +%define mysql_version_default 5.6.23 +%define mysql_release_default 2 +%define mysql_dist_default el6 +%define mysql_download_base_url_default http://repo.mysql.com/yum/mysql-5.6-community/el/6/SRPMS +%define mysql_spec_file_default mysql.spec +%endif + +%{!?mysql_version:%define mysql_version %{mysql_version_default}} +%{!?mysql_release:%define mysql_release %{mysql_release_default}} +%{!?mysql_dist:%define mysql_dist %{mysql_dist_default}} +%{!?mysql_download_base_url:%define mysql_download_base_url %{mysql_download_base_url_default}} +%{!?mysql_spec_file:%define mysql_spec_file %{mysql_spec_file_default}} + +%define groonga_required_version @REQUIRED_GROONGA_VERSION@ + +Name: mysql-community-mroonga +Version: @VERSION@ +Release: 1%{?dist} +Summary: A fast fulltext searchable storage engine for MySQL + +Group: Applications/Databases +License: LGPLv2.1 +URL: http://mroonga.org/ +Source0: http://packages.groonga.org/source/mroonga/mroonga-%{version}.tar.gz + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%(%{__id_u} -n) +BuildRequires: groonga-devel >= %{groonga_required_version} +BuildRequires: groonga-normalizer-mysql-devel +BuildRequires: wget +BuildRequires: which +BuildRequires: gcc, gcc-c++ +BuildRequires: mysql-community-devel +Requires: mysql-community-server = %{mysql_version}-%{mysql_release}.%{mysql_dist} +Requires: mysql-community-client = %{mysql_version}-%{mysql_release}.%{mysql_dist} +Requires: groonga-libs >= %{groonga_required_version} +Requires: groonga-normalizer-mysql + +%description +Mroonga is a fast fulltext searchable storage plugin for MySQL. +It is based on Groonga that is a fast fulltext search engine and +column store. Groonga is good at real-time update. + +%package doc +Summary: Documentation for Mroonga +Group: Documentation +License: LGPLv2.1 + +%description doc +Documentation for Mroonga + + +%prep +%setup -q -n mroonga-%{version} + +mysql_full_version=%{mysql_version}-%{mysql_release}.%{mysql_dist} +srpm=mysql-community-${mysql_full_version}.src.rpm +if [ ! -f ../../SRPMS/$srpm ]; then + wget --continue -O ../../SRPMS/$srpm %{mysql_download_base_url}/$srpm + rpm -Uvh ../../SRPMS/$srpm +fi + +%build +mysql_source=../mysql-%{mysql_version}/mysql-%{mysql_version} +if [ ! -d ${mysql_source} ]; then + specs_dir= + MYSQL_RPMBUILD_TEST=no rpmbuild -bp \ + --define 'runselftest 0' \ + --define 'optflags -O0' \ + ../../SPECS/%{mysql_spec_file} +fi +%configure --disable-static --with-mysql-source=${mysql_source} \ + %{?mroonga_configure_options} +make %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT +rm $RPM_BUILD_ROOT%{_libdir}/mysql/plugin/*.la +mv $RPM_BUILD_ROOT%{_datadir}/doc/mroonga/ mysql-mroonga-doc/ + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +mysql_command=`which mysql` +password_option="" +$mysql_command -u root -e "quit" +if [ $? -ne 0 ]; then + password_option="-p" +fi +current_version=0 +version=`echo %{groonga_required_version} | sed -e 's/\.//g'` +required_version=`expr $version` +version=`$mysql_command -e "SHOW VARIABLES LIKE 'mroonga_libgroonga_version'" | \ + grep mroonga | cut -f 2 | sed -e 's/\.//g'` +if [ -n "$version" ]; then + current_version=`expr $version` +fi +install_sql=%{_datadir}/mroonga/install.sql +uninstall_sql=%{_datadir}/mroonga/uninstall.sql + +if [ "$1" = 2 ] ; then + if [ $current_version -lt $required_version ]; then + command="$mysql_command -u root $password_option" + echo "run the following command after restarting MySQL server:"; + echo " $command < ${uninstall_sql}" + echo " $command < ${install_sql}" + exit 0 + else + command="$mysql_command -u root $password_option < ${uninstall_sql}" + echo $command + eval $command || \ + (echo "run the following command to unregister Mroonga:"; \ + echo " $command") + fi +fi +command="$mysql_command -u root $password_option < ${install_sql}" +echo $command +eval $command || \ + (echo "run the following command to register Mroonga:"; \ + echo " $command") + +%preun +uninstall_sql=%{_datadir}/mroonga/uninstall.sql +mysql_command=`which mysql` +if $mysql_command -u root -e "quit"; then + password_option="" +else + password_option="-p" +fi +if [ "$1" = 0 ]; then + command="$mysql_command -u root $password_option < ${uninstall_sql}" + echo $command + eval $command || \ + (echo "run the following command to unregister Mroonga:"; \ + echo " $command") +fi + +%files +%defattr(-,root,root,-) +%{_libdir}/mysql/plugin/ +%{_datadir}/mroonga/* +%{_datadir}/man/man1/* +%{_datadir}/man/*/man1/* + +%files doc +%defattr(-,root,root,-) +%doc README COPYING +%doc mysql-mroonga-doc/* + +%changelog +* Mon Feb 09 2015 <hayashi@clear-code.com> - 5.00-1 +- new upstream release. + +* Wed Feb 04 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-2 +- build against MySQL 5.6.23-2 on MySQL yum repository. + +* Thu Jan 29 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 4.10-1 +- new upstream release. + +* Mon Dec 29 2014 Kouhei Sutou <kou@cozmixng.org> - 4.09-1 +- new upstream release. + +* Sat Nov 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.08-1 +- new upstream release. + +* Wed Oct 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.07-1 +- new upstream release. + +* Mon Sep 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.06-1 +- new upstream release. + +* Sat Sep 27 2014 Eiichi Sato <miko@cafelounge.net> - 4.05-2 +- build against MySQL 5.6.21-2 on MySQL yum repository. + +* Fri Aug 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.05-1 +- new upstream release. + +* Sat Aug 09 2014 Eiichi Sato <miko@cafelounge.net> - 4.04-2 +- build against MySQL 5.6.20-4 on MySQL yum repository. + +* Tue Jul 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.04-1 +- new upstream release. + +* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-2 +- build against MySQL 5.6.37. Reported by YOSHIDA Mitsuo. Thanks!!! + +* Thu May 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.03-1 +- new upstream release. + +* Tue Apr 29 2014 Kouhei Sutou <kou@clear-code.com> - 4.02-1 +- new upstream release. + +* Sat Mar 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.01-1 +- new upstream release. + +* Thu Mar 06 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-2 +- use MySQL 5.5.36 on CentOS 5. + +* Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 4.00-1 +- new upstream release. + +* Wed Jan 29 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 3.12-1 +- new upstream release. + +* Sun Dec 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.11-1 +- new upstream release. + +* Fri Nov 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.10-1 +- new upstream release. + +* Tue Oct 29 2013 HAYASHI Kentaro <hayashi@clear-code.com> - 3.09-1 +- initial packaging for MySQL 5.5 on CentOS 5. diff --git a/storage/mroonga/packages/source/Makefile.am b/storage/mroonga/packages/source/Makefile.am new file mode 100644 index 00000000000..30721406f0b --- /dev/null +++ b/storage/mroonga/packages/source/Makefile.am @@ -0,0 +1,123 @@ +MROONGA_BASE = $(PACKAGE)-$(VERSION) +MROONGA_TAR_GZ = $(MROONGA_BASE).tar.gz + +GROONGA_VERSION = 5.0.0 +GROONGA_BASE = groonga-$(GROONGA_VERSION) +GROONGA_TAR_GZ = $(GROONGA_BASE).tar.gz + +GROONGA_NORMALIZER_MYSQL_VERSION = 1.0.8 +GROONGA_NORMALIZER_MYSQL_BASE = \ + groonga-normalizer-mysql-$(GROONGA_NORMALIZER_MYSQL_VERSION) +GROONGA_NORMALIZER_MYSQL_TAR_GZ = \ + $(GROONGA_NORMALIZER_MYSQL_BASE).tar.gz + +MARIADB_VERSION = 10.0.16 +MARIADB_BASE = mariadb-$(MARIADB_VERSION) +MARIADB_TAR_GZ = $(MARIADB_BASE).tar.gz + +MARIADB_WITH_MROONGA_BASE = $(MARIADB_BASE)-with-$(MROONGA_BASE) +MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE = $(MARIADB_WITH_MROONGA_BASE)-for-windows + +GROONGA_PROJECT_DOWNLOAD_BASE = http://packages.groonga.org/source +GROONGA_DOWNLOAD_BASE = $(GROONGA_PROJECT_DOWNLOAD_BASE)/groonga +GROONGA_NORMALIZER_MYSQL_DOWNLOAD_BASE = \ + $(GROONGA_PROJECT_DOWNLOAD_BASE)/groonga-normalizer-mysql +MARIADB_DOWNLOAD_BASE = http://ftp.yz.yamagata-u.ac.jp/pub/dbms/mariadb + + +CURL = curl --fail --silent --show-error + +all: + +release: archive upload + +ensure-rsync-path: + @if test -z "$(RSYNC_PATH)"; then \ + echo "--with-rsync-path configure option must be specified."; \ + false; \ + fi + +download: ensure-rsync-path + rsync -avz --progress --delete $(RSYNC_PATH)/source/mroonga/ files + +ARCHIVES = \ + files/$(MROONGA_TAR_GZ) \ + files/$(MARIADB_WITH_MROONGA_BASE).tar.gz \ + files/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).zip + +archive: $(ARCHIVES) + +upload: ensure-rsync-path + rsync -avz --progress --delete files/ $(RSYNC_PATH)/source/mroonga + +files/$(MROONGA_TAR_GZ): $(top_builddir)/$(MROONGA_TAR_GZ) + mkdir -p files + cp -p $< $@ + +tmp/$(GROONGA_TAR_GZ): + mkdir -p tmp + $(CURL) --output $@ $(GROONGA_DOWNLOAD_BASE)/$(GROONGA_TAR_GZ) + +tmp/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ): + mkdir -p tmp + $(CURL) --output $@ $(GROONGA_NORMALIZER_MYSQL_DOWNLOAD_BASE)/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ) + +tmp/$(MARIADB_TAR_GZ): + mkdir -p tmp + $(CURL) --output $@ $(MARIADB_DOWNLOAD_BASE)/mariadb-$(MARIADB_VERSION)/source/$(MARIADB_TAR_GZ) + +MARIADB_WITH_MROONGA_ARCHIVES = \ + tmp/$(GROONGA_TAR_GZ) \ + tmp/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ) \ + tmp/$(MARIADB_TAR_GZ) \ + $(top_builddir)/$(MROONGA_TAR_GZ) + +BUNDLED_MROONGA_PATH = $(MARIADB_BASE)/storage/$(PACKAGE) +BUNDLED_GROONGA_PATH = $(BUNDLED_MROONGA_PATH)/vendor/groonga +BUNDLED_GROONGA_NORMALIZER_MYSQL_PATH = \ + $(BUNDLED_GROONGA_PATH)/vendor/plugins/groonga-normalizer-mysql + +tmp/$(MARIADB_WITH_MROONGA_BASE).stamp: $(MARIADB_WITH_MROONGA_ARCHIVES) + rm -rf $(MARIADB_BASE) + tar xf tmp/$(MARIADB_TAR_GZ) + + rm -fr $(MARIADB_BASE)/storage/mroonga + tar xf $(top_builddir)/$(MROONGA_TAR_GZ) + mv $(MROONGA_BASE) $(BUNDLED_MROONGA_PATH) + + mkdir -p $$(dirname $(BUNDLED_GROONGA_PATH)) + tar xf tmp/$(GROONGA_TAR_GZ) + rm -rf $(GROONGA_BASE)/test + mv $(GROONGA_BASE) $(BUNDLED_GROONGA_PATH) + + tar xf tmp/$(GROONGA_NORMALIZER_MYSQL_TAR_GZ) + rm -rf $(GROONGA_NORMALIZER_MYSQL_BASE)/test + mv $(GROONGA_NORMALIZER_MYSQL_BASE) $(BUNDLED_GROONGA_NORMALIZER_MYSQL_PATH) + + rm -rf tmp/$(MARIADB_WITH_MROONGA_BASE) + mv $(MARIADB_BASE) tmp/$(MARIADB_WITH_MROONGA_BASE) + + touch $@ + +files/$(MARIADB_WITH_MROONGA_BASE).tar.gz: tmp/$(MARIADB_WITH_MROONGA_BASE).stamp + mkdir -p files/ + (cd tmp && tar czf ../$@ $(MARIADB_WITH_MROONGA_BASE)) + +PATCHES = \ + patches/mariadb-10.0.3-windows-build.diff + +tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).stamp: tmp/$(MARIADB_WITH_MROONGA_BASE).stamp $(PATCHES) + rm -rf tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE) + cp -a \ + tmp/$(MARIADB_WITH_MROONGA_BASE) \ + tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE) + for patch in $(PATCHES); do \ + (cd tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE) && \ + patch -p1 < $(abs_srcdir)/$${patch}); \ + done + + touch $@ + +files/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).zip: tmp/$(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE).stamp + mkdir -p files/ + (cd tmp && zip -q -r ../$@ $(MARIADB_WITH_MROONGA_FOR_WINDOWS_BASE)) diff --git a/storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff b/storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff new file mode 100644 index 00000000000..c135088b8cc --- /dev/null +++ b/storage/mroonga/packages/source/patches/mariadb-10.0.3-windows-build.diff @@ -0,0 +1,9 @@ +diff -ur mariadb-10.0.2.orig/sql/sql_locale.cc mariadb-10.0.2/sql/sql_locale.cc +--- mariadb-10.0.2.orig/sql/sql_locale.cc 2013-04-23 13:13:59.000000000 +0900 ++++ mariadb-10.0.2/sql/sql_locale.cc 2013-05-19 12:55:27.590366542 +0900 +@@ -1,4 +1,4 @@ +-/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. ++/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by diff --git a/storage/mroonga/packages/ubuntu/Makefile.am b/storage/mroonga/packages/ubuntu/Makefile.am new file mode 100644 index 00000000000..493419275b3 --- /dev/null +++ b/storage/mroonga/packages/ubuntu/Makefile.am @@ -0,0 +1,24 @@ +CODE_NAMES = precise,trusty,utopic +SOURCE = ../$(PACKAGE)-$(VERSION).tar.gz + +all: + +ensure-launchpad-configuration: + @if test -z "$(LAUNCHPAD_UPLOADER_PGP_KEY)"; then \ + echo "--with-launchpad-uploader-pgp-key configure option must be specified."; \ + false; \ + fi + +upload: source ensure-launchpad-configuration + ./upload.rb \ + --package '$(PACKAGE)' \ + --version '$(VERSION)' \ + --source-archive '$(SOURCE)' \ + --code-names '$(CODE_NAMES)' \ + --debian-directory '$(srcdir)/../debian/' \ + --pgp-sign-key '$(LAUNCHPAD_UPLOADER_PGP_KEY)' + +source: $(SOURCE) + +$(SOURCE): + ln -s $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz $(SOURCE) diff --git a/storage/mroonga/packages/ubuntu/upload.rb b/storage/mroonga/packages/ubuntu/upload.rb new file mode 100755 index 00000000000..3331de6d5eb --- /dev/null +++ b/storage/mroonga/packages/ubuntu/upload.rb @@ -0,0 +1,168 @@ +#!/usr/bin/env ruby +# +# Copyright(C) 2014 Kouhei Sutou <kou@clear-code.com> +# Copyright(C) 2014 HAYASHI Kentaro <hayashi@clear-code.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +require "optparse" +require "fileutils" +require "pathname" +require "open-uri" + +class Uploader + def initialize + @dput_configuration_name = "groonga-ppa" + end + + def run + ensure_dput_configuration + + parse_command_line! + + ensure_mysql_version + + @required_groonga_version = required_groonga_version + + @code_names.each do |code_name| + upload(code_name) + end + end + + private + def ensure_dput_configuration + dput_cf_path = Pathname.new("~/.dput.cf").expand_path + if dput_cf_path.exist? + dput_cf_content = dput_cf_path.read + else + dput_cf_content = "" + end + dput_cf_content.each_line do |line| + return if line.chomp == "[#{@dput_configuration_name}]" + end + + dput_cf_path.open("w") do |dput_cf| + dput_cf.puts(dput_cf_content) + dput_cf.puts(<<-CONFIGURATION) +[#{@dput_configuration_name}] +fqdn = ppa.launchpad.net +method = ftp +incoming = ~groonga/ppa/ubuntu/ +login = anonymous +allow_unsigned_uploads = 0 + CONFIGURATION + end + end + + def ensure_mysql_version + @mysql_version = {} + @code_names.each do |code_name| + open("http://packages.ubuntu.com/#{code_name}/allpackages?format=txt.gz") do |file| + file.each_line do |line| + @mysql_version[code_name] = $1 if line =~ /\Amysql-server \((.+?)\).+/ + end + end + end + end + + def parse_command_line! + + parser = OptionParser.new + parser.on("--package=NAME", + "The package name") do |name| + @package = name + end + parser.on("--version=VERSION", + "The version") do |version| + @version = version + end + parser.on("--source-archive=ARCHIVE", + "The source archive") do |source_archive| + @source_archive = Pathname.new(source_archive).expand_path + end + parser.on("--code-names=CODE_NAME1,CODE_NAME2,CODE_NAME3,...", Array, + "The target code names") do |code_names| + @code_names = code_names + end + parser.on("--debian-directory=DIRECTORY", + "The debian/ directory") do |debian_directory| + @debian_directory = Pathname.new(debian_directory).expand_path + end + parser.on("--pgp-sign-key=KEY", + "The PGP key to sign .changes and .dsc") do |pgp_sign_key| + @pgp_sign_key = pgp_sign_key + end + parser.on("--pbuilder", + "Use pbuilder for build check") do |pbuilder| + @use_pbuilder = pbuilder + end + + parser.parse! + end + + def upload(code_name) + in_temporary_directory do + FileUtils.cp(@source_archive.to_s, + "#{@package}_#{@version}.orig.tar.gz") + run_command("tar", "xf", @source_archive.to_s) + directory_name = "#{@package}-#{@version}" + Dir.chdir(directory_name) do + FileUtils.cp_r(@debian_directory.to_s, "debian") + deb_version = "#{current_deb_version.succ}~#{code_name}1" + run_command("dch", + "--distribution", code_name, + "--newversion", deb_version, + "Build for #{code_name}.") + run_command("sed", + "-i", "-e", "s,MYSQL_VERSION,#{@mysql_version[code_name]},", + "debian/control") + run_command("debuild", "-S", "-sa", "-pgpg2", "-k#{@pgp_sign_key}") + if @use_pbuilder + run_command("pbuilder-dist", code_name, "build", + "../#{@package}_#{deb_version}.dsc") + else + run_command("dput", @dput_configuration_name, + "../#{@package}_#{deb_version}_source.changes") + end + end + end + end + + def required_groonga_version + File.read("../../required_groonga_version").lines.first.chomp + end + + def current_deb_version + /\((.+)\)/ =~ File.read("debian/changelog").lines.first + $1 + end + + def in_temporary_directory + name = "tmp" + FileUtils.rm_rf(name) + FileUtils.mkdir_p(name) + Dir.chdir(name) do + yield + end + end + + def run_command(*command_line) + unless system(*command_line) + raise "failed to run command: #{command_line.join(' ')}" + end + end +end + +uploader = Uploader.new +uploader.run diff --git a/storage/mroonga/packages/windows/Makefile.am b/storage/mroonga/packages/windows/Makefile.am new file mode 100644 index 00000000000..a2ff8f59792 --- /dev/null +++ b/storage/mroonga/packages/windows/Makefile.am @@ -0,0 +1,12 @@ +EXTRA_DIST = \ + README.md \ + build-vc2010.bat \ + build-vc2010-zip-32.bat \ + build-vc2010-zip-64.bat \ + build-vc2010-msi-32.bat \ + build-vc2010-msi-64.bat \ + build-vc2013.bat \ + build-vc2013-zip-32.bat \ + build-vc2013-zip-64.bat \ + build-vc2013-msi-32.bat \ + build-vc2013-msi-64.bat diff --git a/storage/mroonga/packages/windows/README.md b/storage/mroonga/packages/windows/README.md new file mode 100644 index 00000000000..f7788ffe26b --- /dev/null +++ b/storage/mroonga/packages/windows/README.md @@ -0,0 +1,20 @@ +# How to build Windows binaries + +## Preparation + +TODO... + +## Build with Visual C++ Express + +You need to use Visual C++ 2012 or later to build Mroonga with Express +edition. `build-vc2013.bat` is a build batch script to build with +Visual C++ Express 2013. + +Note that you can't build MSI file with Express edition. You need to +use Professional edition or upper editions to build MSI file. + +## Build with Visual C++ Professional + +You can build both zip file MSI file with Professional edition. +`build-vc2010.bat` is a build batch script to build with Visual C++ +Professional 2010. diff --git a/storage/mroonga/packages/windows/build-vc2010-msi-32.bat b/storage/mroonga/packages/windows/build-vc2010-msi-32.bat new file mode 100644 index 00000000000..15185eaba92 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2010-msi-32.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2010-msi-32 +mkdir build-vc2010-msi-32 +cd build-vc2010-msi-32 +cmake ..\source -G "Visual Studio 10" > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target msi > msi.log +move *.msi ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2010-msi-64.bat b/storage/mroonga/packages/windows/build-vc2010-msi-64.bat new file mode 100644 index 00000000000..ea0b7f07eb3 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2010-msi-64.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2010-msi-64 +mkdir build-vc2010-msi-64 +cd build-vc2010-msi-64 +cmake ..\source -G "Visual Studio 10 Win64" > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target msi > msi.log +move *.msi ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2010-zip-32.bat b/storage/mroonga/packages/windows/build-vc2010-zip-32.bat new file mode 100644 index 00000000000..013080755d4 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2010-zip-32.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2010-zip-32 +mkdir build-vc2010-zip-32 +cd build-vc2010-zip-32 +cmake ..\source -G "Visual Studio 10" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target package > zip.log +move *.zip ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2010-zip-64.bat b/storage/mroonga/packages/windows/build-vc2010-zip-64.bat new file mode 100644 index 00000000000..040c921fcef --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2010-zip-64.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2010-zip-64 +mkdir build-vc2010-zip-64 +cd build-vc2010-zip-64 +cmake ..\source -G "Visual Studio 10 Win64" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target package > zip.log +move *.zip ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2010.bat b/storage/mroonga/packages/windows/build-vc2010.bat new file mode 100644 index 00000000000..5fcf0639412 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2010.bat @@ -0,0 +1,4 @@ +build-vc2010-zip-32.bat +build-vc2010-zip-64.bat +build-vc2010-msi-32.bat +build-vc2010-msi-64.bat diff --git a/storage/mroonga/packages/windows/build-vc2013-msi-32.bat b/storage/mroonga/packages/windows/build-vc2013-msi-32.bat new file mode 100644 index 00000000000..22b29972885 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2013-msi-32.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2013-msi-32 +mkdir build-vc2013-msi-32 +cd build-vc2013-msi-32 +cmake ..\source -G "Visual Studio 12" > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target msi > msi.log +move *.msi ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2013-msi-64.bat b/storage/mroonga/packages/windows/build-vc2013-msi-64.bat new file mode 100644 index 00000000000..c83a376cdb9 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2013-msi-64.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2013-msi-64 +mkdir build-vc2013-msi-64 +cd build-vc2013-msi-64 +cmake ..\source -G "Visual Studio 12 Win64" > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target msi > msi.log +move *.msi ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2013-zip-32.bat b/storage/mroonga/packages/windows/build-vc2013-zip-32.bat new file mode 100644 index 00000000000..d3e0e4f8b8e --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2013-zip-32.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2013-zip-32 +mkdir build-vc2013-zip-32 +cd build-vc2013-zip-32 +cmake ..\source -G "Visual Studio 12" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target package > zip.log +move *.zip ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2013-zip-64.bat b/storage/mroonga/packages/windows/build-vc2013-zip-64.bat new file mode 100644 index 00000000000..6ca288b6a8b --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2013-zip-64.bat @@ -0,0 +1,8 @@ +rmdir /S /Q build-vc2013-zip-64 +mkdir build-vc2013-zip-64 +cd build-vc2013-zip-64 +cmake ..\source -G "Visual Studio 12 Win64" -DMRN_GROONGA_EMBED=OFF -DMRN_GROONGA_NORMALIZER_MYSQL_EMBED=OFF > config.log +cmake --build . --config RelWithDebInfo > build.log +cmake --build . --config RelWithDebInfo --target package > zip.log +move *.zip ..\ +cd .. diff --git a/storage/mroonga/packages/windows/build-vc2013.bat b/storage/mroonga/packages/windows/build-vc2013.bat new file mode 100644 index 00000000000..99d7e4042c5 --- /dev/null +++ b/storage/mroonga/packages/windows/build-vc2013.bat @@ -0,0 +1,4 @@ +build-vc2013-zip-32.bat +build-vc2013-zip-64.bat +REM build-vc2013-msi-32.bat +REM build-vc2013-msi-64.bat diff --git a/storage/mroonga/packages/yum/Makefile.am b/storage/mroonga/packages/yum/Makefile.am new file mode 100644 index 00000000000..b110b478a14 --- /dev/null +++ b/storage/mroonga/packages/yum/Makefile.am @@ -0,0 +1,63 @@ +REPOSITORIES_PATH = repositories +DISTRIBUTIONS = centos +ARCHITECTURES = i386 x86_64 +MYSQL_VARIANTS = mysql55 mysql56-community mariadb +SPEC_DIR = $(builddir)/../rpm/centos + +all: + +release: download build sign-packages update-repository upload + +remove-existing-packages: + for distribution in $(DISTRIBUTIONS); do \ + find $${distribution} -name "*.rpm" -delete; \ + done + +ensure-rsync-path: + @if test -z "$(RSYNC_PATH)"; then \ + echo "--with-rsync-path configure option must be specified."; \ + false; \ + fi + +sign-packages: + ./sign-rpm.sh '$(GPG_UID)' '$(REPOSITORIES_PATH)/' '$(DISTRIBUTIONS)' + +update-repository: + ./update-repository.sh '$(REPOSITORIES_PATH)/' '$(DISTRIBUTIONS)' + +upload: ensure-rsync-path + for distribution in $(DISTRIBUTIONS); do \ + rsync -avz --progress --delete --exclude .gitignore \ + $(REPOSITORIES_PATH)/$${distribution}/ \ + $(RSYNC_PATH)/$${distribution}; \ + done + +download: ensure-rsync-path + mkdir -p $(REPOSITORIES_PATH) + for distribution in $(DISTRIBUTIONS); do \ + rsync -avz --progress --delete \ + $(RSYNC_PATH)/$${distribution}/ \ + $(REPOSITORIES_PATH)/$${distribution}; \ + done + +build: build-in-vm + +build-in-vm: source specs env.sh + ./build-in-vm.sh \ + "$(PACKAGE)" \ + "$(SPEC_DIR)" \ + "$(MYSQL_VARIANTS)" \ + "$(ARCHITECTURES)" + +source: tmp/$(PACKAGE)-$(VERSION).tar.gz + +tmp/$(PACKAGE)-$(VERSION).tar.gz: $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz + mkdir -p tmp/ + cp $(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz tmp/ + +$(abs_top_builddir)/$(PACKAGE)-$(VERSION).tar.gz: + cd $(abs_top_builddir) && $(MAKE) dist + +specs: $(SPEC_DIR)/mysql55-$(PACKAGE).spec +specs: $(SPEC_DIR)/mysql56-community-$(PACKAGE).spec +specs: $(SPEC_DIR)/mariadb-$(PACKAGE).spec diff --git a/storage/mroonga/packages/yum/Vagrantfile b/storage/mroonga/packages/yum/Vagrantfile new file mode 100644 index 00000000000..1a9e4584ee4 --- /dev/null +++ b/storage/mroonga/packages/yum/Vagrantfile @@ -0,0 +1,50 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + vms = [ + { + :id => "centos-5-i386", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11-i386_chef-provisionerless.box", + }, + { + :id => "centos-5-x86_64", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11_chef-provisionerless.box", + }, + { + :id => "centos-6-i386", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6-i386_chef-provisionerless.box", + }, + { + :id => "centos-6-x86_64", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6_chef-provisionerless.box", + }, + { + :id => "centos-7-x86_64", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-7.0_chef-provisionerless.box", + }, + ] + + vms.each do |vm| + config.vm.define(vm[:id]) do |node| + node.vm.box = vm[:id] + node.vm.box_url = vm[:box_url] + node.vm.provision(:shell, :path => "build-rpm.sh") + node.vm.provider("virtualbox") do |virtual_box| + system_n_cpus = 1 + if File.exist?("/proc/cpuinfo") + system_n_cpus = File.readlines("/proc/cpuinfo").grep(/^processor/).size + end + if system_n_cpus > 1 + vm_n_cpus = system_n_cpus / 2 + else + vm_n_cpus = 1 + end + virtual_box.cpus = vm_n_cpus + end + end + end +end diff --git a/storage/mroonga/packages/yum/build-in-vm.sh b/storage/mroonga/packages/yum/build-in-vm.sh new file mode 100755 index 00000000000..5dc27ec38dd --- /dev/null +++ b/storage/mroonga/packages/yum/build-in-vm.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +if [ $# != 4 ]; then + echo "Usage: $0 PACKAGE SPEC_DIR MYSQL_VARIANTS ARCHITECTURES" + echo " e.g.: $0 mroonga ../rpm/centos 'mysql55 mariadb' 'i386 x86_64'" + exit 1 +fi + +PACKAGE="$1" +SPEC_DIR="$2" +MYSQL_VARIANTS="$3" +ARCHITECTURES="$4" + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +run vagrant destroy --force + +for mysql_variant in ${MYSQL_VARIANTS}; do + rm -rf tmp/centos/ + mkdir -p tmp/centos/ + cp ${SPEC_DIR}/${mysql_variant}-${PACKAGE}.spec tmp/centos/ + + architectures="${ARCHITECTURES}" + case ${mysql_variant} in + mysql55) + centos_versions="5 6" + ;; + mysql56-community) + centos_versions="6 7" + ;; + mariadb) + centos_versions="7" + ;; + esac + + for architecture in ${architectures}; do + for centos_version in ${centos_versions}; do + if [ ${mysql_variant} = mysql55 -a ${centos_version} = 6 -a ${architecture} = i386 ]; then + continue + fi + if [ ${centos_version} = 7 -a ${architecture} = i386 ]; then + continue + fi + id=centos-${centos_version}-${architecture} + vagrant up ${id} + build_status=$? + if [ $build_status -ne 0 ]; then + exit $build_status + fi + vagrant destroy --force ${id} + done + done +done diff --git a/storage/mroonga/packages/yum/build-rpm.sh b/storage/mroonga/packages/yum/build-rpm.sh new file mode 100755 index 00000000000..6eaa2cce02a --- /dev/null +++ b/storage/mroonga/packages/yum/build-rpm.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +LANG=C + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +rpmbuild_options= + +. /vagrant/env.sh + +distribution=$(cut -d " " -f 1 /etc/redhat-release | tr "A-Z" "a-z") +if grep -q Linux /etc/redhat-release; then + distribution_version=$(cut -d " " -f 4 /etc/redhat-release) +else + distribution_version=$(cut -d " " -f 3 /etc/redhat-release) +fi +distribution_version=$(echo ${distribution_version} | sed -e 's/\..*$//g') + +architecture="$(arch)" +case "${architecture}" in + i*86) + architecture=i386 + ;; +esac + +run yum groupinstall -y "Development Tools" +run yum install -y rpm-build rpmdevtools tar wget + +if [ -x /usr/bin/rpmdev-setuptree ]; then + rm -rf .rpmmacros + run rpmdev-setuptree +else + run cat <<EOM > ~/.rpmmacros +%_topdir ${HOME}/rpmbuild +EOM + run mkdir -p ~/rpmbuild/SOURCES + run mkdir -p ~/rpmbuild/SPECS + run mkdir -p ~/rpmbuild/BUILD + run mkdir -p ~/rpmbuild/RPMS + run mkdir -p ~/rpmbuild/SRPMS +fi + +repository="/vagrant/repositories/${distribution}/${distribution_version}" +rpm_dir="${repository}/${architecture}/Packages" +srpm_dir="${repository}/source/SRPMS" +run mkdir -p "${rpm_dir}" "${srpm_dir}" + +rpmbuild_options="" + +# for debug +# rpmbuild_options="${rpmbuild_options} --define 'optflags -O0 -g3'" + +cd + +run cp /vagrant/tmp/${PACKAGE}-${VERSION}.* rpmbuild/SOURCES/ +run cp /vagrant/tmp/${distribution}/*.spec rpmbuild/SPECS/ + +package_name=$(cd rpmbuild/SPECS; echo *.spec | sed -e 's/\.spec$//g') + +case ${distribution} in + fedora) + USE_MYSQLSERVICES_COMPAT=yes + run yum install -y mariadb-devel + ;; + centos) + case ${package_name} in + mysql55-${PACKAGE}) + USE_MYSQLSERVICES_COMPAT=yes + run yum install -y scl-utils-build + if [ ${distribution_version} = 6 ]; then + run yum install -y centos-release-SCL + fi + run yum install -y mysql55-mysql-devel mysql55-build + ;; + mysql56-community-${PACKAGE}) + release_rpm=mysql-community-release-el${distribution_version}-5.noarch.rpm + run yum -y install http://repo.mysql.com/${release_rpm} + run yum -y install mysql-community-devel + ;; + mariadb-${PACKAGE}) + run yum -y install mariadb-devel + ;; + esac + + release_rpm=groonga-release-1.1.0-1.noarch.rpm + wget http://packages.groonga.org/${distribution}/${release_rpm} + run rpm -U ${release_rpm} + rm -f ${release_rpm} + run yum makecache + ;; +esac +run yum install -y ${DEPENDED_PACKAGES} + +if [ "${USE_MYSQLSERVICES_COMPAT}" = "yes" ]; then + rpmbuild_options="$rpmbuild_options --define 'mroonga_configure_options --with-libmysqlservices-compat'" +fi + +run eval rpmbuild -ba ${rpmbuild_options} rpmbuild/SPECS/${package_name}.spec + +run mv rpmbuild/RPMS/*/* "${rpm_dir}/" +run mv rpmbuild/SRPMS/* "${srpm_dir}/" diff --git a/storage/mroonga/packages/yum/env.sh.in b/storage/mroonga/packages/yum/env.sh.in new file mode 100644 index 00000000000..90e701ec89e --- /dev/null +++ b/storage/mroonga/packages/yum/env.sh.in @@ -0,0 +1,27 @@ +PACKAGE=@PACKAGE@ +VERSION=@VERSION@ +DEPENDED_PACKAGES=" +intltool +libtool +gcc +gcc-c++ +make +gperf +readline-devel +openssl-devel +time +wget +ncurses-devel +sudo +pkgconfig +tar +cmake +libaio-devel +systemtap-sdt-devel +perl-Time-HiRes +perl-Env +perl-Test-Simple +pam-devel +groonga-devel +groonga-normalizer-mysql-devel +" diff --git a/storage/mroonga/packages/yum/sign-rpm.sh b/storage/mroonga/packages/yum/sign-rpm.sh new file mode 100755 index 00000000000..b3a45afe7f5 --- /dev/null +++ b/storage/mroonga/packages/yum/sign-rpm.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +script_base_dir=`dirname $0` + +if [ $# != 3 ]; then + echo "Usage: $0 GPG_UID DESTINATION DISTRIBUTIONS" + echo " e.g.: $0 'F10399C0' repositories/ 'fedora centos'" + exit 1 +fi + +GPG_UID=$1 +DESTINATION=$2 +DISTRIBUTIONS=$3 + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +unsigned_rpms() +{ + while read rpm; do + rpm --checksig "$rpm" | grep -v 'gpg OK' | cut -d":" -f1 + done +} + +if ! gpg --list-keys "${GPG_UID}" > /dev/null 2>&1; then + run gpg --keyserver keyserver.ubuntu.com --recv-key "${GPG_UID}" +fi +run mkdir -p tmp +run gpg --armor --export "${GPG_UID}" > tmp/sign-key +run rpm --import tmp/sign-key +run rm -rf tmp/sign-key + +rpms="" +for distribution in ${DISTRIBUTIONS}; do + rpms="${rpms} $(find ${DESTINATION}${distribution} -name '*.rpm' | unsigned_rpms)" +done + +echo "NOTE: YOU JUST ENTER! YOU DON'T NEED TO INPUT PASSWORD!" +echo " IT'S JUST FOR rpm COMMAND RESTRICTION!" +run echo $rpms | xargs rpm \ + -D "_gpg_name ${GPG_UID}" \ + -D "_gpg_digest_algo sha1" \ + -D "__gpg /usr/bin/gpg2" \ + -D "__gpg_check_password_cmd /bin/true true" \ + -D "__gpg_sign_cmd %{__gpg} gpg --batch --no-verbose --no-armor %{?_gpg_digest_algo:--digest-algo %{_gpg_digest_algo}} --no-secmem-warning -u \"%{_gpg_name}\" -sbo %{__signature_filename} %{__plaintext_filename}" \ + --resign diff --git a/storage/mroonga/packages/yum/update-repository.sh b/storage/mroonga/packages/yum/update-repository.sh new file mode 100755 index 00000000000..630b6c87422 --- /dev/null +++ b/storage/mroonga/packages/yum/update-repository.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +script_base_dir=`dirname $0` + +if [ $# != 2 ]; then + echo "Usage: $0 DESTINATION DISTRIBUTIONS" + echo " e.g.: $0 repositories/ 'fedora centos'" + exit 1 +fi + +DESTINATION=$1 +DISTRIBUTIONS=$2 + +run() +{ + "$@" + if test $? -ne 0; then + echo "Failed $@" + exit 1 + fi +} + +for distribution in ${DISTRIBUTIONS}; do + for dir in ${DESTINATION}${distribution}/*/*; do + # "--checksum sha" is for CentOS 5. If we drop CentOS 5 support, + # we can remove the option. + test -d $dir && run createrepo --checksum sha $dir + done; +done diff --git a/storage/mroonga/plugin_version b/storage/mroonga/plugin_version index be9fc83102e..6e636605163 100644 --- a/storage/mroonga/plugin_version +++ b/storage/mroonga/plugin_version @@ -1 +1 @@ -4.6
\ No newline at end of file +5.0
\ No newline at end of file diff --git a/storage/mroonga/required_groonga_version b/storage/mroonga/required_groonga_version index fcdb2e109f6..43beb4001b8 100644 --- a/storage/mroonga/required_groonga_version +++ b/storage/mroonga/required_groonga_version @@ -1 +1 @@ -4.0.0 +4.0.7 diff --git a/storage/mroonga/tools/travis/install.sh b/storage/mroonga/tools/travis/install.sh index fd3d2187914..95b8b23ba19 100755 --- a/storage/mroonga/tools/travis/install.sh +++ b/storage/mroonga/tools/travis/install.sh @@ -21,8 +21,8 @@ set -e mariadb_download_base=http://mirror.jmu.edu/pub/mariadb -export GROONGA_MASTER=yes -export GROONGA_NORMALIZER_MYSQL_MASTER=yes +# export GROONGA_MASTER=yes +# export GROONGA_NORMALIZER_MYSQL_MASTER=yes curl --silent --location https://github.com/groonga/groonga/raw/master/data/travis/setup.sh | sh curl --silent --location https://github.com/groonga/groonga-normalizer-mysql/raw/master/data/travis/setup.sh | sh @@ -43,6 +43,7 @@ if [ "${MROONGA_BUNDLED}" = "yes" ]; then curl -O ${download_base}/source/${tar_gz} tar xzf $tar_gz mv ${MYSQL_VERSION}/* ./ + rm -rf storage/mroonga mv .mroonga storage/mroonga rm -rf ${MYSQL_VERSION} else @@ -57,7 +58,8 @@ else sudo apt-get -qq -y build-dep mysql-server if [ "$version" = "system" ]; then sudo apt-get -qq -y install \ - mysql-server mysql-testsuite libmysqld-dev + mysql-server mysql-server-5.5 mysql-server-core-5.5 \ + mysql-testsuite libmysqld-dev apt-get -qq source mysql-server ln -s $(find . -maxdepth 1 -type d | sort | tail -1) mysql else diff --git a/storage/mroonga/udf/mrn_udf_command.cpp b/storage/mroonga/udf/mrn_udf_command.cpp index ba92e8daa26..172f64896a2 100644 --- a/storage/mroonga/udf/mrn_udf_command.cpp +++ b/storage/mroonga/udf/mrn_udf_command.cpp @@ -26,10 +26,10 @@ #include <mrn_macro.hpp> #include <mrn_database_manager.hpp> -extern mrn::DatabaseManager *mrn_db_manager; - MRN_BEGIN_DECLS +extern mrn::DatabaseManager *mrn_db_manager; + struct CommandInfo { grn_ctx ctx; @@ -100,7 +100,7 @@ error: grn_obj_close(&(info->ctx), info->db); } grn_ctx_fin(&(info->ctx)); - my_free(info, MYF(0)); + my_free(info); } return TRUE; } @@ -164,7 +164,7 @@ MRN_API void mroonga_command_deinit(UDF_INIT *initid) } grn_ctx_fin(&(info->ctx)); info->result.free(); - my_free(info, MYF(0)); + my_free(info); } } diff --git a/storage/mroonga/udf/mrn_udf_escape.cpp b/storage/mroonga/udf/mrn_udf_escape.cpp index ff997e7581f..36179788596 100644 --- a/storage/mroonga/udf/mrn_udf_escape.cpp +++ b/storage/mroonga/udf/mrn_udf_escape.cpp @@ -81,7 +81,7 @@ MRN_API my_bool mroonga_escape_init(UDF_INIT *initid, UDF_ARGS *args, error: if (info) { grn_ctx_fin(&(info->ctx)); - my_free(info, MYF(0)); + my_free(info); } return TRUE; } @@ -147,7 +147,7 @@ MRN_API void mroonga_escape_deinit(UDF_INIT *initid) grn_obj_unlink(&(info->ctx), &(info->target_characters)); grn_obj_unlink(&(info->ctx), &(info->escaped_query)); grn_ctx_fin(&(info->ctx)); - my_free(info, MYF(0)); + my_free(info); } } diff --git a/storage/mroonga/udf/mrn_udf_snippet.cpp b/storage/mroonga/udf/mrn_udf_snippet.cpp index 84166a36f16..3eaf05eed95 100644 --- a/storage/mroonga/udf/mrn_udf_snippet.cpp +++ b/storage/mroonga/udf/mrn_udf_snippet.cpp @@ -198,7 +198,7 @@ error: if (snip_info) { grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx)); grn_ctx_fin(&snip_info->ctx); - my_free(snip_info, MYF(0)); + my_free(snip_info); } return TRUE; } @@ -295,7 +295,7 @@ MRN_API void mroonga_snippet_deinit(UDF_INIT *initid) snip_info->result_str.free(); grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx)); grn_ctx_fin(&snip_info->ctx); - my_free(snip_info, MYF(0)); + my_free(snip_info); } } diff --git a/storage/mroonga/vendor/groonga/CMakeLists.txt b/storage/mroonga/vendor/groonga/CMakeLists.txt index abaa9911fd6..cddb3df28f6 100644 --- a/storage/mroonga/vendor/groonga/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright(C) 2012-2014 Brazil +# Copyright(C) 2012-2015 Brazil # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -20,12 +20,19 @@ cmake_minimum_required(VERSION 2.6.2) set(GRN_PROJECT_NAME "groonga") project("${GRN_PROJECT_NAME}") +if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + set(CMAKE_COMPILER_IS_CLANGC ON) +endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_COMPILER_IS_CLANGCXX ON) +endif() + file(READ "${CMAKE_CURRENT_SOURCE_DIR}/base_version" VERSION) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version.sh") file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version.sh" GRN_VERSION) else() if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/version.sh") - if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND EXISTS "/bin/sh") execute_process(COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/version-gen.sh") file(READ "${CMAKE_CURRENT_BINARY_DIR}/version.sh" GRN_VERSION) else() @@ -44,6 +51,15 @@ include(CheckCXXCompilerFlag) include(FindPkgConfig) include(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake_modules/ReadFileList.cmake) +if(DEFINED GRN_EMBED) + set(GRN_EMBED_DEFAULT ${GRN_EMBED}) +else() + set(GRN_EMBED_DEFAULT OFF) +endif() +option(GRN_EMBED + "Build as a static library to embed into an application" + ${GRN_EMBED_DEFAULT}) + set(BIN_DIR "bin") set(SBIN_DIR "sbin") set(LIB_DIR "lib") @@ -53,10 +69,14 @@ set(DATA_DIR "share") set(GRN_DATA_DIR "${DATA_DIR}/${GRN_PROJECT_NAME}") set(CONFIG_DIR "etc") set(GRN_CONFIG_DIR "${CONFIG_DIR}/${GRN_PROJECT_NAME}") +set(GRN_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/${GRN_CONFIG_DIR}/groonga.conf") set(GRN_LOG_PATH "${CMAKE_INSTALL_PREFIX}/var/log/${GRN_PROJECT_NAME}/${GRN_PROJECT_NAME}.log" CACHE FILEPATH "log file path") +set(GRN_DEFAULT_ENCODING + "utf8" + CACHE STRING "Groonga's default encoding") set(GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD 0 CACHE STRING "groonga default match escalation threshold") @@ -69,6 +89,9 @@ set(GRN_DEFAULT_RELATIVE_DOCUMENT_ROOT set(GRN_DEFAULT_DOCUMENT_ROOT "${CMAKE_INSTALL_PREFIX}/${GRN_DATA_DIR}/${GRN_DEFAULT_DOCUMENT_ROOT_BASE}" CACHE PATH "groonga default document root") +set(GRN_DEFAULT_DB_KEY + "auto" + CACHE STRING "Groonga's default DB key management algorithm") set(GRN_STACK_SIZE 1024 CACHE STRING @@ -97,15 +120,21 @@ set(GRN_RUBY_SCRIPTS_DIR "${CMAKE_INSTALL_PREFIX}/${GRN_RELATIVE_RUBY_SCRIPTS_DIR}") macro(check_cflag flag) - check_c_compiler_flag(${flag} "HAVE_C_${flag}") - if(HAVE_C_${flag}) + string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag}) + string(TOUPPER "${temporary_variable_name}" temporary_variable_name) + set(temporary_variable_name "CFLAG${temporary_variable_name}") + check_c_compiler_flag(${flag} ${temporary_variable_name}) + if(${temporary_variable_name}) set(GRN_C_COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS} ${flag}") endif() endmacro() macro(check_cxxflag flag) - check_cxx_compiler_flag(${flag} "HAVE_CXX_${flag}") - if(HAVE_CXX_${flag}) + string(REGEX REPLACE "[-=]" "_" temporary_variable_name ${flag}) + string(TOUPPER "${temporary_variable_name}" temporary_variable_name) + set(temporary_variable_name "CXXFLAG${temporary_variable_name}") + check_cxx_compiler_flag(${flag} ${temporary_variable_name}) + if(${temporary_variable_name}) set(GRN_CXX_COMPILE_FLAGS "${GRN_CXX_COMPILE_FLAGS} ${flag}") endif() endmacro() @@ -137,7 +166,10 @@ if(CMAKE_COMPILER_IS_GNUCXX) check_cxxflag("-fexceptions") check_cxxflag("-fimplicit-templates") check_build_flag("-Wno-clobbered") - if(MRN_GROONGA_BUNDLED) +endif() + +if(GRN_EMBED) + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGCXX) check_build_flag("-fPIC") endif() endif() @@ -154,17 +186,15 @@ add_definitions( -DHAVE_CONFIG_H ) -if(CMAKE_COMPILER_IS_GNUC OR - CMAKE_COMPILER_IS_GNUCXX OR - CMAKE_C_COMPILER_ID STREQUAL "Clang") +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGCXX) set(_GNU_SOURCE TRUE) endif() include_directories( BEFORE ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/lib ) macro(ac_check_headers header) @@ -202,6 +232,7 @@ include(build/ac_macros/check_headers.m4) include(build/ac_macros/check_functions.m4) ac_check_symbols(fpclassify math.h) +ac_check_lib(m fpclassify) ac_check_lib(dl dlopen) ac_check_lib(execinfo backtrace) @@ -214,8 +245,7 @@ ac_check_lib(rt clock_gettime) if(HAVE_LIBRT) set(HAVE_CLOCK_GETTIME TRUE) endif() -if(MRN_GROONGA_BUNDLED) - ac_check_lib(m sincos) +if(GRN_EMBED) check_library_exists(stdc++ __cxa_begin_catch "${ARG2}" STDCPP) if(STDCPP) @@ -293,19 +323,29 @@ else() endif() endif() -option(GRN_WITH_ZLIB "use zlib for data compression." OFF) -if(GRN_WITH_ZLIB) +set(GRN_WITH_ZLIB "auto" + CACHE STRING "Support data compression by zlib.") +if(NOT ${GRN_WITH_ZLIB} STREQUAL "no") ac_check_lib(z compress) if(NOT HAVE_LIBZ) - message(FATAL_ERROR "No libz found") + if(${GRN_WITH_ZLIB} STREQUAL "yes") + message(FATAL_ERROR "No libz found") + endif() + set(GRN_WITH_ZLIB "no") endif() endif() -option(GRN_WITH_LZO "use LZO for data compression." OFF) -if(GRN_WITH_LZO) - ac_check_lib(lzo2 lzo1_compress) - if(NOT HAVE_LIBLZO2) - message(FATAL_ERROR "No liblzo2 found") +set(GRN_WITH_LZ4 "auto" + CACHE STRING "Support data compression by LZ4.") +if(NOT ${GRN_WITH_LZ4} STREQUAL "no") + pkg_check_modules(LIBLZ4 liblz4) + if(LIBLZ4_FOUND) + set(GRN_WITH_LZ4 TRUE) + else() + if(${GRN_WITH_LZ4} STREQUAL "yes") + message(FATAL_ERROR "No LZ4 found") + endif() + set(GRN_WITH_LZ4 FALSE) endif() endif() @@ -362,6 +402,38 @@ else() set(GRN_WITH_KYTEA FALSE) endif() +set(GRN_WITH_LIBSTEMMER "auto" + CACHE STRING "use libstemmer for stemming token filter") +if(NOT ${GRN_WITH_LIBSTEMMER} STREQUAL "no") + if(NOT ("${GRN_WITH_LIBSTEMMER}" STREQUAL "yes" OR + "${GRN_WITH_LIBSTEMMER}" STREQUAL "auto")) + if("${LIBSTEMMER_INCLUDE_DIRS}" STREQUAL "") + set(LIBSTEMMER_INCLUDE_DIRS "${GRN_WITH_LIBSTEMMER}/include") + endif() + if("${LIBSTEMMER_LIBRARY_DIRS}" STREQUAL "") + set(LIBSTEMMER_LIBRARY_DIRS "${GRN_WITH_LIBSTEMMER}/lib") + endif() + endif() + set(CMAKE_REQUIRED_INCLUDES_SAVE ${CMAKE_REQUIRED_INCLUDES}) + set(CMAKE_REQUIRED_INCLUDES + ${CMAKE_REQUIRED_INCLUDES} + ${LIBSTEMMER_INCLUDE_DIRS}) + ac_check_headers(libstemmer.h) + ac_check_lib(stemmer sb_stemmer_list "${LIBSTEMMER_LIBRARY_DIRS}") + set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_SAVE}) + if(HAVE_LIBSTEMMER_H AND HAVE_LIBSTEMMER) + set(LIBSTEMMER_LIBRARIES "stemmer") + set(GRN_WITH_LIBSTEMMER TRUE) + else() + if(${GRN_WITH_LIBSTEMMER} STREQUAL "yes") + message(FATAL_ERROR "No libstemmer found") + endif() + set(GRN_WITH_LIBSTEMMER FALSE) + endif() +else() + set(GRN_WITH_LIBSTEMMER FALSE) +endif() + set(GRN_WITH_ZEROMQ "auto" CACHE STRING "use ZeroMQ for suggestion") if(NOT ${GRN_WITH_ZEROMQ} STREQUAL "no") @@ -447,12 +519,16 @@ else() set(MRUBY_LIBS "") endif() -#add_subdirectory(vendor) +if(NOT GRN_EMBED) + add_subdirectory(vendor) +endif() add_subdirectory(lib) -add_subdirectory(src) -#add_subdirectory(plugins) -add_subdirectory(include) -#add_subdirectory(data) +if(NOT GRN_EMBED) + add_subdirectory(src) + add_subdirectory(plugins) + add_subdirectory(include) + add_subdirectory(data) +endif() configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) @@ -476,10 +552,10 @@ set(GRN_EXPANDED_DEFAULT_DOCUMENT_ROOT "${GRN_DEFAULT_DOCUMENT_ROOT}") set(EXEEXT "${CMAKE_EXECUTABLE_SUFFIX}") configure_file(groonga.pc.in "${CMAKE_CURRENT_BINARY_DIR}/groonga.pc" @ONLY) -if(NOT MRN_GROONGA_BUNDLED) +if(NOT GRN_EMBED) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/groonga.pc" DESTINATION "${LIB_DIR}/pkgconfig/") endif() -#add_subdirectory(vendor/plugins) +add_subdirectory(vendor/plugins) diff --git a/storage/mroonga/vendor/groonga/Makefile.am b/storage/mroonga/vendor/groonga/Makefile.am index a5bf404d471..65b7c928770 100644 --- a/storage/mroonga/vendor/groonga/Makefile.am +++ b/storage/mroonga/vendor/groonga/Makefile.am @@ -69,7 +69,6 @@ update-latest-release: misc misc/update-latest-release.rb \ $(PACKAGE) $(OLD_RELEASE) $(OLD_RELEASE_DATE) \ $(VERSION) $(NEW_RELEASE_DATE) \ - packages/rpm/fedora/groonga.spec.in \ packages/rpm/centos/groonga.spec.in \ packages/debian/changelog \ doc/source/install.rst \ diff --git a/storage/mroonga/vendor/groonga/appveyor.yml b/storage/mroonga/vendor/groonga/appveyor.yml new file mode 100644 index 00000000000..aa4b65fb24e --- /dev/null +++ b/storage/mroonga/vendor/groonga/appveyor.yml @@ -0,0 +1,17 @@ +version: "{build}" +clone_depth: 10 +build_script: + - cmake . -G "Visual Studio 12 Win64" + - cmake --build . --config RelWithDebInfo + +notifications: + - provider: Email + to: + - kou@clear-code.com + - groonga-commit@lists.sourceforge.jp + on_build_status_changed: true + +before_test: + - gem install grntest +test_script: + - grntest --groonga src\groonga.exe --base-directory test\command test\command\suite diff --git a/storage/mroonga/vendor/groonga/autogen.sh b/storage/mroonga/vendor/groonga/autogen.sh index 9b3a98eab5d..66184bf13be 100755 --- a/storage/mroonga/vendor/groonga/autogen.sh +++ b/storage/mroonga/vendor/groonga/autogen.sh @@ -18,4 +18,9 @@ FreeBSD) ;; esac +if [ ! -e vendor/mruby-source/.git ]; then + rm -rf vendor/mruby-source +fi +git submodule update --init + ${AUTORECONF:-autoreconf} --force --install diff --git a/storage/mroonga/vendor/groonga/base_version b/storage/mroonga/vendor/groonga/base_version index 9eefef7bd65..28cbf7c0aae 100644 --- a/storage/mroonga/vendor/groonga/base_version +++ b/storage/mroonga/vendor/groonga/base_version @@ -1 +1 @@ -4.0.6
\ No newline at end of file +5.0.0
\ No newline at end of file diff --git a/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c b/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c index 8e1d819538b..72d1d79b73f 100644 --- a/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c +++ b/storage/mroonga/vendor/groonga/benchmark/bench-geo-distance.c @@ -49,7 +49,7 @@ #include <string.h> -#include <db.h> +#include <grn_db.h> #include <groonga.h> #include "lib/benchmark.h" diff --git a/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c b/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c index b934f225330..7b57eaaffdc 100644 --- a/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c +++ b/storage/mroonga/vendor/groonga/benchmark/bench-geo-select.c @@ -58,7 +58,7 @@ #include <string.h> -#include <db.h> +#include <grn_db.h> #include <groonga.h> #include "lib/benchmark.h" diff --git a/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c b/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c index 4c0b500aae2..d45d453cba6 100644 --- a/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c +++ b/storage/mroonga/vendor/groonga/benchmark/bench-range-select.c @@ -53,7 +53,7 @@ #include <stdio.h> #include <string.h> -#include <db.h> +#include <grn_db.h> #include <groonga.h> #include "lib/benchmark.h" diff --git a/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4 b/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4 index 5046e8ce6ab..72e3a9a545d 100644 --- a/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4 +++ b/storage/mroonga/vendor/groonga/build/ac_macros/check_functions.m4 @@ -1,5 +1,8 @@ # -*- autoconf -*- +AC_CHECK_FUNCS(_gmtime64_s) +AC_CHECK_FUNCS(_localtime64_s) +AC_CHECK_FUNCS(_stricmp) AC_CHECK_FUNCS(_strnicmp) AC_CHECK_FUNCS(_strtoui64) AC_CHECK_FUNCS(close) @@ -8,6 +11,8 @@ AC_CHECK_FUNCS(localtime_r) AC_CHECK_FUNCS(mkostemp) AC_CHECK_FUNCS(open) AC_CHECK_FUNCS(read) +AC_CHECK_FUNCS(strcasecmp) AC_CHECK_FUNCS(strncasecmp) AC_CHECK_FUNCS(strtoull) +AC_CHECK_FUNCS(unlink) AC_CHECK_FUNCS(write) diff --git a/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4 b/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4 index 513f61afac4..17de74c11a5 100644 --- a/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4 +++ b/storage/mroonga/vendor/groonga/build/ac_macros/check_headers.m4 @@ -1,9 +1,11 @@ # -*- autoconf -*- +AC_CHECK_HEADERS(dirent.h) AC_CHECK_HEADERS(dlfcn.h) AC_CHECK_HEADERS(errno.h) AC_CHECK_HEADERS(execinfo.h) AC_CHECK_HEADERS(inttypes.h) +AC_CHECK_HEADERS(io.h) AC_CHECK_HEADERS(netdb.h) AC_CHECK_HEADERS(netinet/in.h) AC_CHECK_HEADERS(netinet/tcp.h) diff --git a/storage/mroonga/vendor/groonga/config.h.cmake b/storage/mroonga/vendor/groonga/config.h.cmake index d172bc36dba..e6482f070c7 100644 --- a/storage/mroonga/vendor/groonga/config.h.cmake +++ b/storage/mroonga/vendor/groonga/config.h.cmake @@ -83,8 +83,7 @@ #cmakedefine GRN_WITH_BENCHMARK #cmakedefine GRN_WITH_CUTTER #cmakedefine GRN_WITH_KYTEA -#cmakedefine GRN_WITH_LIBMEMCACHED -#cmakedefine GRN_WITH_LZO +#cmakedefine GRN_WITH_LZ4 #cmakedefine GRN_WITH_MECAB #cmakedefine GRN_WITH_MESSAGE_PACK #cmakedefine GRN_WITH_MRUBY @@ -93,10 +92,12 @@ #cmakedefine GRN_WITH_ZLIB /* headers */ +#cmakedefine HAVE_DIRENT_H #cmakedefine HAVE_DLFCN_H #cmakedefine HAVE_ERRNO_H #cmakedefine HAVE_EXECINFO_H #cmakedefine HAVE_INTTYPES_H +#cmakedefine HAVE_IO_H #cmakedefine HAVE_LINUX_FUTEX_H #cmakedefine HAVE_MEMORY_H #cmakedefine HAVE_NETDB_H @@ -133,6 +134,9 @@ #cmakedefine HAVE_MECAB_DICTIONARY_INFO_T /* functions */ +#cmakedefine HAVE__GMTIME64_S +#cmakedefine HAVE__LOCALTIME64_S +#cmakedefine HAVE__STRICMP #cmakedefine HAVE__STRNICMP #cmakedefine HAVE__STRTOUI64 #cmakedefine HAVE_BACKTRACE @@ -145,8 +149,10 @@ #cmakedefine HAVE_MKOSTEMP #cmakedefine HAVE_OPEN #cmakedefine HAVE_READ +#cmakedefine HAVE_STRCASECMP #cmakedefine HAVE_STRNCASECMP #cmakedefine HAVE_STRTOULL +#cmakedefine HAVE_UNLINK #cmakedefine HAVE_WRITE #cmakedefine HAVE_PTHREAD_MUTEXATTR_SETPSHARED #cmakedefine HAVE_PTHREAD_CONDATTR_SETPSHARED diff --git a/storage/mroonga/vendor/groonga/config.sh.in b/storage/mroonga/vendor/groonga/config.sh.in index b4cec3caba1..d15e5e366e7 100644 --- a/storage/mroonga/vendor/groonga/config.sh.in +++ b/storage/mroonga/vendor/groonga/config.sh.in @@ -4,3 +4,4 @@ export GROONGA="@GROONGA@" export GROONGA_HTTPD="@GROONGA_HTTPD@" export GROONGA_SUGGEST_CREATE_DATASET="@GROONGA_SUGGEST_CREATE_DATASET@" export GROONGA_BENCHMARK="@GROONGA_BENCHMARK@" +export GROONGA_MRUBY="@GROONGA_MRUBY@" diff --git a/storage/mroonga/vendor/groonga/configure.ac b/storage/mroonga/vendor/groonga/configure.ac index 2be82a165e2..1d74bac30f4 100644 --- a/storage/mroonga/vendor/groonga/configure.ac +++ b/storage/mroonga/vendor/groonga/configure.ac @@ -75,7 +75,8 @@ AC_MSG_RESULT([$solaris]) AC_C_BIGENDIAN AC_PROG_CXX AC_PROG_CC -AC_PROG_CC_C99 +m4_ifdef([AC_PROG_CC_C99], + [AC_PROG_CC_C99]) AM_PROG_CC_C_O m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG([0.19]) @@ -160,7 +161,6 @@ if test "$GCC" = "yes"; then CHECK_BUILD_FLAG([-Wdisabled-optimization]) CHECK_BUILD_FLAG([-Wfloat-equal]) CHECK_BUILD_FLAG([-Wpointer-arith]) - CHECK_CFLAG([-Wdeclaration-after-statement]) CHECK_CFLAG([-Wbad-function-cast]) if test "$CLANG" = "no"; then CHECK_BUILD_FLAG([-Wcast-align]) @@ -235,6 +235,7 @@ AC_CONFIG_FILES([ plugins/query_expanders/Makefile plugins/ruby/Makefile plugins/token_filters/Makefile + plugins/sharding/Makefile examples/Makefile examples/dictionary/Makefile examples/dictionary/edict/Makefile @@ -246,7 +247,6 @@ AC_CONFIG_FILES([ packages/ubuntu/Makefile packages/rpm/Makefile packages/rpm/centos/Makefile - packages/rpm/fedora/Makefile packages/yum/Makefile packages/source/Makefile packages/windows/Makefile @@ -684,6 +684,10 @@ AC_SUBST(GROONGA_BENCHMARK) GROONGA_SUGGEST_CREATE_DATASET="${ac_pwd}/src/suggest/groonga-suggest-create-dataset" AC_SUBST(GROONGA_SUGGEST_CREATE_DATASET) +# groonga-mruby binary path +GROONGA_MRUBY="${ac_pwd}/src/groonga-mruby" +AC_SUBST(GROONGA_MRUBY) + # check Cutter with GLib support if available REQUIRED_MINIMUM_CUTTER_VERSION=1.1.6 REQUIRED_MINIMUM_CPPCUTTER_VERSION=1.2.0 @@ -867,28 +871,64 @@ fi # zlib AC_ARG_WITH(zlib, [AS_HELP_STRING([--with-zlib], - [use zlib for data compression. [default=no]])], + [Support data compression by zlib. [default=auto]])], [with_zlib="$withval"], - [with_zlib="no"]) + [with_zlib="auto"]) GRN_WITH_ZLIB=no -if test "x$with_zlib" = "xyes"; then - AC_DEFINE(GRN_WITH_ZLIB, [1], [with zlib]) - AC_SEARCH_LIBS(compress, z, [GRN_WITH_ZLIB=yes], - [AC_MSG_ERROR("No libz found")]) -else - AC_SEARCH_LIBS(compress, z, [GRN_WITH_ZLIB=yes], []) +if test "x$with_zlib" != "xno"; then + # TODO: Support custom zlib include and lib directory by --with-zlib. + AC_SEARCH_LIBS(compress, z, + [ + GRN_WITH_ZLIB=yes + AC_DEFINE(GRN_WITH_ZLIB, [1], + [Support data compression by zlib.]) + ], + [ + if test "x$with_zlib" != "xauto"; then + AC_MSG_ERROR("No libz found") + fi + ]) fi AC_SUBST(GRN_WITH_ZLIB) -# LZO -AC_ARG_WITH(lzo, - [AS_HELP_STRING([--with-lzo], - [use LZO for data compression. [default=no]])], - [with_lzo="$withval"], - [with_lzo="no"]) -if test "x$with_lzo" = "xyes"; then - AC_DEFINE(GRN_WITH_LZO, [1], [with lzo]) - AC_SEARCH_LIBS(lzo1_compress, lzo2, [], [AC_MSG_ERROR("No liblzo2 found")]) +# LZ4 +AC_ARG_WITH(lz4, + [AS_HELP_STRING([--with-lz4], + [Support data compression by LZ4. [default=auto]])], + [with_lz4="$withval"], + [with_lz4="auto"]) +if test "x$with_lz4" != "xno"; then + m4_ifdef([PKG_CHECK_MODULES], [ + PKG_CHECK_MODULES([LIBLZ4], + [liblz4], + [GRN_WITH_LZ4=yes], + [GRN_WITH_LZ4=no]) + ], + [GRN_WITH_LZ4=no]) + if test "$GRN_WITH_LZ4" = "yes"; then + AC_DEFINE(GRN_WITH_LZ4, [1], + [Support data compression by LZ4.]) + else + if test "x$with_lz4" != "xauto"; then + AC_MSG_ERROR("No liblz4 found") + fi + fi +fi + +# jemalloc +AC_ARG_WITH(jemalloc, + [AS_HELP_STRING([--with-jemalloc], + [Use jemalloc for memory allocation. [default=no]])], + [with_jemalloc="$withval"], + [with_jemalloc="no"]) +jemalloc_available="no" +if test "x$with_jemalloc" != "xno"; then + if test "x$with_jemalloc" != "xyes"; then + LDFLAGS="-L$with_jemalloc $LDFLAGS" + fi + AC_SEARCH_LIBS(malloc_conf, jemalloc, + [jemalloc_available="yes"], + [AC_MSG_ERROR("No libjemalloc found")]) fi # MeCab @@ -973,6 +1013,63 @@ if test "x$with_kytea" = "xyes"; then fi AM_CONDITIONAL(WITH_KYTEA, test "x$with_kytea" = "xyes") +# libstemmer +AC_ARG_WITH(libstemmer, + [AS_HELP_STRING([--with-libstemmer], + [use libstemmer for stemming. [default=auto]])], + [with_libstemmer="$withval"], + [with_libstemmer="auto"]) +AC_ARG_WITH(libstemmer-include, + [AS_HELP_STRING([--with-libstemmer-include], + [path to libstemmer.h. [default=auto]])]) +AC_ARG_WITH(libstemmer-lib, + [AS_HELP_STRING([--with-libstemmer-lib], + [path to libstemmer.so. [default=auto]])]) +AC_MSG_CHECKING([whether enable libstemmer]) +AC_MSG_RESULT($with_libstemmer) +if test "x$with_libstemmer" != "xno"; then + LIBSTEMMER_CFLAGS="" + LIBSTEMMER_LDFLAGS="" + LIBSTEMMER_LIBS="" + + CFLAGS_save="${CFLAGS}" + LDFLAGS_save="${LDFLAGS}" + if test "x$with_libstemmer" != "xauto"; then + if test -z "${with_libstemmer_include}"; then + with_libstemmer_include="${with_libstemmer}/include" + fi + LIBSTEMMER_CFLAGS="-I${with_libstemmer_include}" + if test -z "${with_libstemmer_lib}"; then + with_libstemmer_lib="${with_libstemmer}/lib" + fi + LIBSTEMMER_LDFLAGS="-L${with_libstemmer_lib}" + CFLAGS="${CFLAGS} ${LIBSTEMMER_CFLAGS}" + LDFLAGS="${LDFLAGS} ${LIBSTEMMER_LDFLAGS}" + fi + AC_CHECK_HEADERS(libstemmer.h, + [libstemmer_exists=yes], + [libstemmer_exists=no]) + if test "$libstemmer_exists" = "yes"; then + AC_CHECK_LIB(stemmer, sb_stemmer_list, + [LIBSTEMMER_LIBS="-lstemmer"], + [libstemmer_exists=no]) + fi + CFLAGS="${CFLAGS_save}" + LDFLAGS="${LDFLAGS_save}" + + if test "$libstemmer_exists" = "no" -a "x$with_libstemmer" != "xauto"; then + AC_MSG_ERROR("No libstemmer found at ${with_libstemmer_include} and ${with_libstemmer_lib}.") + fi + with_libstemmer="$libstemmer_exists" +fi +if test "x$with_libstemmer" = "xyes"; then + AC_SUBST(LIBSTEMMER_CFLAGS) + AC_SUBST(LIBSTEMMER_LDFLAGS) + AC_SUBST(LIBSTEMMER_LIBS) + AC_DEFINE(GRN_WITH_LIBSTEMMER, [1], [use libstemmer]) +fi +AM_CONDITIONAL(WITH_LIBSTEMMER, test "x$with_libstemmer" = "xyes") + # futex check AC_ARG_ENABLE(futex, [AS_HELP_STRING([--enable-futex], @@ -1136,15 +1233,15 @@ Install it and try again. How to install sphinx-build: For Debian GNU/Linux based system like Ubuntu: - % sudo apt-get install -y python-pip - % sudo pip install sphinx + % sudo apt-get install -y python-sphinx For Red Hat based system like CentOS: % sudo yum install -y python-pip % sudo pip install sphinx For OS X with Homebrew: - % brew install pip + % brew install python + % brew install gettext % export PATH="`brew --prefix gettext`/bin:\$PATH" % pip install sphinx]) fi @@ -1247,6 +1344,9 @@ AC_SUBST(ruby_pluginsdir) token_filter_pluginsdir="\${pluginsdir}/token_filters" AC_SUBST(token_filter_pluginsdir) +sharding_pluginsdir="\${pluginsdir}/sharding" +AC_SUBST(sharding_pluginsdir) + AC_MSG_CHECKING(for the suffix of plugin shared libraries) shrext_cmds=$(./libtool --config | grep '^shrext_cmds=') eval $shrext_cmds @@ -1361,15 +1461,10 @@ if test "$enable_mruby" = "yes"; then fi AC_DEFINE(GRN_WITH_MRUBY, [1], [Define to 1 if mruby is enabled.]) MRUBY_CFLAGS="-I\$(top_srcdir)/vendor/mruby-source/include" - MRUBY_LIBS="\$(top_builddir)/vendor/mruby/libmruby.la" - MRUBY_LIBS="${MRUBY_LIBS} \$(top_builddir)/vendor/onigmo-source/libonig.la" - AC_CONFIG_SUBDIRS([vendor/onigmo]) else - MRUBY_CFLAGS= - MRUBY_LIBS= + MRUBY_CFLAGS="" fi AC_SUBST(MRUBY_CFLAGS) -AC_SUBST(MRUBY_LIBS) AM_CONDITIONAL(WITH_MRUBY, test "$enable_mruby" = "yes") # This option is used in vendor/onigmo/configure @@ -1380,12 +1475,20 @@ AC_ARG_ENABLE(shared-onigmo, [enable_shared_onigmo="no"]) AM_CONDITIONAL(WITH_SHARED_ONIGMO, test "$enable_shared_onigmo" = "yes") +AC_DEFINE(GRN_WITH_ONIGMO, [1], [Use Onigmo.]) +AC_CONFIG_SUBDIRS([vendor/onigmo]) + +ONIGMO_CFLAGS="-I\$(top_srcdir)/vendor/onigmo-source" +ONIGMO_LIBS="\$(top_builddir)/vendor/onigmo-source/libonig.la" +AC_SUBST(ONIGMO_CFLAGS) +AC_SUBST(ONIGMO_LIBS) + # PCRE GRN_WITH_PCRE=no AC_ARG_WITH(pcre, [AS_HELP_STRING([--without-pcre], - [use PCRE for groonga-httpd. [default=auto-detect]])], - [with_pcre="$witheval"], + [Don't use PCRE for groonga-httpd. [default=auto-detect]])], + [with_pcre="$withval"], [with_pcre="auto"]) if test "x$with_pcre" != "xno"; then m4_ifdef([PKG_CHECK_MODULES], [ @@ -1446,7 +1549,6 @@ AC_SUBST(GROONGA_HTTPD_DEFAULT_DATABASE_PATH) AC_OUTPUT([ packages/rpm/centos/groonga.spec - packages/rpm/fedora/groonga.spec packages/apt/debian/groonga-keyring.postrm packages/apt/env.sh packages/yum/env.sh @@ -1489,6 +1591,14 @@ if test "x$with_kytea" = "xyes"; then fi echo +echo "Token filters:" +echo " libstemmer: $with_libstemmer" +if test "x$with_libstemmer" = "xyes"; then + echo " CFLAGS: $LIBSTEMMER_CFLAGS" + echo " LIBS: $LIBSTEMMER_LIBS" +fi +echo + echo "Libraries:" echo " ZeroMQ: $zeromq_available" if test "x$zeromq_available" = "xyes"; then @@ -1506,6 +1616,7 @@ if test "x$message_pack_available" = "xyes"; then echo " LIBS: ${MESSAGE_PACK_LIBS}" fi echo " mruby: $enable_mruby" +echo " jemalloc: $jemalloc_available" echo echo "groonga-httpd:" diff --git a/storage/mroonga/vendor/groonga/examples/Makefile.am b/storage/mroonga/vendor/groonga/examples/Makefile.am new file mode 100644 index 00000000000..f436342d053 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = dictionary diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am new file mode 100644 index 00000000000..ee618a213bd --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/Makefile.am @@ -0,0 +1,34 @@ +SUBDIRS = \ + edict \ + eijiro \ + gene95 \ + jmdict + +dist_examples_dictionary_SCRIPTS = \ + init-db.sh + +nobase_dist_examples_dictionary_DATA = \ + readme.txt \ + $(html_files) + +# find html -type f | sort | sed -e 's,^,\t,g' +html_files = \ + html/css/dictionary.css \ + html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png \ + html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png \ + html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png \ + html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png \ + html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png \ + html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png \ + html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png \ + html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png \ + html/css/smoothness/images/ui-icons_222222_256x240.png \ + html/css/smoothness/images/ui-icons_2e83ff_256x240.png \ + html/css/smoothness/images/ui-icons_454545_256x240.png \ + html/css/smoothness/images/ui-icons_888888_256x240.png \ + html/css/smoothness/images/ui-icons_cd0a0a_256x240.png \ + html/css/smoothness/jquery-ui-1.8.12.custom.css \ + html/index.html \ + html/js/dictionary.js \ + html/js/jquery-1.7.2.js \ + html/js/jquery-ui-1.8.18.custom.js diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am new file mode 100644 index 00000000000..376f9d520ab --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/edict/Makefile.am @@ -0,0 +1,4 @@ +edictdir = $(examples_dictionarydir)/edict +dist_edict_SCRIPTS = \ + edict2grn.rb \ + edict-import.sh diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh new file mode 100755 index 00000000000..b98397be05a --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict-import.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +base_dir=$(dirname $0) + +if [ 1 != $# -a 2 != $# ]; then + echo "usage: $0 db_path [edict.gz_path]" + exit 1 +fi + +if [ -z $2 ]; then + edict_gz=edict.gz + if [ ! -f $edict_gz ]; then + wget -O $edict_gz http://ftp.monash.edu.au/pub/nihongo/edict.gz + fi +else + edict_gz=$2 +fi + +if zcat $edict_gz | ${base_dir}/edict2grn.rb | groonga $1 > /dev/null; then + echo "edict data loaded." +fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb new file mode 100755 index 00000000000..664b12c2148 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/edict/edict2grn.rb @@ -0,0 +1,56 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +$KCODE = 'u' + +require 'English' +require 'kconv' + +class String + def to_json + a = split(//).map {|char| + case char + when '"' then '\\"' + when '\\' then '\\\\' + when "\b" then '\b' + when "\f" then '\f' + when "\n" then '\n' + when "\r" then '' + when "\t" then '\t' + else char + end + } + "\"#{a.join('')}\"" + end +end + +class Array + def to_json + '[' + map {|element| + element.to_json + }.join(',') + ']' + end +end + +puts <<END +column_create item_dictionary edict_desc COLUMN_SCALAR ShortText +column_create bigram item_dictionary_edict_desc COLUMN_INDEX|WITH_POSITION item_dictionary edict_desc +load --table item_dictionary +[["_key","edict_desc","kana"], +END + +while !STDIN.eof? + line = Kconv.toutf8(gets) + key, body = line.strip.split('/', 2) + key = key.strip + if /\s*\[(.+)\]\z/ =~ key + key = $PREMATCH + reading = $1 + body = "[#{reading}] #{body}" + kana = NKF.nkf("-Ww --katakana", reading) + else + kana = NKF.nkf("-Ww --katakana", key) + end + puts [key, body, kana].to_json +end +puts ']' diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am new file mode 100644 index 00000000000..4059a529cef --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/Makefile.am @@ -0,0 +1,4 @@ +eijirodir = $(examples_dictionarydir)/eijiro +dist_eijiro_SCRIPTS = \ + eijiro2grn.rb \ + eijiro-import.sh diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh new file mode 100755 index 00000000000..4042d7fbf56 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro-import.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +base_dir=$(dirname $0) + +if [ 2 != $# ]; then + echo "usage: $0 db_path eijiro.csv_path" + exit 1 +fi + +if iconv -f UCS2 -t UTF8 $2 | ${base_dir}/eijiro2grn.rb | groonga $1 > /dev/null; then + echo "eijiro data loaded." +fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb new file mode 100755 index 00000000000..62c1e1309bf --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/eijiro/eijiro2grn.rb @@ -0,0 +1,61 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +$KCODE = 'u' + +require 'rubygems' +require 'fastercsv' + +class String + def to_json + a = split(//).map {|char| + case char + when '"' then '\\"' + when '\\' then '\\\\' + when "\b" then '\b' + when "\f" then '\f' + when "\n" then '\n' + when "\r" then '' + when "\t" then '\t' + else char + end + } + "\"#{a.join('')}\"" + end +end + +class Array + def to_json + '[' + map {|element| + element.to_json + }.join(',') + ']' + end +end + +puts <<END +column_create item_dictionary eijiro_trans COLUMN_SCALAR ShortText +column_create item_dictionary eijiro_exp COLUMN_SCALAR ShortText +column_create item_dictionary eijiro_level COLUMN_SCALAR Int32 +column_create item_dictionary eijiro_memory COLUMN_SCALAR Int32 +column_create item_dictionary eijiro_modify COLUMN_SCALAR Int32 +column_create item_dictionary eijiro_pron COLUMN_SCALAR ShortText +column_create item_dictionary eijiro_filelink COLUMN_SCALAR ShortText +column_create bigram item_dictionary_eijiro_trans COLUMN_INDEX|WITH_POSITION item_dictionary eijiro_trans +load --table item_dictionary +[["_key","norm","eijiro_trans","eijiro_exp","eijiro_level","eijiro_memory","eijiro_modify","eijiro_pron","eijiro_filelink","kana"], +END + +n = 0 +FasterCSV.new(ARGF, :row_sep => "\r\n").each {|l| + if n > 0 + keyword,word,trans,exp,level,memory,modify,pron,filelink = l + kana = '' + if trans =~ /【@】(.*?)(【|$)/ + kana = $1.split("、") + end + puts [word,keyword,trans,exp,level,memory,modify,pron,filelink,kana].map{|e| e || ''}.to_json + end + n += 1 +} + +puts "]" diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am new file mode 100644 index 00000000000..e89f13f595c --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/Makefile.am @@ -0,0 +1,4 @@ +gene95dir = $(examples_dictionarydir)/gene95 +dist_gene95_SCRIPTS = \ + gene2grn.rb \ + gene-import.sh diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh new file mode 100755 index 00000000000..488d6c83adc --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene-import.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +base_dir=$(dirname $0) + +if [ 1 != $# -a 2 != $# ]; then + echo "usage: $0 db_path [gene.txt_path]" + exit 1 +fi + +if [ -z $2 ]; then + dictionary_dir=gene95-dictionary + gene_txt=${dictionary_dir}/gene.txt + if [ ! -f $gene_txt ]; then + gene95_tar_gz=gene95.tar.gz + wget -O $gene95_tar_gz \ + http://www.namazu.org/~tsuchiya/sdic/data/gene95.tar.gz + mkdir -p ${dictionary_dir} + tar xvzf ${gene95_tar_gz} -C ${dictionary_dir} + fi +else + gene_txt=$2 +fi + +if cat $gene_txt | ${base_dir}/gene2grn.rb | groonga $1 > /dev/null; then + echo "gene95 data loaded." +fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb new file mode 100755 index 00000000000..0d10cfd1085 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/gene95/gene2grn.rb @@ -0,0 +1,46 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +$KCODE = 'u' + +require 'kconv' + +class String + def to_json + a = split(//).map {|char| + case char + when '"' then '\\"' + when '\\' then '\\\\' + when "\b" then '\b' + when "\f" then '\f' + when "\n" then '\n' + when "\r" then '' + when "\t" then '\t' + else char + end + } + "\"#{a.join('')}\"" + end +end + +class Array + def to_json + '[' + map {|element| + element.to_json + }.join(',') + ']' + end +end + +puts <<END +column_create item_dictionary gene95_desc COLUMN_SCALAR ShortText +column_create bigram item_dictionary_gene95_desc COLUMN_INDEX|WITH_POSITION item_dictionary gene95_desc +load --table item_dictionary +[["_key","gene95_desc"], +END + +while !STDIN.eof? + key = Kconv.toutf8(gets.strip) + body = Kconv.toutf8(gets.strip) + puts [key, body].to_json +end +puts ']' diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css new file mode 100644 index 00000000000..72b5a6749b3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/dictionary.css @@ -0,0 +1,3 @@ +#result { + margin-top: 7em; +} diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png Binary files differnew file mode 100644 index 00000000000..5b5dab2ab7b --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png Binary files differnew file mode 100644 index 00000000000..ac8b229af95 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png Binary files differnew file mode 100644 index 00000000000..ad3d6346e00 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png Binary files differnew file mode 100644 index 00000000000..42ccba269b6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png Binary files differnew file mode 100644 index 00000000000..5a46b47cb16 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png Binary files differnew file mode 100644 index 00000000000..86c2baa655e --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png Binary files differnew file mode 100644 index 00000000000..4443fdc1a15 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png Binary files differnew file mode 100644 index 00000000000..7c9fa6c6edc --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png Binary files differnew file mode 100644 index 00000000000..b273ff111d2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_222222_256x240.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png Binary files differnew file mode 100644 index 00000000000..09d1cdc856c --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_2e83ff_256x240.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png Binary files differnew file mode 100644 index 00000000000..59bd45b907c --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_454545_256x240.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png Binary files differnew file mode 100644 index 00000000000..6d02426c114 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_888888_256x240.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png Binary files differnew file mode 100644 index 00000000000..2ab019b73ec --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/images/ui-icons_cd0a0a_256x240.png diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css new file mode 100644 index 00000000000..c85aabaec06 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css @@ -0,0 +1,578 @@ +/* + * jQuery UI CSS Framework 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* + * jQuery UI Resizable 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; + /* http://bugs.jqueryui.com/ticket/7233 + - Resizable: resizable handles fail to work in IE if transparent and content overlaps + */ + background-image:url(data:); +} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* + * jQuery UI Selectable 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * jQuery UI Accordion 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/* + * jQuery UI Autocomplete 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.12 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * jQuery UI Button 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ +.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ +.ui-button .ui-button-text { display: block; line-height: 1.4; } +.ui-button-text-only .ui-button-text { padding: .4em 1em; } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +input.ui-button { padding: .4em 1em; } + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/* + * jQuery UI Dialog 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * jQuery UI Slider 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* + * jQuery UI Tabs 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * jQuery UI Datepicker 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +}/* + * jQuery UI Progressbar 1.8.12 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html b/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html new file mode 100644 index 00000000000..aaad128a290 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/index.html @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> +<head> +<meta http-equiv="Content-Language" content="ja" /> +<meta http-equiv="content-type" content="text/html; charset=utf-8" /> +<title>groonga dictionary search</title> +<meta http-equiv="content-style-type" content="text/css" /> +<meta http-equiv="content-script-type" content="text/javascript" /> +<link type="text/css" href="css/smoothness/jquery-ui-1.8.12.custom.css" rel="stylesheet" /> +<link type="text/css" rel="stylesheet" href="css/dictionary.css" /> +</head> +<body> +<form action="javascript:(function(){$('.search').blur()})()" name="search" id="search"> +<input type="text" size="60" maxlength="60" name="key" class="search" /> +<input type="submit" value="検索"/> +</form> +<script type="text/javascript" src="js/jquery-1.7.2.js"></script> +<script type="text/javascript" src="js/jquery-ui-1.8.18.custom.min.js"></script> +<script type="text/javascript" src="js/dictionary.js"></script> +<script type="text/javascript"> +$(document).ready(function(){ + $(".search").autocomplete({source: dictionarySource("http://" + location.host + "/d/suggest")}); +}); +</script> +<div id="result"></div> +</body> +</html> diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js new file mode 100644 index 00000000000..850c64cc667 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/dictionary.js @@ -0,0 +1,82 @@ +function dictionarySource(url) { + function displayItems(items) { + var results = $("<dl />"); + $.each(items, + function(i, val) { + results.append($("<dt />") + .append($("<span />") + .text(val[0]) + .click(function() { + $(".search").val($(this).text()); + $("#search").submit(); + }))); + results.append($("<dd />") + .append($("<span />").text(val[1])) + .append($("<span />").text(val[2])) + ); + }); + $("#result") + .empty() + .append(results); + }; + + var request_index = 0; + var columns = "_key,gene95_desc,edict_desc"; + var xhr; + function source(request, response) { + function onSuccess(data, status) { + if (this.autocomplete_request != request_index) { + return; + } + var completions = data[1]["complete"]; + var items = []; + if (completions && completions.length > 2) { + completions.shift(); + completions.shift(); + $.each(completions, + function(i, item) { + var key = item[0]; + items.push(key); + if (items.length >= 3) { + return false; + } + return true; + }); + } + if (completions.length > 0) { + displayItems(completions); + } + response(items); + } + + function onError() { + if (this.autocomplete_request != request_index) { + return; + } + response([]); + } + + if (xhr) { + xhr.abort(); + } + xhr = $.ajax(url, + { + data: { + query: request.term, + types: 'complete', + table: 'item_dictionary', + column: 'kana', + limit: 25, + output_columns: columns, + frequency_threshold: 1, + prefix_search: "yes" + }, + dataType: "jsonp", + autocomplete_request: ++request_index, + success: onSuccess, + error: onError + }); + }; + + return source; +} diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js new file mode 100644 index 00000000000..3774ff98613 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-1.7.2.js @@ -0,0 +1,9404 @@ +/*! + * jQuery JavaScript Library v1.7.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Wed Mar 21 12:46:34 2012 -0700 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) + quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z]|[0-9])/ig, + rmsPrefix = /^-ms-/, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context ? context.ownerDocument || context : document ); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.7.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.add( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.fireWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).off( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery.Callbacks( "once memory" ); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + var xml, tmp; + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array, i ) { + var len; + + if ( array ) { + if ( indexOf ) { + return indexOf.call( array, elem, i ); + } + + len = array.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in array && array[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, pass ) { + var exec, + bulk = key == null, + i = 0, + length = elems.length; + + // Sets many values + if ( key && typeof key === "object" ) { + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); + } + chainable = 1; + + // Sets one value + } else if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = pass === undefined && jQuery.isFunction( value ); + + if ( bulk ) { + // Bulk operations only iterate when executing function values + if ( exec ) { + exec = fn; + fn = function( elem, key, value ) { + return exec.call( jQuery( elem ), value ); + }; + + // Otherwise they run against the entire set + } else { + fn.call( elems, value ); + fn = null; + } + } + + if ( fn ) { + for (; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + } + + chainable = 1; + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +// String to Object flags format cache +var flagsCache = {}; + +// Convert String-formatted flags into Object-formatted ones and store in cache +function createFlags( flags ) { + var object = flagsCache[ flags ] = {}, + i, length; + flags = flags.split( /\s+/ ); + for ( i = 0, length = flags.length; i < length; i++ ) { + object[ flags[i] ] = true; + } + return object; +} + +/* + * Create a callback list using the following parameters: + * + * flags: an optional list of space-separated flags that will change how + * the callback list behaves + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible flags: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( flags ) { + + // Convert flags from String-formatted to Object-formatted + // (we check in cache first) + flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; + + var // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = [], + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Add one or several callbacks to the list + add = function( args ) { + var i, + length, + elem, + type, + actual; + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + // Inspect recursively + add( elem ); + } else if ( type === "function" ) { + // Add if not in unique mode and callback is not in + if ( !flags.unique || !self.has( elem ) ) { + list.push( elem ); + } + } + } + }, + // Fire callbacks + fire = function( context, args ) { + args = args || []; + memory = !flags.memory || [ context, args ]; + fired = true; + firing = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { + memory = true; // Mark as halted + break; + } + } + firing = false; + if ( list ) { + if ( !flags.once ) { + if ( stack && stack.length ) { + memory = stack.shift(); + self.fireWith( memory[ 0 ], memory[ 1 ] ); + } + } else if ( memory === true ) { + self.disable(); + } else { + list = []; + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + var length = list.length; + add( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away, unless previous + // firing was halted (stopOnFalse) + } else if ( memory && memory !== true ) { + firingStart = length; + fire( memory[ 0 ], memory[ 1 ] ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + var args = arguments, + argIndex = 0, + argLength = args.length; + for ( ; argIndex < argLength ; argIndex++ ) { + for ( var i = 0; i < list.length; i++ ) { + if ( args[ argIndex ] === list[ i ] ) { + // Handle firingIndex and firingLength + if ( firing ) { + if ( i <= firingLength ) { + firingLength--; + if ( i <= firingIndex ) { + firingIndex--; + } + } + } + // Remove the element + list.splice( i--, 1 ); + // If we have some unicity property then + // we only need to do this once + if ( flags.unique ) { + break; + } + } + } + } + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + if ( list ) { + var i = 0, + length = list.length; + for ( ; i < length; i++ ) { + if ( fn === list[ i ] ) { + return true; + } + } + } + return false; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory || memory === true ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( stack ) { + if ( firing ) { + if ( !flags.once ) { + stack.push( [ context, args ] ); + } + } else if ( !( flags.once && memory ) ) { + fire( context, args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + + + +var // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + + Deferred: function( func ) { + var doneList = jQuery.Callbacks( "once memory" ), + failList = jQuery.Callbacks( "once memory" ), + progressList = jQuery.Callbacks( "memory" ), + state = "pending", + lists = { + resolve: doneList, + reject: failList, + notify: progressList + }, + promise = { + done: doneList.add, + fail: failList.add, + progress: progressList.add, + + state: function() { + return state; + }, + + // Deprecated + isResolved: doneList.fired, + isRejected: failList.fired, + + then: function( doneCallbacks, failCallbacks, progressCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); + return this; + }, + always: function() { + deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); + return this; + }, + pipe: function( fnDone, fnFail, fnProgress ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ], + progress: [ fnProgress, "notify" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + obj = promise; + } else { + for ( var key in promise ) { + obj[ key ] = promise[ key ]; + } + } + return obj; + } + }, + deferred = promise.promise({}), + key; + + for ( key in lists ) { + deferred[ key ] = lists[ key ].fire; + deferred[ key + "With" ] = lists[ key ].fireWith; + } + + // Handle state + deferred.done( function() { + state = "resolved"; + }, failList.disable, progressList.lock ).fail( function() { + state = "rejected"; + }, doneList.disable, progressList.lock ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = sliceDeferred.call( arguments, 0 ), + i = 0, + length = args.length, + pValues = new Array( length ), + count = length, + pCount = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(), + promise = deferred.promise(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( deferred, args ); + } + }; + } + function progressFunc( i ) { + return function( value ) { + pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + deferred.notifyWith( promise, pValues ); + }; + } + if ( length > 1 ) { + for ( ; i < length; i++ ) { + if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return promise; + } +}); + + + + +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + fragment, + tds, + events, + eventName, + i, + isSupported, + div = document.createElement( "div" ), + documentElement = document.documentElement; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form(#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + pixelMargin: true + }; + + // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead + jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat"); + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for ( i in { + submit: 1, + change: 1, + focusin: 1 + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + fragment.removeChild( div ); + + // Null elements to avoid leaks in IE + fragment = select = opt = div = input = null; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, outer, inner, table, td, offsetSupport, + marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight, + paddingMarginBorderVisibility, paddingMarginBorder, + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + conMarginTop = 1; + paddingMarginBorder = "padding:0;margin:0;border:"; + positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;"; + paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;"; + style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;"; + html = "<div " + style + "display:block;'><div style='" + paddingMarginBorder + "0;display:block;overflow:hidden;'></div></div>" + + "<table " + style + "' cellpadding='0' cellspacing='0'>" + + "<tr><td></td></tr></table>"; + + container = document.createElement("div"); + container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "<table><tr><td style='" + paddingMarginBorder + "0;display:none'></td><td>t</td></tr></table>"; + tds = div.getElementsByTagName( "td" ); + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( window.getComputedStyle ) { + div.innerHTML = ""; + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.style.width = "2px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.innerHTML = ""; + div.style.width = div.style.padding = "1px"; + div.style.border = 0; + div.style.overflow = "hidden"; + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = "block"; + div.style.overflow = "visible"; + div.innerHTML = "<div style='width:5px;'></div>"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + } + + div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility; + div.innerHTML = html; + + outer = div.firstChild; + inner = outer.firstChild; + td = outer.nextSibling.firstChild.firstChild; + + offsetSupport = { + doesNotAddBorder: ( inner.offsetTop !== 5 ), + doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) + }; + + inner.style.position = "fixed"; + inner.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); + inner.style.position = inner.style.top = ""; + + outer.style.overflow = "hidden"; + outer.style.position = "relative"; + + offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); + offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); + + if ( window.getComputedStyle ) { + div.style.marginTop = "1%"; + support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%"; + } + + if ( typeof container.style.zoom !== "undefined" ) { + container.style.zoom = 1; + } + + body.removeChild( container ); + marginDiv = div = container = null; + + jQuery.extend( support, offsetSupport ); + }); + + return support; +})(); + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var privateCache, thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, + isEvents = name === "events"; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = ++jQuery.uuid; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + privateCache = thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Users should not attempt to inspect the internal events object using jQuery.data, + // it is undocumented and subject to change. But does anyone listen? No. + if ( isEvents && !thisCache[ name ] ) { + return privateCache.events; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + // Reference to internal data cache key + internalKey = jQuery.expando, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ internalKey ] : internalKey; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split( " " ); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + // Ensure that `cache` is not a window object #10080 + if ( jQuery.support.deleteExpando || !cache.setInterval ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the cache and need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ internalKey ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + } else { + elem[ internalKey ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, part, attr, name, l, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attr = elem.attributes; + for ( l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split( ".", 2 ); + parts[1] = parts[1] ? "." + parts[1] : ""; + part = parts[1] + "!"; + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + data = this.triggerHandler( "getData" + part, [ parts[0] ] ); + + // Try to fetch any internally stored data first + if ( data === undefined && elem ) { + data = jQuery.data( elem, key ); + data = dataAttr( elem, key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } + + parts[1] = value; + this.each(function() { + var self = jQuery( this ); + + self.triggerHandler( "setData" + part, parts ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + part, parts ); + }); + }, null, value, arguments.length > 1, null, false ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + jQuery.isNumeric( data ) ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery._data( elem, deferDataKey ); + if ( defer && + ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && + ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery._data( elem, queueDataKey ) && + !jQuery._data( elem, markDataKey ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.fire(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = ( type || "fx" ) + "mark"; + jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); + if ( count ) { + jQuery._data( elem, key, count ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + var q; + if ( elem ) { + type = ( type || "fx" ) + "queue"; + q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + hooks = {}; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + jQuery._data( elem, type + ".run", hooks ); + fn.call( elem, function() { + jQuery.dequeue( elem, type ); + }, hooks ); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue " + type + ".run", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { + count++; + tmp.add( resolve ); + } + } + resolve(); + return defer.promise( object ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + nodeHook, boolHook, fixSpecified; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = ( value || "" ).split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, i, max, option, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + i = one ? index : 0; + max = one ? index + 1 : options.length; + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, l, isBool, + i = 0; + + if ( value && elem.nodeType === 1 ) { + attrNames = value.toLowerCase().split( rspace ); + l = attrNames.length; + + for ( ; i < l; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + isBool = rboolean.test( name ); + + // See #9699 for explanation of this approach (setting first, then removal) + // Do not do this for boolean attributes (see #10870) + if ( !isBool ) { + jQuery.attr( elem, name, "" ); + } + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( isBool && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true, + coords: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.nodeValue = value + "" ); + } + }; + + // Apply the nodeHook to tabindex + jQuery.attrHooks.tabindex.set = nodeHook.set; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = "" + value ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); + + + + +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, + rhoverHack = /(?:^|\s)hover(\.\S+)?\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, + quickParse = function( selector ) { + var quick = rquickIs.exec( selector ); + if ( quick ) { + // 0 1 2 3 + // [ _, tag, id, class ] + quick[1] = ( quick[1] || "" ).toLowerCase(); + quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); + } + return quick; + }, + quickIs = function( elem, m ) { + var attrs = elem.attributes || {}; + return ( + (!m[1] || elem.nodeName.toLowerCase() === m[1]) && + (!m[2] || (attrs.id || {}).value === m[2]) && + (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) + ); + }, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, quick, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + quick: selector && quickParse( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + t, tns, type, origType, namespaces, origCount, + j, events, special, handle, eventType, handleObj; + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, [ "events", "handle" ], true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var type = event.type || event, + namespaces = [], + cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + old = null; + for ( ; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old && old === elem.ownerDocument ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = [].slice.call( arguments, 0 ), + run_all = !event.exclusive && !event.namespace, + special = jQuery.event.special[ event.type ] || {}, + handlerQueue = [], + i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers that should run if there are delegated events + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !(event.button && event.type === "click") ) { + + // Pregenerate a single jQuery object for reuse with .is() + jqcur = jQuery(this); + jqcur.context = this.ownerDocument || this; + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + + // Don't process events on disabled elements (#6911, #8165) + if ( cur.disabled !== true ) { + selMatch = {}; + matches = []; + jqcur[0] = cur; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = ( + handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) + ); + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) + if ( event.metaKey === undefined ) { + event.metaKey = event.ctrlKey; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady + }, + + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector, + ret; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !form._submit_attached ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + form._submit_attached = true; + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + jQuery.event.simulate( "change", this, event, true ); + } + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + elem._change_attached = true; + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { // && selector != null + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + var handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( var type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + expando = "sizcache" + (Math.random() + '').replace('.', ''), + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rReturn = /\r\n/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context, seed ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set, seed ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set, i, len, match, type, left; + + if ( !expr ) { + return []; + } + + for ( i = 0, len = Expr.order.length; i < len; i++ ) { + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + type, found, item, filter, left, + i, pass, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + filter = Expr.filter[ type ]; + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + pass = not ^ found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Utility function for retreiving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +var getText = Sizzle.getText = function( elem ) { + var i, node, + nodeType = elem.nodeType, + ret = ""; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent || innerText for elements + if ( typeof elem.textContent === 'string' ) { + return elem.textContent; + } else if ( typeof elem.innerText === 'string' ) { + // Replace IE's carriage returns + return elem.innerText.replace( rReturn, '' ); + } else { + // Traverse it's children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + } else { + + // If no nodeType, this is expected to be an array + for ( i = 0; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + if ( node.nodeType !== 8 ) { + ret += getText( node ); + } + } + } + return ret; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var first, last, + doneName, parent, cache, + count, diff, + type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + first = match[2]; + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + doneName = match[0]; + parent = elem.parentNode; + + if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { + count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent[ expando ] = doneName; + } + + diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Sizzle.attr ? + Sizzle.attr( elem, name ) : + Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + !type && Sizzle.attr ? + result != null : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} +// Expose origPOS +// "global" as in regardless of relation to brackets/parens +Expr.match.globalPOS = origPOS; + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem[ expando ] === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem[ expando ] = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context, seed ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet, seed ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +Sizzle.selectors.attrMap = {}; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.globalPOS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + POS.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array (deprecated as of jQuery 1.7) + if ( jQuery.isArray( selectors ) ) { + var level = 1; + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( i = 0; i < selectors.length; i++ ) { + + if ( jQuery( cur ).is( selectors[ i ] ) ) { + ret.push({ selector: selectors[ i ], elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} + + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /<tbody/i, + rhtml = /<|&#?\w+;/, + rnoInnerhtml = /<(?:script|style)/i, + rnocache = /<(?:script|object|embed|option|style)/i, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /\/(java|ecma)script/i, + rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/, + wrapMap = { + option: [ 1, "<select multiple='multiple'>", "</select>" ], + legend: [ 1, "<fieldset>", "</fieldset>" ], + thead: [ 1, "<table>", "</table>" ], + tr: [ 2, "<table><tbody>", "</tbody></table>" ], + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], + area: [ 1, "<map>", "</map>" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize <link> and <script> tags normally +if ( !jQuery.support.htmlSerialize ) { + wrapMap._default = [ 1, "div<div>", "</div>" ]; +} + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery.clean( arguments ); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }, + + after: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery.clean(arguments) ); + return set; + } + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + null; + } + + + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1></$2>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName( "*" ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function( value ) { + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery( value ).detach(); + } + + return this.each(function() { + var next = this.nextSibling, + parent = this.parentNode; + + jQuery( this ).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.length ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; + } + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + var results, first, fragment, parent, + value = args[0], + scripts = []; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + // Make sure that we do not leak memory by inadvertently discarding + // the original fragment (which might have attached data) instead of + // using it; in addition, use the original fragment object for the last + // item instead of first because it can end up being emptied incorrectly + // in certain situations (Bug #8070). + // Fragments from the fragment cache must always be cloned and never used + // in place. + results.cacheable || ( l > 1 && i < lastIndex ) ? + jQuery.clone( fragment, true, true ) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, function( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + type: "GET", + global: false, + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + }); + } + } + + return this; + } +}); + +function root( elem, cur ) { + return jQuery.nodeName(elem, "table") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function cloneFixAttributes( src, dest ) { + var nodeName; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + // clearAttributes removes the attributes, which we don't want, + // but also removes the attachEvent events, which we *do* want + if ( dest.clearAttributes ) { + dest.clearAttributes(); + } + + // mergeAttributes, in contrast, only merges back on the + // original attributes, not the events + if ( dest.mergeAttributes ) { + dest.mergeAttributes( src ); + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 fail to clone children inside object elements that use + // the proprietary classid attribute value (rather than the type + // attribute) to identify the type of content to display + if ( nodeName === "object" ) { + dest.outerHTML = src.outerHTML; + + } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + if ( src.checked ) { + dest.defaultChecked = dest.checked = src.checked; + } + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + + // IE blanks contents when cloning scripts + } else if ( nodeName === "script" && dest.text !== src.text ) { + dest.text = src.text; + } + + // Event data gets referenced instead of copied if the expando + // gets copied too + dest.removeAttribute( jQuery.expando ); + + // Clear flags for bubbling special change/submit events, they must + // be reattached when the newly cloned events are first activated + dest.removeAttribute( "_submit_attached" ); + dest.removeAttribute( "_change_attached" ); +} + +jQuery.buildFragment = function( args, nodes, scripts ) { + var fragment, cacheable, cacheresults, doc, + first = args[ 0 ]; + + // nodes may contain either an explicit document object, + // a jQuery collection or context object. + // If nodes[0] contains a valid object to assign to doc + if ( nodes && nodes[0] ) { + doc = nodes[0].ownerDocument || nodes[0]; + } + + // Ensure that an attr object doesn't incorrectly stand in as a document object + // Chrome and Firefox seem to allow this to occur and will throw exception + // Fixes #8950 + if ( !doc.createDocumentFragment ) { + doc = document; + } + + // Only cache "small" (1/2 KB) HTML strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 + if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document && + first.charAt(0) === "<" && !rnocache.test( first ) && + (jQuery.support.checkClone || !rchecked.test( first )) && + (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { + + cacheable = true; + + cacheresults = jQuery.fragments[ first ]; + if ( cacheresults && cacheresults !== 1 ) { + fragment = cacheresults; + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ first ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; + +jQuery.fragments = {}; + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var ret = [], + insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +}); + +function getAll( elem ) { + if ( typeof elem.getElementsByTagName !== "undefined" ) { + return elem.getElementsByTagName( "*" ); + + } else if ( typeof elem.querySelectorAll !== "undefined" ) { + return elem.querySelectorAll( "*" ); + + } else { + return []; + } +} + +// Used in clean, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( elem.type === "checkbox" || elem.type === "radio" ) { + elem.defaultChecked = elem.checked; + } +} +// Finds all inputs and passes them to fixDefaultChecked +function findInputs( elem ) { + var nodeName = ( elem.nodeName || "" ).toLowerCase(); + if ( nodeName === "input" ) { + fixDefaultChecked( elem ); + // Skip scripts, get other children + } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) { + jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); + } +} + +// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js +function shimCloneNode( elem ) { + var div = document.createElement( "div" ); + safeFragment.appendChild( div ); + + div.innerHTML = elem.outerHTML; + return div.firstChild; +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var srcElements, + destElements, + i, + // IE<=8 does not properly clone detached, unknown element nodes + clone = jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ? + elem.cloneNode( true ) : + shimCloneNode( elem ); + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + // IE copies events bound via attachEvent when using cloneNode. + // Calling detachEvent on the clone will also remove the events + // from the original. In order to get around this, we use some + // proprietary methods to clear the events. Thanks to MooTools + // guys for this hotness. + + cloneFixAttributes( elem, clone ); + + // Using Sizzle here is crazy slow, so we use getElementsByTagName instead + srcElements = getAll( elem ); + destElements = getAll( clone ); + + // Weird iteration because IE will replace the length property + // with an element if you are cloning the body and one of the + // elements on the page has a name or id of "length" + for ( i = 0; srcElements[i]; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + cloneFixAttributes( srcElements[i], destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + cloneCopyEvent( elem, clone ); + + if ( deepDataAndEvents ) { + srcElements = getAll( elem ); + destElements = getAll( clone ); + + for ( i = 0; srcElements[i]; ++i ) { + cloneCopyEvent( srcElements[i], destElements[i] ); + } + } + } + + srcElements = destElements = null; + + // Return the cloned set + return clone; + }, + + clean: function( elems, context, fragment, scripts ) { + var checkScriptType, script, j, + ret = []; + + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + if ( !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + } else { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1></$2>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"), + safeChildNodes = safeFragment.childNodes, + remove; + + // Append wrapper element to unknown element safe doc fragment + if ( context === document ) { + // Use the fragment we've already created for this document + safeFragment.appendChild( div ); + } else { + // Use a fragment created with the owner document + createSafeFragment( context ).appendChild( div ); + } + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted <tbody> from table fragments + if ( !jQuery.support.tbody ) { + + // String was a <table>, *may* have spurious <tbody> + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !hasBody ? + div.childNodes : + []; + + for ( j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + + // Clear elements from DocumentFragment (safeFragment or otherwise) + // to avoid hoarding elements. Fixes #11356 + if ( div ) { + div.parentNode.removeChild( div ); + + // Guard against -1 index exceptions in FF3.6 + if ( safeChildNodes.length > 0 ) { + remove = safeChildNodes[ safeChildNodes.length - 1 ]; + + if ( remove && remove.parentNode ) { + remove.parentNode.removeChild( remove ); + } + } + } + } + } + + // Resets defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + var len; + if ( !jQuery.support.appendChecked ) { + if ( elem[0] && typeof (len = elem.length) === "number" ) { + for ( j = 0; j < len; j++ ) { + findInputs( elem[j] ); + } + } else { + findInputs( elem ); + } + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + checkScriptType = function( elem ) { + return !elem.type || rscriptType.test( elem.type ); + }; + for ( i = 0; ret[i]; i++ ) { + script = ret[i]; + if ( scripts && jQuery.nodeName( script, "script" ) && (!script.type || rscriptType.test( script.type )) ) { + scripts.push( script.parentNode ? script.parentNode.removeChild( script ) : script ); + + } else { + if ( script.nodeType === 1 ) { + var jsTags = jQuery.grep( script.getElementsByTagName( "script" ), checkScriptType ); + + ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); + } + fragment.appendChild( script ); + } + } + } + + return ret; + }, + + cleanData: function( elems ) { + var data, id, + cache = jQuery.cache, + special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + + // Null the DOM reference to avoid IE6/7/8 leak (#7054) + if ( data.handle ) { + data.handle.elem = null; + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + } +}); + + + + +var ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity=([^)]*)/, + // fixed for IE9, see #8346 + rupper = /([A-Z]|^ms)/g, + rnum = /^[\-+]?(?:\d*\.)?\d+$/i, + rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i, + rrelNum = /^([\-+])=([\-+.\de]+)/, + rmargin = /^margin/, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + + // order is important! + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + + curCSS, + + getComputedStyle, + currentStyle; + +jQuery.fn.css = function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); +}; + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + + } else { + return elem.style.opacity; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra ) { + var ret, hooks; + + // Make sure that we're working with the right name + name = jQuery.camelCase( name ); + hooks = jQuery.cssHooks[ name ]; + name = jQuery.cssProps[ name ] || name; + + // cssFloat needs a special treatment + if ( name === "cssFloat" ) { + name = "float"; + } + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name ); + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}, + ret, name; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +// DEPRECATED in 1.3, Use jQuery.css() instead +jQuery.curCSS = jQuery.css; + +if ( document.defaultView && document.defaultView.getComputedStyle ) { + getComputedStyle = function( elem, name ) { + var ret, defaultView, computedStyle, width, + style = elem.style; + + name = name.replace( rupper, "-$1" ).toLowerCase(); + + if ( (defaultView = elem.ownerDocument.defaultView) && + (computedStyle = defaultView.getComputedStyle( elem, null )) ) { + + ret = computedStyle.getPropertyValue( name ); + if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { + ret = jQuery.style( elem, name ); + } + } + + // A tribute to the "awesome hack by Dean Edwards" + // WebKit uses "computed value (percentage if specified)" instead of "used value" for margins + // which is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( !jQuery.support.pixelMargin && computedStyle && rmargin.test( name ) && rnumnonpx.test( ret ) ) { + width = style.width; + style.width = ret; + ret = computedStyle.width; + style.width = width; + } + + return ret; + }; +} + +if ( document.documentElement.currentStyle ) { + currentStyle = function( elem, name ) { + var left, rsLeft, uncomputed, + ret = elem.currentStyle && elem.currentStyle[ name ], + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && (uncomputed = style[ name ]) ) { + ret = uncomputed; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( rnumnonpx.test( ret ) ) { + + // Remember the original values + left = style.left; + rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + elem.runtimeStyle.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + elem.runtimeStyle.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +curCSS = getComputedStyle || currentStyle; + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property + var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + i = name === "width" ? 1 : 0, + len = 4; + + if ( val > 0 ) { + if ( extra !== "border" ) { + for ( ; i < len; i += 2 ) { + if ( !extra ) { + val -= parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0; + } + if ( extra === "margin" ) { + val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ] ) ) || 0; + } else { + val -= parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + } + } + } + + return val + "px"; + } + + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + + // Add padding, border, margin + if ( extra ) { + for ( ; i < len; i += 2 ) { + val += parseFloat( jQuery.css( elem, "padding" + cssExpand[ i ] ) ) || 0; + if ( extra !== "padding" ) { + val += parseFloat( jQuery.css( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + } + if ( extra === "margin" ) { + val += parseFloat( jQuery.css( elem, extra + cssExpand[ i ]) ) || 0; + } + } + } + + return val + "px"; +} + +jQuery.each([ "height", "width" ], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + if ( elem.offsetWidth !== 0 ) { + return getWidthOrHeight( elem, name, extra ); + } else { + return jQuery.swap( elem, cssShow, function() { + return getWidthOrHeight( elem, name, extra ); + }); + } + } + }, + + set: function( elem, value ) { + return rnum.test( value ) ? + value + "px" : + value; + } + }; +}); + +if ( !jQuery.support.opacity ) { + jQuery.cssHooks.opacity = { + get: function( elem, computed ) { + // IE uses filters for opacity + return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? + ( parseFloat( RegExp.$1 ) / 100 ) + "" : + computed ? "1" : ""; + }, + + set: function( elem, value ) { + var style = elem.style, + currentStyle = elem.currentStyle, + opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", + filter = currentStyle && currentStyle.filter || style.filter || ""; + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + style.zoom = 1; + + // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 + if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) { + + // Setting style.filter to null, "" & " " still leave "filter:" in the cssText + // if "filter:" is present at all, clearType is disabled, we want to avoid this + // style.removeAttribute is IE Only, but so apparently is this code path... + style.removeAttribute( "filter" ); + + // if there there is no filter style applied in a css rule, we are done + if ( currentStyle && !currentStyle.filter ) { + return; + } + } + + // otherwise, set new filter values + style.filter = ralpha.test( filter ) ? + filter.replace( ralpha, opacity ) : + filter + " " + opacity; + } + }; +} + +jQuery(function() { + // This hook cannot be added until DOM ready because the support test + // for it is not run until after DOM ready + if ( !jQuery.support.reliableMarginRight ) { + jQuery.cssHooks.marginRight = { + get: function( elem, computed ) { + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + return jQuery.swap( elem, { "display": "inline-block" }, function() { + if ( computed ) { + return curCSS( elem, "margin-right" ); + } else { + return elem.style.marginRight; + } + }); + } + }; + } +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + var width = elem.offsetWidth, + height = elem.offsetHeight; + + return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none"); + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + +// These hooks are used by animate to expand properties +jQuery.each({ + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i, + + // assumes a single number if not a string + parts = typeof value === "string" ? value.split(" ") : [ value ], + expanded = {}; + + for ( i = 0; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; +}); + + + + +var r20 = /%20/g, + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rhash = /#.*$/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL + rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + rquery = /\?/, + rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, + rselectTextarea = /^(?:select|textarea)/i, + rspacesAjax = /\s+/, + rts = /([?&])_=[^&]*/, + rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/, + + // Keep a copy of the old load method + _load = jQuery.fn.load, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Document location + ajaxLocation, + + // Document location segments + ajaxLocParts, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = ["*/"] + ["*"]; + +// #8138, IE may throw an exception when accessing +// a field from window.location if document.domain has been set +try { + ajaxLocation = location.href; +} catch( e ) { + // Use the href attribute of an A element + // since IE will modify it given document.location + ajaxLocation = document.createElement( "a" ); + ajaxLocation.href = ""; + ajaxLocation = ajaxLocation.href; +} + +// Segment location into parts +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + if ( jQuery.isFunction( func ) ) { + var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ), + i = 0, + length = dataTypes.length, + dataType, + list, + placeBefore; + + // For each dataType in the dataTypeExpression + for ( ; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, + dataType /* internal */, inspected /* internal */ ) { + + dataType = dataType || options.dataTypes[ 0 ]; + inspected = inspected || {}; + + inspected[ dataType ] = true; + + var list = structure[ dataType ], + i = 0, + length = list ? list.length : 0, + executeOnly = ( structure === prefilters ), + selection; + + for ( ; i < length && ( executeOnly || !selection ); i++ ) { + selection = list[ i ]( options, originalOptions, jqXHR ); + // If we got redirected to another dataType + // we try there if executing only and not done already + if ( typeof selection === "string" ) { + if ( !executeOnly || inspected[ selection ] ) { + selection = undefined; + } else { + options.dataTypes.unshift( selection ); + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jqXHR, selection, inspected ); + } + } + } + // If we're only executing or nothing was selected + // we try the catchall dataType if not done already + if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jqXHR, "*", inspected ); + } + // unnecessary when only executing (prefilters) + // but it'll be ignored by the caller in that case + return selection; +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } +} + +jQuery.fn.extend({ + load: function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf( " " ); + if ( off >= 0 ) { + var selector = url.slice( off, url.length ); + url = url.slice( 0, off ); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + // Complete callback (responseText is used internally) + complete: function( jqXHR, status, responseText ) { + // Store the response as specified by the jqXHR object + responseText = jqXHR.responseText; + // If successful, inject the HTML into all the matched elements + if ( jqXHR.isResolved() ) { + // #4825: Get the actual response in case + // a dataFilter is present in ajaxSettings + jqXHR.done(function( r ) { + responseText = r; + }); + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("<div>") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + responseText ); + } + + if ( callback ) { + self.each( callback, [ responseText, status, jqXHR ] ); + } + } + }); + + return this; + }, + + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + + serializeArray: function() { + return this.map(function(){ + return this.elements ? jQuery.makeArray( this.elements ) : this; + }) + .filter(function(){ + return this.name && !this.disabled && + ( this.checked || rselectTextarea.test( this.nodeName ) || + rinput.test( this.type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val, i ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + } +}); + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ + jQuery.fn[ o ] = function( f ){ + return this.on( o, f ); + }; +}); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +}); + +jQuery.extend({ + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + if ( settings ) { + // Building a settings object + ajaxExtend( target, jQuery.ajaxSettings ); + } else { + // Extending ajaxSettings + settings = target; + target = jQuery.ajaxSettings; + } + ajaxExtend( target, settings ); + return target; + }, + + ajaxSettings: { + url: ajaxLocation, + isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), + global: true, + type: "GET", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + processData: true, + async: true, + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + traditional: false, + headers: {}, + */ + + accepts: { + xml: "application/xml, text/xml", + html: "text/html", + text: "text/plain", + json: "application/json, text/javascript", + "*": allTypes + }, + + contents: { + xml: /xml/, + html: /html/, + json: /json/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText" + }, + + // List of data converters + // 1) key format is "source_type destination_type" (a single space in-between) + // 2) the catchall symbol "*" can be used for source_type + converters: { + + // Convert anything to text + "* text": window.String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": jQuery.parseJSON, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + context: true, + url: true + } + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + // Callbacks context + callbackContext = s.context || s, + // Context for global events + // It's the callbackContext if one was provided in the options + // and if it's a DOM node or a jQuery collection + globalEventContext = callbackContext !== s && + ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? + jQuery( callbackContext ) : jQuery.event, + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // ifModified key + ifModifiedKey, + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + // Response headers + responseHeadersString, + responseHeaders, + // transport + transport, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + parts, + // The jqXHR state + state = 0, + // To know if global events are to be dispatched + fireGlobals, + // Loop variable + i, + // Fake xhr + jqXHR = { + + readyState: 0, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( !state ) { + var lname = name.toLowerCase(); + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match === undefined ? null : match; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( !state ) { + s.mimeType = type; + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + statusText = statusText || "abort"; + if ( transport ) { + transport.abort( statusText ); + } + done( 0, statusText ); + return this; + } + }; + + // Callback for when everything is done + // It is defined here because jslint complains if it is declared + // at the end of the function (which would be more logical and readable) + function done( status, nativeStatusText, responses, headers ) { + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + var isSuccess, + success, + error, + statusText = nativeStatusText, + response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined, + lastModified, + etag; + + // If successful, handle type chaining + if ( status >= 200 && status < 300 || status === 304 ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + + if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) { + jQuery.lastModified[ ifModifiedKey ] = lastModified; + } + if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) { + jQuery.etag[ ifModifiedKey ] = etag; + } + } + + // If not modified + if ( status === 304 ) { + + statusText = "notmodified"; + isSuccess = true; + + // If we have data + } else { + + try { + success = ajaxConvert( s, response ); + statusText = "success"; + isSuccess = true; + } catch(e) { + // We have a parsererror + statusText = "parsererror"; + error = e; + } + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if ( !statusText || status ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = "" + ( nativeStatusText || statusText ); + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + // Attach deferreds + deferred.promise( jqXHR ); + jqXHR.success = jqXHR.done; + jqXHR.error = jqXHR.fail; + jqXHR.complete = completeDeferred.add; + + // Status-dependent callbacks + jqXHR.statusCode = function( map ) { + if ( map ) { + var tmp; + if ( state < 2 ) { + for ( tmp in map ) { + statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; + } + } else { + tmp = map[ jqXHR.status ]; + jqXHR.then( tmp, tmp ); + } + } + return this; + }; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // We also use the url parameter if available + s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax ); + + // Determine if a cross-domain request is in order + if ( s.crossDomain == null ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( state === 2 ) { + return false; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Get ifModifiedKey before adding the anti-cache parameter + ifModifiedKey = s.url; + + // Add anti-cache in url if needed + if ( s.cache === false ) { + + var ts = jQuery.now(), + // try replacing _= if it is there + ret = s.url.replace( rts, "$1_=" + ts ); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + ifModifiedKey = ifModifiedKey || s.url; + if ( jQuery.lastModified[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); + } + if ( jQuery.etag[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); + } + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { + // Abort if not done already + jqXHR.abort(); + return false; + + } + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + state = 1; + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( state < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + throw e; + } + } + } + + return jqXHR; + }, + + // Serialize an array of form elements or a set of + // key/values into a query string + param: function( a, traditional ) { + var s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : value; + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); + } +}); + +function buildParams( prefix, obj, traditional, add ) { + if ( jQuery.isArray( obj ) ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // If array item is non-scalar (array or object), encode its + // numeric index to resolve deserialization ambiguity issues. + // Note that rack (as of 1.0.0) can't currently deserialize + // nested arrays properly, and attempting to do so may cause + // a server error. Possible fixes are to modify rack's + // deserialization algorithm or to provide an option or flag + // to force array serialization to be shallow. + buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && jQuery.type( obj ) === "object" ) { + // Serialize object item. + for ( var name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} + +// This is still on the jQuery object... for now +// Want to move this to jQuery.ajax some day +jQuery.extend({ + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {} + +}); + +/* Handles responses to an ajax request: + * - sets all responseXXX fields accordingly + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var contents = s.contents, + dataTypes = s.dataTypes, + responseFields = s.responseFields, + ct, + type, + finalDataType, + firstDataType; + + // Fill responseXXX fields + for ( type in responseFields ) { + if ( type in responses ) { + jqXHR[ responseFields[type] ] = responses[ type ]; + } + } + + // Remove auto dataType and get content-type in the process + while( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +// Chain conversions given the request and the original response +function ajaxConvert( s, response ) { + + // Apply the dataFilter if provided + if ( s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + var dataTypes = s.dataTypes, + converters = {}, + i, + key, + length = dataTypes.length, + tmp, + // Current and previous dataTypes + current = dataTypes[ 0 ], + prev, + // Conversion expression + conversion, + // Conversion function + conv, + // Conversion functions (transitive conversion) + conv1, + conv2; + + // For each dataType in the chain + for ( i = 1; i < length; i++ ) { + + // Create converters map + // with lowercased keys + if ( i === 1 ) { + for ( key in s.converters ) { + if ( typeof key === "string" ) { + converters[ key.toLowerCase() ] = s.converters[ key ]; + } + } + } + + // Get the dataTypes + prev = current; + current = dataTypes[ i ]; + + // If current is auto dataType, update it to prev + if ( current === "*" ) { + current = prev; + // If no auto and dataTypes are actually different + } else if ( prev !== "*" && prev !== current ) { + + // Get the converter + conversion = prev + " " + current; + conv = converters[ conversion ] || converters[ "* " + current ]; + + // If there is no direct converter, search transitively + if ( !conv ) { + conv2 = undefined; + for ( conv1 in converters ) { + tmp = conv1.split( " " ); + if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) { + conv2 = converters[ tmp[1] + " " + current ]; + if ( conv2 ) { + conv1 = converters[ conv1 ]; + if ( conv1 === true ) { + conv = conv2; + } else if ( conv2 === true ) { + conv = conv1; + } + break; + } + } + } + } + // If we found no converter, dispatch an error + if ( !( conv || conv2 ) ) { + jQuery.error( "No conversion from " + conversion.replace(" "," to ") ); + } + // If found converter is not an equivalence + if ( conv !== true ) { + // Convert with 1 or 2 converters accordingly + response = conv ? conv( response ) : conv2( conv1(response) ); + } + } + } + return response; +} + + + + +var jsc = jQuery.now(), + jsre = /(\=)\?(&|$)|\?\?/i; + +// Default jsonp settings +jQuery.ajaxSetup({ + jsonp: "callback", + jsonpCallback: function() { + return jQuery.expando + "_" + ( jsc++ ); + } +}); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var inspectData = ( typeof s.data === "string" ) && /^application\/x\-www\-form\-urlencoded/.test( s.contentType ); + + if ( s.dataTypes[ 0 ] === "jsonp" || + s.jsonp !== false && ( jsre.test( s.url ) || + inspectData && jsre.test( s.data ) ) ) { + + var responseContainer, + jsonpCallback = s.jsonpCallback = + jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback, + previous = window[ jsonpCallback ], + url = s.url, + data = s.data, + replace = "$1" + jsonpCallback + "$2"; + + if ( s.jsonp !== false ) { + url = url.replace( jsre, replace ); + if ( s.url === url ) { + if ( inspectData ) { + data = data.replace( jsre, replace ); + } + if ( s.data === data ) { + // Add callback manually + url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback; + } + } + } + + s.url = url; + s.data = data; + + // Install callback + window[ jsonpCallback ] = function( response ) { + responseContainer = [ response ]; + }; + + // Clean-up function + jqXHR.always(function() { + // Set callback back to previous value + window[ jsonpCallback ] = previous; + // Call if it was a function and we have a response + if ( responseContainer && jQuery.isFunction( previous ) ) { + window[ jsonpCallback ]( responseContainer[ 0 ] ); + } + }); + + // Use data converter to retrieve json after script execution + s.converters["script json"] = function() { + if ( !responseContainer ) { + jQuery.error( jsonpCallback + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // force json dataType + s.dataTypes[ 0 ] = "json"; + + // Delegate to script + return "script"; + } +}); + + + + +// Install script dataType +jQuery.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /javascript|ecmascript/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +}); + +// Handle cache's special case and global +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + s.global = false; + } +}); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function(s) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + + var script, + head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; + + return { + + send: function( _, callback ) { + + script = document.createElement( "script" ); + + script.async = "async"; + + if ( s.scriptCharset ) { + script.charset = s.scriptCharset; + } + + script.src = s.url; + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function( _, isAbort ) { + + if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + + // Remove the script + if ( head && script.parentNode ) { + head.removeChild( script ); + } + + // Dereference the script + script = undefined; + + // Callback if not abort + if ( !isAbort ) { + callback( 200, "success" ); + } + } + }; + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709 and #4378). + head.insertBefore( script, head.firstChild ); + }, + + abort: function() { + if ( script ) { + script.onload( 0, 1 ); + } + } + }; + } +}); + + + + +var // #5280: Internet Explorer will keep connections alive if we don't abort on unload + xhrOnUnloadAbort = window.ActiveXObject ? function() { + // Abort all pending requests + for ( var key in xhrCallbacks ) { + xhrCallbacks[ key ]( 0, 1 ); + } + } : false, + xhrId = 0, + xhrCallbacks; + +// Functions to create xhrs +function createStandardXHR() { + try { + return new window.XMLHttpRequest(); + } catch( e ) {} +} + +function createActiveXHR() { + try { + return new window.ActiveXObject( "Microsoft.XMLHTTP" ); + } catch( e ) {} +} + +// Create the request object +// (This is still attached to ajaxSettings for backward compatibility) +jQuery.ajaxSettings.xhr = window.ActiveXObject ? + /* Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ + function() { + return !this.isLocal && createStandardXHR() || createActiveXHR(); + } : + // For all other browsers, use the standard XMLHttpRequest object + createStandardXHR; + +// Determine support properties +(function( xhr ) { + jQuery.extend( jQuery.support, { + ajax: !!xhr, + cors: !!xhr && ( "withCredentials" in xhr ) + }); +})( jQuery.ajaxSettings.xhr() ); + +// Create transport if the browser can provide an xhr +if ( jQuery.support.ajax ) { + + jQuery.ajaxTransport(function( s ) { + // Cross domain only allowed if supported through XMLHttpRequest + if ( !s.crossDomain || jQuery.support.cors ) { + + var callback; + + return { + send: function( headers, complete ) { + + // Get a new xhr + var xhr = s.xhr(), + handle, + i; + + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open( s.type, s.url, s.async, s.username, s.password ); + } else { + xhr.open( s.type, s.url, s.async ); + } + + // Apply custom fields if provided + if ( s.xhrFields ) { + for ( i in s.xhrFields ) { + xhr[ i ] = s.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( s.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( s.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !s.crossDomain && !headers["X-Requested-With"] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Need an extra try/catch for cross domain requests in Firefox 3 + try { + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + } catch( _ ) {} + + // Do send the request + // This may raise an exception which is actually + // handled in jQuery.ajax (so no try/catch here) + xhr.send( ( s.hasContent && s.data ) || null ); + + // Listener + callback = function( _, isAbort ) { + + var status, + statusText, + responseHeaders, + responses, + xml; + + // Firefox throws exceptions when accessing properties + // of an xhr when a network error occured + // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) + try { + + // Was never called and is aborted or complete + if ( callback && ( isAbort || xhr.readyState === 4 ) ) { + + // Only called once + callback = undefined; + + // Do not keep as active anymore + if ( handle ) { + xhr.onreadystatechange = jQuery.noop; + if ( xhrOnUnloadAbort ) { + delete xhrCallbacks[ handle ]; + } + } + + // If it's an abort + if ( isAbort ) { + // Abort it manually if needed + if ( xhr.readyState !== 4 ) { + xhr.abort(); + } + } else { + status = xhr.status; + responseHeaders = xhr.getAllResponseHeaders(); + responses = {}; + xml = xhr.responseXML; + + // Construct response list + if ( xml && xml.documentElement /* #4958 */ ) { + responses.xml = xml; + } + + // When requesting binary data, IE6-9 will throw an exception + // on any attempt to access responseText (#11426) + try { + responses.text = xhr.responseText; + } catch( _ ) { + } + + // Firefox throws an exception when accessing + // statusText for faulty cross-domain requests + try { + statusText = xhr.statusText; + } catch( e ) { + // We normalize with Webkit giving an empty statusText + statusText = ""; + } + + // Filter status for non standard behaviors + + // If the request is local and we have data: assume a success + // (success with no data won't get notified, that's the best we + // can do given current implementations) + if ( !status && s.isLocal && !s.crossDomain ) { + status = responses.text ? 200 : 404; + // IE - #1450: sometimes returns 1223 when it should be 204 + } else if ( status === 1223 ) { + status = 204; + } + } + } + } catch( firefoxAccessException ) { + if ( !isAbort ) { + complete( -1, firefoxAccessException ); + } + } + + // Call complete if needed + if ( responses ) { + complete( status, statusText, responses, responseHeaders ); + } + }; + + // if we're in sync mode or it's in cache + // and has been retrieved directly (IE6 & IE7) + // we need to manually fire the callback + if ( !s.async || xhr.readyState === 4 ) { + callback(); + } else { + handle = ++xhrId; + if ( xhrOnUnloadAbort ) { + // Create the active xhrs callbacks list if needed + // and attach the unload handler + if ( !xhrCallbacks ) { + xhrCallbacks = {}; + jQuery( window ).unload( xhrOnUnloadAbort ); + } + // Add to list of active xhrs callbacks + xhrCallbacks[ handle ] = callback; + } + xhr.onreadystatechange = callback; + } + }, + + abort: function() { + if ( callback ) { + callback(0,1); + } + } + }; + } + }); +} + + + + +var elemdisplay = {}, + iframe, iframeDoc, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i, + timerId, + fxAttrs = [ + // height animations + [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], + // width animations + [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], + // opacity animations + [ "opacity" ] + ], + fxNow; + +jQuery.fn.extend({ + show: function( speed, easing, callback ) { + var elem, display; + + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback ); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + elem = this[ i ]; + + if ( elem.style ) { + display = elem.style.display; + + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery._data(elem, "olddisplay") && display === "none" ) { + display = elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( (display === "" && jQuery.css(elem, "display") === "none") || + !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { + jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) ); + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + elem = this[ i ]; + + if ( elem.style ) { + display = elem.style.display; + + if ( display === "" || display === "none" ) { + elem.style.display = jQuery._data( elem, "olddisplay" ) || ""; + } + } + } + + return this; + } + }, + + hide: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + var elem, display, + i = 0, + j = this.length; + + for ( ; i < j; i++ ) { + elem = this[i]; + if ( elem.style ) { + display = jQuery.css( elem, "display" ); + + if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) { + jQuery._data( elem, "olddisplay", display ); + } + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + if ( this[i].style ) { + this[i].style.display = "none"; + } + } + + return this; + } + }, + + // Save the old toggle function + _toggle: jQuery.fn.toggle, + + toggle: function( fn, fn2, callback ) { + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }, + + fadeTo: function( speed, to, easing, callback ) { + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }, + + animate: function( prop, speed, easing, callback ) { + var optall = jQuery.speed( speed, easing, callback ); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete, [ false ] ); + } + + // Do not change referenced properties as per-property easing will be lost + prop = jQuery.extend( {}, prop ); + + function doAnimation() { + // XXX 'this' does not always have a nodeName when running the + // test suite + + if ( optall.queue === false ) { + jQuery._mark( this ); + } + + var opt = jQuery.extend( {}, optall ), + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + name, val, p, e, hooks, replace, + parts, start, end, unit, + method; + + // will store per property easing and be used to determine when an animation is complete + opt.animatedProperties = {}; + + // first pass over propertys to expand / normalize + for ( p in prop ) { + name = jQuery.camelCase( p ); + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + } + + if ( ( hooks = jQuery.cssHooks[ name ] ) && "expand" in hooks ) { + replace = hooks.expand( prop[ name ] ); + delete prop[ name ]; + + // not quite $.extend, this wont overwrite keys already present. + // also - reusing 'p' from above because we have the correct "name" + for ( p in replace ) { + if ( ! ( p in prop ) ) { + prop[ p ] = replace[ p ]; + } + } + } + } + + for ( name in prop ) { + val = prop[ name ]; + // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default) + if ( jQuery.isArray( val ) ) { + opt.animatedProperties[ name ] = val[ 1 ]; + val = prop[ name ] = val[ 0 ]; + } else { + opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing'; + } + + if ( val === "hide" && hidden || val === "show" && !hidden ) { + return opt.complete.call( this ); + } + + if ( isElement && ( name === "height" || name === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.zoom = 1; + } + } + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + for ( p in prop ) { + e = new jQuery.fx( this, opt, p ); + val = prop[ p ]; + + if ( rfxtypes.test( val ) ) { + + // Tracks whether to show or hide based on private + // data attached to the element + method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 ); + if ( method ) { + jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" ); + e[ method ](); + } else { + e[ val ](); + } + + } else { + parts = rfxnum.exec( val ); + start = e.cur(); + + if ( parts ) { + end = parseFloat( parts[2] ); + unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" ); + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( this, p, (end || 1) + unit); + start = ( (end || 1) / e.cur() ) * start; + jQuery.style( this, p, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + } + + // For JS strict compliance + return true; + } + + return optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + + stop: function( type, clearQueue, gotoEnd ) { + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each(function() { + var index, + hadTimers = false, + timers = jQuery.timers, + data = jQuery._data( this ); + + // clear marker counters if we know they won't be + if ( !gotoEnd ) { + jQuery._unmark( true, this ); + } + + function stopQueue( elem, data, index ) { + var hooks = data[ index ]; + jQuery.removeData( elem, index, true ); + hooks.stop( gotoEnd ); + } + + if ( type == null ) { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) { + stopQueue( this, data, index ); + } + } + } else if ( data[ index = type + ".run" ] && data[ index ].stop ){ + stopQueue( this, data, index ); + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { + if ( gotoEnd ) { + + // force the next step to be the last + timers[ index ]( true ); + } else { + timers[ index ].saveState(); + } + hadTimers = true; + timers.splice( index, 1 ); + } + } + + // start the next in the queue if the last step wasn't forced + // timers currently will call their complete callbacks, which will dequeue + // but only if they were gotoEnd + if ( !( gotoEnd && hadTimers ) ) { + jQuery.dequeue( this, type ); + } + }); + } + +}); + +// Animations created synchronously will run synchronously +function createFxNow() { + setTimeout( clearFxNow, 0 ); + return ( fxNow = jQuery.now() ); +} + +function clearFxNow() { + fxNow = undefined; +} + +// Generate parameters to create a standard animation +function genFx( type, num ) { + var obj = {}; + + jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() { + obj[ this ] = type; + }); + + return obj; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx( "show", 1 ), + slideUp: genFx( "hide", 1 ), + slideToggle: genFx( "toggle", 1 ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.extend({ + speed: function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; + + // normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function( noUnmark ) { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } else if ( noUnmark !== false ) { + jQuery._unmark( this ); + } + }; + + return opt; + }, + + easing: { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return ( -Math.cos( p*Math.PI ) / 2 ) + 0.5; + } + }, + + timers: [], + + fx: function( elem, options, prop ) { + this.options = options; + this.elem = elem; + this.prop = prop; + + options.orig = options.orig || {}; + } + +}); + +jQuery.fx.prototype = { + // Simple function for setting a style value + update: function() { + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this ); + }, + + // Get the current size + cur: function() { + if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) { + return this.elem[ this.prop ]; + } + + var parsed, + r = jQuery.css( this.elem, this.prop ); + // Empty strings, null, undefined and "auto" are converted to 0, + // complex values such as "rotate(1rad)" are returned as is, + // simple values such as "10px" are parsed to Float. + return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed; + }, + + // Start an animation from one number to another + custom: function( from, to, unit ) { + var self = this, + fx = jQuery.fx; + + this.startTime = fxNow || createFxNow(); + this.end = to; + this.now = this.start = from; + this.pos = this.state = 0; + this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" ); + + function t( gotoEnd ) { + return self.step( gotoEnd ); + } + + t.queue = this.options.queue; + t.elem = this.elem; + t.saveState = function() { + if ( jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) { + if ( self.options.hide ) { + jQuery._data( self.elem, "fxshow" + self.prop, self.start ); + } else if ( self.options.show ) { + jQuery._data( self.elem, "fxshow" + self.prop, self.end ); + } + } + }; + + if ( t() && jQuery.timers.push(t) && !timerId ) { + timerId = setInterval( fx.tick, fx.interval ); + } + }, + + // Simple 'show' function + show: function() { + var dataShow = jQuery._data( this.elem, "fxshow" + this.prop ); + + // Remember where we started, so that we can go back to it later + this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop ); + this.options.show = true; + + // Begin the animation + // Make sure that we start at a small width/height to avoid any flash of content + if ( dataShow !== undefined ) { + // This show is picking up where a previous hide or show left off + this.custom( this.cur(), dataShow ); + } else { + this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() ); + } + + // Start by showing the element + jQuery( this.elem ).show(); + }, + + // Simple 'hide' function + hide: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop ); + this.options.hide = true; + + // Begin the animation + this.custom( this.cur(), 0 ); + }, + + // Each step of an animation + step: function( gotoEnd ) { + var p, n, complete, + t = fxNow || createFxNow(), + done = true, + elem = this.elem, + options = this.options; + + if ( gotoEnd || t >= options.duration + this.startTime ) { + this.now = this.end; + this.pos = this.state = 1; + this.update(); + + options.animatedProperties[ this.prop ] = true; + + for ( p in options.animatedProperties ) { + if ( options.animatedProperties[ p ] !== true ) { + done = false; + } + } + + if ( done ) { + // Reset the overflow + if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { + + jQuery.each( [ "", "X", "Y" ], function( index, value ) { + elem.style[ "overflow" + value ] = options.overflow[ index ]; + }); + } + + // Hide the element if the "hide" operation was done + if ( options.hide ) { + jQuery( elem ).hide(); + } + + // Reset the properties, if the item has been hidden or shown + if ( options.hide || options.show ) { + for ( p in options.animatedProperties ) { + jQuery.style( elem, p, options.orig[ p ] ); + jQuery.removeData( elem, "fxshow" + p, true ); + // Toggle data is no longer needed + jQuery.removeData( elem, "toggle" + p, true ); + } + } + + // Execute the complete function + // in the event that the complete function throws an exception + // we must ensure it won't be called twice. #5684 + + complete = options.complete; + if ( complete ) { + + options.complete = false; + complete.call( elem ); + } + } + + return false; + + } else { + // classical easing cannot be used with an Infinity duration + if ( options.duration == Infinity ) { + this.now = t; + } else { + n = t - this.startTime; + this.state = n / options.duration; + + // Perform the easing function, defaults to swing + this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration ); + this.now = this.start + ( (this.end - this.start) * this.pos ); + } + // Perform the next step of the animation + this.update(); + } + + return true; + } +}; + +jQuery.extend( jQuery.fx, { + tick: function() { + var timer, + timers = jQuery.timers, + i = 0; + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + // Checks the timer has not already been removed + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + }, + + interval: 13, + + stop: function() { + clearInterval( timerId ); + timerId = null; + }, + + speeds: { + slow: 600, + fast: 200, + // Default speed + _default: 400 + }, + + step: { + opacity: function( fx ) { + jQuery.style( fx.elem, "opacity", fx.now ); + }, + + _default: function( fx ) { + if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { + fx.elem.style[ fx.prop ] = fx.now + fx.unit; + } else { + fx.elem[ fx.prop ] = fx.now; + } + } + } +}); + +// Ensure props that can't be negative don't go there on undershoot easing +jQuery.each( fxAttrs.concat.apply( [], fxAttrs ), function( i, prop ) { + // exclude marginTop, marginLeft, marginBottom and marginRight from this list + if ( prop.indexOf( "margin" ) ) { + jQuery.fx.step[ prop ] = function( fx ) { + jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit ); + }; + } +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} + +// Try to restore the default display value of an element +function defaultDisplay( nodeName ) { + + if ( !elemdisplay[ nodeName ] ) { + + var body = document.body, + elem = jQuery( "<" + nodeName + ">" ).appendTo( body ), + display = elem.css( "display" ); + elem.remove(); + + // If the simple way fails, + // get element's real default display by attaching it to a temp iframe + if ( display === "none" || display === "" ) { + // No iframe to use yet, so create it + if ( !iframe ) { + iframe = document.createElement( "iframe" ); + iframe.frameBorder = iframe.width = iframe.height = 0; + } + + body.appendChild( iframe ); + + // Create a cacheable copy of the iframe document on first call. + // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML + // document to it; WebKit & Firefox won't allow reusing the iframe document. + if ( !iframeDoc || !iframe.createElement ) { + iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; + iframeDoc.write( ( jQuery.support.boxModel ? "<!doctype html>" : "" ) + "<html><body>" ); + iframeDoc.close(); + } + + elem = iframeDoc.createElement( nodeName ); + + iframeDoc.body.appendChild( elem ); + + display = jQuery.css( elem, "display" ); + body.removeChild( iframe ); + } + + // Store the correct default display + elemdisplay[ nodeName ] = display; + } + + return elemdisplay[ nodeName ]; +} + + + + +var getOffset, + rtable = /^t(?:able|d|h)$/i, + rroot = /^(?:body|html)$/i; + +if ( "getBoundingClientRect" in document.documentElement ) { + getOffset = function( elem, doc, docElem, box ) { + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box ? { top: box.top, left: box.left } : { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow( doc ), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop, + scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft, + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; + +} else { + getOffset = function( elem, doc, docElem ) { + var computedStyle, + offsetParent = elem.offsetParent, + prevOffsetParent = elem, + body = doc.body, + defaultView = doc.defaultView, + prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, + top = elem.offsetTop, + left = elem.offsetLeft; + + while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { + if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) { + break; + } + + computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; + top -= elem.scrollTop; + left -= elem.scrollLeft; + + if ( elem === offsetParent ) { + top += elem.offsetTop; + left += elem.offsetLeft; + + if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevOffsetParent = offsetParent; + offsetParent = elem.offsetParent; + } + + if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevComputedStyle = computedStyle; + } + + if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { + top += body.offsetTop; + left += body.offsetLeft; + } + + if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) { + top += Math.max( docElem.scrollTop, body.scrollTop ); + left += Math.max( docElem.scrollLeft, body.scrollLeft ); + } + + return { top: top, left: left }; + }; +} + +jQuery.fn.offset = function( options ) { + if ( arguments.length ) { + return options === undefined ? + this : + this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + var elem = this[0], + doc = elem && elem.ownerDocument; + + if ( !doc ) { + return null; + } + + if ( elem === doc.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + return getOffset( elem, doc, doc.documentElement ); +}; + +jQuery.offset = { + + bodyOffset: function( body ) { + var top = body.offsetTop, + left = body.offsetLeft; + + if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) { + top += parseFloat( jQuery.css(body, "marginTop") ) || 0; + left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; + } + + return { top: top, left: left }; + }, + + setOffset: function( elem, options, i ) { + var position = jQuery.css( elem, "position" ); + + // set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + var curElem = jQuery( elem ), + curOffset = curElem.offset(), + curCSSTop = jQuery.css( elem, "top" ), + curCSSLeft = jQuery.css( elem, "left" ), + calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, + props = {}, curPosition = {}, curTop, curLeft; + + // need to be able to calculate position if either top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + } else { + curTop = parseFloat( curCSSTop ) || 0; + curLeft = parseFloat( curCSSLeft ) || 0; + } + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if ( options.top != null ) { + props.top = ( options.top - curOffset.top ) + curTop; + } + if ( options.left != null ) { + props.left = ( options.left - curOffset.left ) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + + position: function() { + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) { + var top = /Y/.test( prop ); + + jQuery.fn[ method ] = function( val ) { + return jQuery.access( this, function( elem, method, val ) { + var win = getWindow( elem ); + + if ( val === undefined ) { + return win ? (prop in win) ? win[ prop ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + + if ( win ) { + win.scrollTo( + !top ? val : jQuery( win ).scrollLeft(), + top ? val : jQuery( win ).scrollTop() + ); + + } else { + elem[ method ] = val; + } + }, method, val, arguments.length, null ); + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? + elem : + elem.nodeType === 9 ? + elem.defaultView || elem.parentWindow : + false; +} + + + + +// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods +jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { + var clientProp = "client" + name, + scrollProp = "scroll" + name, + offsetProp = "offset" + name; + + // innerHeight and innerWidth + jQuery.fn[ "inner" + name ] = function() { + var elem = this[0]; + return elem ? + elem.style ? + parseFloat( jQuery.css( elem, type, "padding" ) ) : + this[ type ]() : + null; + }; + + // outerHeight and outerWidth + jQuery.fn[ "outer" + name ] = function( margin ) { + var elem = this[0]; + return elem ? + elem.style ? + parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) : + this[ type ]() : + null; + }; + + jQuery.fn[ type ] = function( value ) { + return jQuery.access( this, function( elem, type, value ) { + var doc, docElemProp, orig, ret; + + if ( jQuery.isWindow( elem ) ) { + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + doc = elem.document; + docElemProp = doc.documentElement[ clientProp ]; + return jQuery.support.boxModel && docElemProp || + doc.body && doc.body[ clientProp ] || docElemProp; + } + + // Get document width or height + if ( elem.nodeType === 9 ) { + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + doc = elem.documentElement; + + // when a window > document, IE6 reports a offset[Width/Height] > client[Width/Height] + // so we can't use max, as it'll choose the incorrect offset[Width/Height] + // instead we use the correct client[Width/Height] + // support:IE6 + if ( doc[ clientProp ] >= doc[ scrollProp ] ) { + return doc[ clientProp ]; + } + + return Math.max( + elem.body[ scrollProp ], doc[ scrollProp ], + elem.body[ offsetProp ], doc[ offsetProp ] + ); + } + + // Get width or height on the element + if ( value === undefined ) { + orig = jQuery.css( elem, type ); + ret = parseFloat( orig ); + return jQuery.isNumeric( ret ) ? ret : orig; + } + + // Set the width or height on the element + jQuery( elem ).css( type, value ); + }, type, value, arguments.length, null ); + }; +}); + + + + +// Expose jQuery to the global object +window.jQuery = window.$ = jQuery; + +// Expose jQuery as an AMD module, but only for AMD loaders that +// understand the issues with loading multiple versions of jQuery +// in a page that all might call define(). The loader will indicate +// they have special allowances for multiple jQuery versions by +// specifying define.amd.jQuery = true. Register as a named module, +// since jQuery can be concatenated with other files that may use define, +// but not use a proper concatenation script that understands anonymous +// AMD modules. A named AMD is safest and most robust way to register. +// Lowercase jquery is used because AMD module names are derived from +// file names, and jQuery is normally delivered in a lowercase file name. +// Do this after creating the global so that if an AMD module wants to call +// noConflict to hide this version of jQuery, it will work. +if ( typeof define === "function" && define.amd && define.amd.jQuery ) { + define( "jquery", [], function () { return jQuery; } ); +} + + + +})( window ); diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js new file mode 100644 index 00000000000..d4444b2bd11 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js @@ -0,0 +1,11802 @@ +/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function( $, undefined ) { + +// prevent duplicate loading +// this is only a problem because we proxy existing functions +// and we don't want to double proxy them +$.ui = $.ui || {}; +if ( $.ui.version ) { + return; +} + +$.extend( $.ui, { + version: "1.8.18", + + keyCode: { + ALT: 18, + BACKSPACE: 8, + CAPS_LOCK: 20, + COMMA: 188, + COMMAND: 91, + COMMAND_LEFT: 91, // COMMAND + COMMAND_RIGHT: 93, + CONTROL: 17, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + INSERT: 45, + LEFT: 37, + MENU: 93, // COMMAND_RIGHT + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SHIFT: 16, + SPACE: 32, + TAB: 9, + UP: 38, + WINDOWS: 91 // COMMAND + } +}); + +// plugins +$.fn.extend({ + propAttr: $.fn.prop || $.fn.attr, + + _focus: $.fn.focus, + focus: function( delay, fn ) { + return typeof delay === "number" ? + this.each(function() { + var elem = this; + setTimeout(function() { + $( elem ).focus(); + if ( fn ) { + fn.call( elem ); + } + }, delay ); + }) : + this._focus.apply( this, arguments ); + }, + + scrollParent: function() { + var scrollParent; + if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); + }).eq(0); + } + + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; + }, + + zIndex: function( zIndex ) { + if ( zIndex !== undefined ) { + return this.css( "zIndex", zIndex ); + } + + if ( this.length ) { + var elem = $( this[ 0 ] ), position, value; + while ( elem.length && elem[ 0 ] !== document ) { + // Ignore z-index if position is set to a value where z-index is ignored by the browser + // This makes behavior of this function consistent across browsers + // WebKit always returns auto if the element is positioned + position = elem.css( "position" ); + if ( position === "absolute" || position === "relative" || position === "fixed" ) { + // IE returns 0 when zIndex is not specified + // other browsers return a string + // we ignore the case of nested elements with an explicit value of 0 + // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> + value = parseInt( elem.css( "zIndex" ), 10 ); + if ( !isNaN( value ) && value !== 0 ) { + return value; + } + } + elem = elem.parent(); + } + } + + return 0; + }, + + disableSelection: function() { + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + + ".ui-disableSelection", function( event ) { + event.preventDefault(); + }); + }, + + enableSelection: function() { + return this.unbind( ".ui-disableSelection" ); + } +}); + +$.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; + if ( border ) { + size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; + } + }); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each(function() { + $( this ).css( type, reduce( this, size ) + "px" ); + }); + }; + + $.fn[ "outer" + name] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each(function() { + $( this).css( type, reduce( this, size, true, margin ) + "px" ); + }); + }; +}); + +// selectors +function focusable( element, isTabIndexNotNaN ) { + var nodeName = element.nodeName.toLowerCase(); + if ( "area" === nodeName ) { + var map = element.parentNode, + mapName = map.name, + img; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap=#" + mapName + "]" )[0]; + return !!img && visible( img ); + } + return ( /input|select|textarea|button|object/.test( nodeName ) + ? !element.disabled + : "a" == nodeName + ? element.href || isTabIndexNotNaN + : isTabIndexNotNaN) + // the element and all of its ancestors must be visible + && visible( element ); +} + +function visible( element ) { + return !$( element ).parents().andSelf().filter(function() { + return $.curCSS( this, "visibility" ) === "hidden" || + $.expr.filters.hidden( this ); + }).length; +} + +$.extend( $.expr[ ":" ], { + data: function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + }, + + focusable: function( element ) { + return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); + }, + + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + isTabIndexNaN = isNaN( tabIndex ); + return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); + } +}); + +// support +$(function() { + var body = document.body, + div = body.appendChild( div = document.createElement( "div" ) ); + + // access offsetHeight before setting the style to prevent a layout bug + // in IE 9 which causes the elemnt to continue to take up space even + // after it is removed from the DOM (#8026) + div.offsetHeight; + + $.extend( div.style, { + minHeight: "100px", + height: "auto", + padding: 0, + borderWidth: 0 + }); + + $.support.minHeight = div.offsetHeight === 100; + $.support.selectstart = "onselectstart" in div; + + // set display to none to avoid a layout bug in IE + // http://dev.jquery.com/ticket/4014 + body.removeChild( div ).style.display = "none"; +}); + + + + + +// deprecated +$.extend( $.ui, { + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function( module, option, set ) { + var proto = $.ui[ module ].prototype; + for ( var i in set ) { + proto.plugins[ i ] = proto.plugins[ i ] || []; + proto.plugins[ i ].push( [ option, set[ i ] ] ); + } + }, + call: function( instance, name, args ) { + var set = instance.plugins[ name ]; + if ( !set || !instance.element[ 0 ].parentNode ) { + return; + } + + for ( var i = 0; i < set.length; i++ ) { + if ( instance.options[ set[ i ][ 0 ] ] ) { + set[ i ][ 1 ].apply( instance.element, args ); + } + } + } + }, + + // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() + contains: function( a, b ) { + return document.compareDocumentPosition ? + a.compareDocumentPosition( b ) & 16 : + a !== b && a.contains( b ); + }, + + // only used by resizable + hasScroll: function( el, a ) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ( $( el ).css( "overflow" ) === "hidden") { + return false; + } + + var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", + has = false; + + if ( el[ scroll ] > 0 ) { + return true; + } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[ scroll ] = 1; + has = ( el[ scroll ] > 0 ); + el[ scroll ] = 0; + return has; + }, + + // these are odd functions, fix the API or move into individual plugins + isOverAxis: function( x, reference, size ) { + //Determines when x coordinate is over "b" element axis + return ( x > reference ) && ( x < ( reference + size ) ); + }, + isOver: function( y, x, top, left, height, width ) { + //Determines when x, y coordinates is over "b" element + return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); + } +}); + +})( jQuery ); +/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function( $, undefined ) { + +// jQuery 1.4+ +if ( $.cleanData ) { + var _cleanData = $.cleanData; + $.cleanData = function( elems ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + try { + $( elem ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + } + _cleanData( elems ); + }; +} else { + var _remove = $.fn.remove; + $.fn.remove = function( selector, keepData ) { + return this.each(function() { + if ( !keepData ) { + if ( !selector || $.filter( selector, [ this ] ).length ) { + $( "*", this ).add( [ this ] ).each(function() { + try { + $( this ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + }); + } + } + return _remove.call( $(this), selector, keepData ); + }); + }; +} + +$.widget = function( name, base, prototype ) { + var namespace = name.split( "." )[ 0 ], + fullName; + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName ] = function( elem ) { + return !!$.data( elem, name ); + }; + + $[ namespace ] = $[ namespace ] || {}; + $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + var basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from +// $.each( basePrototype, function( key, val ) { +// if ( $.isPlainObject(val) ) { +// basePrototype[ key ] = $.extend( {}, val ); +// } +// }); + basePrototype.options = $.extend( true, {}, basePrototype.options ); + $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { + namespace: namespace, + widgetName: name, + widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, + widgetBaseClass: fullName + }, prototype ); + + $.widget.bridge( name, $[ namespace ][ name ] ); +}; + +$.widget.bridge = function( name, object ) { + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = Array.prototype.slice.call( arguments, 1 ), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.extend.apply( null, [ true, options ].concat(args) ) : + options; + + // prevent calls to internal methods + if ( isMethodCall && options.charAt( 0 ) === "_" ) { + return returnValue; + } + + if ( isMethodCall ) { + this.each(function() { + var instance = $.data( this, name ), + methodValue = instance && $.isFunction( instance[options] ) ? + instance[ options ].apply( instance, args ) : + instance; + // TODO: add this back in 1.9 and use $.error() (see #5972) +// if ( !instance ) { +// throw "cannot call methods on " + name + " prior to initialization; " + +// "attempted to call method '" + options + "'"; +// } +// if ( !$.isFunction( instance[options] ) ) { +// throw "no such method '" + options + "' for " + name + " widget instance"; +// } +// var methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue; + return false; + } + }); + } else { + this.each(function() { + var instance = $.data( this, name ); + if ( instance ) { + instance.option( options || {} )._init(); + } else { + $.data( this, name, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } +}; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + options: { + disabled: false + }, + _createWidget: function( options, element ) { + // $.widget.bridge stores the plugin instance, but we do it anyway + // so that it's stored even before the _create function runs + $.data( element, this.widgetName, this ); + this.element = $( element ); + this.options = $.extend( true, {}, + this.options, + this._getCreateOptions(), + options ); + + var self = this; + this.element.bind( "remove." + this.widgetName, function() { + self.destroy(); + }); + + this._create(); + this._trigger( "create" ); + this._init(); + }, + _getCreateOptions: function() { + return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; + }, + _create: function() {}, + _init: function() {}, + + destroy: function() { + this.element + .unbind( "." + this.widgetName ) + .removeData( this.widgetName ); + this.widget() + .unbind( "." + this.widgetName ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetBaseClass + "-disabled " + + "ui-state-disabled" ); + }, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.extend( {}, this.options ); + } + + if (typeof key === "string" ) { + if ( value === undefined ) { + return this.options[ key ]; + } + options = {}; + options[ key ] = value; + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var self = this; + $.each( options, function( key, value ) { + self._setOption( key, value ); + }); + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + [ value ? "addClass" : "removeClass"]( + this.widgetBaseClass + "-disabled" + " " + + "ui-state-disabled" ) + .attr( "aria-disabled", value ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _trigger: function( type, event, data ) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + + return !( $.isFunction(callback) && + callback.call( this.element[0], event, data ) === false || + event.isDefaultPrevented() ); + } +}; + +})( jQuery ); +/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var mouseHandled = false; +$( document ).mouseup( function( e ) { + mouseHandled = false; +}); + +$.widget("ui.mouse", { + options: { + cancel: ':input,option', + distance: 1, + delay: 0 + }, + _mouseInit: function() { + var self = this; + + this.element + .bind('mousedown.'+this.widgetName, function(event) { + return self._mouseDown(event); + }) + .bind('click.'+this.widgetName, function(event) { + if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { + $.removeData(event.target, self.widgetName + '.preventClickEvent'); + event.stopImmediatePropagation(); + return false; + } + }); + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind('.'+this.widgetName); + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + if( mouseHandled ) { return }; + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var self = this, + btnIsLeft = (event.which == 1), + // event.target.nodeName works around a bug in IE 8 with + // disabled inputs (#7620) + elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + self.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // Click event may never have fired (Gecko & Opera) + if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { + $.removeData(event.target, this.widgetName + '.preventClickEvent'); + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return self._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return self._mouseUp(event); + }; + $(document) + .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + event.preventDefault(); + + mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + + if (event.target == this._mouseDownEvent.target) { + $.data(event.target, this.widgetName + '.preventClickEvent', true); + } + + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(event) {}, + _mouseDrag: function(event) {}, + _mouseStop: function(event) {}, + _mouseCapture: function(event) { return true; } +}); + +})(jQuery); +/* + * jQuery UI Draggable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.draggable", $.ui.mouse, { + widgetEventPrefix: "drag", + options: { + addClasses: true, + appendTo: "parent", + axis: false, + connectToSortable: false, + containment: false, + cursor: "auto", + cursorAt: false, + grid: false, + handle: false, + helper: "original", + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scope: "default", + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false + }, + _create: function() { + + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; + + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); + + this._mouseInit(); + + }, + + destroy: function() { + if(!this.element.data('draggable')) return; + this.element + .removeData("draggable") + .unbind(".draggable") + .removeClass("ui-draggable" + + " ui-draggable-dragging" + + " ui-draggable-disabled"); + this._mouseDestroy(); + + return this; + }, + + _mouseCapture: function(event) { + + var o = this.options; + + // among others, prevent a drag on a resizable-handle + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; + + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; + + if ( o.iframeFix ) { + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>') + .css({ + width: this.offsetWidth+"px", height: this.offsetHeight+"px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + } + + return true; + + }, + + _mouseStart: function(event) { + + var o = this.options; + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + //If ddmanager is used for droppables, set the global draggable + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.positionAbs = this.element.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this.position = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + //Trigger event + callbacks + if(this._trigger("start", event) === false) { + this._clear(); + return false; + } + + //Recache the helper size + this._cacheHelperProportions(); + + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.helper.addClass("ui-draggable-dragging"); + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) + if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); + + return true; + }, + + _mouseDrag: function(event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + if(this._trigger('drag', event, ui) === false) { + this._mouseUp({}); + return false; + } + this.position = ui.position; + } + + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if(this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + //if the original element is removed, don't bother to continue if helper is set to "original" + if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original") + return false; + + if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var self = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + if(self._trigger("stop", event) !== false) { + self._clear(); + } + }); + } else { + if(this._trigger("stop", event) !== false) { + this._clear(); + } + } + + return false; + }, + + _mouseUp: function(event) { + if (this.options.iframeFix === true) { + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); + }); //Remove frame helpers + } + + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) + if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); + + return $.ui.mouse.prototype._mouseUp.call(this, event); + }, + + cancel: function() { + + if(this.helper.is(".ui-draggable-dragging")) { + this._mouseUp({}); + } else { + this._clear(); + } + + return this; + + }, + + _getHandle: function(event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function() { + if(this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); + + if(!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"),10) || 0), + top: (parseInt(this.element.css("marginTop"),10) || 0), + right: (parseInt(this.element.css("marginRight"),10) || 0), + bottom: (parseInt(this.element.css("marginBottom"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, + (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var c = $(o.containment); + var ce = c[0]; if(!ce) return; + var co = c.offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), + (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, + (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom + ]; + this.relative_container = c; + + } else if(o.containment.constructor == Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + var containment; + if(this.containment) { + if (this.relative_container){ + var co = this.relative_container.offset(); + containment = [ this.containment[0] + co.left, + this.containment[1] + co.top, + this.containment[2] + co.left, + this.containment[3] + co.top ]; + } + else { + containment = this.containment; + } + + if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; + } + + if(o.grid) { + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; + pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; + pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins: {}, + + _uiHash: function(event) { + return { + helper: this.helper, + position: this.position, + originalPosition: this.originalPosition, + offset: this.positionAbs + }; + } + +}); + +$.extend($.ui.draggable, { + version: "1.8.18" +}); + +$.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop: function(event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); + + $.each(inst.sortables, function() { + if(this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if(this.shouldRevert) this.instance.options.revert = true; + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if(inst.options.helper == 'original') + this.instance.currentItem.css({ top: 'auto', left: 'auto' }); + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), self = this; + + var checkPos = function(o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; + + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; + + $.each(inst.sortables, function(i) { + + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if(this.instance._intersectsWith(this.instance.containerCache)) { + + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if(!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { return ui.helper[0]; }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if(this.instance.currentItem) this.instance._mouseDrag(event); + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if(this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if(this.instance.placeholder) this.instance.placeholder.remove(); + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + }; + + }); + + } +}); + +$.ui.plugin.add("draggable", "cursor", { + start: function(event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } +}); + +$.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if(t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if(o._opacity) $(ui.helper).css('opacity', o._opacity); + } +}); + +$.ui.plugin.add("draggable", "scroll", { + start: function(event, ui) { + var i = $(this).data("draggable"); + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options, scrolled = false; + + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + + if(!o.axis || o.axis != 'x') { + if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if(!o.axis || o.axis != 'y') { + if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if(!o.axis || o.axis != 'x') { + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if(!o.axis || o.axis != 'y') { + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); + + } +}); + +$.ui.plugin.add("draggable", "snap", { + start: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + var $t = $(this); var $o = $t.offset(); + if(this != i.element[0]) i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; + + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (var i = inst.snapElements.length - 1; i >= 0; i--){ + + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { + if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if(o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if(o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + + if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + }; + + } +}); + +$.ui.plugin.add("draggable", "stack", { + start: function(event, ui) { + + var o = $(this).data("draggable").options; + + var group = $.makeArray($(o.stack)).sort(function(a,b) { + return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); + }); + if (!group.length) { return; } + + var min = parseInt(group[0].style.zIndex) || 0; + $(group).each(function(i) { + this.style.zIndex = min + i; + }); + + this[0].style.zIndex = min + group.length; + + } +}); + +$.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if(t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("draggable").options; + if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } +}); + +})(jQuery); +/* + * jQuery UI Droppable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Droppables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js + */ +(function( $, undefined ) { + +$.widget("ui.droppable", { + widgetEventPrefix: "drop", + options: { + accept: '*', + activeClass: false, + addClasses: true, + greedy: false, + hoverClass: false, + scope: 'default', + tolerance: 'intersect' + }, + _create: function() { + + var o = this.options, accept = o.accept; + this.isover = 0; this.isout = 1; + + this.accept = $.isFunction(accept) ? accept : function(d) { + return d.is(accept); + }; + + //Store the droppable's proportions + this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; + + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; + $.ui.ddmanager.droppables[o.scope].push(this); + + (o.addClasses && this.element.addClass("ui-droppable")); + + }, + + destroy: function() { + var drop = $.ui.ddmanager.droppables[this.options.scope]; + for ( var i = 0; i < drop.length; i++ ) + if ( drop[i] == this ) + drop.splice(i, 1); + + this.element + .removeClass("ui-droppable ui-droppable-disabled") + .removeData("droppable") + .unbind(".droppable"); + + return this; + }, + + _setOption: function(key, value) { + + if(key == 'accept') { + this.accept = $.isFunction(value) ? value : function(d) { + return d.is(value); + }; + } + $.Widget.prototype._setOption.apply(this, arguments); + }, + + _activate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.addClass(this.options.activeClass); + (draggable && this._trigger('activate', event, this.ui(draggable))); + }, + + _deactivate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + (draggable && this._trigger('deactivate', event, this.ui(draggable))); + }, + + _over: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); + this._trigger('over', event, this.ui(draggable)); + } + + }, + + _out: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('out', event, this.ui(draggable)); + } + + }, + + _drop: function(event,custom) { + + var draggable = custom || $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element + + var childrenIntersection = false; + this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, 'droppable'); + if( + inst.options.greedy + && !inst.options.disabled + && inst.options.scope == draggable.options.scope + && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) + && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) + ) { childrenIntersection = true; return false; } + }); + if(childrenIntersection) return false; + + if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('drop', event, this.ui(draggable)); + return this.element; + } + + return false; + + }, + + ui: function(c) { + return { + draggable: (c.currentItem || c.element), + helper: c.helper, + position: c.position, + offset: c.positionAbs + }; + } + +}); + +$.extend($.ui.droppable, { + version: "1.8.18" +}); + +$.ui.intersect = function(draggable, droppable, toleranceMode) { + + if (!droppable.offset) return false; + + var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; + var l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; + + switch (toleranceMode) { + case 'fit': + return (l <= x1 && x2 <= r + && t <= y1 && y2 <= b); + break; + case 'intersect': + return (l < x1 + (draggable.helperProportions.width / 2) // Right Half + && x2 - (draggable.helperProportions.width / 2) < r // Left Half + && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half + && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + break; + case 'pointer': + var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), + isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); + return isOver; + break; + case 'touch': + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + break; + default: + return false; + break; + } + +}; + +/* + This manager tracks offsets of draggables and droppables +*/ +$.ui.ddmanager = { + current: null, + droppables: { 'default': [] }, + prepareOffsets: function(t, event) { + + var m = $.ui.ddmanager.droppables[t.options.scope] || []; + var type = event ? event.type : null; // workaround for #2317 + var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + + droppablesLoop: for (var i = 0; i < m.length; i++) { + + if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted + for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item + m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue + + if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables + + m[i].offset = m[i].element.offset(); + m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; + + } + + }, + drop: function(draggable, event) { + + var dropped = false; + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(!this.options) return; + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) + dropped = this._drop.call(this, event) || dropped; + + if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + this.isout = 1; this.isover = 0; + this._deactivate.call(this, event); + } + + }); + return dropped; + + }, + dragStart: function( draggable, event ) { + //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) + draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + }); + }, + drag: function(draggable, event) { + + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + + //Run through all droppables and check their positions based on specific tolerance options + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(this.options.disabled || this.greedyChild || !this.visible) return; + var intersects = $.ui.intersect(draggable, this, this.options.tolerance); + + var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); + if(!c) return; + + var parentInstance; + if (this.options.greedy) { + var parent = this.element.parents(':data(droppable):eq(0)'); + if (parent.length) { + parentInstance = $.data(parent[0], 'droppable'); + parentInstance.greedyChild = (c == 'isover' ? 1 : 0); + } + } + + // we just moved into a greedy child + if (parentInstance && c == 'isover') { + parentInstance['isover'] = 0; + parentInstance['isout'] = 1; + parentInstance._out.call(parentInstance, event); + } + + this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; + this[c == "isover" ? "_over" : "_out"].call(this, event); + + // we just moved out of a greedy child + if (parentInstance && c == 'isout') { + parentInstance['isout'] = 0; + parentInstance['isover'] = 1; + parentInstance._over.call(parentInstance, event); + } + }); + + }, + dragStop: function( draggable, event ) { + draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); + //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + } +}; + +})(jQuery); +/* + * jQuery UI Resizable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.resizable", $.ui.mouse, { + widgetEventPrefix: "resize", + options: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + containment: false, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + zIndex: 1000 + }, + _create: function() { + + var self = this, o = this.options; + this.element.addClass("ui-resizable"); + + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null + }); + + //Wrap the element if it cannot hold child nodes + if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { + + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({ + position: this.element.css('position'), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css('top'), + left: this.element.css('left') + }) + ); + + //Overwrite the original this.element + this.element = this.element.parent().data( + "resizable", this.element.data('resizable') + ); + + this.elementIsWrapper = true; + + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); + + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css('resize'); + this.originalElement.css('resize', 'none'); + + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); + + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css('margin') }); + + // fix handlers offset + this._proportionallyResize(); + + } + + this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); + if(this.handles.constructor == String) { + + if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; + var n = this.handles.split(","); this.handles = {}; + + for(var i = 0; i < n.length; i++) { + + var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; + var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>'); + + // increase zIndex of sw, se, ne, nw axis + //TODO : this modifies original option + if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex }); + + //TODO : What's going on here? + if ('se' == handle) { + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); + }; + + //Insert into internal handles object and append to element + this.handles[handle] = '.ui-resizable-'+handle; + this.element.append(axis); + } + + } + + this._renderAxis = function(target) { + + target = target || this.element; + + for(var i in this.handles) { + + if(this.handles[i].constructor == String) + this.handles[i] = $(this.handles[i], this.element).show(); + + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + + var axis = $(this.handles[i], this.element), padWrapper = 0; + + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + + //The padding type i have to apply... + var padPos = [ 'padding', + /ne|nw|n/.test(i) ? 'Top' : + /se|sw|s/.test(i) ? 'Bottom' : + /^e$/.test(i) ? 'Right' : 'Left' ].join(""); + + target.css(padPos, padWrapper); + + this._proportionallyResize(); + + } + + //TODO: What's that good for? There's not anything to be executed left + if(!$(this.handles[i]).length) + continue; + + } + }; + + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); + + this._handles = $('.ui-resizable-handle', this.element) + .disableSelection(); + + //Matching axis name + this._handles.mouseover(function() { + if (!self.resizing) { + if (this.className) + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + //Axis, default = se + self.axis = axis && axis[1] ? axis[1] : 'se'; + } + }); + + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .hover(function() { + if (o.disabled) return; + $(this).removeClass("ui-resizable-autohide"); + self._handles.show(); + }, + function(){ + if (o.disabled) return; + if (!self.resizing) { + $(this).addClass("ui-resizable-autohide"); + self._handles.hide(); + } + }); + } + + //Initialize the mouse interaction + this._mouseInit(); + + }, + + destroy: function() { + + this._mouseDestroy(); + + var _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); + }; + + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + var wrapper = this.element; + wrapper.after( + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }) + ).remove(); + } + + this.originalElement.css('resize', this.originalResizeStyle); + _destroy(this.originalElement); + + return this; + }, + + _mouseCapture: function(event) { + var handle = false; + for (var i in this.handles) { + if ($(this.handles[i])[0] == event.target) { + handle = true; + } + } + + return !this.options.disabled && handle; + }, + + _mouseStart: function(event) { + + var o = this.options, iniPos = this.element.position(), el = this.element; + + this.resizing = true; + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; + + // bugfix for http://dev.jquery.com/ticket/1749 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); + } + + this._renderProxy(); + + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); + + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; + } + + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; + + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); + + var cursor = $('.ui-resizable-' + this.axis).css('cursor'); + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); + + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; + }, + + _mouseDrag: function(event) { + + //Increase performance, avoid regex + var el = this.helper, o = this.options, props = {}, + self = this, smp = this.originalMousePosition, a = this.axis; + + var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; + var trigger = this._change[a]; + if (!trigger) return false; + + // Calculate the attrs that will be change + var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; + + // Put this in the mouseDrag handler since the user can start pressing shift while resizing + this._updateVirtualBoundaries(event.shiftKey); + if (this._aspectRatio || event.shiftKey) + data = this._updateRatio(data, event); + + data = this._respectSize(data, event); + + // plugins callbacks need to be called first + this._propagate("resize", event); + + el.css({ + top: this.position.top + "px", left: this.position.left + "px", + width: this.size.width + "px", height: this.size.height + "px" + }); + + if (!this._helper && this._proportionallyResizeElements.length) + this._proportionallyResize(); + + this._updateCache(data); + + // calling the user callback at the end + this._trigger('resize', event, this.ui()); + + return false; + }, + + _mouseStop: function(event) { + + this.resizing = false; + var o = this.options, self = this; + + if(this._helper) { + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + if (!o.animate) + this.element.css($.extend(s, { top: top, left: left })); + + self.helper.height(self.size.height); + self.helper.width(self.size.width); + + if (this._helper && !o.animate) this._proportionallyResize(); + } + + $('body').css('cursor', 'auto'); + + this.element.removeClass("ui-resizable-resizing"); + + this._propagate("stop", event); + + if (this._helper) this.helper.remove(); + return false; + + }, + + _updateVirtualBoundaries: function(forceAspectRatio) { + var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; + + b = { + minWidth: isNumber(o.minWidth) ? o.minWidth : 0, + maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, + minHeight: isNumber(o.minHeight) ? o.minHeight : 0, + maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity + }; + + if(this._aspectRatio || forceAspectRatio) { + // We want to create an enclosing box whose aspect ration is the requested one + // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension + pMinWidth = b.minHeight * this.aspectRatio; + pMinHeight = b.minWidth / this.aspectRatio; + pMaxWidth = b.maxHeight * this.aspectRatio; + pMaxHeight = b.maxWidth / this.aspectRatio; + + if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; + if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; + if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; + if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; + } + this._vBoundaries = b; + }, + + _updateCache: function(data) { + var o = this.options; + this.offset = this.helper.offset(); + if (isNumber(data.left)) this.position.left = data.left; + if (isNumber(data.top)) this.position.top = data.top; + if (isNumber(data.height)) this.size.height = data.height; + if (isNumber(data.width)) this.size.width = data.width; + }, + + _updateRatio: function(data, event) { + + var o = this.options, cpos = this.position, csize = this.size, a = this.axis; + + if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); + else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); + + if (a == 'sw') { + data.left = cpos.left + (csize.width - data.width); + data.top = null; + } + if (a == 'nw') { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); + } + + return data; + }, + + _respectSize: function(data, event) { + + var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); + + if (isminw) data.width = o.minWidth; + if (isminh) data.height = o.minHeight; + if (ismaxw) data.width = o.maxWidth; + if (ismaxh) data.height = o.maxHeight; + + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); + + if (isminw && cw) data.left = dw - o.minWidth; + if (ismaxw && cw) data.left = dw - o.maxWidth; + if (isminh && ch) data.top = dh - o.minHeight; + if (ismaxh && ch) data.top = dh - o.maxHeight; + + // fixing jump error on top/left - bug #2330 + var isNotwh = !data.width && !data.height; + if (isNotwh && !data.left && data.top) data.top = null; + else if (isNotwh && !data.top && data.left) data.left = null; + + return data; + }, + + _proportionallyResize: function() { + + var o = this.options; + if (!this._proportionallyResizeElements.length) return; + var element = this.helper || this.element; + + for (var i=0; i < this._proportionallyResizeElements.length; i++) { + + var prel = this._proportionallyResizeElements[i]; + + if (!this.borderDif) { + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; + + this.borderDif = $.map(b, function(v, i) { + var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; + return border + padding; + }); + } + + if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) + continue; + + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); + + }; + + }, + + _renderProxy: function() { + + var el = this.element, o = this.options; + this.elementOffset = el.offset(); + + if(this._helper) { + + this.helper = this.helper || $('<div style="overflow:hidden;"></div>'); + + // fix ie6 offset TODO: This seems broken + var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), + pxyoffset = ( ie6 ? 2 : -1 ); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() + pxyoffset, + height: this.element.outerHeight() + pxyoffset, + position: 'absolute', + left: this.elementOffset.left - ie6offset +'px', + top: this.elementOffset.top - ie6offset +'px', + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; + } + + }, + + _change: { + e: function(event, dx, dy) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + } + }, + + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n != "resize" && this._trigger(n, event, this.ui())); + }, + + plugins: {}, + + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } + +}); + +$.extend($.ui.resizable, { + version: "1.8.18" +}); + +/* + * Resizable Extensions + */ + +$.ui.plugin.add("resizable", "alsoResize", { + + start: function (event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var _store = function (exp) { + $(exp).each(function() { + var el = $(this); + el.data("resizable-alsoresize", { + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), + left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) + }); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } + else { $.each(o.alsoResize, function (exp) { _store(exp); }); } + }else{ + _store(o.alsoResize); + } + }, + + resize: function (event, ui) { + var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; + + var delta = { + height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, + top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 + }, + + _alsoResize = function (exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, + css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; + + $.each(css, function (i, prop) { + var sum = (start[prop]||0) + (delta[prop]||0); + if (sum && sum >= 0) + style[prop] = sum || null; + }); + + el.css(style); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); + }else{ + _alsoResize(o.alsoResize); + } + }, + + stop: function (event, ui) { + $(this).removeData("resizable-alsoresize"); + } +}); + +$.ui.plugin.add("resizable", "animate", { + + stop: function(event, ui) { + var self = $(this).data("resizable"), o = self.options; + + var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, + soffsetw = ista ? 0 : self.sizeDiff.width; + + var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, + left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, + top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; + + self.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(self.element.css('width'), 10), + height: parseInt(self.element.css('height'), 10), + top: parseInt(self.element.css('top'), 10), + left: parseInt(self.element.css('left'), 10) + }; + + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); + + // propagating resize, and updating values for each animation step + self._updateCache(data); + self._propagate("resize", event); + + } + } + ); + } + +}); + +$.ui.plugin.add("resizable", "containment", { + + start: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, el = self.element; + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + if (!ce) return; + + self.containerElement = $(ce); + + if (/document/.test(oc) || oc == document) { + self.containerOffset = { left: 0, top: 0 }; + self.containerPosition = { left: 0, top: 0 }; + + self.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; + } + + // i'm a node, so compute top, left, right, bottom + else { + var element = $(ce), p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); + + self.containerOffset = element.offset(); + self.containerPosition = element.position(); + self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; + + var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); + + self.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; + } + }, + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, + ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, + pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; + + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; + + if (cp.left < (self._helper ? co.left : 0)) { + self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); + if (pRatio) self.size.height = self.size.width / o.aspectRatio; + self.position.left = o.helper ? co.left : 0; + } + + if (cp.top < (self._helper ? co.top : 0)) { + self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); + if (pRatio) self.size.width = self.size.height * o.aspectRatio; + self.position.top = self._helper ? co.top : 0; + } + + self.offset.left = self.parentData.left+self.position.left; + self.offset.top = self.parentData.top+self.position.top; + + var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), + hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); + + var isParent = self.containerElement.get(0) == self.element.parent().get(0), + isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); + + if(isParent && isOffsetRelative) woset -= self.parentData.left; + + if (woset + self.size.width >= self.parentData.width) { + self.size.width = self.parentData.width - woset; + if (pRatio) self.size.height = self.size.width / self.aspectRatio; + } + + if (hoset + self.size.height >= self.parentData.height) { + self.size.height = self.parentData.height - hoset; + if (pRatio) self.size.width = self.size.height * self.aspectRatio; + } + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"), o = self.options, cp = self.position, + co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; + + var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; + + if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + if (self._helper && !o.animate && (/static/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + } +}); + +$.ui.plugin.add("resizable", "ghost", { + + start: function(event, ui) { + + var self = $(this).data("resizable"), o = self.options, cs = self.size; + + self.ghost = self.originalElement.clone(); + self.ghost + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass('ui-resizable-ghost') + .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + + self.ghost.appendTo(self.helper); + + }, + + resize: function(event, ui){ + var self = $(this).data("resizable"), o = self.options; + if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); + }, + + stop: function(event, ui){ + var self = $(this).data("resizable"), o = self.options; + if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); + } + +}); + +$.ui.plugin.add("resizable", "grid", { + + resize: function(event, ui) { + var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; + var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); + + if (/^(se|s|e)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + } + else if (/^(ne)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + } + else if (/^(sw)$/.test(a)) { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.left = op.left - ox; + } + else { + self.size.width = os.width + ox; + self.size.height = os.height + oy; + self.position.top = op.top - oy; + self.position.left = op.left - ox; + } + } + +}); + +var num = function(v) { + return parseInt(v, 10) || 0; +}; + +var isNumber = function(value) { + return !isNaN(parseInt(value, 10)); +}; + +})(jQuery); +/* + * jQuery UI Selectable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.selectable", $.ui.mouse, { + options: { + appendTo: 'body', + autoRefresh: true, + distance: 0, + filter: '*', + tolerance: 'touch' + }, + _create: function() { + var self = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(self.options.filter, self.element[0]); + selectees.addClass("ui-selectee"); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("<div class='ui-selectable-helper'></div>"); + }, + + destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled") + .removeData("selectable") + .unbind(".selectable"); + this._mouseDestroy(); + + return this; + }, + + _mouseStart: function(event) { + var self = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) + return; + + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey && !event.ctrlKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected'); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + self._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + return false; + } + }); + + }, + + _mouseDrag: function(event) { + var self = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == self.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + self._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if ((event.metaKey || event.ctrlKey) && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + self._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var self = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + self._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + self._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +}); + +$.extend($.ui.selectable, { + version: "1.8.18" +}); + +})(jQuery); +/* + * jQuery UI Sortable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.sortable", $.ui.mouse, { + widgetEventPrefix: "sort", + ready: false, + options: { + appendTo: "parent", + axis: false, + connectWith: false, + containment: false, + cursor: 'auto', + cursorAt: false, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: '> *', + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000 + }, + _create: function() { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are being displayed horizontally + this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + //We're ready to go + this.ready = true + + }, + + destroy: function() { + $.Widget.prototype.destroy.call( this ); + this.element + .removeClass("ui-sortable ui-sortable-disabled"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) + this.items[i].item.removeData(this.widgetName + "-item"); + + return this; + }, + + _setOption: function(key, value){ + if ( key === "disabled" ) { + this.options[ key ] = value; + + this.widget() + [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" ); + } else { + // Don't call widget base _setOption for disable as it adds ui-state-disabled class + $.Widget.prototype._setOption.apply(this, arguments); + } + }, + + _mouseCapture: function(event, overrideHandle) { + var that = this; + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { + if($.data(this, that.widgetName + '-item') == self) { + currentItem = $(this); + return false; + } + }); + if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target); + + if(!currentItem) return false; + if(this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); + if(!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart: function(event, overrideHandle, noActivation) { + + var o = this.options, self = this; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + if(o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); + } + + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } + + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if(!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } + } + + //Prepare possible droppables + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag: function(event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if(this.options.scroll) { + var o = this.options, scrolled = false; + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + if(itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) + //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event, noPropagation) { + + if(!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if(this.options.revert) { + var self = this; + var cur = self.placeholder.offset(); + + self.reverting = true; + + $(this.helper).animate({ + left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function() { + self._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel: function() { + + var self = this; + + if(this.dragging) { + + this._mouseUp({ target: null }); + + if(this.options.helper == "original") + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + else + this.currentItem.show(); + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + this.containers[i]._trigger("deactivate", null, self._uiHash(this)); + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, self._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + } + + return this; + + }, + + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); + }); + + if(!str.length && o.key) { + str.push(o.key + '='); + } + + return str.join('&'); + + }, + + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if( this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function(item) { + + var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + + }, + + _intersectsWithSides: function(item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); + }, + + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + return this; + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; + }, + + _getItemsAsjQuery: function(connected) { + + var self = this; + var items = []; + var queries = []; + var connectWith = this._connectWith(); + + if(connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], this.widgetName); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); + } + }; + }; + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); + + for (var i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + }; + + return $(items); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); + + for (var i=0; i < this.items.length; i++) { + + for (var j=0; j < list.length; j++) { + if(list[j] == this.items[i].item[0]) + this.items.splice(i,1); + }; + + }; + + }, + + _refreshItems: function(event) { + + this.items = []; + this.containers = [this]; + var items = this.items; + var self = this; + var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; + var connectWith = this._connectWith(); + + if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], this.widgetName); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + }; + }; + } + + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; + + for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); + + item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) + + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + }; + }; + + }, + + refreshPositions: function(fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + for (var i = this.items.length - 1; i >= 0; i--){ + var item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + var p = t.offset(); + item.left = p.left; + item.top = p.top; + }; + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--){ + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + }; + } + + return this; + }, + + _createPlaceholder: function(that) { + + var self = that || this, o = self.options; + + if(!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element: function() { + + var el = $(document.createElement(self.currentItem[0].nodeName)) + .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if(!className) + el.style.visibility = "hidden"; + + return el; + }, + update: function(container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; + if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; + } + }; + } + + //Create the placeholder + self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); + + //Append it after the actual current item + self.currentItem.after(self.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(self, self.placeholder); + + }, + + _contactContainers: function(event) { + + // get innermost container that intersects with item + var innermostContainer = null, innermostIndex = null; + + + for (var i = this.containers.length - 1; i >= 0; i--){ + + // never consider a container that's located within the item itself + if($.ui.contains(this.currentItem[0], this.containers[i].element[0])) + continue; + + if(this._intersectsWith(this.containers[i].containerCache)) { + + // if we've already found a container and it's more "inner" than this, then continue + if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) + continue; + + innermostContainer = this.containers[i]; + innermostIndex = i; + + } else { + // container doesn't intersect. trigger "out" event if necessary + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + // if no intersecting containers found, return + if(!innermostContainer) return; + + // move the item into the container if it's not there already + if(this.containers.length === 1) { + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } else if(this.currentContainer != this.containers[innermostIndex]) { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; + for (var j = this.items.length - 1; j >= 0; j--) { + if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; + var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + } + } + + if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + return; + + this.currentContainer = this.containers[innermostIndex]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } + + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); + + if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + + if(helper[0] == this.currentItem[0]) + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + + if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.currentItem.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange: function(event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var self = this, counter = this.counter; + + window.setTimeout(function() { + if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + },0); + + }, + + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = [], self = this; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if(this.helper[0] == this.currentItem[0]) { + for(var i in this._storedCSS) { + if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed + if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element + if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + for (var i = this.containers.length - 1; i >= 0; i--){ + if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + } + }; + }; + + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity + if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + return false; + } + + if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + + if(!noPropagation) { + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger: function() { + if ($.Widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash: function(inst) { + var self = inst || this; + return { + helper: self.helper, + placeholder: self.placeholder || $([]), + position: self.position, + originalPosition: self.originalPosition, + offset: self.positionAbs, + item: self.currentItem, + sender: inst ? inst.element : null + }; + } + +}); + +$.extend($.ui.sortable, { + version: "1.8.18" +}); + +})(jQuery); +/* + * jQuery UI Effects 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */ +;jQuery.effects || (function($, undefined) { + +$.effects = {}; + + + +/******************************************************************************/ +/****************************** COLOR ANIMATIONS ******************************/ +/******************************************************************************/ + +// override the animation for color styles +$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', + 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'], +function(i, attr) { + $.fx.step[attr] = function(fx) { + if (!fx.colorInit) { + fx.start = getColor(fx.elem, attr); + fx.end = getRGB(fx.end); + fx.colorInit = true; + } + + fx.elem.style[attr] = 'rgb(' + + Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' + + Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' + + Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')'; + }; +}); + +// Color Conversion functions from highlightFade +// By Blair Mitchelmore +// http://jquery.offput.ca/highlightFade/ + +// Parse strings looking for color tuples [255,255,255] +function getRGB(color) { + var result; + + // Check if we're already dealing with an array of colors + if ( color && color.constructor == Array && color.length == 3 ) + return color; + + // Look for rgb(num,num,num) + if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) + return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; + + // Look for rgb(num%,num%,num%) + if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) + return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; + + // Look for #a0b1c2 + if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) + return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; + + // Look for #fff + if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) + return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; + + // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 + if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) + return colors['transparent']; + + // Otherwise, we're most likely dealing with a named color + return colors[$.trim(color).toLowerCase()]; +} + +function getColor(elem, attr) { + var color; + + do { + color = $.curCSS(elem, attr); + + // Keep going until we find an element that has color, or we hit the body + if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) + break; + + attr = "backgroundColor"; + } while ( elem = elem.parentNode ); + + return getRGB(color); +}; + +// Some named colors to work with +// From Interface by Stefan Petre +// http://interface.eyecon.ro/ + +var colors = { + aqua:[0,255,255], + azure:[240,255,255], + beige:[245,245,220], + black:[0,0,0], + blue:[0,0,255], + brown:[165,42,42], + cyan:[0,255,255], + darkblue:[0,0,139], + darkcyan:[0,139,139], + darkgrey:[169,169,169], + darkgreen:[0,100,0], + darkkhaki:[189,183,107], + darkmagenta:[139,0,139], + darkolivegreen:[85,107,47], + darkorange:[255,140,0], + darkorchid:[153,50,204], + darkred:[139,0,0], + darksalmon:[233,150,122], + darkviolet:[148,0,211], + fuchsia:[255,0,255], + gold:[255,215,0], + green:[0,128,0], + indigo:[75,0,130], + khaki:[240,230,140], + lightblue:[173,216,230], + lightcyan:[224,255,255], + lightgreen:[144,238,144], + lightgrey:[211,211,211], + lightpink:[255,182,193], + lightyellow:[255,255,224], + lime:[0,255,0], + magenta:[255,0,255], + maroon:[128,0,0], + navy:[0,0,128], + olive:[128,128,0], + orange:[255,165,0], + pink:[255,192,203], + purple:[128,0,128], + violet:[128,0,128], + red:[255,0,0], + silver:[192,192,192], + white:[255,255,255], + yellow:[255,255,0], + transparent: [255,255,255] +}; + + + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ + +var classAnimationActions = ['add', 'remove', 'toggle'], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +function getElementStyles() { + var style = document.defaultView + ? document.defaultView.getComputedStyle(this, null) + : this.currentStyle, + newStyle = {}, + key, + camelCase; + + // webkit enumerates style porperties + if (style && style.length && style[0] && style[style[0]]) { + var len = style.length; + while (len--) { + key = style[len]; + if (typeof style[key] == 'string') { + camelCase = key.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + newStyle[camelCase] = style[key]; + } + } + } else { + for (key in style) { + if (typeof style[key] === 'string') { + newStyle[key] = style[key]; + } + } + } + + return newStyle; +} + +function filterStyles(styles) { + var name, value; + for (name in styles) { + value = styles[name]; + if ( + // ignore null and undefined values + value == null || + // ignore functions (when does this occur?) + $.isFunction(value) || + // shorthand styles that need to be expanded + name in shorthandStyles || + // ignore scrollbars (break in IE) + (/scrollbar/).test(name) || + + // only colors or values that can be converted to numbers + (!(/color/i).test(name) && isNaN(parseFloat(value))) + ) { + delete styles[name]; + } + } + + return styles; +} + +function styleDifference(oldStyle, newStyle) { + var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459 + name; + + for (name in newStyle) { + if (oldStyle[name] != newStyle[name]) { + diff[name] = newStyle[name]; + } + } + + return diff; +} + +$.effects.animateClass = function(value, duration, easing, callback) { + if ($.isFunction(easing)) { + callback = easing; + easing = null; + } + + return this.queue(function() { + var that = $(this), + originalStyleAttr = that.attr('style') || ' ', + originalStyle = filterStyles(getElementStyles.call(this)), + newStyle, + className = that.attr('class'); + + $.each(classAnimationActions, function(i, action) { + if (value[action]) { + that[action + 'Class'](value[action]); + } + }); + newStyle = filterStyles(getElementStyles.call(this)); + that.attr('class', className); + + that.animate(styleDifference(originalStyle, newStyle), { + queue: false, + duration: duration, + easing: easing, + complete: function() { + $.each(classAnimationActions, function(i, action) { + if (value[action]) { that[action + 'Class'](value[action]); } + }); + // work around bug in IE by clearing the cssText before setting it + if (typeof that.attr('style') == 'object') { + that.attr('style').cssText = ''; + that.attr('style').cssText = originalStyleAttr; + } else { + that.attr('style', originalStyleAttr); + } + if (callback) { callback.apply(this, arguments); } + $.dequeue( this ); + } + }); + }); +}; + +$.fn.extend({ + _addClass: $.fn.addClass, + addClass: function(classNames, speed, easing, callback) { + return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); + }, + + _removeClass: $.fn.removeClass, + removeClass: function(classNames,speed,easing,callback) { + return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); + }, + + _toggleClass: $.fn.toggleClass, + toggleClass: function(classNames, force, speed, easing, callback) { + if ( typeof force == "boolean" || force === undefined ) { + if ( !speed ) { + // without speed parameter; + return this._toggleClass(classNames, force); + } else { + return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]); + } + } else { + // without switch parameter; + return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]); + } + }, + + switchClass: function(remove,add,speed,easing,callback) { + return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); + } +}); + + + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +$.extend($.effects, { + version: "1.8.18", + + // Saves a set of properties in a data storage + save: function(element, set) { + for(var i=0; i < set.length; i++) { + if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]); + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function(element, set) { + for(var i=0; i < set.length; i++) { + if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i])); + } + }, + + setMode: function(el, mode) { + if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle + return mode; + }, + + getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value + // this should be a little more flexible in the future to handle a string & hash + var y, x; + switch (origin[0]) { + case 'top': y = 0; break; + case 'middle': y = 0.5; break; + case 'bottom': y = 1; break; + default: y = origin[0] / original.height; + }; + switch (origin[1]) { + case 'left': x = 0; break; + case 'center': x = 0.5; break; + case 'right': x = 1; break; + default: x = origin[1] / original.width; + }; + return {x: x, y: y}; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function(element) { + + // if the element is already wrapped, return it + if (element.parent().is('.ui-effects-wrapper')) { + return element.parent(); + } + + // wrap the element + var props = { + width: element.outerWidth(true), + height: element.outerHeight(true), + 'float': element.css('float') + }, + wrapper = $('<div></div>') + .addClass('ui-effects-wrapper') + .css({ + fontSize: '100%', + background: 'transparent', + border: 'none', + margin: 0, + padding: 0 + }), + active = document.activeElement; + + element.wrap(wrapper); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + + wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element + + // transfer positioning properties to the wrapper + if (element.css('position') == 'static') { + wrapper.css({ position: 'relative' }); + element.css({ position: 'relative' }); + } else { + $.extend(props, { + position: element.css('position'), + zIndex: element.css('z-index') + }); + $.each(['top', 'left', 'bottom', 'right'], function(i, pos) { + props[pos] = element.css(pos); + if (isNaN(parseInt(props[pos], 10))) { + props[pos] = 'auto'; + } + }); + element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' }); + } + + return wrapper.css(props).show(); + }, + + removeWrapper: function(element) { + var parent, + active = document.activeElement; + + if (element.parent().is('.ui-effects-wrapper')) { + parent = element.parent().replaceWith(element); + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + return parent; + } + + return element; + }, + + setTransition: function(element, list, factor, value) { + value = value || {}; + $.each(list, function(i, x){ + unit = element.cssUnit(x); + if (unit[0] > 0) value[x] = unit[0] * factor + unit[1]; + }); + return value; + } +}); + + +function _normalizeArguments(effect, options, speed, callback) { + // shift params for method overloading + if (typeof effect == 'object') { + callback = options; + speed = null; + options = effect; + effect = options.effect; + } + if ($.isFunction(options)) { + callback = options; + speed = null; + options = {}; + } + if (typeof options == 'number' || $.fx.speeds[options]) { + callback = speed; + speed = options; + options = {}; + } + if ($.isFunction(speed)) { + callback = speed; + speed = null; + } + + options = options || {}; + + speed = speed || options.duration; + speed = $.fx.off ? 0 : typeof speed == 'number' + ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default; + + callback = callback || options.complete; + + return [effect, options, speed, callback]; +} + +function standardSpeed( speed ) { + // valid standard speeds + if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { + return true; + } + + // invalid strings - treat as "normal" speed + if ( typeof speed === "string" && !$.effects[ speed ] ) { + return true; + } + + return false; +} + +$.fn.extend({ + effect: function(effect, options, speed, callback) { + var args = _normalizeArguments.apply(this, arguments), + // TODO: make effects take actual parameters instead of a hash + args2 = { + options: args[1], + duration: args[2], + callback: args[3] + }, + mode = args2.options.mode, + effectMethod = $.effects[effect]; + + if ( $.fx.off || !effectMethod ) { + // delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args2.duration, args2.callback ); + } else { + return this.each(function() { + if ( args2.callback ) { + args2.callback.call( this ); + } + }); + } + } + + return effectMethod.call(this, args2); + }, + + _show: $.fn.show, + show: function(speed) { + if ( standardSpeed( speed ) ) { + return this._show.apply(this, arguments); + } else { + var args = _normalizeArguments.apply(this, arguments); + args[1].mode = 'show'; + return this.effect.apply(this, args); + } + }, + + _hide: $.fn.hide, + hide: function(speed) { + if ( standardSpeed( speed ) ) { + return this._hide.apply(this, arguments); + } else { + var args = _normalizeArguments.apply(this, arguments); + args[1].mode = 'hide'; + return this.effect.apply(this, args); + } + }, + + // jQuery core overloads toggle and creates _toggle + __toggle: $.fn.toggle, + toggle: function(speed) { + if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { + return this.__toggle.apply(this, arguments); + } else { + var args = _normalizeArguments.apply(this, arguments); + args[1].mode = 'toggle'; + return this.effect.apply(this, args); + } + }, + + // helper functions + cssUnit: function(key) { + var style = this.css(key), val = []; + $.each( ['em','px','%','pt'], function(i, unit){ + if(style.indexOf(unit) > 0) + val = [parseFloat(style), unit]; + }); + return val; + } +}); + + + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +/* + * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ + * + * Uses the built in easing capabilities added In jQuery 1.1 + * to offer multiple easing options + * + * TERMS OF USE - jQuery Easing + * + * Open source under the BSD License. + * + * Copyright 2008 George McGinley Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +// t: current time, b: begInnIng value, c: change In value, d: duration +$.easing.jswing = $.easing.swing; + +$.extend($.easing, +{ + def: 'easeOutQuad', + swing: function (x, t, b, c, d) { + //alert($.easing.default); + return $.easing[$.easing.def](x, t, b, c, d); + }, + easeInQuad: function (x, t, b, c, d) { + return c*(t/=d)*t + b; + }, + easeOutQuad: function (x, t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + easeInOutQuad: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + }, + easeInCubic: function (x, t, b, c, d) { + return c*(t/=d)*t*t + b; + }, + easeOutCubic: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t + 1) + b; + }, + easeInOutCubic: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + }, + easeInQuart: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t + b; + }, + easeOutQuart: function (x, t, b, c, d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; + }, + easeInOutQuart: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t + b; + return -c/2 * ((t-=2)*t*t*t - 2) + b; + }, + easeInQuint: function (x, t, b, c, d) { + return c*(t/=d)*t*t*t*t + b; + }, + easeOutQuint: function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t*t*t + 1) + b; + }, + easeInOutQuint: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; + return c/2*((t-=2)*t*t*t*t + 2) + b; + }, + easeInSine: function (x, t, b, c, d) { + return -c * Math.cos(t/d * (Math.PI/2)) + c + b; + }, + easeOutSine: function (x, t, b, c, d) { + return c * Math.sin(t/d * (Math.PI/2)) + b; + }, + easeInOutSine: function (x, t, b, c, d) { + return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; + }, + easeInExpo: function (x, t, b, c, d) { + return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; + }, + easeOutExpo: function (x, t, b, c, d) { + return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; + }, + easeInOutExpo: function (x, t, b, c, d) { + if (t==0) return b; + if (t==d) return b+c; + if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; + return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; + }, + easeInCirc: function (x, t, b, c, d) { + return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; + }, + easeOutCirc: function (x, t, b, c, d) { + return c * Math.sqrt(1 - (t=t/d-1)*t) + b; + }, + easeInOutCirc: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; + return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; + }, + easeInElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + }, + easeOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; + }, + easeInOutElastic: function (x, t, b, c, d) { + var s=1.70158;var p=0;var a=c; + if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); + if (a < Math.abs(c)) { a=c; var s=p/4; } + else var s = p/(2*Math.PI) * Math.asin (c/a); + if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; + return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; + }, + easeInBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*(t/=d)*t*((s+1)*t - s) + b; + }, + easeOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; + }, + easeInOutBack: function (x, t, b, c, d, s) { + if (s == undefined) s = 1.70158; + if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; + return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; + }, + easeInBounce: function (x, t, b, c, d) { + return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b; + }, + easeOutBounce: function (x, t, b, c, d) { + if ((t/=d) < (1/2.75)) { + return c*(7.5625*t*t) + b; + } else if (t < (2/2.75)) { + return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; + } else if (t < (2.5/2.75)) { + return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; + } else { + return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; + } + }, + easeInOutBounce: function (x, t, b, c, d) { + if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; + return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; + } +}); + +/* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +})(jQuery); +/* + * jQuery UI Effects Blind 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Blind + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.blind = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'vertical'; // Default direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var ref = (direction == 'vertical') ? 'height' : 'width'; + var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width(); + if(mode == 'show') wrapper.css(ref, 0); // Shift + + // Animation + var animation = {}; + animation[ref] = mode == 'show' ? distance : 0; + + // Animate + wrapper.animate(animation, o.duration, o.options.easing, function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Bounce 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Bounce + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.bounce = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var direction = o.options.direction || 'up'; // Default direction + var distance = o.options.distance || 20; // Default distance + var times = o.options.times || 5; // Default # of times + var speed = o.duration || 250; // Default speed per bounce + if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3); + if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift + if (mode == 'hide') distance = distance / (times * 2); + if (mode != 'hide') times--; + + // Animate + if (mode == 'show') { // Show Bounce + var animation = {opacity: 1}; + animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation, speed / 2, o.options.easing); + distance = distance / 2; + times--; + }; + for (var i = 0; i < times; i++) { // Bounces + var animation1 = {}, animation2 = {}; + animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing); + distance = (mode == 'hide') ? distance * 2 : distance / 2; + }; + if (mode == 'hide') { // Last Bounce + var animation = {opacity: 0}; + animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + el.animate(animation, speed / 2, o.options.easing, function(){ + el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + } else { + var animation1 = {}, animation2 = {}; + animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; + el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){ + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + }; + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Clip 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Clip + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.clip = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right','height','width']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'vertical'; // Default direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var animate = el[0].tagName == 'IMG' ? wrapper : el; + var ref = { + size: (direction == 'vertical') ? 'height' : 'width', + position: (direction == 'vertical') ? 'top' : 'left' + }; + var distance = (direction == 'vertical') ? animate.height() : animate.width(); + if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift + + // Animation + var animation = {}; + animation[ref.size] = mode == 'show' ? distance : 0; + animation[ref.position] = mode == 'show' ? 0 : distance / 2; + + // Animate + animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Drop 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Drop + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.drop = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right','opacity']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var direction = o.options.direction || 'left'; // Default Direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2); + if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift + + // Animation + var animation = {opacity: mode == 'show' ? 1 : 0}; + animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Explode 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Explode + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.explode = function(o) { + + return this.queue(function() { + + var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; + + o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode; + var el = $(this).show().css('visibility', 'hidden'); + var offset = el.offset(); + + //Substract the margins - not fixing the problem yet. + offset.top -= parseInt(el.css("marginTop"),10) || 0; + offset.left -= parseInt(el.css("marginLeft"),10) || 0; + + var width = el.outerWidth(true); + var height = el.outerHeight(true); + + for(var i=0;i<rows;i++) { // = + for(var j=0;j<cells;j++) { // || + el + .clone() + .appendTo('body') + .wrap('<div></div>') + .css({ + position: 'absolute', + visibility: 'visible', + left: -j*(width/cells), + top: -i*(height/rows) + }) + .parent() + .addClass('ui-effects-explode') + .css({ + position: 'absolute', + overflow: 'hidden', + width: width/cells, + height: height/rows, + left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0), + top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0), + opacity: o.options.mode == 'show' ? 0 : 1 + }).animate({ + left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)), + top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)), + opacity: o.options.mode == 'show' ? 1 : 0 + }, o.duration || 500); + } + } + + // Set a timeout, to call the callback approx. when the other animations have finished + setTimeout(function() { + + o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide(); + if(o.callback) o.callback.apply(el[0]); // Callback + el.dequeue(); + + $('div.ui-effects-explode').remove(); + + }, o.duration || 500); + + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Fade 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.fade = function(o) { + return this.queue(function() { + var elem = $(this), + mode = $.effects.setMode(elem, o.options.mode || 'hide'); + + elem.animate({ opacity: mode }, { + queue: false, + duration: o.duration, + easing: o.options.easing, + complete: function() { + (o.callback && o.callback.apply(this, arguments)); + elem.dequeue(); + } + }); + }); +}; + +})(jQuery); +/* + * jQuery UI Effects Fold 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.fold = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode + var size = o.options.size || 15; // Default fold size + var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value + var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var widthFirst = ((mode == 'show') != horizFirst); + var ref = widthFirst ? ['width', 'height'] : ['height', 'width']; + var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()]; + var percent = /([0-9]+)%/.exec(size); + if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1]; + if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift + + // Animation + var animation1 = {}, animation2 = {}; + animation1[ref[0]] = mode == 'show' ? distance[0] : size; + animation2[ref[1]] = mode == 'show' ? distance[1] : 0; + + // Animate + wrapper.animate(animation1, duration, o.options.easing) + .animate(animation2, duration, o.options.easing, function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(el[0], arguments); // Callback + el.dequeue(); + }); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Highlight 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.highlight = function(o) { + return this.queue(function() { + var elem = $(this), + props = ['backgroundImage', 'backgroundColor', 'opacity'], + mode = $.effects.setMode(elem, o.options.mode || 'show'), + animation = { + backgroundColor: elem.css('backgroundColor') + }; + + if (mode == 'hide') { + animation.opacity = 0; + } + + $.effects.save(elem, props); + elem + .show() + .css({ + backgroundImage: 'none', + backgroundColor: o.options.color || '#ffff99' + }) + .animate(animation, { + queue: false, + duration: o.duration, + easing: o.options.easing, + complete: function() { + (mode == 'hide' && elem.hide()); + $.effects.restore(elem, props); + (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); + (o.callback && o.callback.apply(this, arguments)); + elem.dequeue(); + } + }); + }); +}; + +})(jQuery); +/* + * jQuery UI Effects Pulsate 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.pulsate = function(o) { + return this.queue(function() { + var elem = $(this), + mode = $.effects.setMode(elem, o.options.mode || 'show'); + times = ((o.options.times || 5) * 2) - 1; + duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2, + isVisible = elem.is(':visible'), + animateTo = 0; + + if (!isVisible) { + elem.css('opacity', 0).show(); + animateTo = 1; + } + + if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) { + times--; + } + + for (var i = 0; i < times; i++) { + elem.animate({ opacity: animateTo }, duration, o.options.easing); + animateTo = (animateTo + 1) % 2; + } + + elem.animate({ opacity: animateTo }, duration, o.options.easing, function() { + if (animateTo == 0) { + elem.hide(); + } + (o.callback && o.callback.apply(this, arguments)); + }); + + elem + .queue('fx', function() { elem.dequeue(); }) + .dequeue(); + }); +}; + +})(jQuery); +/* + * jQuery UI Effects Scale 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Scale + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.puff = function(o) { + return this.queue(function() { + var elem = $(this), + mode = $.effects.setMode(elem, o.options.mode || 'hide'), + percent = parseInt(o.options.percent, 10) || 150, + factor = percent / 100, + original = { height: elem.height(), width: elem.width() }; + + $.extend(o.options, { + fade: true, + mode: mode, + percent: mode == 'hide' ? percent : 100, + from: mode == 'hide' + ? original + : { + height: original.height * factor, + width: original.width * factor + } + }); + + elem.effect('scale', o.options, o.duration, o.callback); + elem.dequeue(); + }); +}; + +$.effects.scale = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this); + + // Set options + var options = $.extend(true, {}, o.options); + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent + var direction = o.options.direction || 'both'; // Set default axis + var origin = o.options.origin; // The origin of the scaling + if (mode != 'effect') { // Set default origin and restore for show/hide + options.origin = origin || ['middle','center']; + options.restore = true; + } + var original = {height: el.height(), width: el.width()}; // Save original + el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state + + // Adjust + var factor = { // Set scaling factor + y: direction != 'horizontal' ? (percent / 100) : 1, + x: direction != 'vertical' ? (percent / 100) : 1 + }; + el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state + + if (o.options.fade) { // Fade option to support puff + if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;}; + if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;}; + }; + + // Animation + options.from = el.from; options.to = el.to; options.mode = mode; + + // Animate + el.effect('size', options, o.duration, o.callback); + el.dequeue(); + }); + +}; + +$.effects.size = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity']; + var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore + var props2 = ['width','height','overflow']; // Copy for children + var cProps = ['fontSize']; + var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; + var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var restore = o.options.restore || false; // Default restore + var scale = o.options.scale || 'both'; // Default scale mode + var origin = o.options.origin; // The origin of the sizing + var original = {height: el.height(), width: el.width()}; // Save original + el.from = o.options.from || original; // Default from state + el.to = o.options.to || original; // Default to state + // Adjust + if (origin) { // Calculate baseline shifts + var baseline = $.effects.getBaseline(origin, original); + el.from.top = (original.height - el.from.height) * baseline.y; + el.from.left = (original.width - el.from.width) * baseline.x; + el.to.top = (original.height - el.to.height) * baseline.y; + el.to.left = (original.width - el.to.width) * baseline.x; + }; + var factor = { // Set scaling factor + from: {y: el.from.height / original.height, x: el.from.width / original.width}, + to: {y: el.to.height / original.height, x: el.to.width / original.width} + }; + if (scale == 'box' || scale == 'both') { // Scale the css box + if (factor.from.y != factor.to.y) { // Vertical props scaling + props = props.concat(vProps); + el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from); + el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to); + }; + if (factor.from.x != factor.to.x) { // Horizontal props scaling + props = props.concat(hProps); + el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from); + el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to); + }; + }; + if (scale == 'content' || scale == 'both') { // Scale the content + if (factor.from.y != factor.to.y) { // Vertical props scaling + props = props.concat(cProps); + el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from); + el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to); + }; + }; + $.effects.save(el, restore ? props : props1); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + el.css('overflow','hidden').css(el.from); // Shift + + // Animate + if (scale == 'content' || scale == 'both') { // Scale the children + vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size + hProps = hProps.concat(['marginLeft','marginRight']); // Add margins + props2 = props.concat(vProps).concat(hProps); // Concat + el.find("*[width]").each(function(){ + child = $(this); + if (restore) $.effects.save(child, props2); + var c_original = {height: child.height(), width: child.width()}; // Save original + child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x}; + child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x}; + if (factor.from.y != factor.to.y) { // Vertical props scaling + child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from); + child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to); + }; + if (factor.from.x != factor.to.x) { // Horizontal props scaling + child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from); + child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to); + }; + child.css(child.from); // Shift children + child.animate(child.to, o.duration, o.options.easing, function(){ + if (restore) $.effects.restore(child, props2); // Restore children + }); // Animate children + }); + }; + + // Animate + el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if (el.to.opacity === 0) { + el.css('opacity', el.from.opacity); + } + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Shake 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Shake + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.shake = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode + var direction = o.options.direction || 'left'; // Default direction + var distance = o.options.distance || 20; // Default distance + var times = o.options.times || 3; // Default # of times + var speed = o.duration || o.options.duration || 140; // Default speed per shake + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + + // Animation + var animation = {}, animation1 = {}, animation2 = {}; + animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; + animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2; + animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2; + + // Animate + el.animate(animation, speed, o.options.easing); + for (var i = 1; i < times; i++) { // Shakes + el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing); + }; + el.animate(animation1, speed, o.options.easing). + animate(animation, speed / 2, o.options.easing, function(){ // Last shake + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + }); + el.queue('fx', function() { el.dequeue(); }); + el.dequeue(); + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Slide 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Slide + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.slide = function(o) { + + return this.queue(function() { + + // Create element + var el = $(this), props = ['position','top','bottom','left','right']; + + // Set options + var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode + var direction = o.options.direction || 'left'; // Default Direction + + // Adjust + $.effects.save(el, props); el.show(); // Save & Show + $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper + var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; + var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; + var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true})); + if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift + + // Animation + var animation = {}; + animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; + + // Animate + el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { + if(mode == 'hide') el.hide(); // Hide + $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore + if(o.callback) o.callback.apply(this, arguments); // Callback + el.dequeue(); + }}); + + }); + +}; + +})(jQuery); +/* + * jQuery UI Effects Transfer 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Transfer + * + * Depends: + * jquery.effects.core.js + */ +(function( $, undefined ) { + +$.effects.transfer = function(o) { + return this.queue(function() { + var elem = $(this), + target = $(o.options.to), + endPosition = target.offset(), + animation = { + top: endPosition.top, + left: endPosition.left, + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = elem.offset(), + transfer = $('<div class="ui-effects-transfer"></div>') + .appendTo(document.body) + .addClass(o.options.className) + .css({ + top: startPosition.top, + left: startPosition.left, + height: elem.innerHeight(), + width: elem.innerWidth(), + position: 'absolute' + }) + .animate(animation, o.duration, o.options.easing, function() { + transfer.remove(); + (o.callback && o.callback.apply(elem[0], arguments)); + elem.dequeue(); + }); + }); +}; + +})(jQuery); +/* + * jQuery UI Accordion 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget( "ui.accordion", { + options: { + active: 0, + animated: "slide", + autoHeight: true, + clearStyle: false, + collapsible: false, + event: "click", + fillSpace: false, + header: "> li > :first-child,> :not(li):even", + icons: { + header: "ui-icon-triangle-1-e", + headerSelected: "ui-icon-triangle-1-s" + }, + navigation: false, + navigationFilter: function() { + return this.href.toLowerCase() === location.href.toLowerCase(); + } + }, + + _create: function() { + var self = this, + options = self.options; + + self.running = 0; + + self.element + .addClass( "ui-accordion ui-widget ui-helper-reset" ) + // in lack of child-selectors in CSS + // we need to mark top-LIs in a UL-accordion for some IE-fix + .children( "li" ) + .addClass( "ui-accordion-li-fix" ); + + self.headers = self.element.find( options.header ) + .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ) + .bind( "mouseenter.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-hover" ); + }) + .bind( "mouseleave.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( "ui-state-hover" ); + }) + .bind( "focus.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-focus" ); + }) + .bind( "blur.accordion", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( "ui-state-focus" ); + }); + + self.headers.next() + .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); + + if ( options.navigation ) { + var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 ); + if ( current.length ) { + var header = current.closest( ".ui-accordion-header" ); + if ( header.length ) { + // anchor within header + self.active = header; + } else { + // anchor within content + self.active = current.closest( ".ui-accordion-content" ).prev(); + } + } + } + + self.active = self._findActive( self.active || options.active ) + .addClass( "ui-state-default ui-state-active" ) + .toggleClass( "ui-corner-all" ) + .toggleClass( "ui-corner-top" ); + self.active.next().addClass( "ui-accordion-content-active" ); + + self._createIcons(); + self.resize(); + + // ARIA + self.element.attr( "role", "tablist" ); + + self.headers + .attr( "role", "tab" ) + .bind( "keydown.accordion", function( event ) { + return self._keydown( event ); + }) + .next() + .attr( "role", "tabpanel" ); + + self.headers + .not( self.active || "" ) + .attr({ + "aria-expanded": "false", + "aria-selected": "false", + tabIndex: -1 + }) + .next() + .hide(); + + // make sure at least one header is in the tab order + if ( !self.active.length ) { + self.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + self.active + .attr({ + "aria-expanded": "true", + "aria-selected": "true", + tabIndex: 0 + }); + } + + // only need links in tab order for Safari + if ( !$.browser.safari ) { + self.headers.find( "a" ).attr( "tabIndex", -1 ); + } + + if ( options.event ) { + self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) { + self._clickHandler.call( self, event, this ); + event.preventDefault(); + }); + } + }, + + _createIcons: function() { + var options = this.options; + if ( options.icons ) { + $( "<span></span>" ) + .addClass( "ui-icon " + options.icons.header ) + .prependTo( this.headers ); + this.active.children( ".ui-icon" ) + .toggleClass(options.icons.header) + .toggleClass(options.icons.headerSelected); + this.element.addClass( "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this.headers.children( ".ui-icon" ).remove(); + this.element.removeClass( "ui-accordion-icons" ); + }, + + destroy: function() { + var options = this.options; + + this.element + .removeClass( "ui-accordion ui-widget ui-helper-reset" ) + .removeAttr( "role" ); + + this.headers + .unbind( ".accordion" ) + .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeAttr( "role" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-selected" ) + .removeAttr( "tabIndex" ); + + this.headers.find( "a" ).removeAttr( "tabIndex" ); + this._destroyIcons(); + var contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role" ) + .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); + if ( options.autoHeight || options.fillHeight ) { + contents.css( "height", "" ); + } + + return $.Widget.prototype.destroy.call( this ); + }, + + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + + if ( key == "active" ) { + this.activate( value ); + } + if ( key == "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + // #5332 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + if ( key == "disabled" ) { + this.headers.add(this.headers.next()) + [ value ? "addClass" : "removeClass" ]( + "ui-accordion-disabled ui-state-disabled" ); + } + }, + + _keydown: function( event ) { + if ( this.options.disabled || event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._clickHandler( { target: event.target }, event.target ); + event.preventDefault(); + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + toFocus.focus(); + return false; + } + + return true; + }, + + resize: function() { + var options = this.options, + maxHeight; + + if ( options.fillSpace ) { + if ( $.browser.msie ) { + var defOverflow = this.element.parent().css( "overflow" ); + this.element.parent().css( "overflow", "hidden"); + } + maxHeight = this.element.parent().height(); + if ($.browser.msie) { + this.element.parent().css( "overflow", defOverflow ); + } + + this.headers.each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.headers.next() + .each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( options.autoHeight ) { + maxHeight = 0; + this.headers.next() + .each(function() { + maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); + }) + .height( maxHeight ); + } + + return this; + }, + + activate: function( index ) { + // TODO this gets called on init, changing the option without an explicit call for that + this.options.active = index; + // call clickHandler with custom event + var active = this._findActive( index )[ 0 ]; + this._clickHandler( { target: active }, active ); + + return this; + }, + + _findActive: function( selector ) { + return selector + ? typeof selector === "number" + ? this.headers.filter( ":eq(" + selector + ")" ) + : this.headers.not( this.headers.not( selector ) ) + : selector === false + ? $( [] ) + : this.headers.filter( ":eq(0)" ); + }, + + // TODO isn't event.target enough? why the separate target argument? + _clickHandler: function( event, target ) { + var options = this.options; + if ( options.disabled ) { + return; + } + + // called only when using activate(false) to close all parts programmatically + if ( !event.target ) { + if ( !options.collapsible ) { + return; + } + this.active + .removeClass( "ui-state-active ui-corner-top" ) + .addClass( "ui-state-default ui-corner-all" ) + .children( ".ui-icon" ) + .removeClass( options.icons.headerSelected ) + .addClass( options.icons.header ); + this.active.next().addClass( "ui-accordion-content-active" ); + var toHide = this.active.next(), + data = { + options: options, + newHeader: $( [] ), + oldHeader: options.active, + newContent: $( [] ), + oldContent: toHide + }, + toShow = ( this.active = $( [] ) ); + this._toggle( toShow, toHide, data ); + return; + } + + // get the click target + var clicked = $( event.currentTarget || target ), + clickedIsActive = clicked[0] === this.active[0]; + + // TODO the option is changed, is that correct? + // TODO if it is correct, shouldn't that happen after determining that the click is valid? + options.active = options.collapsible && clickedIsActive ? + false : + this.headers.index( clicked ); + + // if animations are still active, or the active header is the target, ignore click + if ( this.running || ( !options.collapsible && clickedIsActive ) ) { + return; + } + + // find elements to show and hide + var active = this.active, + toShow = clicked.next(), + toHide = this.active.next(), + data = { + options: options, + newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, + oldHeader: this.active, + newContent: clickedIsActive && options.collapsible ? $([]) : toShow, + oldContent: toHide + }, + down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); + + // when the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $([]) : clicked; + this._toggle( toShow, toHide, data, clickedIsActive, down ); + + // switch classes + active + .removeClass( "ui-state-active ui-corner-top" ) + .addClass( "ui-state-default ui-corner-all" ) + .children( ".ui-icon" ) + .removeClass( options.icons.headerSelected ) + .addClass( options.icons.header ); + if ( !clickedIsActive ) { + clicked + .removeClass( "ui-state-default ui-corner-all" ) + .addClass( "ui-state-active ui-corner-top" ) + .children( ".ui-icon" ) + .removeClass( options.icons.header ) + .addClass( options.icons.headerSelected ); + clicked + .next() + .addClass( "ui-accordion-content-active" ); + } + + return; + }, + + _toggle: function( toShow, toHide, data, clickedIsActive, down ) { + var self = this, + options = self.options; + + self.toShow = toShow; + self.toHide = toHide; + self.data = data; + + var complete = function() { + if ( !self ) { + return; + } + return self._completed.apply( self, arguments ); + }; + + // trigger changestart event + self._trigger( "changestart", null, self.data ); + + // count elements to animate + self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); + + if ( options.animated ) { + var animOptions = {}; + + if ( options.collapsible && clickedIsActive ) { + animOptions = { + toShow: $( [] ), + toHide: toHide, + complete: complete, + down: down, + autoHeight: options.autoHeight || options.fillSpace + }; + } else { + animOptions = { + toShow: toShow, + toHide: toHide, + complete: complete, + down: down, + autoHeight: options.autoHeight || options.fillSpace + }; + } + + if ( !options.proxied ) { + options.proxied = options.animated; + } + + if ( !options.proxiedDuration ) { + options.proxiedDuration = options.duration; + } + + options.animated = $.isFunction( options.proxied ) ? + options.proxied( animOptions ) : + options.proxied; + + options.duration = $.isFunction( options.proxiedDuration ) ? + options.proxiedDuration( animOptions ) : + options.proxiedDuration; + + var animations = $.ui.accordion.animations, + duration = options.duration, + easing = options.animated; + + if ( easing && !animations[ easing ] && !$.easing[ easing ] ) { + easing = "slide"; + } + if ( !animations[ easing ] ) { + animations[ easing ] = function( options ) { + this.slide( options, { + easing: easing, + duration: duration || 700 + }); + }; + } + + animations[ easing ]( animOptions ); + } else { + if ( options.collapsible && clickedIsActive ) { + toShow.toggle(); + } else { + toHide.hide(); + toShow.show(); + } + + complete( true ); + } + + // TODO assert that the blur and focus triggers are really necessary, remove otherwise + toHide.prev() + .attr({ + "aria-expanded": "false", + "aria-selected": "false", + tabIndex: -1 + }) + .blur(); + toShow.prev() + .attr({ + "aria-expanded": "true", + "aria-selected": "true", + tabIndex: 0 + }) + .focus(); + }, + + _completed: function( cancel ) { + this.running = cancel ? 0 : --this.running; + if ( this.running ) { + return; + } + + if ( this.options.clearStyle ) { + this.toShow.add( this.toHide ).css({ + height: "", + overflow: "" + }); + } + + // other classes are removed before the animation; this one needs to stay until completed + this.toHide.removeClass( "ui-accordion-content-active" ); + // Work around for rendering bug in IE (#5421) + if ( this.toHide.length ) { + this.toHide.parent()[0].className = this.toHide.parent()[0].className; + } + + this._trigger( "change", null, this.data ); + } +}); + +$.extend( $.ui.accordion, { + version: "1.8.18", + animations: { + slide: function( options, additions ) { + options = $.extend({ + easing: "swing", + duration: 300 + }, options, additions ); + if ( !options.toHide.size() ) { + options.toShow.animate({ + height: "show", + paddingTop: "show", + paddingBottom: "show" + }, options ); + return; + } + if ( !options.toShow.size() ) { + options.toHide.animate({ + height: "hide", + paddingTop: "hide", + paddingBottom: "hide" + }, options ); + return; + } + var overflow = options.toShow.css( "overflow" ), + percentDone = 0, + showProps = {}, + hideProps = {}, + fxAttrs = [ "height", "paddingTop", "paddingBottom" ], + originalWidth; + // fix width before calculating height of hidden element + var s = options.toShow; + originalWidth = s[0].style.width; + s.width( s.parent().width() + - parseFloat( s.css( "paddingLeft" ) ) + - parseFloat( s.css( "paddingRight" ) ) + - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 ) + - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) ); + + $.each( fxAttrs, function( i, prop ) { + hideProps[ prop ] = "hide"; + + var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ); + showProps[ prop ] = { + value: parts[ 1 ], + unit: parts[ 2 ] || "px" + }; + }); + options.toShow.css({ height: 0, overflow: "hidden" }).show(); + options.toHide + .filter( ":hidden" ) + .each( options.complete ) + .end() + .filter( ":visible" ) + .animate( hideProps, { + step: function( now, settings ) { + // only calculate the percent when animating height + // IE gets very inconsistent results when animating elements + // with small values, which is common for padding + if ( settings.prop == "height" ) { + percentDone = ( settings.end - settings.start === 0 ) ? 0 : + ( settings.now - settings.start ) / ( settings.end - settings.start ); + } + + options.toShow[ 0 ].style[ settings.prop ] = + ( percentDone * showProps[ settings.prop ].value ) + + showProps[ settings.prop ].unit; + }, + duration: options.duration, + easing: options.easing, + complete: function() { + if ( !options.autoHeight ) { + options.toShow.css( "height", "" ); + } + options.toShow.css({ + width: originalWidth, + overflow: overflow + }); + options.complete(); + } + }); + }, + bounceslide: function( options ) { + this.slide( options, { + easing: options.down ? "easeOutBounce" : "swing", + duration: options.down ? 1000 : 200 + }); + } + } +}); + +})( jQuery ); +/* + * jQuery UI Autocomplete 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function( $, undefined ) { + +// used to prevent race conditions with remote data sources +var requestIndex = 0; + +$.widget( "ui.autocomplete", { + options: { + appendTo: "body", + autoFocus: false, + delay: 300, + minLength: 1, + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null + }, + + pending: 0, + + _create: function() { + var self = this, + doc = this.element[ 0 ].ownerDocument, + suppressKeyPress; + + this.element + .addClass( "ui-autocomplete-input" ) + .attr( "autocomplete", "off" ) + // TODO verify these actually work as intended + .attr({ + role: "textbox", + "aria-autocomplete": "list", + "aria-haspopup": "true" + }) + .bind( "keydown.autocomplete", function( event ) { + if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) { + return; + } + + suppressKeyPress = false; + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + self._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + self._move( "nextPage", event ); + break; + case keyCode.UP: + self._move( "previous", event ); + // prevent moving cursor to beginning of text field in some browsers + event.preventDefault(); + break; + case keyCode.DOWN: + self._move( "next", event ); + // prevent moving cursor to end of text field in some browsers + event.preventDefault(); + break; + case keyCode.ENTER: + case keyCode.NUMPAD_ENTER: + // when menu is open and has focus + if ( self.menu.active ) { + // #6055 - Opera still allows the keypress to occur + // which causes forms to submit + suppressKeyPress = true; + event.preventDefault(); + } + //passthrough - ENTER and TAB both select the current element + case keyCode.TAB: + if ( !self.menu.active ) { + return; + } + self.menu.select( event ); + break; + case keyCode.ESCAPE: + self.element.val( self.term ); + self.close( event ); + break; + default: + // keypress is triggered before the input value is changed + clearTimeout( self.searching ); + self.searching = setTimeout(function() { + // only search if the value has changed + if ( self.term != self.element.val() ) { + self.selectedItem = null; + self.search( null, event ); + } + }, self.options.delay ); + break; + } + }) + .bind( "keypress.autocomplete", function( event ) { + if ( suppressKeyPress ) { + suppressKeyPress = false; + event.preventDefault(); + } + }) + .bind( "focus.autocomplete", function() { + if ( self.options.disabled ) { + return; + } + + self.selectedItem = null; + self.previous = self.element.val(); + }) + .bind( "blur.autocomplete", function( event ) { + if ( self.options.disabled ) { + return; + } + + clearTimeout( self.searching ); + // clicks on the menu (or a button to trigger a search) will cause a blur event + self.closing = setTimeout(function() { + self.close( event ); + self._change( event ); + }, 150 ); + }); + this._initSource(); + this.response = function() { + return self._response.apply( self, arguments ); + }; + this.menu = $( "<ul></ul>" ) + .addClass( "ui-autocomplete" ) + .appendTo( $( this.options.appendTo || "body", doc )[0] ) + // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) + .mousedown(function( event ) { + // clicking on the scrollbar causes focus to shift to the body + // but we can't detect a mouseup or a click immediately afterward + // so we have to track the next mousedown and close the menu if + // the user clicks somewhere outside of the autocomplete + var menuElement = self.menu.element[ 0 ]; + if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { + setTimeout(function() { + $( document ).one( 'mousedown', function( event ) { + if ( event.target !== self.element[ 0 ] && + event.target !== menuElement && + !$.ui.contains( menuElement, event.target ) ) { + self.close(); + } + }); + }, 1 ); + } + + // use another timeout to make sure the blur-event-handler on the input was already triggered + setTimeout(function() { + clearTimeout( self.closing ); + }, 13); + }) + .menu({ + focus: function( event, ui ) { + var item = ui.item.data( "item.autocomplete" ); + if ( false !== self._trigger( "focus", event, { item: item } ) ) { + // use value to match what will end up in the input, if it was a key event + if ( /^key/.test(event.originalEvent.type) ) { + self.element.val( item.value ); + } + } + }, + selected: function( event, ui ) { + var item = ui.item.data( "item.autocomplete" ), + previous = self.previous; + + // only trigger when focus was lost (click on menu) + if ( self.element[0] !== doc.activeElement ) { + self.element.focus(); + self.previous = previous; + // #6109 - IE triggers two focus events and the second + // is asynchronous, so we need to reset the previous + // term synchronously and asynchronously :-( + setTimeout(function() { + self.previous = previous; + self.selectedItem = item; + }, 1); + } + + if ( false !== self._trigger( "select", event, { item: item } ) ) { + self.element.val( item.value ); + } + // reset the term after the select event + // this allows custom select handling to work properly + self.term = self.element.val(); + + self.close( event ); + self.selectedItem = item; + }, + blur: function( event, ui ) { + // don't set the value of the text field if it's already correct + // this prevents moving the cursor unnecessarily + if ( self.menu.element.is(":visible") && + ( self.element.val() !== self.term ) ) { + self.element.val( self.term ); + } + } + }) + .zIndex( this.element.zIndex() + 1 ) + // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 + .css({ top: 0, left: 0 }) + .hide() + .data( "menu" ); + if ( $.fn.bgiframe ) { + this.menu.element.bgiframe(); + } + // turning off autocomplete prevents the browser from remembering the + // value when navigating through history, so we re-enable autocomplete + // if the page is unloaded before the widget is destroyed. #7790 + self.beforeunloadHandler = function() { + self.element.removeAttr( "autocomplete" ); + }; + $( window ).bind( "beforeunload", self.beforeunloadHandler ); + }, + + destroy: function() { + this.element + .removeClass( "ui-autocomplete-input" ) + .removeAttr( "autocomplete" ) + .removeAttr( "role" ) + .removeAttr( "aria-autocomplete" ) + .removeAttr( "aria-haspopup" ); + this.menu.element.remove(); + $( window ).unbind( "beforeunload", this.beforeunloadHandler ); + $.Widget.prototype.destroy.call( this ); + }, + + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + if ( key === "source" ) { + this._initSource(); + } + if ( key === "appendTo" ) { + this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) + } + if ( key === "disabled" && value && this.xhr ) { + this.xhr.abort(); + } + }, + + _initSource: function() { + var self = this, + array, + url; + if ( $.isArray(this.options.source) ) { + array = this.options.source; + this.source = function( request, response ) { + response( $.ui.autocomplete.filter(array, request.term) ); + }; + } else if ( typeof this.options.source === "string" ) { + url = this.options.source; + this.source = function( request, response ) { + if ( self.xhr ) { + self.xhr.abort(); + } + self.xhr = $.ajax({ + url: url, + data: request, + dataType: "json", + context: { + autocompleteRequest: ++requestIndex + }, + success: function( data, status ) { + if ( this.autocompleteRequest === requestIndex ) { + response( data ); + } + }, + error: function() { + if ( this.autocompleteRequest === requestIndex ) { + response( [] ); + } + } + }); + }; + } else { + this.source = this.options.source; + } + }, + + search: function( value, event ) { + value = value != null ? value : this.element.val(); + + // always save the actual value, not the one passed as an argument + this.term = this.element.val(); + + if ( value.length < this.options.minLength ) { + return this.close( event ); + } + + clearTimeout( this.closing ); + if ( this._trigger( "search", event ) === false ) { + return; + } + + return this._search( value ); + }, + + _search: function( value ) { + this.pending++; + this.element.addClass( "ui-autocomplete-loading" ); + + this.source( { term: value }, this.response ); + }, + + _response: function( content ) { + if ( !this.options.disabled && content && content.length ) { + content = this._normalize( content ); + this._suggest( content ); + this._trigger( "open" ); + } else { + this.close(); + } + this.pending--; + if ( !this.pending ) { + this.element.removeClass( "ui-autocomplete-loading" ); + } + }, + + close: function( event ) { + clearTimeout( this.closing ); + if ( this.menu.element.is(":visible") ) { + this.menu.element.hide(); + this.menu.deactivate(); + this._trigger( "close", event ); + } + }, + + _change: function( event ) { + if ( this.previous !== this.element.val() ) { + this._trigger( "change", event, { item: this.selectedItem } ); + } + }, + + _normalize: function( items ) { + // assume all items have the right format when the first item is complete + if ( items.length && items[0].label && items[0].value ) { + return items; + } + return $.map( items, function(item) { + if ( typeof item === "string" ) { + return { + label: item, + value: item + }; + } + return $.extend({ + label: item.label || item.value, + value: item.value || item.label + }, item ); + }); + }, + + _suggest: function( items ) { + var ul = this.menu.element + .empty() + .zIndex( this.element.zIndex() + 1 ); + this._renderMenu( ul, items ); + // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate + this.menu.deactivate(); + this.menu.refresh(); + + // size and position menu + ul.show(); + this._resizeMenu(); + ul.position( $.extend({ + of: this.element + }, this.options.position )); + + if ( this.options.autoFocus ) { + this.menu.next( new $.Event("mouseover") ); + } + }, + + _resizeMenu: function() { + var ul = this.menu.element; + ul.outerWidth( Math.max( + // Firefox wraps long text (possibly a rounding bug) + // so we add 1px to avoid the wrapping (#7513) + ul.width( "" ).outerWidth() + 1, + this.element.outerWidth() + ) ); + }, + + _renderMenu: function( ul, items ) { + var self = this; + $.each( items, function( index, item ) { + self._renderItem( ul, item ); + }); + }, + + _renderItem: function( ul, item) { + return $( "<li></li>" ) + .data( "item.autocomplete", item ) + .append( $( "<a></a>" ).text( item.label ) ) + .appendTo( ul ); + }, + + _move: function( direction, event ) { + if ( !this.menu.element.is(":visible") ) { + this.search( null, event ); + return; + } + if ( this.menu.first() && /^previous/.test(direction) || + this.menu.last() && /^next/.test(direction) ) { + this.element.val( this.term ); + this.menu.deactivate(); + return; + } + this.menu[ direction ]( event ); + }, + + widget: function() { + return this.menu.element; + } +}); + +$.extend( $.ui.autocomplete, { + escapeRegex: function( value ) { + return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + }, + filter: function(array, term) { + var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); + return $.grep( array, function(value) { + return matcher.test( value.label || value.value || value ); + }); + } +}); + +}( jQuery )); + +/* + * jQuery UI Menu (not officially released) + * + * This widget isn't yet finished and the API is subject to change. We plan to finish + * it for the next release. You're welcome to give it a try anyway and give us feedback, + * as long as you're okay with migrating your code later on. We can help with that, too. + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function($) { + +$.widget("ui.menu", { + _create: function() { + var self = this; + this.element + .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") + .attr({ + role: "listbox", + "aria-activedescendant": "ui-active-menuitem" + }) + .click(function( event ) { + if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { + return; + } + // temporary + event.preventDefault(); + self.select( event ); + }); + this.refresh(); + }, + + refresh: function() { + var self = this; + + // don't refresh list items that are already adapted + var items = this.element.children("li:not(.ui-menu-item):has(a)") + .addClass("ui-menu-item") + .attr("role", "menuitem"); + + items.children("a") + .addClass("ui-corner-all") + .attr("tabindex", -1) + // mouseenter doesn't work with event delegation + .mouseenter(function( event ) { + self.activate( event, $(this).parent() ); + }) + .mouseleave(function() { + self.deactivate(); + }); + }, + + activate: function( event, item ) { + this.deactivate(); + if (this.hasScroll()) { + var offset = item.offset().top - this.element.offset().top, + scroll = this.element.scrollTop(), + elementHeight = this.element.height(); + if (offset < 0) { + this.element.scrollTop( scroll + offset); + } else if (offset >= elementHeight) { + this.element.scrollTop( scroll + offset - elementHeight + item.height()); + } + } + this.active = item.eq(0) + .children("a") + .addClass("ui-state-hover") + .attr("id", "ui-active-menuitem") + .end(); + this._trigger("focus", event, { item: item }); + }, + + deactivate: function() { + if (!this.active) { return; } + + this.active.children("a") + .removeClass("ui-state-hover") + .removeAttr("id"); + this._trigger("blur"); + this.active = null; + }, + + next: function(event) { + this.move("next", ".ui-menu-item:first", event); + }, + + previous: function(event) { + this.move("prev", ".ui-menu-item:last", event); + }, + + first: function() { + return this.active && !this.active.prevAll(".ui-menu-item").length; + }, + + last: function() { + return this.active && !this.active.nextAll(".ui-menu-item").length; + }, + + move: function(direction, edge, event) { + if (!this.active) { + this.activate(event, this.element.children(edge)); + return; + } + var next = this.active[direction + "All"](".ui-menu-item").eq(0); + if (next.length) { + this.activate(event, next); + } else { + this.activate(event, this.element.children(edge)); + } + }, + + // TODO merge with previousPage + nextPage: function(event) { + if (this.hasScroll()) { + // TODO merge with no-scroll-else + if (!this.active || this.last()) { + this.activate(event, this.element.children(".ui-menu-item:first")); + return; + } + var base = this.active.offset().top, + height = this.element.height(), + result = this.element.children(".ui-menu-item").filter(function() { + var close = $(this).offset().top - base - height + $(this).height(); + // TODO improve approximation + return close < 10 && close > -10; + }); + + // TODO try to catch this earlier when scrollTop indicates the last page anyway + if (!result.length) { + result = this.element.children(".ui-menu-item:last"); + } + this.activate(event, result); + } else { + this.activate(event, this.element.children(".ui-menu-item") + .filter(!this.active || this.last() ? ":first" : ":last")); + } + }, + + // TODO merge with nextPage + previousPage: function(event) { + if (this.hasScroll()) { + // TODO merge with no-scroll-else + if (!this.active || this.first()) { + this.activate(event, this.element.children(".ui-menu-item:last")); + return; + } + + var base = this.active.offset().top, + height = this.element.height(); + result = this.element.children(".ui-menu-item").filter(function() { + var close = $(this).offset().top - base + height - $(this).height(); + // TODO improve approximation + return close < 10 && close > -10; + }); + + // TODO try to catch this earlier when scrollTop indicates the last page anyway + if (!result.length) { + result = this.element.children(".ui-menu-item:first"); + } + this.activate(event, result); + } else { + this.activate(event, this.element.children(".ui-menu-item") + .filter(!this.active || this.first() ? ":last" : ":first")); + } + }, + + hasScroll: function() { + return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); + }, + + select: function( event ) { + this._trigger("selected", event, { item: this.active }); + } +}); + +}(jQuery)); +/* + * jQuery UI Button 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var lastActive, startXPos, startYPos, clickDragged, + baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", + stateClasses = "ui-state-hover ui-state-active ", + typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", + formResetHandler = function() { + var buttons = $( this ).find( ":ui-button" ); + setTimeout(function() { + buttons.button( "refresh" ); + }, 1 ); + }, + radioGroup = function( radio ) { + var name = radio.name, + form = radio.form, + radios = $( [] ); + if ( name ) { + if ( form ) { + radios = $( form ).find( "[name='" + name + "']" ); + } else { + radios = $( "[name='" + name + "']", radio.ownerDocument ) + .filter(function() { + return !this.form; + }); + } + } + return radios; + }; + +$.widget( "ui.button", { + options: { + disabled: null, + text: true, + label: null, + icons: { + primary: null, + secondary: null + } + }, + _create: function() { + this.element.closest( "form" ) + .unbind( "reset.button" ) + .bind( "reset.button", formResetHandler ); + + if ( typeof this.options.disabled !== "boolean" ) { + this.options.disabled = !!this.element.propAttr( "disabled" ); + } else { + this.element.propAttr( "disabled", this.options.disabled ); + } + + this._determineButtonType(); + this.hasTitle = !!this.buttonElement.attr( "title" ); + + var self = this, + options = this.options, + toggleButton = this.type === "checkbox" || this.type === "radio", + hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ), + focusClass = "ui-state-focus"; + + if ( options.label === null ) { + options.label = this.buttonElement.html(); + } + + this.buttonElement + .addClass( baseClasses ) + .attr( "role", "button" ) + .bind( "mouseenter.button", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-hover" ); + if ( this === lastActive ) { + $( this ).addClass( "ui-state-active" ); + } + }) + .bind( "mouseleave.button", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( hoverClass ); + }) + .bind( "click.button", function( event ) { + if ( options.disabled ) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }); + + this.element + .bind( "focus.button", function() { + // no need to check disabled, focus won't be triggered anyway + self.buttonElement.addClass( focusClass ); + }) + .bind( "blur.button", function() { + self.buttonElement.removeClass( focusClass ); + }); + + if ( toggleButton ) { + this.element.bind( "change.button", function() { + if ( clickDragged ) { + return; + } + self.refresh(); + }); + // if mouse moves between mousedown and mouseup (drag) set clickDragged flag + // prevents issue where button state changes but checkbox/radio checked state + // does not in Firefox (see ticket #6970) + this.buttonElement + .bind( "mousedown.button", function( event ) { + if ( options.disabled ) { + return; + } + clickDragged = false; + startXPos = event.pageX; + startYPos = event.pageY; + }) + .bind( "mouseup.button", function( event ) { + if ( options.disabled ) { + return; + } + if ( startXPos !== event.pageX || startYPos !== event.pageY ) { + clickDragged = true; + } + }); + } + + if ( this.type === "checkbox" ) { + this.buttonElement.bind( "click.button", function() { + if ( options.disabled || clickDragged ) { + return false; + } + $( this ).toggleClass( "ui-state-active" ); + self.buttonElement.attr( "aria-pressed", self.element[0].checked ); + }); + } else if ( this.type === "radio" ) { + this.buttonElement.bind( "click.button", function() { + if ( options.disabled || clickDragged ) { + return false; + } + $( this ).addClass( "ui-state-active" ); + self.buttonElement.attr( "aria-pressed", "true" ); + + var radio = self.element[ 0 ]; + radioGroup( radio ) + .not( radio ) + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + }); + } else { + this.buttonElement + .bind( "mousedown.button", function() { + if ( options.disabled ) { + return false; + } + $( this ).addClass( "ui-state-active" ); + lastActive = this; + $( document ).one( "mouseup", function() { + lastActive = null; + }); + }) + .bind( "mouseup.button", function() { + if ( options.disabled ) { + return false; + } + $( this ).removeClass( "ui-state-active" ); + }) + .bind( "keydown.button", function(event) { + if ( options.disabled ) { + return false; + } + if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) { + $( this ).addClass( "ui-state-active" ); + } + }) + .bind( "keyup.button", function() { + $( this ).removeClass( "ui-state-active" ); + }); + + if ( this.buttonElement.is("a") ) { + this.buttonElement.keyup(function(event) { + if ( event.keyCode === $.ui.keyCode.SPACE ) { + // TODO pass through original event correctly (just as 2nd argument doesn't work) + $( this ).click(); + } + }); + } + } + + // TODO: pull out $.Widget's handling for the disabled option into + // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can + // be overridden by individual plugins + this._setOption( "disabled", options.disabled ); + this._resetButton(); + }, + + _determineButtonType: function() { + + if ( this.element.is(":checkbox") ) { + this.type = "checkbox"; + } else if ( this.element.is(":radio") ) { + this.type = "radio"; + } else if ( this.element.is("input") ) { + this.type = "input"; + } else { + this.type = "button"; + } + + if ( this.type === "checkbox" || this.type === "radio" ) { + // we don't search against the document in case the element + // is disconnected from the DOM + var ancestor = this.element.parents().filter(":last"), + labelSelector = "label[for='" + this.element.attr("id") + "']"; + this.buttonElement = ancestor.find( labelSelector ); + if ( !this.buttonElement.length ) { + ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); + this.buttonElement = ancestor.filter( labelSelector ); + if ( !this.buttonElement.length ) { + this.buttonElement = ancestor.find( labelSelector ); + } + } + this.element.addClass( "ui-helper-hidden-accessible" ); + + var checked = this.element.is( ":checked" ); + if ( checked ) { + this.buttonElement.addClass( "ui-state-active" ); + } + this.buttonElement.attr( "aria-pressed", checked ); + } else { + this.buttonElement = this.element; + } + }, + + widget: function() { + return this.buttonElement; + }, + + destroy: function() { + this.element + .removeClass( "ui-helper-hidden-accessible" ); + this.buttonElement + .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) + .removeAttr( "role" ) + .removeAttr( "aria-pressed" ) + .html( this.buttonElement.find(".ui-button-text").html() ); + + if ( !this.hasTitle ) { + this.buttonElement.removeAttr( "title" ); + } + + $.Widget.prototype.destroy.call( this ); + }, + + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + if ( key === "disabled" ) { + if ( value ) { + this.element.propAttr( "disabled", true ); + } else { + this.element.propAttr( "disabled", false ); + } + return; + } + this._resetButton(); + }, + + refresh: function() { + var isDisabled = this.element.is( ":disabled" ); + if ( isDisabled !== this.options.disabled ) { + this._setOption( "disabled", isDisabled ); + } + if ( this.type === "radio" ) { + radioGroup( this.element[0] ).each(function() { + if ( $( this ).is( ":checked" ) ) { + $( this ).button( "widget" ) + .addClass( "ui-state-active" ) + .attr( "aria-pressed", "true" ); + } else { + $( this ).button( "widget" ) + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + } + }); + } else if ( this.type === "checkbox" ) { + if ( this.element.is( ":checked" ) ) { + this.buttonElement + .addClass( "ui-state-active" ) + .attr( "aria-pressed", "true" ); + } else { + this.buttonElement + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + } + } + }, + + _resetButton: function() { + if ( this.type === "input" ) { + if ( this.options.label ) { + this.element.val( this.options.label ); + } + return; + } + var buttonElement = this.buttonElement.removeClass( typeClasses ), + buttonText = $( "<span></span>", this.element[0].ownerDocument ) + .addClass( "ui-button-text" ) + .html( this.options.label ) + .appendTo( buttonElement.empty() ) + .text(), + icons = this.options.icons, + multipleIcons = icons.primary && icons.secondary, + buttonClasses = []; + + if ( icons.primary || icons.secondary ) { + if ( this.options.text ) { + buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); + } + + if ( icons.primary ) { + buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); + } + + if ( icons.secondary ) { + buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); + } + + if ( !this.options.text ) { + buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); + + if ( !this.hasTitle ) { + buttonElement.attr( "title", buttonText ); + } + } + } else { + buttonClasses.push( "ui-button-text-only" ); + } + buttonElement.addClass( buttonClasses.join( " " ) ); + } +}); + +$.widget( "ui.buttonset", { + options: { + items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" + }, + + _create: function() { + this.element.addClass( "ui-buttonset" ); + }, + + _init: function() { + this.refresh(); + }, + + _setOption: function( key, value ) { + if ( key === "disabled" ) { + this.buttons.button( "option", key, value ); + } + + $.Widget.prototype._setOption.apply( this, arguments ); + }, + + refresh: function() { + var rtl = this.element.css( "direction" ) === "rtl"; + + this.buttons = this.element.find( this.options.items ) + .filter( ":ui-button" ) + .button( "refresh" ) + .end() + .not( ":ui-button" ) + .button() + .end() + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) + .filter( ":first" ) + .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) + .end() + .filter( ":last" ) + .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) + .end() + .end(); + }, + + destroy: function() { + this.element.removeClass( "ui-buttonset" ); + this.buttons + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-corner-left ui-corner-right" ) + .end() + .button( "destroy" ); + + $.Widget.prototype.destroy.call( this ); + } +}); + +}( jQuery ) ); +/* + * jQuery UI Datepicker 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker + * + * Depends: + * jquery.ui.core.js + */ +(function( $, undefined ) { + +$.extend($.ui, { datepicker: { version: "1.8.18" } }); + +var PROP_NAME = 'datepicker'; +var dpuuid = new Date().getTime(); +var instActive; + +/* Date picker manager. + Use the singleton instance of this class, $.datepicker, to interact with the date picker. + Settings for (groups of) date pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Datepicker() { + this.debug = false; // Change this to true to start debugging + this._curInst = null; // The current instance in use + this._keyEvent = false; // If the last event was a key event + this._disabledInputs = []; // List of date picker inputs that have been disabled + this._datepickerShowing = false; // True if the popup picker is showing , false if not + this._inDialog = false; // True if showing within a "dialog", false if not + this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division + this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class + this._appendClass = 'ui-datepicker-append'; // The name of the append marker class + this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class + this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class + this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class + this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class + this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class + this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + closeText: 'Done', // Display text for close link + prevText: 'Prev', // Display text for previous month link + nextText: 'Next', // Display text for next month link + currentText: 'Today', // Display text for current month link + monthNames: ['January','February','March','April','May','June', + 'July','August','September','October','November','December'], // Names of months for drop-down and formatting + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting + dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday + weekHeader: 'Wk', // Column header for week of the year + dateFormat: 'mm/dd/yy', // See format options on parseDate + firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... + isRTL: false, // True if right-to-left language, false if left-to-right + showMonthAfterYear: false, // True if the year select precedes month, false for month then year + yearSuffix: '' // Additional text to append to the year in the month headers + }; + this._defaults = { // Global defaults for all the date picker instances + showOn: 'focus', // 'focus' for popup on focus, + // 'button' for trigger button, or 'both' for either + showAnim: 'fadeIn', // Name of jQuery animation for popup + showOptions: {}, // Options for enhanced animations + defaultDate: null, // Used when field is blank: actual date, + // +/-number for offset from today, null for today + appendText: '', // Display text following the input box, e.g. showing the format + buttonText: '...', // Text for trigger button + buttonImage: '', // URL for trigger button image + buttonImageOnly: false, // True if the image appears alone, false if it appears on a button + hideIfNoPrevNext: false, // True to hide next/previous month links + // if not applicable, false to just disable them + navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links + gotoCurrent: false, // True if today link goes back to current selection instead + changeMonth: false, // True if month can be selected directly, false if only prev/next + changeYear: false, // True if year can be selected directly, false if only prev/next + yearRange: 'c-10:c+10', // Range of years to display in drop-down, + // either relative to today's year (-nn:+nn), relative to currently displayed year + // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) + showOtherMonths: false, // True to show dates in other months, false to leave blank + selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable + showWeek: false, // True to show week of the year, false to not show it + calculateWeek: this.iso8601Week, // How to calculate the week of the year, + // takes a Date and returns the number of the week for it + shortYearCutoff: '+10', // Short year values < this are in the current century, + // > this are in the previous century, + // string value starting with '+' for current year + value + minDate: null, // The earliest selectable date, or null for no limit + maxDate: null, // The latest selectable date, or null for no limit + duration: 'fast', // Duration of display/closure + beforeShowDay: null, // Function that takes a date and returns an array with + // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', + // [2] = cell title (optional), e.g. $.datepicker.noWeekends + beforeShow: null, // Function that takes an input field and + // returns a set of custom settings for the date picker + onSelect: null, // Define a callback function when a date is selected + onChangeMonthYear: null, // Define a callback function when the month or year is changed + onClose: null, // Define a callback function when the datepicker is closed + numberOfMonths: 1, // Number of months to show at a time + showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) + stepMonths: 1, // Number of months to step back/forward + stepBigMonths: 12, // Number of months to step back/forward for the big links + altField: '', // Selector for an alternate field to store selected dates into + altFormat: '', // The date format to use for the alternate field + constrainInput: true, // The input is constrained by the current date format + showButtonPanel: false, // True to show button panel, false to not show it + autoSize: false, // True to size the input for the date format, false to leave as is + disabled: false // The initial disabled state + }; + $.extend(this._defaults, this.regional['']); + this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')); +} + +$.extend(Datepicker.prototype, { + /* Class name added to elements to indicate already configured with a date picker. */ + markerClassName: 'hasDatepicker', + + //Keep track of the maximum number of rows displayed (see #7043) + maxRows: 4, + + /* Debug logging (if enabled). */ + log: function () { + if (this.debug) + console.log.apply('', arguments); + }, + + // TODO rename to "widget" when switching to widget factory + _widgetDatepicker: function() { + return this.dpDiv; + }, + + /* Override the default settings for all instances of the date picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* Attach the date picker to a jQuery selection. + @param target element - the target input field or division or span + @param settings object - the new settings to use for this date picker instance (anonymous) */ + _attachDatepicker: function(target, settings) { + // check for settings on the control itself - in namespace 'date:' + var inlineSettings = null; + for (var attrName in this._defaults) { + var attrValue = target.getAttribute('date:' + attrName); + if (attrValue) { + inlineSettings = inlineSettings || {}; + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + var nodeName = target.nodeName.toLowerCase(); + var inline = (nodeName == 'div' || nodeName == 'span'); + if (!target.id) { + this.uuid += 1; + target.id = 'dp' + this.uuid; + } + var inst = this._newInst($(target), inline); + inst.settings = $.extend({}, settings || {}, inlineSettings || {}); + if (nodeName == 'input') { + this._connectDatepicker(target, inst); + } else if (inline) { + this._inlineDatepicker(target, inst); + } + }, + + /* Create a new instance object. */ + _newInst: function(target, inline) { + var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars + return {id: id, input: target, // associated target + selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection + drawMonth: 0, drawYear: 0, // month being drawn + inline: inline, // is datepicker inline or not + dpDiv: (!inline ? this.dpDiv : // presentation div + bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))}; + }, + + /* Attach the date picker to an input field. */ + _connectDatepicker: function(target, inst) { + var input = $(target); + inst.append = $([]); + inst.trigger = $([]); + if (input.hasClass(this.markerClassName)) + return; + this._attachments(input, inst); + input.addClass(this.markerClassName).keydown(this._doKeyDown). + keypress(this._doKeyPress).keyup(this._doKeyUp). + bind("setData.datepicker", function(event, key, value) { + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key) { + return this._get(inst, key); + }); + this._autoSize(inst); + $.data(target, PROP_NAME, inst); + //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } + }, + + /* Make attachments based on settings. */ + _attachments: function(input, inst) { + var appendText = this._get(inst, 'appendText'); + var isRTL = this._get(inst, 'isRTL'); + if (inst.append) + inst.append.remove(); + if (appendText) { + inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>'); + input[isRTL ? 'before' : 'after'](inst.append); + } + input.unbind('focus', this._showDatepicker); + if (inst.trigger) + inst.trigger.remove(); + var showOn = this._get(inst, 'showOn'); + if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field + input.focus(this._showDatepicker); + if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked + var buttonText = this._get(inst, 'buttonText'); + var buttonImage = this._get(inst, 'buttonImage'); + inst.trigger = $(this._get(inst, 'buttonImageOnly') ? + $('<img/>').addClass(this._triggerClass). + attr({ src: buttonImage, alt: buttonText, title: buttonText }) : + $('<button type="button"></button>').addClass(this._triggerClass). + html(buttonImage == '' ? buttonText : $('<img/>').attr( + { src:buttonImage, alt:buttonText, title:buttonText }))); + input[isRTL ? 'before' : 'after'](inst.trigger); + inst.trigger.click(function() { + if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) + $.datepicker._hideDatepicker(); + else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) { + $.datepicker._hideDatepicker(); + $.datepicker._showDatepicker(input[0]); + } else + $.datepicker._showDatepicker(input[0]); + return false; + }); + } + }, + + /* Apply the maximum length for the date format. */ + _autoSize: function(inst) { + if (this._get(inst, 'autoSize') && !inst.inline) { + var date = new Date(2009, 12 - 1, 20); // Ensure double digits + var dateFormat = this._get(inst, 'dateFormat'); + if (dateFormat.match(/[DM]/)) { + var findMax = function(names) { + var max = 0; + var maxI = 0; + for (var i = 0; i < names.length; i++) { + if (names[i].length > max) { + max = names[i].length; + maxI = i; + } + } + return maxI; + }; + date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? + 'monthNames' : 'monthNamesShort')))); + date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? + 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); + } + inst.input.attr('size', this._formatDate(inst, date).length); + } + }, + + /* Attach an inline date picker to a div. */ + _inlineDatepicker: function(target, inst) { + var divSpan = $(target); + if (divSpan.hasClass(this.markerClassName)) + return; + divSpan.addClass(this.markerClassName).append(inst.dpDiv). + bind("setData.datepicker", function(event, key, value){ + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key){ + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + this._setDate(inst, this._getDefaultDate(inst), true); + this._updateDatepicker(inst); + this._updateAlternate(inst); + //If disabled option is true, disable the datepicker before showing it (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } + // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements + // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height + inst.dpDiv.css( "display", "block" ); + }, + + /* Pop-up the date picker in a "dialog" box. + @param input element - ignored + @param date string or Date - the initial date to display + @param onSelect function - the function to call when a date is selected + @param settings object - update the dialog date picker instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen or + event - with x/y coordinates or + leave empty for default (screen centre) + @return the manager object */ + _dialogDatepicker: function(input, date, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + this.uuid += 1; + var id = 'dp' + this.uuid; + this._dialogInput = $('<input type="text" id="' + id + + '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>'); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + inst = this._dialogInst = this._newInst(this._dialogInput, false); + inst.settings = {}; + $.data(this._dialogInput[0], PROP_NAME, inst); + } + extendRemove(inst.settings, settings || {}); + date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); + this._dialogInput.val(date); + + this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); + if (!this._pos) { + var browserWidth = document.documentElement.clientWidth; + var browserHeight = document.documentElement.clientHeight; + var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollY = document.documentElement.scrollTop || document.body.scrollTop; + this._pos = // should use actual width/height below + [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; + } + + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); + inst.settings.onSelect = onSelect; + this._inDialog = true; + this.dpDiv.addClass(this._dialogClass); + this._showDatepicker(this._dialogInput[0]); + if ($.blockUI) + $.blockUI(this.dpDiv); + $.data(this._dialogInput[0], PROP_NAME, inst); + return this; + }, + + /* Detach a datepicker from its control. + @param target element - the target input field or division or span */ + _destroyDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + $.removeData(target, PROP_NAME); + if (nodeName == 'input') { + inst.append.remove(); + inst.trigger.remove(); + $target.removeClass(this.markerClassName). + unbind('focus', this._showDatepicker). + unbind('keydown', this._doKeyDown). + unbind('keypress', this._doKeyPress). + unbind('keyup', this._doKeyUp); + } else if (nodeName == 'div' || nodeName == 'span') + $target.removeClass(this.markerClassName).empty(); + }, + + /* Enable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _enableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = false; + inst.trigger.filter('button'). + each(function() { this.disabled = false; }).end(). + filter('img').css({opacity: '1.0', cursor: ''}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().removeClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + removeAttr("disabled"); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + }, + + /* Disable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _disableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = true; + inst.trigger.filter('button'). + each(function() { this.disabled = true; }).end(). + filter('img').css({opacity: '0.5', cursor: 'default'}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().addClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + attr("disabled", "disabled"); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + this._disabledInputs[this._disabledInputs.length] = target; + }, + + /* Is the first field in a jQuery collection disabled as a datepicker? + @param target element - the target input field or division or span + @return boolean - true if disabled, false if enabled */ + _isDisabledDatepicker: function(target) { + if (!target) { + return false; + } + for (var i = 0; i < this._disabledInputs.length; i++) { + if (this._disabledInputs[i] == target) + return true; + } + return false; + }, + + /* Retrieve the instance data for the target control. + @param target element - the target input field or division or span + @return object - the associated instance data + @throws error if a jQuery problem getting data */ + _getInst: function(target) { + try { + return $.data(target, PROP_NAME); + } + catch (err) { + throw 'Missing instance data for this datepicker'; + } + }, + + /* Update or retrieve the settings for a date picker attached to an input field or division. + @param target element - the target input field or division or span + @param name object - the new settings to update or + string - the name of the setting to change or retrieve, + when retrieving also 'all' for all instance settings or + 'defaults' for all global defaults + @param value any - the new value for the setting + (omit if above is an object or to retrieve a value) */ + _optionDatepicker: function(target, name, value) { + var inst = this._getInst(target); + if (arguments.length == 2 && typeof name == 'string') { + return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : + (inst ? (name == 'all' ? $.extend({}, inst.settings) : + this._get(inst, name)) : null)); + } + var settings = name || {}; + if (typeof name == 'string') { + settings = {}; + settings[name] = value; + } + if (inst) { + if (this._curInst == inst) { + this._hideDatepicker(); + } + var date = this._getDateDatepicker(target, true); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + extendRemove(inst.settings, settings); + // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided + if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) + inst.settings.minDate = this._formatDate(inst, minDate); + if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) + inst.settings.maxDate = this._formatDate(inst, maxDate); + this._attachments($(target), inst); + this._autoSize(inst); + this._setDate(inst, date); + this._updateAlternate(inst); + this._updateDatepicker(inst); + } + }, + + // change method deprecated + _changeDatepicker: function(target, name, value) { + this._optionDatepicker(target, name, value); + }, + + /* Redraw the date picker attached to an input field or division. + @param target element - the target input field or division or span */ + _refreshDatepicker: function(target) { + var inst = this._getInst(target); + if (inst) { + this._updateDatepicker(inst); + } + }, + + /* Set the dates for a jQuery selection. + @param target element - the target input field or division or span + @param date Date - the new date */ + _setDateDatepicker: function(target, date) { + var inst = this._getInst(target); + if (inst) { + this._setDate(inst, date); + this._updateDatepicker(inst); + this._updateAlternate(inst); + } + }, + + /* Get the date(s) for the first entry in a jQuery selection. + @param target element - the target input field or division or span + @param noDefault boolean - true if no default date is to be used + @return Date - the current date */ + _getDateDatepicker: function(target, noDefault) { + var inst = this._getInst(target); + if (inst && !inst.inline) + this._setDateFromField(inst, noDefault); + return (inst ? this._getDate(inst) : null); + }, + + /* Handle keystrokes. */ + _doKeyDown: function(event) { + var inst = $.datepicker._getInst(event.target); + var handled = true; + var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); + inst._keyEvent = true; + if ($.datepicker._datepickerShowing) + switch (event.keyCode) { + case 9: $.datepicker._hideDatepicker(); + handled = false; + break; // hide on tab out + case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + + $.datepicker._currentClass + ')', inst.dpDiv); + if (sel[0]) + $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); + var onSelect = $.datepicker._get(inst, 'onSelect'); + if (onSelect) { + var dateStr = $.datepicker._formatDate(inst); + + // trigger custom callback + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); + } + else + $.datepicker._hideDatepicker(); + return false; // don't submit the form + break; // select the value on enter + case 27: $.datepicker._hideDatepicker(); + break; // hide on escape + case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // previous month/year on page up/+ ctrl + case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // next month/year on page down/+ ctrl + case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); + handled = event.ctrlKey || event.metaKey; + break; // clear on ctrl or command +end + case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); + handled = event.ctrlKey || event.metaKey; + break; // current on ctrl or command +home + case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); + handled = event.ctrlKey || event.metaKey; + // -1 day on ctrl or command +left + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +left on Mac + break; + case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // -1 week on ctrl or command +up + case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); + handled = event.ctrlKey || event.metaKey; + // +1 day on ctrl or command +right + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +right + break; + case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // +1 week on ctrl or command +down + default: handled = false; + } + else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home + $.datepicker._showDatepicker(this); + else { + handled = false; + } + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }, + + /* Filter entered characters - based on date format. */ + _doKeyPress: function(event) { + var inst = $.datepicker._getInst(event.target); + if ($.datepicker._get(inst, 'constrainInput')) { + var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); + var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); + } + }, + + /* Synchronise manual entry and field/alternate field. */ + _doKeyUp: function(event) { + var inst = $.datepicker._getInst(event.target); + if (inst.input.val() != inst.lastVal) { + try { + var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + (inst.input ? inst.input.val() : null), + $.datepicker._getFormatConfig(inst)); + if (date) { // only if valid + $.datepicker._setDateFromField(inst); + $.datepicker._updateAlternate(inst); + $.datepicker._updateDatepicker(inst); + } + } + catch (event) { + $.datepicker.log(event); + } + } + return true; + }, + + /* Pop-up the date picker for a given input field. + If false returned from beforeShow event handler do not show. + @param input element - the input field attached to the date picker or + event - if triggered by focus */ + _showDatepicker: function(input) { + input = input.target || input; + if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger + input = $('input', input.parentNode)[0]; + if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here + return; + var inst = $.datepicker._getInst(input); + if ($.datepicker._curInst && $.datepicker._curInst != inst) { + $.datepicker._curInst.dpDiv.stop(true, true); + if ( inst && $.datepicker._datepickerShowing ) { + $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); + } + } + var beforeShow = $.datepicker._get(inst, 'beforeShow'); + var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; + if(beforeShowSettings === false){ + //false + return; + } + extendRemove(inst.settings, beforeShowSettings); + inst.lastVal = null; + $.datepicker._lastInput = input; + $.datepicker._setDateFromField(inst); + if ($.datepicker._inDialog) // hide cursor + input.value = ''; + if (!$.datepicker._pos) { // position below input + $.datepicker._pos = $.datepicker._findPos(input); + $.datepicker._pos[1] += input.offsetHeight; // add the height + } + var isFixed = false; + $(input).parents().each(function() { + isFixed |= $(this).css('position') == 'fixed'; + return !isFixed; + }); + if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled + $.datepicker._pos[0] -= document.documentElement.scrollLeft; + $.datepicker._pos[1] -= document.documentElement.scrollTop; + } + var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; + $.datepicker._pos = null; + //to avoid flashes on Firefox + inst.dpDiv.empty(); + // determine sizing offscreen + inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); + $.datepicker._updateDatepicker(inst); + // fix width for dynamic number of date pickers + // and adjust position before showing + offset = $.datepicker._checkOffset(inst, offset, isFixed); + inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? + 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', + left: offset.left + 'px', top: offset.top + 'px'}); + if (!inst.inline) { + var showAnim = $.datepicker._get(inst, 'showAnim'); + var duration = $.datepicker._get(inst, 'duration'); + var postProcess = function() { + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !! cover.length ){ + var borders = $.datepicker._getBorders(inst.dpDiv); + cover.css({left: -borders[0], top: -borders[1], + width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); + } + }; + inst.dpDiv.zIndex($(input).zIndex()+1); + $.datepicker._datepickerShowing = true; + if ($.effects && $.effects[showAnim]) + inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); + if (!showAnim || !duration) + postProcess(); + if (inst.input.is(':visible') && !inst.input.is(':disabled')) + inst.input.focus(); + $.datepicker._curInst = inst; + } + }, + + /* Generate the date picker content. */ + _updateDatepicker: function(inst) { + var self = this; + self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) + var borders = $.datepicker._getBorders(inst.dpDiv); + instActive = inst; // for delegate hover events + inst.dpDiv.empty().append(this._generateHTML(inst)); + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 + cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) + } + inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); + var numMonths = this._getNumberOfMonths(inst); + var cols = numMonths[1]; + var width = 17; + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); + if (cols > 1) + inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); + inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + + 'Class']('ui-datepicker-multi'); + inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + + 'Class']('ui-datepicker-rtl'); + if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && + // #6694 - don't focus the input if it's already focused + // this breaks the change event in IE + inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) + inst.input.focus(); + // deffered render of the years select (to avoid flashes on Firefox) + if( inst.yearshtml ){ + var origyearshtml = inst.yearshtml; + setTimeout(function(){ + //assure that inst.yearshtml didn't change. + if( origyearshtml === inst.yearshtml && inst.yearshtml ){ + inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); + } + origyearshtml = inst.yearshtml = null; + }, 0); + } + }, + + /* Retrieve the size of left and top borders for an element. + @param elem (jQuery object) the element of interest + @return (number[2]) the left and top borders */ + _getBorders: function(elem) { + var convert = function(value) { + return {thin: 1, medium: 2, thick: 3}[value] || value; + }; + return [parseFloat(convert(elem.css('border-left-width'))), + parseFloat(convert(elem.css('border-top-width')))]; + }, + + /* Check positioning to remain on screen. */ + _checkOffset: function(inst, offset, isFixed) { + var dpWidth = inst.dpDiv.outerWidth(); + var dpHeight = inst.dpDiv.outerHeight(); + var inputWidth = inst.input ? inst.input.outerWidth() : 0; + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft(); + var viewHeight = document.documentElement.clientHeight + $(document).scrollTop(); + + offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; + + // now check if datepicker is showing outside window viewport - move to a better place if so. + offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? + Math.abs(offset.left + dpWidth - viewWidth) : 0); + offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? + Math.abs(dpHeight + inputHeight) : 0); + + return offset; + }, + + /* Find an object's position on the screen. */ + _findPos: function(obj) { + var inst = this._getInst(obj); + var isRTL = this._get(inst, 'isRTL'); + while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { + obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; + } + var position = $(obj).offset(); + return [position.left, position.top]; + }, + + /* Hide the date picker from view. + @param input element - the input field attached to the date picker */ + _hideDatepicker: function(input) { + var inst = this._curInst; + if (!inst || (input && inst != $.data(input, PROP_NAME))) + return; + if (this._datepickerShowing) { + var showAnim = this._get(inst, 'showAnim'); + var duration = this._get(inst, 'duration'); + var self = this; + var postProcess = function() { + $.datepicker._tidyDialog(inst); + self._curInst = null; + }; + if ($.effects && $.effects[showAnim]) + inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : + (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); + if (!showAnim) + postProcess(); + this._datepickerShowing = false; + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); + this._lastInput = null; + if (this._inDialog) { + this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this.dpDiv); + } + } + this._inDialog = false; + } + }, + + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); + }, + + /* Close date picker if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!$.datepicker._curInst) + return; + + var $target = $(event.target), + inst = $.datepicker._getInst($target[0]); + + if ( ( ( $target[0].id != $.datepicker._mainDivId && + $target.parents('#' + $.datepicker._mainDivId).length == 0 && + !$target.hasClass($.datepicker.markerClassName) && + !$target.closest("." + $.datepicker._triggerClass).length && + $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || + ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) ) + $.datepicker._hideDatepicker(); + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._isDisabledDatepicker(target[0])) { + return; + } + this._adjustInstDate(inst, offset + + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning + period); + this._updateDatepicker(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._get(inst, 'gotoCurrent') && inst.currentDay) { + inst.selectedDay = inst.currentDay; + inst.drawMonth = inst.selectedMonth = inst.currentMonth; + inst.drawYear = inst.selectedYear = inst.currentYear; + } + else { + var date = new Date(); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + } + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var target = $(id); + var inst = this._getInst(target[0]); + inst['selected' + (period == 'M' ? 'Month' : 'Year')] = + inst['draw' + (period == 'M' ? 'Month' : 'Year')] = + parseInt(select.options[select.selectedIndex].value,10); + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a day. */ + _selectDay: function(id, month, year, td) { + var target = $(id); + if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { + return; + } + var inst = this._getInst(target[0]); + inst.selectedDay = inst.currentDay = $('a', td).html(); + inst.selectedMonth = inst.currentMonth = month; + inst.selectedYear = inst.currentYear = year; + this._selectDate(id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + }, + + /* Erase the input field and hide the date picker. */ + _clearDate: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + this._selectDate(target, ''); + }, + + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var target = $(id); + var inst = this._getInst(target[0]); + dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); + if (inst.input) + inst.input.val(dateStr); + this._updateAlternate(inst); + var onSelect = this._get(inst, 'onSelect'); + if (onSelect) + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback + else if (inst.input) + inst.input.trigger('change'); // fire the change event + if (inst.inline) + this._updateDatepicker(inst); + else { + this._hideDatepicker(); + this._lastInput = inst.input[0]; + if (typeof(inst.input[0]) != 'object') + inst.input.focus(); // restore focus + this._lastInput = null; + } + }, + + /* Update any alternate field to synchronise with the main field. */ + _updateAlternate: function(inst) { + var altField = this._get(inst, 'altField'); + if (altField) { // update alternate field too + var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); + var date = this._getDate(inst); + var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); + $(altField).each(function() { $(this).val(dateStr); }); + } + }, + + /* Set as beforeShowDay function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, + + /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + @param date Date - the date to get the week for + @return number - the number of the week within the year that contains this date */ + iso8601Week: function(date) { + var checkDate = new Date(date.getTime()); + // Find Thursday of this week starting on Monday + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + }, + + /* Parse a string value into a date object. + See formatDate below for the possible formats. + + @param format string - the expected format of the date + @param value string - the date in the above format + @param settings Object - attributes include: + shortYearCutoff number - the cutoff year for determining the century (optional) + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return Date - the extracted date value or null if value is blank */ + parseDate: function (format, value, settings) { + if (format == null || value == null) + throw 'Invalid arguments'; + value = (typeof value == 'object' ? value.toString() : value + ''); + if (value == '') + return null; + var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Extract a number from the string value + var getNumber = function(match) { + var isDoubled = lookAhead(match); + var size = (match == '@' ? 14 : (match == '!' ? 20 : + (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); + var digits = new RegExp('^\\d{1,' + size + '}'); + var num = value.substring(iValue).match(digits); + if (!num) + throw 'Missing number at position ' + iValue; + iValue += num[0].length; + return parseInt(num[0], 10); + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames) { + var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { + return [ [k, v] ]; + }).sort(function (a, b) { + return -(a[1].length - b[1].length); + }); + var index = -1; + $.each(names, function (i, pair) { + var name = pair[1]; + if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { + index = pair[0]; + iValue += name.length; + return false; + } + }); + if (index != -1) + return index + 1; + else + throw 'Unknown name at position ' + iValue; + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) != format.charAt(iFormat)) + throw 'Unexpected literal at position ' + iValue; + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + checkLiteral(); + else + switch (format.charAt(iFormat)) { + case 'd': + day = getNumber('d'); + break; + case 'D': + getName('D', dayNamesShort, dayNames); + break; + case 'o': + doy = getNumber('o'); + break; + case 'm': + month = getNumber('m'); + break; + case 'M': + month = getName('M', monthNamesShort, monthNames); + break; + case 'y': + year = getNumber('y'); + break; + case '@': + var date = new Date(getNumber('@')); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case '!': + var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if (lookAhead("'")) + checkLiteral(); + else + literal = true; + break; + default: + checkLiteral(); + } + } + if (iValue < value.length){ + throw "Extra/unparsed characters found in date: " + value.substring(iValue); + } + if (year == -1) + year = new Date().getFullYear(); + else if (year < 100) + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + if (doy > -1) { + month = 1; + day = doy; + do { + var dim = this._getDaysInMonth(year, month - 1); + if (day <= dim) + break; + month++; + day -= dim; + } while (true); + } + var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); + if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) + throw 'Invalid date'; // E.g. 31/02/00 + return date; + }, + + /* Standard date formats. */ + ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) + COOKIE: 'D, dd M yy', + ISO_8601: 'yy-mm-dd', + RFC_822: 'D, d M y', + RFC_850: 'DD, dd-M-y', + RFC_1036: 'D, d M y', + RFC_1123: 'D, d M yy', + RFC_2822: 'D, d M yy', + RSS: 'D, d M y', // RFC 822 + TICKS: '!', + TIMESTAMP: '@', + W3C: 'yy-mm-dd', // ISO 8601 + + _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), + + /* Format a date object into a string value. + The format can be combinations of the following: + d - day of month (no leading zero) + dd - day of month (two digit) + o - day of year (no leading zeros) + oo - day of year (three digit) + D - day name short + DD - day name long + m - month of year (no leading zero) + mm - month of year (two digit) + M - month name short + MM - month name long + y - year (two digit) + yy - year (four digit) + @ - Unix timestamp (ms since 01/01/1970) + ! - Windows ticks (100ns since 01/01/0001) + '...' - literal text + '' - single quote + + @param format string - the desired format of the date + @param date Date - the date value to format + @param settings Object - attributes include: + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return string - the date in the above format */ + formatDate: function (format, date, settings) { + if (!date) + return ''; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Format a number, with leading zero if necessary + var formatNumber = function(match, value, len) { + var num = '' + value; + if (lookAhead(match)) + while (num.length < len) + num = '0' + num; + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (lookAhead(match) ? longNames[value] : shortNames[value]); + }; + var output = ''; + var literal = false; + if (date) + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': + output += formatNumber('d', date.getDate(), 2); + break; + case 'D': + output += formatName('D', date.getDay(), dayNamesShort, dayNames); + break; + case 'o': + output += formatNumber('o', + Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); + break; + case 'm': + output += formatNumber('m', date.getMonth() + 1, 2); + break; + case 'M': + output += formatName('M', date.getMonth(), monthNamesShort, monthNames); + break; + case 'y': + output += (lookAhead('y') ? date.getFullYear() : + (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); + break; + case '@': + output += date.getTime(); + break; + case '!': + output += date.getTime() * 10000 + this._ticksTo1970; + break; + case "'": + if (lookAhead("'")) + output += "'"; + else + literal = true; + break; + default: + output += format.charAt(iFormat); + } + } + return output; + }, + + /* Extract all possible characters from the date format. */ + _possibleChars: function (format) { + var chars = ''; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + for (var iFormat = 0; iFormat < format.length; iFormat++) + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + chars += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': case 'm': case 'y': case '@': + chars += '0123456789'; + break; + case 'D': case 'M': + return null; // Accept anything + case "'": + if (lookAhead("'")) + chars += "'"; + else + literal = true; + break; + default: + chars += format.charAt(iFormat); + } + return chars; + }, + + /* Get a setting value, defaulting if necessary. */ + _get: function(inst, name) { + return inst.settings[name] !== undefined ? + inst.settings[name] : this._defaults[name]; + }, + + /* Parse existing date and initialise date picker. */ + _setDateFromField: function(inst, noDefault) { + if (inst.input.val() == inst.lastVal) { + return; + } + var dateFormat = this._get(inst, 'dateFormat'); + var dates = inst.lastVal = inst.input ? inst.input.val() : null; + var date, defaultDate; + date = defaultDate = this._getDefaultDate(inst); + var settings = this._getFormatConfig(inst); + try { + date = this.parseDate(dateFormat, dates, settings) || defaultDate; + } catch (event) { + this.log(event); + dates = (noDefault ? '' : dates); + } + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + inst.currentDay = (dates ? date.getDate() : 0); + inst.currentMonth = (dates ? date.getMonth() : 0); + inst.currentYear = (dates ? date.getFullYear() : 0); + this._adjustInstDate(inst); + }, + + /* Retrieve the default date shown on opening. */ + _getDefaultDate: function(inst) { + return this._restrictMinMax(inst, + this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); + }, + + /* A date may be specified as an exact value or a relative one. */ + _determineDate: function(inst, date, defaultDate) { + var offsetNumeric = function(offset) { + var date = new Date(); + date.setDate(date.getDate() + offset); + return date; + }; + var offsetString = function(offset) { + try { + return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + offset, $.datepicker._getFormatConfig(inst)); + } + catch (e) { + // Ignore + } + var date = (offset.toLowerCase().match(/^c/) ? + $.datepicker._getDate(inst) : null) || new Date(); + var year = date.getFullYear(); + var month = date.getMonth(); + var day = date.getDate(); + var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var matches = pattern.exec(offset); + while (matches) { + switch (matches[2] || 'd') { + case 'd' : case 'D' : + day += parseInt(matches[1],10); break; + case 'w' : case 'W' : + day += parseInt(matches[1],10) * 7; break; + case 'm' : case 'M' : + month += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + case 'y': case 'Y' : + year += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + } + matches = pattern.exec(offset); + } + return new Date(year, month, day); + }; + var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : + (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); + newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); + if (newDate) { + newDate.setHours(0); + newDate.setMinutes(0); + newDate.setSeconds(0); + newDate.setMilliseconds(0); + } + return this._daylightSavingAdjust(newDate); + }, + + /* Handle switch to/from daylight saving. + Hours may be non-zero on daylight saving cut-over: + > 12 when midnight changeover, but then cannot generate + midnight datetime, so jump to 1AM, otherwise reset. + @param date (Date) the date to check + @return (Date) the corrected date */ + _daylightSavingAdjust: function(date) { + if (!date) return null; + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + }, + + /* Set the date(s) directly. */ + _setDate: function(inst, date, noChange) { + var clear = !date; + var origMonth = inst.selectedMonth; + var origYear = inst.selectedYear; + var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); + inst.selectedDay = inst.currentDay = newDate.getDate(); + inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); + inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); + if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) + this._notifyChange(inst); + this._adjustInstDate(inst); + if (inst.input) { + inst.input.val(clear ? '' : this._formatDate(inst)); + } + }, + + /* Retrieve the date(s) directly. */ + _getDate: function(inst) { + var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + this._daylightSavingAdjust(new Date( + inst.currentYear, inst.currentMonth, inst.currentDay))); + return startDate; + }, + + /* Generate the HTML for the current state of the date picker. */ + _generateHTML: function(inst) { + var today = new Date(); + today = this._daylightSavingAdjust( + new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time + var isRTL = this._get(inst, 'isRTL'); + var showButtonPanel = this._get(inst, 'showButtonPanel'); + var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); + var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); + var numMonths = this._getNumberOfMonths(inst); + var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); + var stepMonths = this._get(inst, 'stepMonths'); + var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); + var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : + new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var drawMonth = inst.drawMonth - showCurrentAtPos; + var drawYear = inst.drawYear; + if (drawMonth < 0) { + drawMonth += 12; + drawYear--; + } + if (maxDate) { + var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), + maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); + maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); + while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { + drawMonth--; + if (drawMonth < 0) { + drawMonth = 11; + drawYear--; + } + } + } + inst.drawMonth = drawMonth; + inst.drawYear = drawYear; + var prevText = this._get(inst, 'prevText'); + prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), + this._getFormatConfig(inst))); + var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? + '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid + + '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' + + ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' : + (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>')); + var nextText = this._get(inst, 'nextText'); + nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), + this._getFormatConfig(inst))); + var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? + '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid + + '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' + + ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' : + (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>')); + var currentText = this._get(inst, 'currentText'); + var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); + currentText = (!navigationAsDateFormat ? currentText : + this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); + var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid + + '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : ''); + var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') + + (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid + + '.datepicker._gotoToday(\'#' + inst.id + '\');"' + + '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : ''; + var firstDay = parseInt(this._get(inst, 'firstDay'),10); + firstDay = (isNaN(firstDay) ? 0 : firstDay); + var showWeek = this._get(inst, 'showWeek'); + var dayNames = this._get(inst, 'dayNames'); + var dayNamesShort = this._get(inst, 'dayNamesShort'); + var dayNamesMin = this._get(inst, 'dayNamesMin'); + var monthNames = this._get(inst, 'monthNames'); + var monthNamesShort = this._get(inst, 'monthNamesShort'); + var beforeShowDay = this._get(inst, 'beforeShowDay'); + var showOtherMonths = this._get(inst, 'showOtherMonths'); + var selectOtherMonths = this._get(inst, 'selectOtherMonths'); + var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; + var defaultDate = this._getDefaultDate(inst); + var html = ''; + for (var row = 0; row < numMonths[0]; row++) { + var group = ''; + this.maxRows = 4; + for (var col = 0; col < numMonths[1]; col++) { + var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); + var cornerClass = ' ui-corner-all'; + var calender = ''; + if (isMultiMonth) { + calender += '<div class="ui-datepicker-group'; + if (numMonths[1] > 1) + switch (col) { + case 0: calender += ' ui-datepicker-group-first'; + cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break; + case numMonths[1]-1: calender += ' ui-datepicker-group-last'; + cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break; + default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break; + } + calender += '">'; + } + calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' + + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, + row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers + '</div><table class="ui-datepicker-calendar"><thead>' + + '<tr>'; + var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : ''); + for (var dow = 0; dow < 7; dow++) { // days of the week + var day = (dow + firstDay) % 7; + thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + + '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>'; + } + calender += thead + '</tr></thead><tbody>'; + var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); + if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) + inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; + var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate + var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) + this.maxRows = numRows; + var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); + for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows + calender += '<tr>'; + var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' + + this._get(inst, 'calculateWeek')(printDate) + '</td>'); + for (var dow = 0; dow < 7; dow++) { // create date picker days + var daySettings = (beforeShowDay ? + beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); + var otherMonth = (printDate.getMonth() != drawMonth); + var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + tbody += '<td class="' + + ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends + (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months + ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key + (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ? + // or defaultDate is current printedDate and defaultDate is selectedDate + ' ' + this._dayOverClass : '') + // highlight selected day + (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days + (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates + (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day + (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different) + ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title + (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' + + inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions + (otherMonth && !showOtherMonths ? ' ' : // display for other months + (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' + + (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') + + (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day + (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months + '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date + printDate.setDate(printDate.getDate() + 1); + printDate = this._daylightSavingAdjust(printDate); + } + calender += tbody + '</tr>'; + } + drawMonth++; + if (drawMonth > 11) { + drawMonth = 0; + drawYear++; + } + calender += '</tbody></table>' + (isMultiMonth ? '</div>' + + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : ''); + group += calender; + } + html += group; + } + html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? + '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '<div class="ui-datepicker-title">'; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>'; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += '<select class="ui-datepicker-month" ' + + 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' + + '>'; + for (var month = 0; month < 12; month++) { + if ((!inMinYear || month >= minDate.getMonth()) && + (!inMaxYear || month <= maxDate.getMonth())) + monthHtml += '<option value="' + month + '"' + + (month == drawMonth ? ' selected="selected"' : '') + + '>' + monthNamesShort[month] + '</option>'; + } + monthHtml += '</select>'; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if ( !inst.yearshtml ) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '<span class="ui-datepicker-year">' + drawYear + '</span>'; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function(value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += '<select class="ui-datepicker-year" ' + + 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' + + '>'; + for (; year <= endYear; year++) { + inst.yearshtml += '<option value="' + year + '"' + + (year == drawYear ? ' selected="selected"' : '') + + '>' + year + '</option>'; + } + inst.yearshtml += '</select>'; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '</div>'; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate: function(inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ +function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.bind('mouseout', function(event) { + var elem = $( event.target ).closest( selector ); + if ( !elem.length ) { + return; + } + elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); + }) + .bind('mouseover', function(event) { + var elem = $( event.target ).closest( selector ); + if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || + !elem.length ) { + return; + } + elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + elem.addClass('ui-state-hover'); + if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); + if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); + }); +} + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Determine whether an object is an array. */ +function isArray(a) { + return (a && (($.browser.safari && typeof a == 'object' && a.length) || + (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if ( !this.length ) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find('body').append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "1.8.18"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window['DP_jQuery_' + dpuuid] = $; + +})(jQuery); +/* + * jQuery UI Dialog 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function( $, undefined ) { + +var uiDialogClasses = + 'ui-dialog ' + + 'ui-widget ' + + 'ui-widget-content ' + + 'ui-corner-all ', + sizeRelatedOptions = { + buttons: true, + height: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + width: true + }, + resizableRelatedOptions = { + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true + }, + // support for jQuery 1.3.2 - handle common attrFn methods for dialog + attrFn = $.attrFn || { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true, + click: true + }; + +$.widget("ui.dialog", { + options: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: 'close', + dialogClass: '', + draggable: true, + hide: null, + height: 'auto', + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: 'center', + at: 'center', + collision: 'fit', + // ensure that the titlebar is never outside the document + using: function(pos) { + var topOffset = $(this).css(pos).offset().top; + if (topOffset < 0) { + $(this).css('top', pos.top - topOffset); + } + } + }, + resizable: true, + show: null, + stack: true, + title: '', + width: 300, + zIndex: 1000 + }, + + _create: function() { + this.originalTitle = this.element.attr('title'); + // #5742 - .attr() might return a DOMElement + if ( typeof this.originalTitle !== "string" ) { + this.originalTitle = ""; + } + + this.options.title = this.options.title || this.originalTitle; + var self = this, + options = self.options, + + title = options.title || ' ', + titleId = $.ui.dialog.getTitleId(self.element), + + uiDialog = (self.uiDialog = $('<div></div>')) + .appendTo(document.body) + .hide() + .addClass(uiDialogClasses + options.dialogClass) + .css({ + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + // setting outline to 0 prevents a border on focus in Mozilla + .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { + if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE) { + + self.close(event); + event.preventDefault(); + } + }) + .attr({ + role: 'dialog', + 'aria-labelledby': titleId + }) + .mousedown(function(event) { + self.moveToTop(false, event); + }), + + uiDialogContent = self.element + .show() + .removeAttr('title') + .addClass( + 'ui-dialog-content ' + + 'ui-widget-content') + .appendTo(uiDialog), + + uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>')) + .addClass( + 'ui-dialog-titlebar ' + + 'ui-widget-header ' + + 'ui-corner-all ' + + 'ui-helper-clearfix' + ) + .prependTo(uiDialog), + + uiDialogTitlebarClose = $('<a href="#"></a>') + .addClass( + 'ui-dialog-titlebar-close ' + + 'ui-corner-all' + ) + .attr('role', 'button') + .hover( + function() { + uiDialogTitlebarClose.addClass('ui-state-hover'); + }, + function() { + uiDialogTitlebarClose.removeClass('ui-state-hover'); + } + ) + .focus(function() { + uiDialogTitlebarClose.addClass('ui-state-focus'); + }) + .blur(function() { + uiDialogTitlebarClose.removeClass('ui-state-focus'); + }) + .click(function(event) { + self.close(event); + return false; + }) + .appendTo(uiDialogTitlebar), + + uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>')) + .addClass( + 'ui-icon ' + + 'ui-icon-closethick' + ) + .text(options.closeText) + .appendTo(uiDialogTitlebarClose), + + uiDialogTitle = $('<span></span>') + .addClass('ui-dialog-title') + .attr('id', titleId) + .html(title) + .prependTo(uiDialogTitlebar); + + //handling of deprecated beforeclose (vs beforeClose) option + //Ticket #4669 http://dev.jqueryui.com/ticket/4669 + //TODO: remove in 1.9pre + if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { + options.beforeClose = options.beforeclose; + } + + uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); + + if (options.draggable && $.fn.draggable) { + self._makeDraggable(); + } + if (options.resizable && $.fn.resizable) { + self._makeResizable(); + } + + self._createButtons(options.buttons); + self._isOpen = false; + + if ($.fn.bgiframe) { + uiDialog.bgiframe(); + } + }, + + _init: function() { + if ( this.options.autoOpen ) { + this.open(); + } + }, + + destroy: function() { + var self = this; + + if (self.overlay) { + self.overlay.destroy(); + } + self.uiDialog.hide(); + self.element + .unbind('.dialog') + .removeData('dialog') + .removeClass('ui-dialog-content ui-widget-content') + .hide().appendTo('body'); + self.uiDialog.remove(); + + if (self.originalTitle) { + self.element.attr('title', self.originalTitle); + } + + return self; + }, + + widget: function() { + return this.uiDialog; + }, + + close: function(event) { + var self = this, + maxZ, thisZ; + + if (false === self._trigger('beforeClose', event)) { + return; + } + + if (self.overlay) { + self.overlay.destroy(); + } + self.uiDialog.unbind('keypress.ui-dialog'); + + self._isOpen = false; + + if (self.options.hide) { + self.uiDialog.hide(self.options.hide, function() { + self._trigger('close', event); + }); + } else { + self.uiDialog.hide(); + self._trigger('close', event); + } + + $.ui.dialog.overlay.resize(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if (self.options.modal) { + maxZ = 0; + $('.ui-dialog').each(function() { + if (this !== self.uiDialog[0]) { + thisZ = $(this).css('z-index'); + if(!isNaN(thisZ)) { + maxZ = Math.max(maxZ, thisZ); + } + } + }); + $.ui.dialog.maxZ = maxZ; + } + + return self; + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function(force, event) { + var self = this, + options = self.options, + saveScroll; + + if ((options.modal && !force) || + (!options.stack && !options.modal)) { + return self._trigger('focus', event); + } + + if (options.zIndex > $.ui.dialog.maxZ) { + $.ui.dialog.maxZ = options.zIndex; + } + if (self.overlay) { + $.ui.dialog.maxZ += 1; + self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); + } + + //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. + // http://ui.jquery.com/bugs/ticket/3193 + saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; + $.ui.dialog.maxZ += 1; + self.uiDialog.css('z-index', $.ui.dialog.maxZ); + self.element.attr(saveScroll); + self._trigger('focus', event); + + return self; + }, + + open: function() { + if (this._isOpen) { return; } + + var self = this, + options = self.options, + uiDialog = self.uiDialog; + + self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; + self._size(); + self._position(options.position); + uiDialog.show(options.show); + self.moveToTop(true); + + // prevent tabbing out of modal dialogs + if ( options.modal ) { + uiDialog.bind( "keydown.ui-dialog", function( event ) { + if ( event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + + var tabbables = $(':tabbable', this), + first = tabbables.filter(':first'), + last = tabbables.filter(':last'); + + if (event.target === last[0] && !event.shiftKey) { + first.focus(1); + return false; + } else if (event.target === first[0] && event.shiftKey) { + last.focus(1); + return false; + } + }); + } + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + $(self.element.find(':tabbable').get().concat( + uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( + uiDialog.get()))).eq(0).focus(); + + self._isOpen = true; + self._trigger('open'); + + return self; + }, + + _createButtons: function(buttons) { + var self = this, + hasButtons = false, + uiDialogButtonPane = $('<div></div>') + .addClass( + 'ui-dialog-buttonpane ' + + 'ui-widget-content ' + + 'ui-helper-clearfix' + ), + uiButtonSet = $( "<div></div>" ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + // if we already have a button pane, remove it + self.uiDialog.find('.ui-dialog-buttonpane').remove(); + + if (typeof buttons === 'object' && buttons !== null) { + $.each(buttons, function() { + return !(hasButtons = true); + }); + } + if (hasButtons) { + $.each(buttons, function(name, props) { + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + var button = $('<button type="button"></button>') + .click(function() { + props.click.apply(self.element[0], arguments); + }) + .appendTo(uiButtonSet); + // can't use .attr( props, true ) with jQuery 1.3.2. + $.each( props, function( key, value ) { + if ( key === "click" ) { + return; + } + if ( key in attrFn ) { + button[ key ]( value ); + } else { + button.attr( key, value ); + } + }); + if ($.fn.button) { + button.button(); + } + }); + uiDialogButtonPane.appendTo(self.uiDialog); + } + }, + + _makeDraggable: function() { + var self = this, + options = self.options, + doc = $(document), + heightBeforeDrag; + + function filteredUi(ui) { + return { + position: ui.position, + offset: ui.offset + }; + } + + self.uiDialog.draggable({ + cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', + handle: '.ui-dialog-titlebar', + containment: 'document', + start: function(event, ui) { + heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); + $(this).height($(this).height()).addClass("ui-dialog-dragging"); + self._trigger('dragStart', event, filteredUi(ui)); + }, + drag: function(event, ui) { + self._trigger('drag', event, filteredUi(ui)); + }, + stop: function(event, ui) { + options.position = [ui.position.left - doc.scrollLeft(), + ui.position.top - doc.scrollTop()]; + $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); + self._trigger('dragStop', event, filteredUi(ui)); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function(handles) { + handles = (handles === undefined ? this.options.resizable : handles); + var self = this, + options = self.options, + // .ui-resizable has position: relative defined in the stylesheet + // but dialogs have to use absolute or fixed positioning + position = self.uiDialog.css('position'), + resizeHandles = (typeof handles === 'string' ? + handles : + 'n,e,s,w,se,sw,ne,nw' + ); + + function filteredUi(ui) { + return { + originalPosition: ui.originalPosition, + originalSize: ui.originalSize, + position: ui.position, + size: ui.size + }; + } + + self.uiDialog.resizable({ + cancel: '.ui-dialog-content', + containment: 'document', + alsoResize: self.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: self._minHeight(), + handles: resizeHandles, + start: function(event, ui) { + $(this).addClass("ui-dialog-resizing"); + self._trigger('resizeStart', event, filteredUi(ui)); + }, + resize: function(event, ui) { + self._trigger('resize', event, filteredUi(ui)); + }, + stop: function(event, ui) { + $(this).removeClass("ui-dialog-resizing"); + options.height = $(this).height(); + options.width = $(this).width(); + self._trigger('resizeStop', event, filteredUi(ui)); + $.ui.dialog.overlay.resize(); + } + }) + .css('position', position) + .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); + }, + + _minHeight: function() { + var options = this.options; + + if (options.height === 'auto') { + return options.minHeight; + } else { + return Math.min(options.minHeight, options.height); + } + }, + + _position: function(position) { + var myAt = [], + offset = [0, 0], + isVisible; + + if (position) { + // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( + // if (typeof position == 'string' || $.isArray(position)) { + // myAt = $.isArray(position) ? position : position.split(' '); + + if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { + myAt = position.split ? position.split(' ') : [position[0], position[1]]; + if (myAt.length === 1) { + myAt[1] = myAt[0]; + } + + $.each(['left', 'top'], function(i, offsetPosition) { + if (+myAt[i] === myAt[i]) { + offset[i] = myAt[i]; + myAt[i] = offsetPosition; + } + }); + + position = { + my: myAt.join(" "), + at: myAt.join(" "), + offset: offset.join(" ") + }; + } + + position = $.extend({}, $.ui.dialog.prototype.options.position, position); + } else { + position = $.ui.dialog.prototype.options.position; + } + + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is(':visible'); + if (!isVisible) { + this.uiDialog.show(); + } + this.uiDialog + // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 + .css({ top: 0, left: 0 }) + .position($.extend({ of: window }, position)); + if (!isVisible) { + this.uiDialog.hide(); + } + }, + + _setOptions: function( options ) { + var self = this, + resizableOptions = {}, + resize = false; + + $.each( options, function( key, value ) { + self._setOption( key, value ); + + if ( key in sizeRelatedOptions ) { + resize = true; + } + if ( key in resizableRelatedOptions ) { + resizableOptions[ key ] = value; + } + }); + + if ( resize ) { + this._size(); + } + if ( this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", resizableOptions ); + } + }, + + _setOption: function(key, value){ + var self = this, + uiDialog = self.uiDialog; + + switch (key) { + //handling of deprecated beforeclose (vs beforeClose) option + //Ticket #4669 http://dev.jqueryui.com/ticket/4669 + //TODO: remove in 1.9pre + case "beforeclose": + key = "beforeClose"; + break; + case "buttons": + self._createButtons(value); + break; + case "closeText": + // ensure that we always pass a string + self.uiDialogTitlebarCloseText.text("" + value); + break; + case "dialogClass": + uiDialog + .removeClass(self.options.dialogClass) + .addClass(uiDialogClasses + value); + break; + case "disabled": + if (value) { + uiDialog.addClass('ui-dialog-disabled'); + } else { + uiDialog.removeClass('ui-dialog-disabled'); + } + break; + case "draggable": + var isDraggable = uiDialog.is( ":data(draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } + + if ( !isDraggable && value ) { + self._makeDraggable(); + } + break; + case "position": + self._position(value); + break; + case "resizable": + // currently resizable, becoming non-resizable + var isResizable = uiDialog.is( ":data(resizable)" ); + if (isResizable && !value) { + uiDialog.resizable('destroy'); + } + + // currently resizable, changing handles + if (isResizable && typeof value === 'string') { + uiDialog.resizable('option', 'handles', value); + } + + // currently non-resizable, becoming resizable + if (!isResizable && value !== false) { + self._makeResizable(value); + } + break; + case "title": + // convert whatever was passed in o a string, for html() to not throw up + $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); + break; + } + + $.Widget.prototype._setOption.apply(self, arguments); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var options = this.options, + nonContentHeight, + minContentHeight, + isVisible = this.uiDialog.is( ":visible" ); + + // reset content sizing + this.element.show().css({ + width: 'auto', + minHeight: 0, + height: 0 + }); + + if (options.minWidth > options.width) { + options.width = options.minWidth; + } + + // reset wrapper sizing + // determine the height of all the non-content elements + nonContentHeight = this.uiDialog.css({ + height: 'auto', + width: options.width + }) + .height(); + minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); + + if ( options.height === "auto" ) { + // only needed for IE6 support + if ( $.support.minHeight ) { + this.element.css({ + minHeight: minContentHeight, + height: "auto" + }); + } else { + this.uiDialog.show(); + var autoHeight = this.element.css( "height", "auto" ).height(); + if ( !isVisible ) { + this.uiDialog.hide(); + } + this.element.height( Math.max( autoHeight, minContentHeight ) ); + } + } else { + this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + } + + if (this.uiDialog.is(':data(resizable)')) { + this.uiDialog.resizable('option', 'minHeight', this._minHeight()); + } + } +}); + +$.extend($.ui.dialog, { + version: "1.8.18", + + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + var id = $el.attr('id'); + if (!id) { + this.uuid += 1; + id = this.uuid; + } + return 'ui-dialog-title-' + id; + }, + + overlay: function(dialog) { + this.$el = $.ui.dialog.overlay.create(dialog); + } +}); + +$.extend($.ui.dialog.overlay, { + instances: [], + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + oldInstances: [], + maxZ: 0, + events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), + function(event) { return event + '.dialog-overlay'; }).join(' '), + create: function(dialog) { + if (this.instances.length === 0) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ($.ui.dialog.overlay.instances.length) { + $(document).bind($.ui.dialog.overlay.events, function(event) { + // stop events if the z-index of the target is < the z-index of the overlay + // we cannot return true when we don't want to cancel the event (#3523) + if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) { + return false; + } + }); + } + }, 1); + + // allow closing by pressing the escape key + $(document).bind('keydown.dialog-overlay', function(event) { + if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE) { + + dialog.close(event); + event.preventDefault(); + } + }); + + // handle window resize + $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); + } + + var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay')) + .appendTo(document.body) + .css({ + width: this.width(), + height: this.height() + }); + + if ($.fn.bgiframe) { + $el.bgiframe(); + } + + this.instances.push($el); + return $el; + }, + + destroy: function($el) { + var indexOf = $.inArray($el, this.instances); + if (indexOf != -1){ + this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); + } + + if (this.instances.length === 0) { + $([document, window]).unbind('.dialog-overlay'); + } + + $el.remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + var maxZ = 0; + $.each(this.instances, function() { + maxZ = Math.max(maxZ, this.css('z-index')); + }); + this.maxZ = maxZ; + }, + + height: function() { + var scrollHeight, + offsetHeight; + // handle IE 6 + if ($.browser.msie && $.browser.version < 7) { + scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if (scrollHeight < offsetHeight) { + return $(window).height() + 'px'; + } else { + return scrollHeight + 'px'; + } + // handle "good" browsers + } else { + return $(document).height() + 'px'; + } + }, + + width: function() { + var scrollWidth, + offsetWidth; + // handle IE + if ( $.browser.msie ) { + scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if (scrollWidth < offsetWidth) { + return $(window).width() + 'px'; + } else { + return scrollWidth + 'px'; + } + // handle "good" browsers + } else { + return $(document).width() + 'px'; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $([]); + $.each($.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add(this); + }); + + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); + } +}); + +$.extend($.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy(this.$el); + } +}); + +}(jQuery)); +/* + * jQuery UI Position 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */ +(function( $, undefined ) { + +$.ui = $.ui || {}; + +var horizontalPositions = /left|center|right/, + verticalPositions = /top|center|bottom/, + center = "center", + support = {}, + _position = $.fn.position, + _offset = $.fn.offset; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var target = $( options.of ), + targetElem = target[0], + collision = ( options.collision || "flip" ).split( " " ), + offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], + targetWidth, + targetHeight, + basePosition; + + if ( targetElem.nodeType === 9 ) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top: 0, left: 0 }; + // TODO: use $.isWindow() in 1.9 + } else if ( targetElem.setTimeout ) { + targetWidth = target.width(); + targetHeight = target.height(); + basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; + } else if ( targetElem.preventDefault ) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + basePosition = { top: options.of.pageY, left: options.of.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + basePosition = target.offset(); + } + + // force my and at to have valid horizontal and veritcal positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[this] || "" ).split( " " ); + if ( pos.length === 1) { + pos = horizontalPositions.test( pos[0] ) ? + pos.concat( [center] ) : + verticalPositions.test( pos[0] ) ? + [ center ].concat( pos ) : + [ center, center ]; + } + pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; + pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; + options[ this ] = pos; + }); + + // normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + // normalize offset option + offset[ 0 ] = parseInt( offset[0], 10 ) || 0; + if ( offset.length === 1 ) { + offset[ 1 ] = offset[ 0 ]; + } + offset[ 1 ] = parseInt( offset[1], 10 ) || 0; + + if ( options.at[0] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[0] === center ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[1] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[1] === center ) { + basePosition.top += targetHeight / 2; + } + + basePosition.left += offset[ 0 ]; + basePosition.top += offset[ 1 ]; + + return this.each(function() { + var elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, + marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, + collisionWidth = elemWidth + marginLeft + + ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), + collisionHeight = elemHeight + marginTop + + ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), + position = $.extend( {}, basePosition ), + collisionPosition; + + if ( options.my[0] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[0] === center ) { + position.left -= elemWidth / 2; + } + + if ( options.my[1] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[1] === center ) { + position.top -= elemHeight / 2; + } + + // prevent fractions if jQuery version doesn't support them (see #5280) + if ( !support.fractions ) { + position.left = Math.round( position.left ); + position.top = Math.round( position.top ); + } + + collisionPosition = { + left: position.left - marginLeft, + top: position.top - marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[i] ] ) { + $.ui.position[ collision[i] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: offset, + my: options.my, + at: options.at + }); + } + }); + + if ( $.fn.bgiframe ) { + elem.bgiframe(); + } + elem.offset( $.extend( position, { using: options.using } ) ); + }); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var win = $( window ), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); + position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); + }, + top: function( position, data ) { + var win = $( window ), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); + position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); + } + }, + + flip: { + left: function( position, data ) { + if ( data.at[0] === center ) { + return; + } + var win = $( window ), + over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + -data.targetWidth, + offset = -2 * data.offset[ 0 ]; + position.left += data.collisionPosition.left < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + }, + top: function( position, data ) { + if ( data.at[1] === center ) { + return; + } + var win = $( window ), + over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), + myOffset = data.my[ 1 ] === "top" ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + -data.targetHeight, + offset = -2 * data.offset[ 1 ]; + position.top += data.collisionPosition.top < 0 ? + myOffset + atOffset + offset : + over > 0 ? + myOffset + atOffset + offset : + 0; + } + } +}; + +// offset setter from jQuery 1.4 +if ( !$.offset.setOffset ) { + $.offset.setOffset = function( elem, options ) { + // set position first, in-case top/left are set even on static elem + if ( /static/.test( $.curCSS( elem, "position" ) ) ) { + elem.style.position = "relative"; + } + var curElem = $( elem ), + curOffset = curElem.offset(), + curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, + curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, + props = { + top: (options.top - curOffset.top) + curTop, + left: (options.left - curOffset.left) + curLeft + }; + + if ( 'using' in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + }; + + $.fn.offset = function( options ) { + var elem = this[ 0 ]; + if ( !elem || !elem.ownerDocument ) { return null; } + if ( options ) { + return this.each(function() { + $.offset.setOffset( this, options ); + }); + } + return _offset.call( this ); + }; +} + +// fraction support test (older versions of jQuery don't support fractions) +(function () { + var body = document.getElementsByTagName( "body" )[ 0 ], + div = document.createElement( "div" ), + testElement, testElementParent, testElementStyle, offset, offsetTotal; + + //Create a "fake body" for testing based on method used in jQuery.support + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + $.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( var i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || document.documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;"; + + offset = $( div ).offset( function( _, offset ) { + return offset; + }).offset(); + + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 ); + support.fractions = offsetTotal > 21 && offsetTotal < 22; +})(); + +}( jQuery )); +/* + * jQuery UI Progressbar 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget( "ui.progressbar", { + options: { + value: 0, + max: 100 + }, + + min: 0, + + _create: function() { + this.element + .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .attr({ + role: "progressbar", + "aria-valuemin": this.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this._value() + }); + + this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) + .appendTo( this.element ); + + this.oldValue = this._value(); + this._refreshValue(); + }, + + destroy: function() { + this.element + .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + + this.valueDiv.remove(); + + $.Widget.prototype.destroy.apply( this, arguments ); + }, + + value: function( newValue ) { + if ( newValue === undefined ) { + return this._value(); + } + + this._setOption( "value", newValue ); + return this; + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + this.options.value = value; + this._refreshValue(); + if ( this._value() === this.options.max ) { + this._trigger( "complete" ); + } + } + + $.Widget.prototype._setOption.apply( this, arguments ); + }, + + _value: function() { + var val = this.options.value; + // normalize invalid value + if ( typeof val !== "number" ) { + val = 0; + } + return Math.min( this.options.max, Math.max( this.min, val ) ); + }, + + _percentage: function() { + return 100 * this._value() / this.options.max; + }, + + _refreshValue: function() { + var value = this.value(); + var percentage = this._percentage(); + + if ( this.oldValue !== value ) { + this.oldValue = value; + this._trigger( "change" ); + } + + this.valueDiv + .toggle( value > this.min ) + .toggleClass( "ui-corner-right", value === this.options.max ) + .width( percentage.toFixed(0) + "%" ); + this.element.attr( "aria-valuenow", value ); + } +}); + +$.extend( $.ui.progressbar, { + version: "1.8.18" +}); + +})( jQuery ); +/* + * jQuery UI Slider 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) +var numPages = 5; + +$.widget( "ui.slider", $.ui.mouse, { + + widgetEventPrefix: "slide", + + options: { + animate: false, + distance: 0, + max: 100, + min: 0, + orientation: "horizontal", + range: false, + step: 1, + value: 0, + values: null + }, + + _create: function() { + var self = this, + o = this.options, + existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), + handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", + handleCount = ( o.values && o.values.length ) || 1, + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass( "ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); + + this.range = $([]); + + if ( o.range ) { + if ( o.range === true ) { + if ( !o.values ) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if ( o.values.length && o.values.length !== 2 ) { + o.values = [ o.values[0], o.values[0] ]; + } + } + + this.range = $( "<div></div>" ) + .appendTo( this.element ) + .addClass( "ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); + } + + for ( var i = existingHandles.length; i < handleCount; i += 1 ) { + handles.push( handle ); + } + + this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); + + this.handle = this.handles.eq( 0 ); + + this.handles.add( this.range ).filter( "a" ) + .click(function( event ) { + event.preventDefault(); + }) + .hover(function() { + if ( !o.disabled ) { + $( this ).addClass( "ui-state-hover" ); + } + }, function() { + $( this ).removeClass( "ui-state-hover" ); + }) + .focus(function() { + if ( !o.disabled ) { + $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); + $( this ).addClass( "ui-state-focus" ); + } else { + $( this ).blur(); + } + }) + .blur(function() { + $( this ).removeClass( "ui-state-focus" ); + }); + + this.handles.each(function( i ) { + $( this ).data( "index.ui-slider-handle", i ); + }); + + this.handles + .keydown(function( event ) { + var index = $( this ).data( "index.ui-slider-handle" ), + allowed, + curVal, + newVal, + step; + + if ( self.options.disabled ) { + return; + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + event.preventDefault(); + if ( !self._keySliding ) { + self._keySliding = true; + $( this ).addClass( "ui-state-active" ); + allowed = self._start( event, index ); + if ( allowed === false ) { + return; + } + } + break; + } + + step = self.options.step; + if ( self.options.values && self.options.values.length ) { + curVal = newVal = self.values( index ); + } else { + curVal = newVal = self.value(); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + newVal = self._valueMin(); + break; + case $.ui.keyCode.END: + newVal = self._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if ( curVal === self._valueMax() ) { + return; + } + newVal = self._trimAlignValue( curVal + step ); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if ( curVal === self._valueMin() ) { + return; + } + newVal = self._trimAlignValue( curVal - step ); + break; + } + + self._slide( event, index, newVal ); + }) + .keyup(function( event ) { + var index = $( this ).data( "index.ui-slider-handle" ); + + if ( self._keySliding ) { + self._keySliding = false; + self._stop( event, index ); + self._change( event, index ); + $( this ).removeClass( "ui-state-active" ); + } + + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + destroy: function() { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass( "ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" ) + .removeData( "slider" ) + .unbind( ".slider" ); + + this._mouseDestroy(); + + return this; + }, + + _mouseCapture: function( event ) { + var o = this.options, + position, + normValue, + distance, + closestHandle, + self, + index, + allowed, + offset, + mouseOverHandle; + + if ( o.disabled ) { + return false; + } + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x: event.pageX, y: event.pageY }; + normValue = this._normValueFromMouse( position ); + distance = this._valueMax() - this._valueMin() + 1; + self = this; + this.handles.each(function( i ) { + var thisDistance = Math.abs( normValue - self.values(i) ); + if ( distance > thisDistance ) { + distance = thisDistance; + closestHandle = $( this ); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if( o.range === true && this.values(1) === o.min ) { + index += 1; + closestHandle = $( this.handles[index] ); + } + + allowed = this._start( event, index ); + if ( allowed === false ) { + return false; + } + this._mouseSliding = true; + + self._handleIndex = index; + + closestHandle + .addClass( "ui-state-active" ) + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - ( closestHandle.width() / 2 ), + top: event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - + ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) + }; + + if ( !this.handles.hasClass( "ui-state-hover" ) ) { + this._slide( event, index, normValue ); + } + this._animateOff = true; + return true; + }, + + _mouseStart: function( event ) { + return true; + }, + + _mouseDrag: function( event ) { + var position = { x: event.pageX, y: event.pageY }, + normValue = this._normValueFromMouse( position ); + + this._slide( event, this._handleIndex, normValue ); + + return false; + }, + + _mouseStop: function( event ) { + this.handles.removeClass( "ui-state-active" ); + this._mouseSliding = false; + + this._stop( event, this._handleIndex ); + this._change( event, this._handleIndex ); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation: function() { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse: function( position ) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if ( this.orientation === "horizontal" ) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + } + + percentMouse = ( pixelMouse / pixelTotal ); + if ( percentMouse > 1 ) { + percentMouse = 1; + } + if ( percentMouse < 0 ) { + percentMouse = 0; + } + if ( this.orientation === "vertical" ) { + percentMouse = 1 - percentMouse; + } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue( valueMouse ); + }, + + _start: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + return this._trigger( "start", event, uiHash ); + }, + + _slide: function( event, index, newVal ) { + var otherVal, + newValues, + allowed; + + if ( this.options.values && this.options.values.length ) { + otherVal = this.values( index ? 0 : 1 ); + + if ( ( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if ( newVal !== this.values( index ) ) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal, + values: newValues + } ); + otherVal = this.values( index ? 0 : 1 ); + if ( allowed !== false ) { + this.values( index, newVal, true ); + } + } + } else { + if ( newVal !== this.value() ) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal + } ); + if ( allowed !== false ) { + this.value( newVal ); + } + } + } + }, + + _stop: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "stop", event, uiHash ); + }, + + _change: function( event, index ) { + if ( !this._keySliding && !this._mouseSliding ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "change", event, uiHash ); + } + }, + + value: function( newValue ) { + if ( arguments.length ) { + this.options.value = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, 0 ); + return; + } + + return this._value(); + }, + + values: function( index, newValue ) { + var vals, + newValues, + i; + + if ( arguments.length > 1 ) { + this.options.values[ index ] = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, index ); + return; + } + + if ( arguments.length ) { + if ( $.isArray( arguments[ 0 ] ) ) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for ( i = 0; i < vals.length; i += 1 ) { + vals[ i ] = this._trimAlignValue( newValues[ i ] ); + this._change( null, i ); + } + this._refreshValue(); + } else { + if ( this.options.values && this.options.values.length ) { + return this._values( index ); + } else { + return this.value(); + } + } + } else { + return this._values(); + } + }, + + _setOption: function( key, value ) { + var i, + valsLength = 0; + + if ( $.isArray( this.options.values ) ) { + valsLength = this.options.values.length; + } + + $.Widget.prototype._setOption.apply( this, arguments ); + + switch ( key ) { + case "disabled": + if ( value ) { + this.handles.filter( ".ui-state-focus" ).blur(); + this.handles.removeClass( "ui-state-hover" ); + this.handles.propAttr( "disabled", true ); + this.element.addClass( "ui-disabled" ); + } else { + this.handles.propAttr( "disabled", false ); + this.element.removeClass( "ui-disabled" ); + } + break; + case "orientation": + this._detectOrientation(); + this.element + .removeClass( "ui-slider-horizontal ui-slider-vertical" ) + .addClass( "ui-slider-" + this.orientation ); + this._refreshValue(); + break; + case "value": + this._animateOff = true; + this._refreshValue(); + this._change( null, 0 ); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for ( i = 0; i < valsLength; i += 1 ) { + this._change( null, i ); + } + this._animateOff = false; + break; + } + }, + + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value: function() { + var val = this.options.value; + val = this._trimAlignValue( val ); + + return val; + }, + + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values: function( index ) { + var val, + vals, + i; + + if ( arguments.length ) { + val = this.options.values[ index ]; + val = this._trimAlignValue( val ); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for ( i = 0; i < vals.length; i+= 1) { + vals[ i ] = this._trimAlignValue( vals[ i ] ); + } + + return vals; + } + }, + + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function( val ) { + if ( val <= this._valueMin() ) { + return this._valueMin(); + } + if ( val >= this._valueMax() ) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat( alignValue.toFixed(5) ); + }, + + _valueMin: function() { + return this.options.min; + }, + + _valueMax: function() { + return this.options.max; + }, + + _refreshValue: function() { + var oRange = this.options.range, + o = this.options, + self = this, + animate = ( !this._animateOff ) ? o.animate : false, + valPercent, + _set = {}, + lastValPercent, + value, + valueMin, + valueMax; + + if ( this.options.values && this.options.values.length ) { + this.handles.each(function( i, j ) { + valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + if ( self.options.range === true ) { + if ( self.orientation === "horizontal" ) { + if ( i === 0 ) { + self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); + } + if ( i === 1 ) { + self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } else { + if ( i === 0 ) { + self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); + } + if ( i === 1 ) { + self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + lastValPercent = valPercent; + }); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + + if ( oRange === "min" && this.orientation === "horizontal" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "horizontal" ) { + this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + if ( oRange === "min" && this.orientation === "vertical" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "vertical" ) { + this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + +}); + +$.extend( $.ui.slider, { + version: "1.8.18" +}); + +}(jQuery)); +/* + * jQuery UI Tabs 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var tabId = 0, + listId = 0; + +function getNextTabId() { + return ++tabId; +} + +function getNextListId() { + return ++listId; +} + +$.widget( "ui.tabs", { + options: { + add: null, + ajaxOptions: null, + cache: false, + cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + collapsible: false, + disable: null, + disabled: [], + enable: null, + event: "click", + fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } + idPrefix: "ui-tabs-", + load: null, + panelTemplate: "<div></div>", + remove: null, + select: null, + show: null, + spinner: "<em>Loading…</em>", + tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>" + }, + + _create: function() { + this._tabify( true ); + }, + + _setOption: function( key, value ) { + if ( key == "selected" ) { + if (this.options.collapsible && value == this.options.selected ) { + return; + } + this.select( value ); + } else { + this.options[ key ] = value; + this._tabify(); + } + }, + + _tabId: function( a ) { + return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || + this.options.idPrefix + getNextTabId(); + }, + + _sanitizeSelector: function( hash ) { + // we need this because an id may contain a ":" + return hash.replace( /:/g, "\\:" ); + }, + + _cookie: function() { + var cookie = this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); + return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); + }, + + _ui: function( tab, panel ) { + return { + tab: tab, + panel: panel, + index: this.anchors.index( tab ) + }; + }, + + _cleanup: function() { + // restore all former loading tabs labels + this.lis.filter( ".ui-state-processing" ) + .removeClass( "ui-state-processing" ) + .find( "span:data(label.tabs)" ) + .each(function() { + var el = $( this ); + el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); + }); + }, + + _tabify: function( init ) { + var self = this, + o = this.options, + fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash + + this.list = this.element.find( "ol,ul" ).eq( 0 ); + this.lis = $( " > li:has(a[href])", this.list ); + this.anchors = this.lis.map(function() { + return $( "a", this )[ 0 ]; + }); + this.panels = $( [] ); + + this.anchors.each(function( i, a ) { + var href = $( a ).attr( "href" ); + // For dynamically created HTML that contains a hash as href IE < 8 expands + // such href to the full page url with hash and then misinterprets tab as ajax. + // Same consideration applies for an added tab with a fragment identifier + // since a[href=#fragment-identifier] does unexpectedly not match. + // Thus normalize href attribute... + var hrefBase = href.split( "#" )[ 0 ], + baseEl; + if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || + ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { + href = a.hash; + a.href = href; + } + + // inline tab + if ( fragmentId.test( href ) ) { + self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); + // remote tab + // prevent loading the page itself if href is just "#" + } else if ( href && href !== "#" ) { + // required for restore on destroy + $.data( a, "href.tabs", href ); + + // TODO until #3808 is fixed strip fragment identifier from url + // (IE fails to load from such url) + $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); + + var id = self._tabId( a ); + a.href = "#" + id; + var $panel = self.element.find( "#" + id ); + if ( !$panel.length ) { + $panel = $( o.panelTemplate ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .insertAfter( self.panels[ i - 1 ] || self.list ); + $panel.data( "destroy.tabs", true ); + } + self.panels = self.panels.add( $panel ); + // invalid tab href + } else { + o.disabled.push( i ); + } + }); + + // initialization from scratch + if ( init ) { + // attach necessary classes for styling + this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); + this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); + this.lis.addClass( "ui-state-default ui-corner-top" ); + this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); + + // Selected tab + // use "selected" option or try to retrieve: + // 1. from fragment identifier in url + // 2. from cookie + // 3. from selected class attribute on <li> + if ( o.selected === undefined ) { + if ( location.hash ) { + this.anchors.each(function( i, a ) { + if ( a.hash == location.hash ) { + o.selected = i; + return false; + } + }); + } + if ( typeof o.selected !== "number" && o.cookie ) { + o.selected = parseInt( self._cookie(), 10 ); + } + if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { + o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + } + o.selected = o.selected || ( this.lis.length ? 0 : -1 ); + } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release + o.selected = -1; + } + + // sanity check - default to first tab... + o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) + ? o.selected + : 0; + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + // A selected tab cannot become disabled. + o.disabled = $.unique( o.disabled.concat( + $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { + return self.lis.index( n ); + }) + ) ).sort(); + + if ( $.inArray( o.selected, o.disabled ) != -1 ) { + o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 ); + } + + // highlight selected tab + this.panels.addClass( "ui-tabs-hide" ); + this.lis.removeClass( "ui-tabs-selected ui-state-active" ); + // check for length avoids error when initializing empty list + if ( o.selected >= 0 && this.anchors.length ) { + self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); + this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); + + // seems to be expected behavior that the show callback is fired + self.element.queue( "tabs", function() { + self._trigger( "show", null, + self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); + }); + + this.load( o.selected ); + } + + // clean up to avoid memory leaks in certain versions of IE 6 + // TODO: namespace this event + $( window ).bind( "unload", function() { + self.lis.add( self.anchors ).unbind( ".tabs" ); + self.lis = self.anchors = self.panels = null; + }); + // update selected after add/remove + } else { + o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); + } + + // update collapsible + // TODO: use .toggleClass() + this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); + + // set or update cookie after init and add/remove respectively + if ( o.cookie ) { + this._cookie( o.selected, o.cookie ); + } + + // disable tabs + for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { + $( li )[ $.inArray( i, o.disabled ) != -1 && + // TODO: use .toggleClass() + !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); + } + + // reset cache if switching from cached to not cached + if ( o.cache === false ) { + this.anchors.removeData( "cache.tabs" ); + } + + // remove all handlers before, tabify may run on existing tabs after add or option change + this.lis.add( this.anchors ).unbind( ".tabs" ); + + if ( o.event !== "mouseover" ) { + var addState = function( state, el ) { + if ( el.is( ":not(.ui-state-disabled)" ) ) { + el.addClass( "ui-state-" + state ); + } + }; + var removeState = function( state, el ) { + el.removeClass( "ui-state-" + state ); + }; + this.lis.bind( "mouseover.tabs" , function() { + addState( "hover", $( this ) ); + }); + this.lis.bind( "mouseout.tabs", function() { + removeState( "hover", $( this ) ); + }); + this.anchors.bind( "focus.tabs", function() { + addState( "focus", $( this ).closest( "li" ) ); + }); + this.anchors.bind( "blur.tabs", function() { + removeState( "focus", $( this ).closest( "li" ) ); + }); + } + + // set up animations + var hideFx, showFx; + if ( o.fx ) { + if ( $.isArray( o.fx ) ) { + hideFx = o.fx[ 0 ]; + showFx = o.fx[ 1 ]; + } else { + hideFx = showFx = o.fx; + } + } + + // Reset certain styles left over from animation + // and prevent IE's ClearType bug... + function resetStyle( $el, fx ) { + $el.css( "display", "" ); + if ( !$.support.opacity && fx.opacity ) { + $el[ 0 ].style.removeAttribute( "filter" ); + } + } + + // Show a tab... + var showTab = showFx + ? function( clicked, $show ) { + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way + .animate( showFx, showFx.duration || "normal", function() { + resetStyle( $show, showFx ); + self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); + }); + } + : function( clicked, $show ) { + $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); + $show.removeClass( "ui-tabs-hide" ); + self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); + }; + + // Hide a tab, $show is optional... + var hideTab = hideFx + ? function( clicked, $hide ) { + $hide.animate( hideFx, hideFx.duration || "normal", function() { + self.lis.removeClass( "ui-tabs-selected ui-state-active" ); + $hide.addClass( "ui-tabs-hide" ); + resetStyle( $hide, hideFx ); + self.element.dequeue( "tabs" ); + }); + } + : function( clicked, $hide, $show ) { + self.lis.removeClass( "ui-tabs-selected ui-state-active" ); + $hide.addClass( "ui-tabs-hide" ); + self.element.dequeue( "tabs" ); + }; + + // attach tab event handler, unbind to avoid duplicates from former tabifying... + this.anchors.bind( o.event + ".tabs", function() { + var el = this, + $li = $(el).closest( "li" ), + $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), + $show = self.element.find( self._sanitizeSelector( el.hash ) ); + + // If tab is already selected and not collapsible or tab disabled or + // or is already loading or click callback returns false stop here. + // Check if click handler returns false last so that it is not executed + // for a disabled or loading tab! + if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || + $li.hasClass( "ui-state-disabled" ) || + $li.hasClass( "ui-state-processing" ) || + self.panels.filter( ":animated" ).length || + self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { + this.blur(); + return false; + } + + o.selected = self.anchors.index( this ); + + self.abort(); + + // if tab may be closed + if ( o.collapsible ) { + if ( $li.hasClass( "ui-tabs-selected" ) ) { + o.selected = -1; + + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + self.element.queue( "tabs", function() { + hideTab( el, $hide ); + }).dequeue( "tabs" ); + + this.blur(); + return false; + } else if ( !$hide.length ) { + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + self.element.queue( "tabs", function() { + showTab( el, $show ); + }); + + // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 + self.load( self.anchors.index( this ) ); + + this.blur(); + return false; + } + } + + if ( o.cookie ) { + self._cookie( o.selected, o.cookie ); + } + + // show new tab + if ( $show.length ) { + if ( $hide.length ) { + self.element.queue( "tabs", function() { + hideTab( el, $hide ); + }); + } + self.element.queue( "tabs", function() { + showTab( el, $show ); + }); + + self.load( self.anchors.index( this ) ); + } else { + throw "jQuery UI Tabs: Mismatching fragment identifier."; + } + + // Prevent IE from keeping other link focussed when using the back button + // and remove dotted border from clicked link. This is controlled via CSS + // in modern browsers; blur() removes focus from address bar in Firefox + // which can become a usability and annoying problem with tabs('rotate'). + if ( $.browser.msie ) { + this.blur(); + } + }); + + // disable click in any case + this.anchors.bind( "click.tabs", function(){ + return false; + }); + }, + + _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. + // also sanitizes numerical indexes to valid values. + if ( typeof index == "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) ); + } + + return index; + }, + + destroy: function() { + var o = this.options; + + this.abort(); + + this.element + .unbind( ".tabs" ) + .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ) + .removeData( "tabs" ); + + this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); + + this.anchors.each(function() { + var href = $.data( this, "href.tabs" ); + if ( href ) { + this.href = href; + } + var $this = $( this ).unbind( ".tabs" ); + $.each( [ "href", "load", "cache" ], function( i, prefix ) { + $this.removeData( prefix + ".tabs" ); + }); + }); + + this.lis.unbind( ".tabs" ).add( this.panels ).each(function() { + if ( $.data( this, "destroy.tabs" ) ) { + $( this ).remove(); + } else { + $( this ).removeClass([ + "ui-state-default", + "ui-corner-top", + "ui-tabs-selected", + "ui-state-active", + "ui-state-hover", + "ui-state-focus", + "ui-state-disabled", + "ui-tabs-panel", + "ui-widget-content", + "ui-corner-bottom", + "ui-tabs-hide" + ].join( " " ) ); + } + }); + + if ( o.cookie ) { + this._cookie( null, o.cookie ); + } + + return this; + }, + + add: function( url, label, index ) { + if ( index === undefined ) { + index = this.anchors.length; + } + + var self = this, + o = this.options, + $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); + + $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); + + // try to find an existing element before creating a new one + var $panel = self.element.find( "#" + id ); + if ( !$panel.length ) { + $panel = $( o.panelTemplate ) + .attr( "id", id ) + .data( "destroy.tabs", true ); + } + $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); + + if ( index >= this.lis.length ) { + $li.appendTo( this.list ); + $panel.appendTo( this.list[ 0 ].parentNode ); + } else { + $li.insertBefore( this.lis[ index ] ); + $panel.insertBefore( this.panels[ index ] ); + } + + o.disabled = $.map( o.disabled, function( n, i ) { + return n >= index ? ++n : n; + }); + + this._tabify(); + + if ( this.anchors.length == 1 ) { + o.selected = 0; + $li.addClass( "ui-tabs-selected ui-state-active" ); + $panel.removeClass( "ui-tabs-hide" ); + this.element.queue( "tabs", function() { + self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); + }); + + this.load( 0 ); + } + + this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, + + remove: function( index ) { + index = this._getIndex( index ); + var o = this.options, + $li = this.lis.eq( index ).remove(), + $panel = this.panels.eq( index ).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { + this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); + } + + o.disabled = $.map( + $.grep( o.disabled, function(n, i) { + return n != index; + }), + function( n, i ) { + return n >= index ? --n : n; + }); + + this._tabify(); + + this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); + return this; + }, + + enable: function( index ) { + index = this._getIndex( index ); + var o = this.options; + if ( $.inArray( index, o.disabled ) == -1 ) { + return; + } + + this.lis.eq( index ).removeClass( "ui-state-disabled" ); + o.disabled = $.grep( o.disabled, function( n, i ) { + return n != index; + }); + + this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, + + disable: function( index ) { + index = this._getIndex( index ); + var self = this, o = this.options; + // cannot disable already selected tab + if ( index != o.selected ) { + this.lis.eq( index ).addClass( "ui-state-disabled" ); + + o.disabled.push( index ); + o.disabled.sort(); + + this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + + return this; + }, + + select: function( index ) { + index = this._getIndex( index ); + if ( index == -1 ) { + if ( this.options.collapsible && this.options.selected != -1 ) { + index = this.options.selected; + } else { + return this; + } + } + this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); + return this; + }, + + load: function( index ) { + index = this._getIndex( index ); + var self = this, + o = this.options, + a = this.anchors.eq( index )[ 0 ], + url = $.data( a, "load.tabs" ); + + this.abort(); + + // not remote or from cache + if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { + this.element.dequeue( "tabs" ); + return; + } + + // load remote from here on + this.lis.eq( index ).addClass( "ui-state-processing" ); + + if ( o.spinner ) { + var span = $( "span", a ); + span.data( "label.tabs", span.html() ).html( o.spinner ); + } + + this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { + url: url, + success: function( r, s ) { + self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); + + // take care of tab labels + self._cleanup(); + + if ( o.cache ) { + $.data( a, "cache.tabs", true ); + } + + self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); + try { + o.ajaxOptions.success( r, s ); + } + catch ( e ) {} + }, + error: function( xhr, s, e ) { + // take care of tab labels + self._cleanup(); + + self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + o.ajaxOptions.error( xhr, s, index, a ); + } + catch ( e ) {} + } + } ) ); + + // last, so that load event is fired before show... + self.element.dequeue( "tabs" ); + + return this; + }, + + abort: function() { + // stop possibly running animations + this.element.queue( [] ); + this.panels.stop( false, true ); + + // "tabs" queue must not contain more than two elements, + // which are the callbacks for the latest clicked tab... + this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); + + // terminate pending requests from other tabs + if ( this.xhr ) { + this.xhr.abort(); + delete this.xhr; + } + + // take care of tab labels + this._cleanup(); + return this; + }, + + url: function( index, url ) { + this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); + return this; + }, + + length: function() { + return this.anchors.length; + } +}); + +$.extend( $.ui.tabs, { + version: "1.8.18" +}); + +/* + * Tabs Extensions + */ + +/* + * Rotate + */ +$.extend( $.ui.tabs.prototype, { + rotation: null, + rotate: function( ms, continuing ) { + var self = this, + o = this.options; + + var rotate = self._rotate || ( self._rotate = function( e ) { + clearTimeout( self.rotation ); + self.rotation = setTimeout(function() { + var t = o.selected; + self.select( ++t < self.anchors.length ? t : 0 ); + }, ms ); + + if ( e ) { + e.stopPropagation(); + } + }); + + var stop = self._unrotate || ( self._unrotate = !continuing + ? function(e) { + if (e.clientX) { // in case of a true click + self.rotate(null); + } + } + : function( e ) { + t = o.selected; + rotate(); + }); + + // start rotation + if ( ms ) { + this.element.bind( "tabsshow", rotate ); + this.anchors.bind( o.event + ".tabs", stop ); + rotate(); + // stop rotation + } else { + clearTimeout( self.rotation ); + this.element.unbind( "tabsshow", rotate ); + this.anchors.unbind( o.event + ".tabs", stop ); + delete this._rotate; + delete this._unrotate; + } + + return this; + } +}); + +})( jQuery ); diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js new file mode 100644 index 00000000000..f00a62f133f --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.min.js @@ -0,0 +1,356 @@ +/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */(function(a,b){function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;if(!b.href||!g||f.nodeName.toLowerCase()!=="map")return!1;h=a("img[usemap=#"+g+"]")[0];return!!h&&d(h)}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}a.ui=a.ui||{};a.ui.version||(a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a.each(["Width","Height"],function(c,d){function h(b,c,d,f){a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)});return c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){if(c===b)return g["inner"+d].call(this);return this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){if(typeof b!="number")return g["outer"+d].call(this,b);return this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!!d&&!!a.element[0].parentNode)for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;if(b[d]>0)return!0;b[d]=1,e=b[d]>0,b[d]=0;return e},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}}))})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}});return d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;e=!f&&g.length?a.extend.apply(null,[!0,e].concat(g)):e;if(f&&e.charAt(0)==="_")return h;f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b){h=f;return!1}}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))});return h}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}this._setOptions(e);return this},_setOptions:function(b){var c=this;a.each(b,function(a,b){c._setOption(a,b)});return this},_setOption:function(a,b){this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b);return this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);this.element.trigger(c,d);return!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||c.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent")){a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation();return!1}}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(b){if(!c){this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted){b.preventDefault();return!0}}!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0;return!0}},_mouseMove:function(b){if(a.browser.msie&&!(document.documentMode>=9)&&!b.button)return this._mouseUp(b);if(this._mouseStarted){this._mouseDrag(b);return b.preventDefault()}this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b));return!this._mouseStarted},_mouseUp:function(b){a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b));return!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);/* + * jQuery UI Position 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */(function(a,b){a.ui=a.ui||{};var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1];return this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]!==e){var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0}},top:function(b,c){if(c.at[1]!==e){var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];if(!c||!c.ownerDocument)return null;if(b)return this.each(function(){a.offset.setOffset(this,b)});return h.call(this)}),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);/* + * jQuery UI Draggable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.draggable",a.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},destroy:function(){if(!!this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy();return this}},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle"))return!1;this.handle=this._getHandle(b);if(!this.handle)return!1;c.iframeFix&&a(c.iframeFix===!0?"iframe":c.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(a(this).offset()).appendTo("body")});return!0},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b),this._cacheHelperProportions(),a.ui.ddmanager&&(a.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,c.cursorAt&&this._adjustOffsetFromHelper(c.cursorAt),c.containment&&this._setContainment();if(this._trigger("start",b)===!1){this._clear();return!1}this._cacheHelperProportions(),a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.helper.addClass("ui-draggable-dragging"),this._mouseDrag(b,!0),a.ui.ddmanager&&a.ui.ddmanager.dragStart(this,b);return!0},_mouseDrag:function(b,c){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute");if(!c){var d=this._uiHash();if(this._trigger("drag",b,d)===!1){this._mouseUp({});return!1}this.position=d.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";a.ui.ddmanager&&a.ui.ddmanager.drag(this,b);return!1},_mouseStop:function(b){var c=!1;a.ui.ddmanager&&!this.options.dropBehaviour&&(c=a.ui.ddmanager.drop(this,b)),this.dropped&&(c=this.dropped,this.dropped=!1);if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return!1;if(this.options.revert=="invalid"&&!c||this.options.revert=="valid"&&c||this.options.revert===!0||a.isFunction(this.options.revert)&&this.options.revert.call(this.element,c)){var d=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){d._trigger("stop",b)!==!1&&d._clear()})}else this._trigger("stop",b)!==!1&&this._clear();return!1},_mouseUp:function(b){this.options.iframeFix===!0&&a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),a.ui.ddmanager&&a.ui.ddmanager.dragStop(this,b);return a.ui.mouse.prototype._mouseUp.call(this,b)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?!0:!1;a(this.options.handle,this.element).find("*").andSelf().each(function(){this==b.target&&(c=!0)});return c},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b])):c.helper=="clone"?this.element.clone().removeAttr("id"):this.element;d.parents("body").length||d.appendTo(c.appendTo=="parent"?this.element[0].parentNode:c.appendTo),d[0]!=this.element[0]&&!/(fixed|absolute)/.test(d.css("position"))&&d.css("position","absolute");return d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[b.containment=="document"?0:a(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,b.containment=="document"?0:a(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(b.containment=="document"?0:a(window).scrollLeft())+a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(b.containment=="document"?0:a(window).scrollTop())+(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)&&b.containment.constructor!=Array){var c=a(b.containment),d=c[0];if(!d)return;var e=c.offset(),f=a(d).css("overflow")!="hidden";this.containment=[(parseInt(a(d).css("borderLeftWidth"),10)||0)+(parseInt(a(d).css("paddingLeft"),10)||0),(parseInt(a(d).css("borderTopWidth"),10)||0)+(parseInt(a(d).css("paddingTop"),10)||0),(f?Math.max(d.scrollWidth,d.offsetWidth):d.offsetWidth)-(parseInt(a(d).css("borderLeftWidth"),10)||0)-(parseInt(a(d).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(f?Math.max(d.scrollHeight,d.offsetHeight):d.offsetHeight)-(parseInt(a(d).css("borderTopWidth"),10)||0)-(parseInt(a(d).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=c}else b.containment.constructor==Array&&(this.containment=b.containment)},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName),f=b.pageX,g=b.pageY;if(this.originalPosition){var h;if(this.containment){if(this.relative_container){var i=this.relative_container.offset();h=[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]}else h=this.containment;b.pageX-this.offset.click.left<h[0]&&(f=h[0]+this.offset.click.left),b.pageY-this.offset.click.top<h[1]&&(g=h[1]+this.offset.click.top),b.pageX-this.offset.click.left>h[2]&&(f=h[2]+this.offset.click.left),b.pageY-this.offset.click.top>h[3]&&(g=h[3]+this.offset.click.top)}if(c.grid){var j=c.grid[1]?this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1]:this.originalPageY;g=h?j-this.offset.click.top<h[1]||j-this.offset.click.top>h[3]?j-this.offset.click.top<h[1]?j+c.grid[1]:j-c.grid[1]:j:j;var k=c.grid[0]?this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0]:this.originalPageX;f=h?k-this.offset.click.left<h[0]||k-this.offset.click.left>h[2]?k-this.offset.click.left<h[0]?k+c.grid[0]:k-c.grid[0]:k:k}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&a.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(b,c,d){d=d||this._uiHash(),a.ui.plugin.call(this,b,[c,d]),b=="drag"&&(this.positionAbs=this._convertPositionTo("absolute"));return a.Widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(a){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),a.extend(a.ui.draggable,{version:"1.8.18"}),a.ui.plugin.add("draggable","connectToSortable",{start:function(b,c){var d=a(this).data("draggable"),e=d.options,f=a.extend({},c,{item:d.element});d.sortables=[],a(e.connectToSortable).each(function(){var c=a.data(this,"sortable");c&&!c.options.disabled&&(d.sortables.push({instance:c,shouldRevert:c.options.revert}),c.refreshPositions(),c._trigger("activate",b,f))})},stop:function(b,c){var d=a(this).data("draggable"),e=a.extend({},c,{item:d.element});a.each(d.sortables,function(){this.instance.isOver?(this.instance.isOver=0,d.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(b),this.instance.options.helper=this.instance.options._helper,d.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",b,e))})},drag:function(b,c){var d=a(this).data("draggable"),e=this,f=function(b){var c=this.offset.click.top,d=this.offset.click.left,e=this.positionAbs.top,f=this.positionAbs.left,g=b.height,h=b.width,i=b.top,j=b.left;return a.ui.isOver(e+c,f+d,i,j,g,h)};a.each(d.sortables,function(f){this.instance.positionAbs=d.positionAbs,this.instance.helperProportions=d.helperProportions,this.instance.offset.click=d.offset.click,this.instance._intersectsWith(this.instance.containerCache)?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=a(e).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return c.helper[0]},b.target=this.instance.currentItem[0],this.instance._mouseCapture(b,!0),this.instance._mouseStart(b,!0,!0),this.instance.offset.click.top=d.offset.click.top,this.instance.offset.click.left=d.offset.click.left,this.instance.offset.parent.left-=d.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=d.offset.parent.top-this.instance.offset.parent.top,d._trigger("toSortable",b),d.dropped=this.instance.element,d.currentItem=d.element,this.instance.fromOutside=d),this.instance.currentItem&&this.instance._mouseDrag(b)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",b,this.instance._uiHash(this.instance)),this.instance._mouseStop(b,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),d._trigger("fromSortable",b),d.dropped=!1)})}}),a.ui.plugin.add("draggable","cursor",{start:function(b,c){var d=a("body"),e=a(this).data("draggable").options;d.css("cursor")&&(e._cursor=d.css("cursor")),d.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;d._cursor&&a("body").css("cursor",d._cursor)}}),a.ui.plugin.add("draggable","opacity",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("opacity")&&(e._opacity=d.css("opacity")),d.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;d._opacity&&a(c.helper).css("opacity",d._opacity)}}),a.ui.plugin.add("draggable","scroll",{start:function(b,c){var d=a(this).data("draggable");d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"&&(d.overflowOffset=d.scrollParent.offset())},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=!1;if(d.scrollParent[0]!=document&&d.scrollParent[0].tagName!="HTML"){if(!e.axis||e.axis!="x")d.overflowOffset.top+d.scrollParent[0].offsetHeight-b.pageY<e.scrollSensitivity?d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop+e.scrollSpeed:b.pageY-d.overflowOffset.top<e.scrollSensitivity&&(d.scrollParent[0].scrollTop=f=d.scrollParent[0].scrollTop-e.scrollSpeed);if(!e.axis||e.axis!="y")d.overflowOffset.left+d.scrollParent[0].offsetWidth-b.pageX<e.scrollSensitivity?d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft+e.scrollSpeed:b.pageX-d.overflowOffset.left<e.scrollSensitivity&&(d.scrollParent[0].scrollLeft=f=d.scrollParent[0].scrollLeft-e.scrollSpeed)}else{if(!e.axis||e.axis!="x")b.pageY-a(document).scrollTop()<e.scrollSensitivity?f=a(document).scrollTop(a(document).scrollTop()-e.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<e.scrollSensitivity&&(f=a(document).scrollTop(a(document).scrollTop()+e.scrollSpeed));if(!e.axis||e.axis!="y")b.pageX-a(document).scrollLeft()<e.scrollSensitivity?f=a(document).scrollLeft(a(document).scrollLeft()-e.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<e.scrollSensitivity&&(f=a(document).scrollLeft(a(document).scrollLeft()+e.scrollSpeed))}f!==!1&&a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(d,b)}}),a.ui.plugin.add("draggable","snap",{start:function(b,c){var d=a(this).data("draggable"),e=d.options;d.snapElements=[],a(e.snap.constructor!=String?e.snap.items||":data(draggable)":e.snap).each(function(){var b=a(this),c=b.offset();this!=d.element[0]&&d.snapElements.push({item:this,width:b.outerWidth(),height:b.outerHeight(),top:c.top,left:c.left})})},drag:function(b,c){var d=a(this).data("draggable"),e=d.options,f=e.snapTolerance,g=c.offset.left,h=g+d.helperProportions.width,i=c.offset.top,j=i+d.helperProportions.height;for(var k=d.snapElements.length-1;k>=0;k--){var l=d.snapElements[k].left,m=l+d.snapElements[k].width,n=d.snapElements[k].top,o=n+d.snapElements[k].height;if(!(l-f<g&&g<m+f&&n-f<i&&i<o+f||l-f<g&&g<m+f&&n-f<j&&j<o+f||l-f<h&&h<m+f&&n-f<i&&i<o+f||l-f<h&&h<m+f&&n-f<j&&j<o+f)){d.snapElements[k].snapping&&d.options.snap.release&&d.options.snap.release.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=!1;continue}if(e.snapMode!="inner"){var p=Math.abs(n-j)<=f,q=Math.abs(o-i)<=f,r=Math.abs(l-h)<=f,s=Math.abs(m-g)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n-d.helperProportions.height,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l-d.helperProportions.width}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m}).left-d.margins.left)}var t=p||q||r||s;if(e.snapMode!="outer"){var p=Math.abs(n-i)<=f,q=Math.abs(o-j)<=f,r=Math.abs(l-g)<=f,s=Math.abs(m-h)<=f;p&&(c.position.top=d._convertPositionTo("relative",{top:n,left:0}).top-d.margins.top),q&&(c.position.top=d._convertPositionTo("relative",{top:o-d.helperProportions.height,left:0}).top-d.margins.top),r&&(c.position.left=d._convertPositionTo("relative",{top:0,left:l}).left-d.margins.left),s&&(c.position.left=d._convertPositionTo("relative",{top:0,left:m-d.helperProportions.width}).left-d.margins.left)}!d.snapElements[k].snapping&&(p||q||r||s||t)&&d.options.snap.snap&&d.options.snap.snap.call(d.element,b,a.extend(d._uiHash(),{snapItem:d.snapElements[k].item})),d.snapElements[k].snapping=p||q||r||s||t}}}),a.ui.plugin.add("draggable","stack",{start:function(b,c){var d=a(this).data("draggable").options,e=a.makeArray(a(d.stack)).sort(function(b,c){return(parseInt(a(b).css("zIndex"),10)||0)-(parseInt(a(c).css("zIndex"),10)||0)});if(!!e.length){var f=parseInt(e[0].style.zIndex)||0;a(e).each(function(a){this.style.zIndex=f+a}),this[0].style.zIndex=f+e.length}}}),a.ui.plugin.add("draggable","zIndex",{start:function(b,c){var d=a(c.helper),e=a(this).data("draggable").options;d.css("zIndex")&&(e._zIndex=d.css("zIndex")),d.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;d._zIndex&&a(c.helper).css("zIndex",d._zIndex)}})})(jQuery);/* + * jQuery UI Droppable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Droppables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js + */(function(a,b){a.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var b=this.options,c=b.accept;this.isover=0,this.isout=1,this.accept=a.isFunction(c)?c:function(a){return a.is(c)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},a.ui.ddmanager.droppables[b.scope]=a.ui.ddmanager.droppables[b.scope]||[],a.ui.ddmanager.droppables[b.scope].push(this),b.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++)b[c]==this&&b.splice(c,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(b,c){b=="accept"&&(this.accept=a.isFunction(c)?c:function(a){return a.is(c)}),a.Widget.prototype._setOption.apply(this,arguments)},_activate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),c&&this._trigger("activate",b,this.ui(c))},_deactivate:function(b){var c=a.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),c&&this._trigger("deactivate",b,this.ui(c))},_over:function(b){var c=a.ui.ddmanager.current;!!c&&(c.currentItem||c.element)[0]!=this.element[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",b,this.ui(c)))},_out:function(b){var c=a.ui.ddmanager.current;!!c&&(c.currentItem||c.element)[0]!=this.element[0]&&this.accept.call(this.element[0],c.currentItem||c.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",b,this.ui(c)))},_drop:function(b,c){var d=c||a.ui.ddmanager.current;if(!d||(d.currentItem||d.element)[0]==this.element[0])return!1;var e=!1;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var b=a.data(this,"droppable");if(b.options.greedy&&!b.options.disabled&&b.options.scope==d.options.scope&&b.accept.call(b.element[0],d.currentItem||d.element)&&a.ui.intersect(d,a.extend(b,{offset:b.element.offset()}),b.options.tolerance)){e=!0;return!1}});if(e)return!1;if(this.accept.call(this.element[0],d.currentItem||d.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",b,this.ui(d));return this.element}return!1},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}}),a.extend(a.ui.droppable,{version:"1.8.18"}),a.ui.intersect=function(b,c,d){if(!c.offset)return!1;var e=(b.positionAbs||b.position.absolute).left,f=e+b.helperProportions.width,g=(b.positionAbs||b.position.absolute).top,h=g+b.helperProportions.height,i=c.offset.left,j=i+c.proportions.width,k=c.offset.top,l=k+c.proportions.height;switch(d){case"fit":return i<=e&&f<=j&&k<=g&&h<=l;case"intersect":return i<e+b.helperProportions.width/2&&f-b.helperProportions.width/2<j&&k<g+b.helperProportions.height/2&&h-b.helperProportions.height/2<l;case"pointer":var m=(b.positionAbs||b.position.absolute).left+(b.clickOffset||b.offset.click).left,n=(b.positionAbs||b.position.absolute).top+(b.clickOffset||b.offset.click).top,o=a.ui.isOver(n,m,k,i,c.proportions.height,c.proportions.width);return o;case"touch":return(g>=k&&g<=l||h>=k&&h<=l||g<k&&h>l)&&(e>=i&&e<=j||f>=i&&f<=j||e<i&&f>j);default:return!1}},a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(b,c){var d=a.ui.ddmanager.droppables[b.options.scope]||[],e=c?c.type:null,f=(b.currentItem||b.element).find(":data(droppable)").andSelf();droppablesLoop:for(var g=0;g<d.length;g++){if(d[g].options.disabled||b&&!d[g].accept.call(d[g].element[0],b.currentItem||b.element))continue;for(var h=0;h<f.length;h++)if(f[h]==d[g].element[0]){d[g].proportions.height=0;continue droppablesLoop}d[g].visible=d[g].element.css("display")!="none";if(!d[g].visible)continue;e=="mousedown"&&d[g]._activate.call(d[g],c),d[g].offset=d[g].element.offset(),d[g].proportions={width:d[g].element[0].offsetWidth,height:d[g].element[0].offsetHeight}}},drop:function(b,c){var d=!1;a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){!this.options||(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)&&(d=this._drop.call(this,c)||d),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],b.currentItem||b.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,c)))});return d},dragStart:function(b,c){b.element.parents(":not(body,html)").bind("scroll.droppable",function(){b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)})},drag:function(b,c){b.options.refreshPositions&&a.ui.ddmanager.prepareOffsets(b,c),a.each(a.ui.ddmanager.droppables[b.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var d=a.ui.intersect(b,this,this.options.tolerance),e=!d&&this.isover==1?"isout":d&&this.isover==0?"isover":null;if(!e)return;var f;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");g.length&&(f=a.data(g[0],"droppable"),f.greedyChild=e=="isover"?1:0)}f&&e=="isover"&&(f.isover=0,f.isout=1,f._out.call(f,c)),this[e]=1,this[e=="isout"?"isover":"isout"]=0,this[e=="isover"?"_over":"_out"].call(this,c),f&&e=="isout"&&(f.isout=0,f.isover=1,f._over.call(f,c))}})},dragStop:function(b,c){b.element.parents(":not(body,html)").unbind("scroll.droppable"),b.options.refreshPositions||a.ui.ddmanager.prepareOffsets(b,c)}}})(jQuery);/* + * jQuery UI Resizable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.resizable",a.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var b=this,c=this.options;this.element.addClass("ui-resizable"),a.extend(this,{_aspectRatio:!!c.aspectRatio,aspectRatio:c.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:c.helper||c.ghost||c.animate?c.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(a('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=c.handles||(a(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var d=this.handles.split(",");this.handles={};for(var e=0;e<d.length;e++){var f=a.trim(d[e]),g="ui-resizable-"+f,h=a('<div class="ui-resizable-handle '+g+'"></div>');/sw|se|ne|nw/.test(f)&&h.css({zIndex:++c.zIndex}),"se"==f&&h.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[f]=".ui-resizable-"+f,this.element.append(h)}}this._renderAxis=function(b){b=b||this.element;for(var c in this.handles){this.handles[c].constructor==String&&(this.handles[c]=a(this.handles[c],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var d=a(this.handles[c],this.element),e=0;e=/sw|ne|nw|se|n|s/.test(c)?d.outerHeight():d.outerWidth();var f=["padding",/ne|nw|n/.test(c)?"Top":/se|sw|s/.test(c)?"Bottom":/^e$/.test(c)?"Right":"Left"].join("");b.css(f,e),this._proportionallyResize()}if(!a(this.handles[c]).length)continue}},this._renderAxis(this.element),this._handles=a(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!b.resizing){if(this.className)var a=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=a&&a[1]?a[1]:"se"}}),c.autoHide&&(this._handles.hide(),a(this.element).addClass("ui-resizable-autohide").hover(function(){c.disabled||(a(this).removeClass("ui-resizable-autohide"),b._handles.show())},function(){c.disabled||b.resizing||(a(this).addClass("ui-resizable-autohide"),b._handles.hide())})),this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(b){a(b).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var c=this.element;c.after(this.originalElement.css({position:c.css("position"),width:c.outerWidth(),height:c.outerHeight(),top:c.css("top"),left:c.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle),b(this.originalElement);return this},_mouseCapture:function(b){var c=!1;for(var d in this.handles)a(this.handles[d])[0]==b.target&&(c=!0);return!this.options.disabled&&c},_mouseStart:function(b){var d=this.options,e=this.element.position(),f=this.element;this.resizing=!0,this.documentScroll={top:a(document).scrollTop(),left:a(document).scrollLeft()},(f.is(".ui-draggable")||/absolute/.test(f.css("position")))&&f.css({position:"absolute",top:e.top,left:e.left}),this._renderProxy();var g=c(this.helper.css("left")),h=c(this.helper.css("top"));d.containment&&(g+=a(d.containment).scrollLeft()||0,h+=a(d.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:g,top:h},this.size=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalSize=this._helper?{width:f.outerWidth(),height:f.outerHeight()}:{width:f.width(),height:f.height()},this.originalPosition={left:g,top:h},this.sizeDiff={width:f.outerWidth()-f.width(),height:f.outerHeight()-f.height()},this.originalMousePosition={left:b.pageX,top:b.pageY},this.aspectRatio=typeof d.aspectRatio=="number"?d.aspectRatio:this.originalSize.width/this.originalSize.height||1;var i=a(".ui-resizable-"+this.axis).css("cursor");a("body").css("cursor",i=="auto"?this.axis+"-resize":i),f.addClass("ui-resizable-resizing"),this._propagate("start",b);return!0},_mouseDrag:function(b){var c=this.helper,d=this.options,e={},f=this,g=this.originalMousePosition,h=this.axis,i=b.pageX-g.left||0,j=b.pageY-g.top||0,k=this._change[h];if(!k)return!1;var l=k.apply(this,[b,i,j]),m=a.browser.msie&&a.browser.version<7,n=this.sizeDiff;this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)l=this._updateRatio(l,b);l=this._respectSize(l,b),this._propagate("resize",b),c.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",b,this.ui());return!1},_mouseStop:function(b){this.resizing=!1;var c=this.options,d=this;if(this._helper){var e=this._proportionallyResizeElements,f=e.length&&/textarea/i.test(e[0].nodeName),g=f&&a.ui.hasScroll(e[0],"left")?0:d.sizeDiff.height,h=f?0:d.sizeDiff.width,i={width:d.helper.width()-h,height:d.helper.height()-g},j=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,k=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;c.animate||this.element.css(a.extend(i,{top:k,left:j})),d.helper.height(d.size.height),d.helper.width(d.size.width),this._helper&&!c.animate&&this._proportionallyResize()}a("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",b),this._helper&&this.helper.remove();return!1},_updateVirtualBoundaries:function(a){var b=this.options,c,e,f,g,h;h={minWidth:d(b.minWidth)?b.minWidth:0,maxWidth:d(b.maxWidth)?b.maxWidth:Infinity,minHeight:d(b.minHeight)?b.minHeight:0,maxHeight:d(b.maxHeight)?b.maxHeight:Infinity};if(this._aspectRatio||a)c=h.minHeight*this.aspectRatio,f=h.minWidth/this.aspectRatio,e=h.maxHeight*this.aspectRatio,g=h.maxWidth/this.aspectRatio,c>h.minWidth&&(h.minWidth=c),f>h.minHeight&&(h.minHeight=f),e<h.maxWidth&&(h.maxWidth=e),g<h.maxHeight&&(h.maxHeight=g);this._vBoundaries=h},_updateCache:function(a){var b=this.options;this.offset=this.helper.offset(),d(a.left)&&(this.position.left=a.left),d(a.top)&&(this.position.top=a.top),d(a.height)&&(this.size.height=a.height),d(a.width)&&(this.size.width=a.width)},_updateRatio:function(a,b){var c=this.options,e=this.position,f=this.size,g=this.axis;d(a.height)?a.width=a.height*this.aspectRatio:d(a.width)&&(a.height=a.width/this.aspectRatio),g=="sw"&&(a.left=e.left+(f.width-a.width),a.top=null),g=="nw"&&(a.top=e.top+(f.height-a.height),a.left=e.left+(f.width-a.width));return a},_respectSize:function(a,b){var c=this.helper,e=this._vBoundaries,f=this._aspectRatio||b.shiftKey,g=this.axis,h=d(a.width)&&e.maxWidth&&e.maxWidth<a.width,i=d(a.height)&&e.maxHeight&&e.maxHeight<a.height,j=d(a.width)&&e.minWidth&&e.minWidth>a.width,k=d(a.height)&&e.minHeight&&e.minHeight>a.height;j&&(a.width=e.minWidth),k&&(a.height=e.minHeight),h&&(a.width=e.maxWidth),i&&(a.height=e.maxHeight);var l=this.originalPosition.left+this.originalSize.width,m=this.position.top+this.size.height,n=/sw|nw|w/.test(g),o=/nw|ne|n/.test(g);j&&n&&(a.left=l-e.minWidth),h&&n&&(a.left=l-e.maxWidth),k&&o&&(a.top=m-e.minHeight),i&&o&&(a.top=m-e.maxHeight);var p=!a.width&&!a.height;p&&!a.left&&a.top?a.top=null:p&&!a.top&&a.left&&(a.left=null);return a},_proportionallyResize:function(){var b=this.options;if(!!this._proportionallyResizeElements.length){var c=this.helper||this.element;for(var d=0;d<this._proportionallyResizeElements.length;d++){var e=this._proportionallyResizeElements[d];if(!this.borderDif){var f=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],g=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];this.borderDif=a.map(f,function(a,b){var c=parseInt(a,10)||0,d=parseInt(g[b],10)||0;return c+d})}if(a.browser.msie&&(!!a(c).is(":hidden")||!!a(c).parents(":hidden").length))continue;e.css({height:c.height()-this.borderDif[0]-this.borderDif[2]||0,width:c.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var b=this.element,c=this.options;this.elementOffset=b.offset();if(this._helper){this.helper=this.helper||a('<div style="overflow:hidden;"></div>');var d=a.browser.msie&&a.browser.version<7,e=d?1:0,f=d?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+f,height:this.element.outerHeight()+f,position:"absolute",left:this.elementOffset.left-e+"px",top:this.elementOffset.top-e+"px",zIndex:++c.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(a,b,c){return{width:this.originalSize.width+b}},w:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{left:f.left+b,width:e.width-b}},n:function(a,b,c){var d=this.options,e=this.originalSize,f=this.originalPosition;return{top:f.top+c,height:e.height-c}},s:function(a,b,c){return{height:this.originalSize.height+c}},se:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},sw:function(b,c,d){return a.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,c,d]))},ne:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,c,d]))},nw:function(b,c,d){return a.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,c,d]))}},_propagate:function(b,c){a.ui.plugin.call(this,b,[c,this.ui()]),b!="resize"&&this._trigger(b,c,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),a.extend(a.ui.resizable,{version:"1.8.18"}),a.ui.plugin.add("resizable","alsoResize",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=function(b){a(b).each(function(){var b=a(this);b.data("resizable-alsoresize",{width:parseInt(b.width(),10),height:parseInt(b.height(),10),left:parseInt(b.css("left"),10),top:parseInt(b.css("top"),10)})})};typeof e.alsoResize=="object"&&!e.alsoResize.parentNode?e.alsoResize.length?(e.alsoResize=e.alsoResize[0],f(e.alsoResize)):a.each(e.alsoResize,function(a){f(a)}):f(e.alsoResize)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.originalSize,g=d.originalPosition,h={height:d.size.height-f.height||0,width:d.size.width-f.width||0,top:d.position.top-g.top||0,left:d.position.left-g.left||0},i=function(b,d){a(b).each(function(){var b=a(this),e=a(this).data("resizable-alsoresize"),f={},g=d&&d.length?d:b.parents(c.originalElement[0]).length?["width","height"]:["width","height","top","left"];a.each(g,function(a,b){var c=(e[b]||0)+(h[b]||0);c&&c>=0&&(f[b]=c||null)}),b.css(f)})};typeof e.alsoResize=="object"&&!e.alsoResize.nodeType?a.each(e.alsoResize,function(a,b){i(a,b)}):i(e.alsoResize)},stop:function(b,c){a(this).removeData("resizable-alsoresize")}}),a.ui.plugin.add("resizable","animate",{stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d._proportionallyResizeElements,g=f.length&&/textarea/i.test(f[0].nodeName),h=g&&a.ui.hasScroll(f[0],"left")?0:d.sizeDiff.height,i=g?0:d.sizeDiff.width,j={width:d.size.width-i,height:d.size.height-h},k=parseInt(d.element.css("left"),10)+(d.position.left-d.originalPosition.left)||null,l=parseInt(d.element.css("top"),10)+(d.position.top-d.originalPosition.top)||null;d.element.animate(a.extend(j,l&&k?{top:l,left:k}:{}),{duration:e.animateDuration,easing:e.animateEasing,step:function(){var c={width:parseInt(d.element.css("width"),10),height:parseInt(d.element.css("height"),10),top:parseInt(d.element.css("top"),10),left:parseInt(d.element.css("left"),10)};f&&f.length&&a(f[0]).css({width:c.width,height:c.height}),d._updateCache(c),d._propagate("resize",b)}})}}),a.ui.plugin.add("resizable","containment",{start:function(b,d){var e=a(this).data("resizable"),f=e.options,g=e.element,h=f.containment,i=h instanceof a?h.get(0):/parent/.test(h)?g.parent().get(0):h;if(!!i){e.containerElement=a(i);if(/document/.test(h)||h==document)e.containerOffset={left:0,top:0},e.containerPosition={left:0,top:0},e.parentData={element:a(document),left:0,top:0,width:a(document).width(),height:a(document).height()||document.body.parentNode.scrollHeight};else{var j=a(i),k=[];a(["Top","Right","Left","Bottom"]).each(function(a,b){k[a]=c(j.css("padding"+b))}),e.containerOffset=j.offset(),e.containerPosition=j.position(),e.containerSize={height:j.innerHeight()-k[3],width:j.innerWidth()-k[1]};var l=e.containerOffset,m=e.containerSize.height,n=e.containerSize.width,o=a.ui.hasScroll(i,"left")?i.scrollWidth:n,p=a.ui.hasScroll(i)?i.scrollHeight:m;e.parentData={element:i,left:l.left,top:l.top,width:o,height:p}}}},resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.containerSize,g=d.containerOffset,h=d.size,i=d.position,j=d._aspectRatio||b.shiftKey,k={top:0,left:0},l=d.containerElement;l[0]!=document&&/static/.test(l.css("position"))&&(k=g),i.left<(d._helper?g.left:0)&&(d.size.width=d.size.width+(d._helper?d.position.left-g.left:d.position.left-k.left),j&&(d.size.height=d.size.width/e.aspectRatio),d.position.left=e.helper?g.left:0),i.top<(d._helper?g.top:0)&&(d.size.height=d.size.height+(d._helper?d.position.top-g.top:d.position.top),j&&(d.size.width=d.size.height*e.aspectRatio),d.position.top=d._helper?g.top:0),d.offset.left=d.parentData.left+d.position.left,d.offset.top=d.parentData.top+d.position.top;var m=Math.abs((d._helper?d.offset.left-k.left:d.offset.left-k.left)+d.sizeDiff.width),n=Math.abs((d._helper?d.offset.top-k.top:d.offset.top-g.top)+d.sizeDiff.height),o=d.containerElement.get(0)==d.element.parent().get(0),p=/relative|absolute/.test(d.containerElement.css("position"));o&&p&&(m-=d.parentData.left),m+d.size.width>=d.parentData.width&&(d.size.width=d.parentData.width-m,j&&(d.size.height=d.size.width/d.aspectRatio)),n+d.size.height>=d.parentData.height&&(d.size.height=d.parentData.height-n,j&&(d.size.width=d.size.height*d.aspectRatio))},stop:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.position,g=d.containerOffset,h=d.containerPosition,i=d.containerElement,j=a(d.helper),k=j.offset(),l=j.outerWidth()-d.sizeDiff.width,m=j.outerHeight()-d.sizeDiff.height;d._helper&&!e.animate&&/relative/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m}),d._helper&&!e.animate&&/static/.test(i.css("position"))&&a(this).css({left:k.left-h.left-g.left,width:l,height:m})}}),a.ui.plugin.add("resizable","ghost",{start:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size;d.ghost=d.originalElement.clone(),d.ghost.css({opacity:.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof e.ghost=="string"?e.ghost:""),d.ghost.appendTo(d.helper)},resize:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})},stop:function(b,c){var d=a(this).data("resizable"),e=d.options;d.ghost&&d.helper&&d.helper.get(0).removeChild(d.ghost.get(0))}}),a.ui.plugin.add("resizable","grid",{resize:function(b,c){var d=a(this).data("resizable"),e=d.options,f=d.size,g=d.originalSize,h=d.originalPosition,i=d.axis,j=e._aspectRatio||b.shiftKey;e.grid=typeof e.grid=="number"?[e.grid,e.grid]:e.grid;var k=Math.round((f.width-g.width)/(e.grid[0]||1))*(e.grid[0]||1),l=Math.round((f.height-g.height)/(e.grid[1]||1))*(e.grid[1]||1);/^(se|s|e)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l):/^(ne)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l):/^(sw)$/.test(i)?(d.size.width=g.width+k,d.size.height=g.height+l,d.position.left=h.left-k):(d.size.width=g.width+k,d.size.height=g.height+l,d.position.top=h.top-l,d.position.left=h.left-k)}});var c=function(a){return parseInt(a,10)||0},d=function(a){return!isNaN(parseInt(a,10))}})(jQuery);/* + * jQuery UI Selectable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.selectable",a.ui.mouse,{options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var b=this;this.element.addClass("ui-selectable"),this.dragged=!1;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]),c.addClass("ui-selectee"),c.each(function(){var b=a(this),c=b.offset();a.data(this,"selectable-item",{element:this,$element:b,left:c.left,top:c.top,right:c.left+b.outerWidth(),bottom:c.top+b.outerHeight(),startselected:!1,selected:b.hasClass("ui-selected"),selecting:b.hasClass("ui-selecting"),unselecting:b.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=c.addClass("ui-selectee"),this._mouseInit(),this.helper=a("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable"),this._mouseDestroy();return this},_mouseStart:function(b){var c=this;this.opos=[b.pageX,b.pageY];if(!this.options.disabled){var d=this.options;this.selectees=a(d.filter,this.element[0]),this._trigger("start",b),a(d.appendTo).append(this.helper),this.helper.css({left:b.clientX,top:b.clientY,width:0,height:0}),d.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var d=a.data(this,"selectable-item");d.startselected=!0,!b.metaKey&&!b.ctrlKey&&(d.$element.removeClass("ui-selected"),d.selected=!1,d.$element.addClass("ui-unselecting"),d.unselecting=!0,c._trigger("unselecting",b,{unselecting:d.element}))}),a(b.target).parents().andSelf().each(function(){var d=a.data(this,"selectable-item");if(d){var e=!b.metaKey&&!b.ctrlKey||!d.$element.hasClass("ui-selected");d.$element.removeClass(e?"ui-unselecting":"ui-selected").addClass(e?"ui-selecting":"ui-unselecting"),d.unselecting=!e,d.selecting=e,d.selected=e,e?c._trigger("selecting",b,{selecting:d.element}):c._trigger("unselecting",b,{unselecting:d.element});return!1}})}},_mouseDrag:function(b){var c=this;this.dragged=!0;if(!this.options.disabled){var d=this.options,e=this.opos[0],f=this.opos[1],g=b.pageX,h=b.pageY;if(e>g){var i=g;g=e,e=i}if(f>h){var i=h;h=f,f=i}this.helper.css({left:e,top:f,width:g-e,height:h-f}),this.selectees.each(function(){var i=a.data(this,"selectable-item");if(!!i&&i.element!=c.element[0]){var j=!1;d.tolerance=="touch"?j=!(i.left>g||i.right<e||i.top>h||i.bottom<f):d.tolerance=="fit"&&(j=i.left>e&&i.right<g&&i.top>f&&i.bottom<h),j?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,c._trigger("selecting",b,{selecting:i.element}))):(i.selecting&&((b.metaKey||b.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),c._trigger("unselecting",b,{unselecting:i.element}))),i.selected&&!b.metaKey&&!b.ctrlKey&&!i.startselected&&(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,c._trigger("unselecting",b,{unselecting:i.element})))}});return!1}},_mouseStop:function(b){var c=this;this.dragged=!1;var d=this.options;a(".ui-unselecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-unselecting"),d.unselecting=!1,d.startselected=!1,c._trigger("unselected",b,{unselected:d.element})}),a(".ui-selecting",this.element[0]).each(function(){var d=a.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected"),d.selecting=!1,d.selected=!0,d.startselected=!0,c._trigger("selected",b,{selected:d.element})}),this._trigger("stop",b),this.helper.remove();return!1}}),a.extend(a.ui.selectable,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Sortable 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.sortable",a.ui.mouse,{widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var a=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},destroy:function(){a.Widget.prototype.destroy.call(this),this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--)this.items[b].item.removeData(this.widgetName+"-item");return this},_setOption:function(b,c){b==="disabled"?(this.options[b]=c,this.widget()[c?"addClass":"removeClass"]("ui-sortable-disabled")):a.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(b,c){var d=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(b);var e=null,f=this,g=a(b.target).parents().each(function(){if(a.data(this,d.widgetName+"-item")==f){e=a(this);return!1}});a.data(b.target,d.widgetName+"-item")==f&&(e=a(b.target));if(!e)return!1;if(this.options.handle&&!c){var h=!1;a(this.options.handle,e).find("*").andSelf().each(function(){this==b.target&&(h=!0)});if(!h)return!1}this.currentItem=e,this._removeCurrentsFromItems();return!0},_mouseStart:function(b,c,d){var e=this.options,f=this;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(b),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this._generatePosition(b),this.originalPageX=b.pageX,this.originalPageY=b.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),e.containment&&this._setContainment(),e.cursor&&(a("body").css("cursor")&&(this._storedCursor=a("body").css("cursor")),a("body").css("cursor",e.cursor)),e.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",e.opacity)),e.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",e.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",b,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!d)for(var g=this.containers.length-1;g>=0;g--)this.containers[g]._trigger("activate",b,f._uiHash(this));a.ui.ddmanager&&(a.ui.ddmanager.current=this),a.ui.ddmanager&&!e.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(b);return!0},_mouseDrag:function(b){this.position=this._generatePosition(b),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var c=this.options,d=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-b.pageY<c.scrollSensitivity?this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop+c.scrollSpeed:b.pageY-this.overflowOffset.top<c.scrollSensitivity&&(this.scrollParent[0].scrollTop=d=this.scrollParent[0].scrollTop-c.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-b.pageX<c.scrollSensitivity?this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft+c.scrollSpeed:b.pageX-this.overflowOffset.left<c.scrollSensitivity&&(this.scrollParent[0].scrollLeft=d=this.scrollParent[0].scrollLeft-c.scrollSpeed)):(b.pageY-a(document).scrollTop()<c.scrollSensitivity?d=a(document).scrollTop(a(document).scrollTop()-c.scrollSpeed):a(window).height()-(b.pageY-a(document).scrollTop())<c.scrollSensitivity&&(d=a(document).scrollTop(a(document).scrollTop()+c.scrollSpeed)),b.pageX-a(document).scrollLeft()<c.scrollSensitivity?d=a(document).scrollLeft(a(document).scrollLeft()-c.scrollSpeed):a(window).width()-(b.pageX-a(document).scrollLeft())<c.scrollSensitivity&&(d=a(document).scrollLeft(a(document).scrollLeft()+c.scrollSpeed))),d!==!1&&a.ui.ddmanager&&!c.dropBehaviour&&a.ui.ddmanager.prepareOffsets(this,b)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var e=this.items.length-1;e>=0;e--){var f=this.items[e],g=f.item[0],h=this._intersectsWithPointer(f);if(!h)continue;if(g!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=g&&!a.ui.contains(this.placeholder[0],g)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],g):!0)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(f))this._rearrange(b,f);else break;this._trigger("change",b,this._uiHash());break}}this._contactContainers(b),a.ui.ddmanager&&a.ui.ddmanager.drag(this,b),this._trigger("sort",b,this._uiHash()),this.lastPositionAbs=this.positionAbs;return!1},_mouseStop:function(b,c){if(!!b){a.ui.ddmanager&&!this.options.dropBehaviour&&a.ui.ddmanager.drop(this,b);if(this.options.revert){var d=this,e=d.placeholder.offset();d.reverting=!0,a(this.helper).animate({left:e.left-this.offset.parent.left-d.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-d.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){d._clear(b)})}else this._clear(b,c);return!1}},cancel:function(){var b=this;if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("deactivate",null,b._uiHash(this)),this.containers[c].containerCache.over&&(this.containers[c]._trigger("out",null,b._uiHash(this)),this.containers[c].containerCache.over=0)}this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),a.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?a(this.domPosition.prev).after(this.currentItem):a(this.domPosition.parent).prepend(this.currentItem));return this},serialize:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];b=b||{},a(c).each(function(){var c=(a(b.item||this).attr(b.attribute||"id")||"").match(b.expression||/(.+)[-=_](.+)/);c&&d.push((b.key||c[1]+"[]")+"="+(b.key&&b.expression?c[1]:c[2]))}),!d.length&&b.key&&d.push(b.key+"=");return d.join("&")},toArray:function(b){var c=this._getItemsAsjQuery(b&&b.connected),d=[];b=b||{},c.each(function(){d.push(a(b.item||this).attr(b.attribute||"id")||"")});return d},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,d=this.positionAbs.top,e=d+this.helperProportions.height,f=a.left,g=f+a.width,h=a.top,i=h+a.height,j=this.offset.click.top,k=this.offset.click.left,l=d+j>h&&d+j<i&&b+k>f&&b+k<g;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?l:f<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<g&&h<d+this.helperProportions.height/2&&e-this.helperProportions.height/2<i},_intersectsWithPointer:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left,b.width),e=c&&d,f=this._getDragVerticalDirection(),g=this._getDragHorizontalDirection();if(!e)return!1;return this.floating?g&&g=="right"||f=="down"?2:1:f&&(f=="down"?2:1)},_intersectsWithSides:function(b){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,b.top+b.height/2,b.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,b.left+b.width/2,b.width),e=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();return this.floating&&f?f=="right"&&d||f=="left"&&!d:e&&(e=="down"&&c||e=="up"&&!c)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a),this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(b){var c=this,d=[],e=[],f=this._connectWith();if(f&&b)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&e.push([a.isFunction(j.options.items)?j.options.items.call(j.element):a(j.options.items,j.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),j])}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var g=e.length-1;g>=0;g--)e[g][0].each(function(){d.push(this)});return a(d)},_removeCurrentsFromItems:function(){var a=this.currentItem.find(":data("+this.widgetName+"-item)");for(var b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(b){this.items=[],this.containers=[this];var c=this.items,d=this,e=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]],f=this._connectWith();if(f&&this.ready)for(var g=f.length-1;g>=0;g--){var h=a(f[g]);for(var i=h.length-1;i>=0;i--){var j=a.data(h[i],this.widgetName);j&&j!=this&&!j.options.disabled&&(e.push([a.isFunction(j.options.items)?j.options.items.call(j.element[0],b,{item:this.currentItem}):a(j.options.items,j.element),j]),this.containers.push(j))}}for(var g=e.length-1;g>=0;g--){var k=e[g][1],l=e[g][0];for(var i=0,m=l.length;i<m;i++){var n=a(l[i]);n.data(this.widgetName+"-item",k),c.push({item:n,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var c=this.items.length-1;c>=0;c--){var d=this.items[c];if(d.instance!=this.currentContainer&&this.currentContainer&&d.item[0]!=this.currentItem[0])continue;var e=this.options.toleranceElement?a(this.options.toleranceElement,d.item):d.item;b||(d.width=e.outerWidth(),d.height=e.outerHeight());var f=e.offset();d.left=f.left,d.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var c=this.containers.length-1;c>=0;c--){var f=this.containers[c].element.offset();this.containers[c].containerCache.left=f.left,this.containers[c].containerCache.top=f.top,this.containers[c].containerCache.width=this.containers[c].element.outerWidth(),this.containers[c].containerCache.height=this.containers[c].element.outerHeight()}return this},_createPlaceholder:function(b){var c=b||this,d=c.options;if(!d.placeholder||d.placeholder.constructor==String){var e=d.placeholder;d.placeholder={element:function(){var b=a(document.createElement(c.currentItem[0].nodeName)).addClass(e||c.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];e||(b.style.visibility="hidden");return b},update:function(a,b){if(!e||!!d.forcePlaceholderSize)b.height()||b.height(c.currentItem.innerHeight()-parseInt(c.currentItem.css("paddingTop")||0,10)-parseInt(c.currentItem.css("paddingBottom")||0,10)),b.width()||b.width(c.currentItem.innerWidth()-parseInt(c.currentItem.css("paddingLeft")||0,10)-parseInt(c.currentItem.css("paddingRight")||0,10))}}}c.placeholder=a(d.placeholder.element.call(c.element,c.currentItem)),c.currentItem.after(c.placeholder),d.placeholder.update(c,c.placeholder)},_contactContainers:function(b){var c=null,d=null;for(var e=this.containers.length-1;e>=0;e--){if(a.ui.contains(this.currentItem[0],this.containers[e].element[0]))continue;if(this._intersectsWith(this.containers[e].containerCache)){if(c&&a.ui.contains(this.containers[e].element[0],c.element[0]))continue;c=this.containers[e],d=e}else this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",b,this._uiHash(this)),this.containers[e].containerCache.over=0)}if(!!c)if(this.containers.length===1)this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1;else if(this.currentContainer!=this.containers[d]){var f=1e4,g=null,h=this.positionAbs[this.containers[d].floating?"left":"top"];for(var i=this.items.length-1;i>=0;i--){if(!a.ui.contains(this.containers[d].element[0],this.items[i].item[0]))continue;var j=this.items[i][this.containers[d].floating?"left":"top"];Math.abs(j-h)<f&&(f=Math.abs(j-h),g=this.items[i])}if(!g&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[d],g?this._rearrange(b,g,null,!0):this._rearrange(b,null,this.containers[d].element,!0),this._trigger("change",b,this._uiHash()),this.containers[d]._trigger("change",b,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[d]._trigger("over",b,this._uiHash(this)),this.containers[d].containerCache.over=1}},_createHelper:function(b){var c=this.options,d=a.isFunction(c.helper)?a(c.helper.apply(this.element[0],[b,this.currentItem])):c.helper=="clone"?this.currentItem.clone():this.currentItem;d.parents("body").length||a(c.appendTo!="parent"?c.appendTo:this.currentItem[0].parentNode)[0].appendChild(d[0]),d[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(d[0].style.width==""||c.forceHelperSize)&&d.width(this.currentItem.width()),(d[0].style.height==""||c.forceHelperSize)&&d.height(this.currentItem.height());return d},_adjustOffsetFromHelper:function(b){typeof b=="string"&&(b=b.split(" ")),a.isArray(b)&&(b={left:+b[0],top:+b[1]||0}),"left"in b&&(this.offset.click.left=b.left+this.margins.left),"right"in b&&(this.offset.click.left=this.helperProportions.width-b.right+this.margins.left),"top"in b&&(this.offset.click.top=b.top+this.margins.top),"bottom"in b&&(this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])&&(b.left+=this.scrollParent.scrollLeft(),b.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)b={top:0,left:0};return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var b=this.options;b.containment=="parent"&&(b.containment=this.helper[0].parentNode);if(b.containment=="document"||b.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(b.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(b.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(b.containment)){var c=a(b.containment)[0],d=a(b.containment).offset(),e=a(c).css("overflow")!="hidden";this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(e?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(e?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(b,c){c||(c=this.position);var d=b=="absolute"?1:-1,e=this.options,f=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=/(html|body)/i.test(f[0].tagName);return{top:c.top+this.offset.relative.top*d+this.offset.parent.top*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():g?0:f.scrollTop())*d),left:c.left+this.offset.relative.left*d+this.offset.parent.left*d-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:f.scrollLeft())*d)}},_generatePosition:function(b){var c=this.options,d=this.cssPosition=="absolute"&&(this.scrollParent[0]==document||!a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(d[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var f=b.pageX,g=b.pageY;if(this.originalPosition){this.containment&&(b.pageX-this.offset.click.left<this.containment[0]&&(f=this.containment[0]+this.offset.click.left),b.pageY-this.offset.click.top<this.containment[1]&&(g=this.containment[1]+this.offset.click.top),b.pageX-this.offset.click.left>this.containment[2]&&(f=this.containment[2]+this.offset.click.left),b.pageY-this.offset.click.top>this.containment[3]&&(g=this.containment[3]+this.offset.click.top));if(c.grid){var h=this.originalPageY+Math.round((g-this.originalPageY)/c.grid[1])*c.grid[1];g=this.containment?h-this.offset.click.top<this.containment[1]||h-this.offset.click.top>this.containment[3]?h-this.offset.click.top<this.containment[1]?h+c.grid[1]:h-c.grid[1]:h:h;var i=this.originalPageX+Math.round((f-this.originalPageX)/c.grid[0])*c.grid[0];f=this.containment?i-this.offset.click.left<this.containment[0]||i-this.offset.click.left>this.containment[2]?i-this.offset.click.left<this.containment[0]?i+c.grid[0]:i-c.grid[0]:i:i}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:d.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:d.scrollLeft())}},_rearrange:function(a,b,c,d){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var e=this,f=this.counter;window.setTimeout(function(){f==e.counter&&e.refreshPositions(!d)},0)},_clear:function(b,c){this.reverting=!1;var d=[],e=this;!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var f in this._storedCSS)if(this._storedCSS[f]=="auto"||this._storedCSS[f]=="static")this._storedCSS[f]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!c&&d.push(function(a){this._trigger("receive",a,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!c&&d.push(function(a){this._trigger("update",a,this._uiHash())});if(!a.ui.contains(this.element[0],this.currentItem[0])){c||d.push(function(a){this._trigger("remove",a,this._uiHash())});for(var f=this.containers.length-1;f>=0;f--)a.ui.contains(this.containers[f].element[0],this.currentItem[0])&&!c&&(d.push(function(a){return function(b){a._trigger("receive",b,this._uiHash(this))}}.call(this,this.containers[f])),d.push(function(a){return function(b){a._trigger("update",b,this._uiHash(this))}}.call(this,this.containers[f])))}for(var f=this.containers.length-1;f>=0;f--)c||d.push(function(a){return function(b){a._trigger("deactivate",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over&&(d.push(function(a){return function(b){a._trigger("out",b,this._uiHash(this))}}.call(this,this.containers[f])),this.containers[f].containerCache.over=0);this._storedCursor&&a("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!c){this._trigger("beforeStop",b,this._uiHash());for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}return!1}c||this._trigger("beforeStop",b,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!c){for(var f=0;f<d.length;f++)d[f].call(this,b);this._trigger("stop",b,this._uiHash())}this.fromOutside=!1;return!0},_trigger:function(){a.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(b){var c=b||this;return{helper:c.helper,placeholder:c.placeholder||a([]),position:c.position,originalPosition:c.originalPosition,offset:c.positionAbs,item:c.currentItem,sender:b?b.element:null}}}),a.extend(a.ui.sortable,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Accordion 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:!0,clearStyle:!1,collapsible:!1,event:"click",fillSpace:!1,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var b=this,c=b.options;b.running=0,b.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"),b.headers=b.element.find(c.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c.disabled||a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c.disabled||a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c.disabled||a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c.disabled||a(this).removeClass("ui-state-focus")}),b.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");if(c.navigation){var d=b.element.find("a").filter(c.navigationFilter).eq(0);if(d.length){var e=d.closest(".ui-accordion-header");e.length?b.active=e:b.active=d.closest(".ui-accordion-content").prev()}}b.active=b._findActive(b.active||c.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top"),b.active.next().addClass("ui-accordion-content-active"),b._createIcons(),b.resize(),b.element.attr("role","tablist"),b.headers.attr("role","tab").bind("keydown.accordion",function(a){return b._keydown(a)}).next().attr("role","tabpanel"),b.headers.not(b.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide(),b.active.length?b.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):b.headers.eq(0).attr("tabIndex",0),a.browser.safari||b.headers.find("a").attr("tabIndex",-1),c.event&&b.headers.bind(c.event.split(" ").join(".accordion ")+".accordion",function(a){b._clickHandler.call(b,a,this),a.preventDefault()})},_createIcons:function(){var b=this.options;b.icons&&(a("<span></span>").addClass("ui-icon "+b.icons.header).prependTo(this.headers),this.active.children(".ui-icon").toggleClass(b.icons.header).toggleClass(b.icons.headerSelected),this.element.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.children(".ui-icon").remove(),this.element.removeClass("ui-accordion-icons")},destroy:function(){var b=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"),this.headers.find("a").removeAttr("tabIndex"),this._destroyIcons();var c=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");(b.autoHeight||b.fillHeight)&&c.css("height","");return a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b=="active"&&this.activate(c),b=="icons"&&(this._destroyIcons(),c&&this._createIcons()),b=="disabled"&&this.headers.add(this.headers.next())[c?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(b){if(!(this.options.disabled||b.altKey||b.ctrlKey)){var c=a.ui.keyCode,d=this.headers.length,e=this.headers.index(b.target),f=!1;switch(b.keyCode){case c.RIGHT:case c.DOWN:f=this.headers[(e+1)%d];break;case c.LEFT:case c.UP:f=this.headers[(e-1+d)%d];break;case c.SPACE:case c.ENTER:this._clickHandler({target:b.target},b.target),b.preventDefault()}if(f){a(b.target).attr("tabIndex",-1),a(f).attr("tabIndex",0),f.focus();return!1}return!0}},resize:function(){var b=this.options,c;if(b.fillSpace){if(a.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}c=this.element.parent().height(),a.browser.msie&&this.element.parent().css("overflow",d),this.headers.each(function(){c-=a(this).outerHeight(!0)}),this.headers.next().each(function(){a(this).height(Math.max(0,c-a(this).innerHeight()+a(this).height()))}).css("overflow","auto")}else b.autoHeight&&(c=0,this.headers.next().each(function(){c=Math.max(c,a(this).height("").height())}).height(c));return this},activate:function(a){this.options.active=a;var b=this._findActive(a)[0];this._clickHandler({target:b},b);return this},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===!1?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,c){var d=this.options;if(!d.disabled){if(!b.target){if(!d.collapsible)return;this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),this.active.next().addClass("ui-accordion-content-active");var e=this.active.next(),f={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:e},g=this.active=a([]);this._toggle(g,e,f);return}var h=a(b.currentTarget||c),i=h[0]===this.active[0];d.active=d.collapsible&&i?!1:this.headers.index(h);if(this.running||!d.collapsible&&i)return;var j=this.active,g=h.next(),e=this.active.next(),f={options:d,newHeader:i&&d.collapsible?a([]):h,oldHeader:this.active,newContent:i&&d.collapsible?a([]):g,oldContent:e},k=this.headers.index(this.active[0])>this.headers.index(h[0]);this.active=i?a([]):h,this._toggle(g,e,f,i,k),j.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header),i||(h.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected),h.next().addClass("ui-accordion-content-active"));return}},_toggle:function(b,c,d,e,f){var g=this,h=g.options;g.toShow=b,g.toHide=c,g.data=d;var i=function(){if(!!g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data),g.running=c.size()===0?b.size():c.size();if(h.animated){var j={};h.collapsible&&e?j={toShow:a([]),toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace}:j={toShow:b,toHide:c,complete:i,down:f,autoHeight:h.autoHeight||h.fillSpace},h.proxied||(h.proxied=h.animated),h.proxiedDuration||(h.proxiedDuration=h.duration),h.animated=a.isFunction(h.proxied)?h.proxied(j):h.proxied,h.duration=a.isFunction(h.proxiedDuration)?h.proxiedDuration(j):h.proxiedDuration;var k=a.ui.accordion.animations,l=h.duration,m=h.animated;m&&!k[m]&&!a.easing[m]&&(m="slide"),k[m]||(k[m]=function(a){this.slide(a,{easing:m,duration:l||700})}),k[m](j)}else h.collapsible&&e?b.toggle():(c.hide(),b.show()),i(!0);c.prev().attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).blur(),b.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;this.running||(this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""}),this.toHide.removeClass("ui-accordion-content-active"),this.toHide.length&&(this.toHide.parent()[0].className=this.toHide.parent()[0].className),this._trigger("change",null,this.data))}}),a.extend(a.ui.accordion,{version:"1.8.18",animations:{slide:function(b,c){b=a.extend({easing:"swing",duration:300},b,c);if(!b.toHide.size())b.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},b);else{if(!b.toShow.size()){b.toHide.animate({height:"hide",paddingTop:"hide",paddingBottom:"hide"},b);return}var d=b.toShow.css("overflow"),e=0,f={},g={},h=["height","paddingTop","paddingBottom"],i,j=b.toShow;i=j[0].style.width,j.width(j.parent().width()-parseFloat(j.css("paddingLeft"))-parseFloat(j.css("paddingRight"))-(parseFloat(j.css("borderLeftWidth"))||0)-(parseFloat(j.css("borderRightWidth"))||0)),a.each(h,function(c,d){g[d]="hide";var e=(""+a.css(b.toShow[0],d)).match(/^([\d+-.]+)(.*)$/);f[d]={value:e[1],unit:e[2]||"px"}}),b.toShow.css({height:0,overflow:"hidden"}).show(),b.toHide.filter(":hidden").each(b.complete).end().filter(":visible").animate(g,{step:function(a,c){c.prop=="height"&&(e=c.end-c.start===0?0:(c.now-c.start)/(c.end-c.start)),b.toShow[0].style[c.prop]=e*f[c.prop].value+f[c.prop].unit},duration:b.duration,easing:b.easing,complete:function(){b.autoHeight||b.toShow.css("height",""),b.toShow.css({width:i,overflow:d}),b.complete()}})}},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1e3:200})}}})})(jQuery);/* + * jQuery UI Autocomplete 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */(function(a,b){var c=0;a.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var b=this,c=this.element[0].ownerDocument,d;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!b.options.disabled&&!b.element.propAttr("readOnly")){d=!1;var e=a.ui.keyCode;switch(c.keyCode){case e.PAGE_UP:b._move("previousPage",c);break;case e.PAGE_DOWN:b._move("nextPage",c);break;case e.UP:b._move("previous",c),c.preventDefault();break;case e.DOWN:b._move("next",c),c.preventDefault();break;case e.ENTER:case e.NUMPAD_ENTER:b.menu.active&&(d=!0,c.preventDefault());case e.TAB:if(!b.menu.active)return;b.menu.select(c);break;case e.ESCAPE:b.element.val(b.term),b.close(c);break;default:clearTimeout(b.searching),b.searching=setTimeout(function(){b.term!=b.element.val()&&(b.selectedItem=null,b.search(null,c))},b.options.delay)}}}).bind("keypress.autocomplete",function(a){d&&(d=!1,a.preventDefault())}).bind("focus.autocomplete",function(){b.options.disabled||(b.selectedItem=null,b.previous=b.element.val())}).bind("blur.autocomplete",function(a){b.options.disabled||(clearTimeout(b.searching),b.closing=setTimeout(function(){b.close(a),b._change(a)},150))}),this._initSource(),this.response=function(){return b._response.apply(b,arguments)},this.menu=a("<ul></ul>").addClass("ui-autocomplete").appendTo(a(this.options.appendTo||"body",c)[0]).mousedown(function(c){var d=b.menu.element[0];a(c.target).closest(".ui-menu-item").length||setTimeout(function(){a(document).one("mousedown",function(c){c.target!==b.element[0]&&c.target!==d&&!a.ui.contains(d,c.target)&&b.close()})},1),setTimeout(function(){clearTimeout(b.closing)},13)}).menu({focus:function(a,c){var d=c.item.data("item.autocomplete");!1!==b._trigger("focus",a,{item:d})&&/^key/.test(a.originalEvent.type)&&b.element.val(d.value)},selected:function(a,d){var e=d.item.data("item.autocomplete"),f=b.previous;b.element[0]!==c.activeElement&&(b.element.focus(),b.previous=f,setTimeout(function(){b.previous=f,b.selectedItem=e},1)),!1!==b._trigger("select",a,{item:e})&&b.element.val(e.value),b.term=b.element.val(),b.close(a),b.selectedItem=e},blur:function(a,c){b.menu.element.is(":visible")&&b.element.val()!==b.term&&b.element.val(b.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"),a.fn.bgiframe&&this.menu.element.bgiframe(),b.beforeunloadHandler=function(){b.element.removeAttr("autocomplete")},a(window).bind("beforeunload",b.beforeunloadHandler)},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup"),this.menu.element.remove(),a(window).unbind("beforeunload",this.beforeunloadHandler),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments),b==="source"&&this._initSource(),b==="appendTo"&&this.menu.element.appendTo(a(c||"body",this.element[0].ownerDocument)[0]),b==="disabled"&&c&&this.xhr&&this.xhr.abort()},_initSource:function(){var b=this,d,e;a.isArray(this.options.source)?(d=this.options.source,this.source=function(b,c){c(a.ui.autocomplete.filter(d,b.term))}):typeof this.options.source=="string"?(e=this.options.source,this.source=function(d,f){b.xhr&&b.xhr.abort(),b.xhr=a.ajax({url:e,data:d,dataType:"json",context:{autocompleteRequest:++c},success:function(a,b){this.autocompleteRequest===c&&f(a)},error:function(){this.autocompleteRequest===c&&f([])}})}):this.source=this.options.source},search:function(a,b){a=a!=null?a:this.element.val(),this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search",b)!==!1)return this._search(a)},_search:function(a){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.source({term:a},this.response)},_response:function(a){!this.options.disabled&&a&&a.length?(a=this._normalize(a),this._suggest(a),this._trigger("open")):this.close(),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.deactivate(),this._trigger("close",a))},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(b){if(b.length&&b[0].label&&b[0].value)return b;return a.map(b,function(b){if(typeof b=="string")return{label:b,value:b};return a.extend({label:b.label||b.value,value:b.value||b.label},b)})},_suggest:function(b){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(c,b),this.menu.deactivate(),this.menu.refresh(),c.show(),this._resizeMenu(),c.position(a.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(new a.Event("mouseover"))},_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(b,c){var d=this;a.each(c,function(a,c){d._renderItem(b,c)})},_renderItem:function(b,c){return a("<li></li>").data("item.autocomplete",c).append(a("<a></a>").text(c.label)).appendTo(b)},_move:function(a,b){if(!this.menu.element.is(":visible"))this.search(null,b);else{if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term),this.menu.deactivate();return}this.menu[a](b)}},widget:function(){return this.menu.element}}),a.extend(a.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")},filter:function(b,c){var d=new RegExp(a.ui.autocomplete.escapeRegex(c),"i");return a.grep(b,function(a){return d.test(a.label||a.value||a)})}})})(jQuery),function(a){a.widget("ui.menu",{_create:function(){var b=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){!a(c.target).closest(".ui-menu-item a").length||(c.preventDefault(),b.select(c))}),this.refresh()},refresh:function(){var b=this,c=this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem");c.children("a").addClass("ui-corner-all").attr("tabindex",-1).mouseenter(function(c){b.activate(c,a(this).parent())}).mouseleave(function(){b.deactivate()})},activate:function(a,b){this.deactivate();if(this.hasScroll()){var c=b.offset().top-this.element.offset().top,d=this.element.scrollTop(),e=this.element.height();c<0?this.element.scrollTop(d+c):c>=e&&this.element.scrollTop(d+c-e+b.height())}this.active=b.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end(),this._trigger("focus",a,{item:b})},deactivate:function(){!this.active||(this.active.children("a").removeClass("ui-state-hover").removeAttr("id"),this._trigger("blur"),this.active=null)},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(a,b,c){if(!this.active)this.activate(c,this.element.children(b));else{var d=this.active[a+"All"](".ui-menu-item").eq(0);d.length?this.activate(c,d):this.activate(c,this.element.children(b))}},nextPage:function(b){if(this.hasScroll()){if(!this.active||this.last()){this.activate(b,this.element.children(".ui-menu-item:first"));return}var c=this.active.offset().top,d=this.element.height(),e=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c-d+a(this).height();return b<10&&b>-10});e.length||(e=this.element.children(".ui-menu-item:last")),this.activate(b,e)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.last()?":first":":last"))},previousPage:function(b){if(this.hasScroll()){if(!this.active||this.first()){this.activate(b,this.element.children(".ui-menu-item:last"));return}var c=this.active.offset().top,d=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var b=a(this).offset().top-c+d-a(this).height();return b<10&&b>-10}),result.length||(result=this.element.children(".ui-menu-item:first")),this.activate(b,result)}else this.activate(b,this.element.children(".ui-menu-item").filter(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element[a.fn.prop?"prop":"attr"]("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})}(jQuery);/* + * jQuery UI Button 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){var c,d,e,f,g="ui-button ui-widget ui-state-default ui-corner-all",h="ui-state-hover ui-state-active ",i="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",j=function(){var b=a(this).find(":ui-button");setTimeout(function(){b.button("refresh")},1)},k=function(b){var c=b.name,d=b.form,e=a([]);c&&(d?e=a(d).find("[name='"+c+"']"):e=a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form}));return e};a.widget("ui.button",{options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",j),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.propAttr("disabled"):this.element.propAttr("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var b=this,h=this.options,i=this.type==="checkbox"||this.type==="radio",l="ui-state-hover"+(i?"":" ui-state-active"),m="ui-state-focus";h.label===null&&(h.label=this.buttonElement.html()),this.buttonElement.addClass(g).attr("role","button").bind("mouseenter.button",function(){h.disabled||(a(this).addClass("ui-state-hover"),this===c&&a(this).addClass("ui-state-active"))}).bind("mouseleave.button",function(){h.disabled||a(this).removeClass(l)}).bind("click.button",function(a){h.disabled&&(a.preventDefault(),a.stopImmediatePropagation())}),this.element.bind("focus.button",function(){b.buttonElement.addClass(m)}).bind("blur.button",function(){b.buttonElement.removeClass(m)}),i&&(this.element.bind("change.button",function(){f||b.refresh()}),this.buttonElement.bind("mousedown.button",function(a){h.disabled||(f=!1,d=a.pageX,e=a.pageY)}).bind("mouseup.button",function(a){!h.disabled&&(d!==a.pageX||e!==a.pageY)&&(f=!0)})),this.type==="checkbox"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).toggleClass("ui-state-active"),b.buttonElement.attr("aria-pressed",b.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click.button",function(){if(h.disabled||f)return!1;a(this).addClass("ui-state-active"),b.buttonElement.attr("aria-pressed","true");var c=b.element[0];k(c).not(c).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown.button",function(){if(h.disabled)return!1;a(this).addClass("ui-state-active"),c=this,a(document).one("mouseup",function(){c=null})}).bind("mouseup.button",function(){if(h.disabled)return!1;a(this).removeClass("ui-state-active")}).bind("keydown.button",function(b){if(h.disabled)return!1;(b.keyCode==a.ui.keyCode.SPACE||b.keyCode==a.ui.keyCode.ENTER)&&a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(b){b.keyCode===a.ui.keyCode.SPACE&&a(this).click()})),this._setOption("disabled",h.disabled),this._resetButton()},_determineButtonType:function(){this.element.is(":checkbox")?this.type="checkbox":this.element.is(":radio")?this.type="radio":this.element.is("input")?this.type="input":this.type="button";if(this.type==="checkbox"||this.type==="radio"){var a=this.element.parents().filter(":last"),b="label[for='"+this.element.attr("id")+"']";this.buttonElement=a.find(b),this.buttonElement.length||(a=a.length?a.siblings():this.element.siblings(),this.buttonElement=a.filter(b),this.buttonElement.length||(this.buttonElement=a.find(b))),this.element.addClass("ui-helper-hidden-accessible");var c=this.element.is(":checked");c&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.attr("aria-pressed",c)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(g+" "+h+" "+i).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title"),a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);b==="disabled"?c?this.element.propAttr("disabled",!0):this.element.propAttr("disabled",!1):this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b),this.type==="radio"?k(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass(i),c=a("<span></span>",this.element[0].ownerDocument).addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary,f=[];d.primary||d.secondary?(this.options.text&&f.push("ui-button-text-icon"+(e?"s":d.primary?"-primary":"-secondary")),d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>"),d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>"),this.options.text||(f.push(e?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||b.attr("title",c))):f.push("ui-button-text-only"),b.addClass(f.join(" "))}}}),a.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c),a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var b=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(b?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(b?"ui-corner-left":"ui-corner-right").end().end()},destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"),a.Widget.prototype.destroy.call(this)}})})(jQuery);/* + * jQuery UI Dialog 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */(function(a,b){var c="ui-dialog ui-widget ui-widget-content ui-corner-all ",d={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},e={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},f=a.attrFn||{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0,click:!0};a.widget("ui.dialog",{options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",collision:"fit",using:function(b){var c=a(this).css(b).offset().top;c<0&&a(this).css("top",b.top-c)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.options.title=this.options.title||this.originalTitle;var b=this,d=b.options,e=d.title||" ",f=a.ui.dialog.getTitleId(b.element),g=(b.uiDialog=a("<div></div>")).appendTo(document.body).hide().addClass(c+d.dialogClass).css({zIndex:d.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(c){d.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}).attr({role:"dialog","aria-labelledby":f}).mousedown(function(a){b.moveToTop(!1,a)}),h=b.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g),i=(b.uiDialogTitlebar=a("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),j=a('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){j.addClass("ui-state-hover")},function(){j.removeClass("ui-state-hover")}).focus(function(){j.addClass("ui-state-focus")}).blur(function(){j.removeClass("ui-state-focus")}).click(function(a){b.close(a);return!1}).appendTo(i),k=(b.uiDialogTitlebarCloseText=a("<span></span>")).addClass("ui-icon ui-icon-closethick").text(d.closeText).appendTo(j),l=a("<span></span>").addClass("ui-dialog-title").attr("id",f).html(e).prependTo(i);a.isFunction(d.beforeclose)&&!a.isFunction(d.beforeClose)&&(d.beforeClose=d.beforeclose),i.find("*").add(i).disableSelection(),d.draggable&&a.fn.draggable&&b._makeDraggable(),d.resizable&&a.fn.resizable&&b._makeResizable(),b._createButtons(d.buttons),b._isOpen=!1,a.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy(),a.uiDialog.hide(),a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),a.uiDialog.remove(),a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(b){var c=this,d,e;if(!1!==c._trigger("beforeClose",b)){c.overlay&&c.overlay.destroy(),c.uiDialog.unbind("keypress.ui-dialog"),c._isOpen=!1,c.options.hide?c.uiDialog.hide(c.options.hide,function(){c._trigger("close",b)}):(c.uiDialog.hide(),c._trigger("close",b)),a.ui.dialog.overlay.resize(),c.options.modal&&(d=0,a(".ui-dialog").each(function(){this!==c.uiDialog[0]&&(e=a(this).css("z-index"),isNaN(e)||(d=Math.max(d,e)))}),a.ui.dialog.maxZ=d);return c}},isOpen:function(){return this._isOpen},moveToTop:function(b,c){var d=this,e=d.options,f;if(e.modal&&!b||!e.stack&&!e.modal)return d._trigger("focus",c);e.zIndex>a.ui.dialog.maxZ&&(a.ui.dialog.maxZ=e.zIndex),d.overlay&&(a.ui.dialog.maxZ+=1,d.overlay.$el.css("z-index",a.ui.dialog.overlay.maxZ=a.ui.dialog.maxZ)),f={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()},a.ui.dialog.maxZ+=1,d.uiDialog.css("z-index",a.ui.dialog.maxZ),d.element.attr(f),d._trigger("focus",c);return d},open:function(){if(!this._isOpen){var b=this,c=b.options,d=b.uiDialog;b.overlay=c.modal?new a.ui.dialog.overlay(b):null,b._size(),b._position(c.position),d.show(c.show),b.moveToTop(!0),c.modal&&d.bind("keydown.ui-dialog",function(b){if(b.keyCode===a.ui.keyCode.TAB){var c=a(":tabbable",this),d=c.filter(":first"),e=c.filter(":last");if(b.target===e[0]&&!b.shiftKey){d.focus(1);return!1}if(b.target===d[0]&&b.shiftKey){e.focus(1);return!1}}}),a(b.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus(),b._isOpen=!0,b._trigger("open");return b}},_createButtons:function(b){var c=this,d=!1,e=a("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=a("<div></div>").addClass("ui-dialog-buttonset").appendTo(e);c.uiDialog.find(".ui-dialog-buttonpane").remove(),typeof b=="object"&&b!==null&&a.each(b,function(){return!(d=!0)}),d&&(a.each(b,function(b,d){d=a.isFunction(d)?{click:d,text:b}:d;var e=a('<button type="button"></button>').click(function(){d.click.apply(c.element[0],arguments)}).appendTo(g);a.each(d,function(a,b){a!=="click"&&(a in f?e[a](b):e.attr(a,b))}),a.fn.button&&e.button()}),e.appendTo(c.uiDialog))},_makeDraggable:function(){function f(a){return{position:a.position,offset:a.offset}}var b=this,c=b.options,d=a(document),e;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(d,g){e=c.height==="auto"?"auto":a(this).height(),a(this).height(a(this).height()).addClass("ui-dialog-dragging"),b._trigger("dragStart",d,f(g))},drag:function(a,c){b._trigger("drag",a,f(c))},stop:function(g,h){c.position=[h.position.left-d.scrollLeft(),h.position.top-d.scrollTop()],a(this).removeClass("ui-dialog-dragging").height(e),b._trigger("dragStop",g,f(h)),a.ui.dialog.overlay.resize()}})},_makeResizable:function(c){function h(a){return{originalPosition:a.originalPosition,originalSize:a.originalSize,position:a.position,size:a.size}}c=c===b?this.options.resizable:c;var d=this,e=d.options,f=d.uiDialog.css("position"),g=typeof c=="string"?c:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:g,start:function(b,c){a(this).addClass("ui-dialog-resizing"),d._trigger("resizeStart",b,h(c))},resize:function(a,b){d._trigger("resize",a,h(b))},stop:function(b,c){a(this).removeClass("ui-dialog-resizing"),e.height=a(this).height(),e.width=a(this).width(),d._trigger("resizeStop",b,h(c)),a.ui.dialog.overlay.resize()}}).css("position",f).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(b){var c=[],d=[0,0],e;if(b){if(typeof b=="string"||typeof b=="object"&&"0"in b)c=b.split?b.split(" "):[b[0],b[1]],c.length===1&&(c[1]=c[0]),a.each(["left","top"],function(a,b){+c[a]===c[a]&&(d[a]=c[a],c[a]=b)}),b={my:c.join(" "),at:c.join(" "),offset:d.join(" ")};b=a.extend({},a.ui.dialog.prototype.options.position,b)}else b=a.ui.dialog.prototype.options.position;e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.css({top:0,left:0}).position(a.extend({of:window},b)),e||this.uiDialog.hide()},_setOptions:function(b){var c=this,f={},g=!1;a.each(b,function(a,b){c._setOption(a,b),a in d&&(g=!0),a in e&&(f[a]=b)}),g&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",f)},_setOption:function(b,d){var e=this,f=e.uiDialog;switch(b){case"beforeclose":b="beforeClose";break;case"buttons":e._createButtons(d);break;case"closeText":e.uiDialogTitlebarCloseText.text(""+d);break;case"dialogClass":f.removeClass(e.options.dialogClass).addClass(c+d);break;case"disabled":d?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case"draggable":var g=f.is(":data(draggable)");g&&!d&&f.draggable("destroy"),!g&&d&&e._makeDraggable();break;case"position":e._position(d);break;case"resizable":var h=f.is(":data(resizable)");h&&!d&&f.resizable("destroy"),h&&typeof d=="string"&&f.resizable("option","handles",d),!h&&d!==!1&&e._makeResizable(d);break;case"title":a(".ui-dialog-title",e.uiDialogTitlebar).html(""+(d||" "))}a.Widget.prototype._setOption.apply(e,arguments)},_size:function(){var b=this.options,c,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),b.minWidth>b.width&&(b.width=b.minWidth),c=this.uiDialog.css({height:"auto",width:b.width}).height(),d=Math.max(0,b.minHeight-c);if(b.height==="auto")if(a.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();var f=this.element.css("height","auto").height();e||this.uiDialog.hide(),this.element.height(Math.max(f,d))}else this.element.height(Math.max(b.height-c,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),a.extend(a.ui.dialog,{version:"1.8.18",uuid:0,maxZ:0,getTitleId:function(a){var b=a.attr("id");b||(this.uuid+=1,b=this.uuid);return"ui-dialog-title-"+b},overlay:function(b){this.$el=a.ui.dialog.overlay.create(b)}}),a.extend(a.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:a.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(b){this.instances.length===0&&(setTimeout(function(){a.ui.dialog.overlay.instances.length&&a(document).bind(a.ui.dialog.overlay.events,function(b){if(a(b.target).zIndex()<a.ui.dialog.overlay.maxZ)return!1})},1),a(document).bind("keydown.dialog-overlay",function(c){b.options.closeOnEscape&&!c.isDefaultPrevented()&&c.keyCode&&c.keyCode===a.ui.keyCode.ESCAPE&&(b.close(c),c.preventDefault())}),a(window).bind("resize.dialog-overlay",a.ui.dialog.overlay.resize));var c=(this.oldInstances.pop()||a("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});a.fn.bgiframe&&c.bgiframe(),this.instances.push(c);return c},destroy:function(b){var c=a.inArray(b,this.instances);c!=-1&&this.oldInstances.push(this.instances.splice(c,1)[0]),this.instances.length===0&&a([document,window]).unbind(".dialog-overlay"),b.remove();var d=0;a.each(this.instances,function(){d=Math.max(d,this.css("z-index"))}),this.maxZ=d},height:function(){var b,c;if(a.browser.msie&&a.browser.version<7){b=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),c=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return b<c?a(window).height()+"px":b+"px"}return a(document).height()+"px"},width:function(){var b,c;if(a.browser.msie){b=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),c=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return b<c?a(window).width()+"px":b+"px"}return a(document).width()+"px"},resize:function(){var b=a([]);a.each(a.ui.dialog.overlay.instances,function(){b=b.add(this)}),b.css({width:0,height:0}).css({width:a.ui.dialog.overlay.width(),height:a.ui.dialog.overlay.height()})}}),a.extend(a.ui.dialog.overlay.prototype,{destroy:function(){a.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);/* + * jQuery UI Slider 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */(function(a,b){var c=5;a.widget("ui.slider",a.ui.mouse,{widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var b=this,d=this.options,e=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",g=d.values&&d.values.length||1,h=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(d.disabled?" ui-slider-disabled ui-disabled":"")),this.range=a([]),d.range&&(d.range===!0&&(d.values||(d.values=[this._valueMin(),this._valueMin()]),d.values.length&&d.values.length!==2&&(d.values=[d.values[0],d.values[0]])),this.range=a("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(d.range==="min"||d.range==="max"?" ui-slider-range-"+d.range:"")));for(var i=e.length;i<g;i+=1)h.push(f);this.handles=e.add(a(h.join("")).appendTo(b.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(a){a.preventDefault()}).hover(function(){d.disabled||a(this).addClass("ui-state-hover")},function(){a(this).removeClass("ui-state-hover")}).focus(function(){d.disabled?a(this).blur():(a(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),a(this).addClass("ui-state-focus"))}).blur(function(){a(this).removeClass("ui-state-focus")}),this.handles.each(function(b){a(this).data("index.ui-slider-handle",b)}),this.handles.keydown(function(d){var e=a(this).data("index.ui-slider-handle"),f,g,h,i;if(!b.options.disabled){switch(d.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.PAGE_UP:case a.ui.keyCode.PAGE_DOWN:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:d.preventDefault();if(!b._keySliding){b._keySliding=!0,a(this).addClass("ui-state-active"),f=b._start(d,e);if(f===!1)return}}i=b.options.step,b.options.values&&b.options.values.length?g=h=b.values(e):g=h=b.value();switch(d.keyCode){case a.ui.keyCode.HOME:h=b._valueMin();break;case a.ui.keyCode.END:h=b._valueMax();break;case a.ui.keyCode.PAGE_UP:h=b._trimAlignValue(g+(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.PAGE_DOWN:h=b._trimAlignValue(g-(b._valueMax()-b._valueMin())/c);break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g===b._valueMax())return;h=b._trimAlignValue(g+i);break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g===b._valueMin())return;h=b._trimAlignValue(g-i)}b._slide(d,e,h)}}).keyup(function(c){var d=a(this).data("index.ui-slider-handle");b._keySliding&&(b._keySliding=!1,b._stop(c,d),b._change(c,d),a(this).removeClass("ui-state-active"))}),this._refreshValue(),this._animateOff=!1},destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider"),this._mouseDestroy();return this},_mouseCapture:function(b){var c=this.options,d,e,f,g,h,i,j,k,l;if(c.disabled)return!1;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),d={x:b.pageX,y:b.pageY},e=this._normValueFromMouse(d),f=this._valueMax()-this._valueMin()+1,h=this,this.handles.each(function(b){var c=Math.abs(e-h.values(b));f>c&&(f=c,g=a(this),i=b)}),c.range===!0&&this.values(1)===c.min&&(i+=1,g=a(this.handles[i])),j=this._start(b,i);if(j===!1)return!1;this._mouseSliding=!0,h._handleIndex=i,g.addClass("ui-state-active").focus(),k=g.offset(),l=!a(b.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:b.pageX-k.left-g.width()/2,top:b.pageY-k.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(b,i,e),this._animateOff=!0;return!0},_mouseStart:function(a){return!0},_mouseDrag:function(a){var b={x:a.pageX,y:a.pageY},c=this._normValueFromMouse(b);this._slide(a,this._handleIndex,c);return!1},_mouseStop:function(a){this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(a,this._handleIndex),this._change(a,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1;return!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b,c,d,e,f;this.orientation==="horizontal"?(b=this.elementSize.width,c=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(b=this.elementSize.height,c=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),d=c/b,d>1&&(d=1),d<0&&(d=0),this.orientation==="vertical"&&(d=1-d),e=this._valueMax()-this._valueMin(),f=this._valueMin()+d*e;return this._trimAlignValue(f)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values());return this._trigger("start",a,c)},_slide:function(a,b,c){var d,e,f;this.options.values&&this.options.values.length?(d=this.values(b?0:1),this.options.values.length===2&&this.options.range===!0&&(b===0&&c>d||b===1&&c<d)&&(c=d),c!==this.values(b)&&(e=this.values(),e[b]=c,f=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e}),d=this.values(b?0:1),f!==!1&&this.values(b,c,!0))):c!==this.value()&&(f=this._trigger("slide",a,{handle:this.handles[b],value:c}),f!==!1&&this.value(c))},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};this.options.values&&this.options.values.length&&(c.value=this.values(b),c.values=this.values()),this._trigger("change",a,c)}},value:function(a){if(arguments.length)this.options.value=this._trimAlignValue(a),this._refreshValue(),this._change(null,0);else return this._value()},values:function(b,c){var d,e,f;if(arguments.length>1)this.options.values[b]=this._trimAlignValue(c),this._refreshValue(),this._change(null,b);else{if(!arguments.length)return this._values();if(!a.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(b):this.value();d=this.options.values,e=arguments[0];for(f=0;f<d.length;f+=1)d[f]=this._trimAlignValue(e[f]),this._change(null,f);this._refreshValue()}},_setOption:function(b,c){var d,e=0;a.isArray(this.options.values)&&(e=this.options.values.length),a.Widget.prototype._setOption.apply(this,arguments);switch(b){case"disabled":c?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.propAttr("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.propAttr("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(d=0;d<e;d+=1)this._change(null,d);this._animateOff=!1}},_value:function(){var a=this.options.value;a=this._trimAlignValue(a);return a},_values:function(a){var b,c,d;if(arguments.length){b=this.options.values[a],b=this._trimAlignValue(b);return b}c=this.options.values.slice();for(d=0;d<c.length;d+=1)c[d]=this._trimAlignValue(c[d]);return c},_trimAlignValue:function(a){if(a<=this._valueMin())return this._valueMin();if(a>=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b,d=a-c;Math.abs(c)*2>=b&&(d+=c>0?b:-b);return parseFloat(d.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var b=this.options.range,c=this.options,d=this,e=this._animateOff?!1:c.animate,f,g={},h,i,j,k;this.options.values&&this.options.values.length?this.handles.each(function(b,i){f=(d.values(b)-d._valueMin())/(d._valueMax()-d._valueMin())*100,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",a(this).stop(1,1)[e?"animate":"css"](g,c.animate),d.options.range===!0&&(d.orientation==="horizontal"?(b===0&&d.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({width:f-h+"%"},{queue:!1,duration:c.animate})):(b===0&&d.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},c.animate),b===1&&d.range[e?"animate":"css"]({height:f-h+"%"},{queue:!1,duration:c.animate}))),h=f}):(i=this.value(),j=this._valueMin(),k=this._valueMax(),f=k!==j?(i-j)/(k-j)*100:0,g[d.orientation==="horizontal"?"left":"bottom"]=f+"%",this.handle.stop(1,1)[e?"animate":"css"](g,c.animate),b==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},c.animate),b==="max"&&this.orientation==="horizontal"&&this.range[e?"animate":"css"]({width:100-f+"%"},{queue:!1,duration:c.animate}),b==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},c.animate),b==="max"&&this.orientation==="vertical"&&this.range[e?"animate":"css"]({height:100-f+"%"},{queue:!1,duration:c.animate}))}}),a.extend(a.ui.slider,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Tabs 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){function f(){return++d}function e(){return++c}var c=0,d=0;a.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:!1,cookie:null,collapsible:!1,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading…</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(!0)},_setOption:function(a,b){if(a=="selected"){if(this.options.collapsible&&b==this.options.selected)return;this.select(b)}else this.options[a]=b,this._tabify()},_tabId:function(a){return a.title&&a.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+e()},_sanitizeSelector:function(a){return a.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+f());return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(a,b){return{tab:a,panel:b,index:this.anchors.index(a)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function m(b,c){b.css("display",""),!a.support.opacity&&c.opacity&&b[0].style.removeAttribute("filter")}var d=this,e=this.options,f=/^#.+/;this.list=this.element.find("ol,ul").eq(0),this.lis=a(" > li:has(a[href])",this.list),this.anchors=this.lis.map(function(){return a("a",this)[0]}),this.panels=a([]),this.anchors.each(function(b,c){var g=a(c).attr("href"),h=g.split("#")[0],i;h&&(h===location.toString().split("#")[0]||(i=a("base")[0])&&h===i.href)&&(g=c.hash,c.href=g);if(f.test(g))d.panels=d.panels.add(d.element.find(d._sanitizeSelector(g)));else if(g&&g!=="#"){a.data(c,"href.tabs",g),a.data(c,"load.tabs",g.replace(/#.*$/,""));var j=d._tabId(c);c.href="#"+j;var k=d.element.find("#"+j);k.length||(k=a(e.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(d.panels[b-1]||d.list),k.data("destroy.tabs",!0)),d.panels=d.panels.add(k)}else e.disabled.push(b)}),c?(this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"),this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.lis.addClass("ui-state-default ui-corner-top"),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom"),e.selected===b?(location.hash&&this.anchors.each(function(a,b){if(b.hash==location.hash){e.selected=a;return!1}}),typeof e.selected!="number"&&e.cookie&&(e.selected=parseInt(d._cookie(),10)),typeof e.selected!="number"&&this.lis.filter(".ui-tabs-selected").length&&(e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))),e.selected=e.selected||(this.lis.length?0:-1)):e.selected===null&&(e.selected=-1),e.selected=e.selected>=0&&this.anchors[e.selected]||e.selected<0?e.selected:0,e.disabled=a.unique(e.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(a,b){return d.lis.index(a)}))).sort(),a.inArray(e.selected,e.disabled)!=-1&&e.disabled.splice(a.inArray(e.selected,e.disabled),1),this.panels.addClass("ui-tabs-hide"),this.lis.removeClass("ui-tabs-selected ui-state-active"),e.selected>=0&&this.anchors.length&&(d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash)).removeClass("ui-tabs-hide"),this.lis.eq(e.selected).addClass("ui-tabs-selected ui-state-active"),d.element.queue("tabs",function(){d._trigger("show",null,d._ui(d.anchors[e.selected],d.element.find(d._sanitizeSelector(d.anchors[e.selected].hash))[0]))}),this.load(e.selected)),a(window).bind("unload",function(){d.lis.add(d.anchors).unbind(".tabs"),d.lis=d.anchors=d.panels=null})):e.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")),this.element[e.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible"),e.cookie&&this._cookie(e.selected,e.cookie);for(var g=0,h;h=this.lis[g];g++)a(h)[a.inArray(g,e.disabled)!=-1&&!a(h).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");e.cache===!1&&this.anchors.removeData("cache.tabs"),this.lis.add(this.anchors).unbind(".tabs");if(e.event!=="mouseover"){var i=function(a,b){b.is(":not(.ui-state-disabled)")&&b.addClass("ui-state-"+a)},j=function(a,b){b.removeClass("ui-state-"+a)};this.lis.bind("mouseover.tabs",function(){i("hover",a(this))}),this.lis.bind("mouseout.tabs",function(){j("hover",a(this))}),this.anchors.bind("focus.tabs",function(){i("focus",a(this).closest("li"))}),this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var k,l;e.fx&&(a.isArray(e.fx)?(k=e.fx[0],l=e.fx[1]):k=l=e.fx);var n=l?function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.hide().removeClass("ui-tabs-hide").animate(l,l.duration||"normal",function(){m(c,l),d._trigger("show",null,d._ui(b,c[0]))})}:function(b,c){a(b).closest("li").addClass("ui-tabs-selected ui-state-active"),c.removeClass("ui-tabs-hide"),d._trigger("show",null,d._ui(b,c[0]))},o=k?function(a,b){b.animate(k,k.duration||"normal",function(){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),m(b,k),d.element.dequeue("tabs")})}:function(a,b,c){d.lis.removeClass("ui-tabs-selected ui-state-active"),b.addClass("ui-tabs-hide"),d.element.dequeue("tabs")};this.anchors.bind(e.event+".tabs",function(){var b=this,c=a(b).closest("li"),f=d.panels.filter(":not(.ui-tabs-hide)"),g=d.element.find(d._sanitizeSelector(b.hash));if(c.hasClass("ui-tabs-selected")&&!e.collapsible||c.hasClass("ui-state-disabled")||c.hasClass("ui-state-processing")||d.panels.filter(":animated").length||d._trigger("select",null,d._ui(this,g[0]))===!1){this.blur();return!1}e.selected=d.anchors.index(this),d.abort();if(e.collapsible){if(c.hasClass("ui-tabs-selected")){e.selected=-1,e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){o(b,f)}).dequeue("tabs"),this.blur();return!1}if(!f.length){e.cookie&&d._cookie(e.selected,e.cookie),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this)),this.blur();return!1}}e.cookie&&d._cookie(e.selected,e.cookie);if(g.length)f.length&&d.element.queue("tabs",function(){o(b,f)}),d.element.queue("tabs",function(){n(b,g)}),d.load(d.anchors.index(this));else throw"jQuery UI Tabs: Mismatching fragment identifier.";a.browser.msie&&this.blur()}),this.anchors.bind("click.tabs",function(){return!1})},_getIndex:function(a){typeof a=="string"&&(a=this.anchors.index(this.anchors.filter("[href$="+a+"]")));return a},destroy:function(){var b=this.options;this.abort(),this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs"),this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all"),this.anchors.each(function(){var b=a.data(this,"href.tabs");b&&(this.href=b);var c=a(this).unbind(".tabs");a.each(["href","load","cache"],function(a,b){c.removeData(b+".tabs")})}),this.lis.unbind(".tabs").add(this.panels).each(function(){a.data(this,"destroy.tabs")?a(this).remove():a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}),b.cookie&&this._cookie(null,b.cookie);return this},add:function(c,d,e){e===b&&(e=this.anchors.length);var f=this,g=this.options,h=a(g.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,d)),i=c.indexOf("#")?this._tabId(a("a",h)[0]):c.replace("#","");h.addClass("ui-state-default ui-corner-top").data("destroy.tabs",!0);var j=f.element.find("#"+i);j.length||(j=a(g.panelTemplate).attr("id",i).data("destroy.tabs",!0)),j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide"),e>=this.lis.length?(h.appendTo(this.list),j.appendTo(this.list[0].parentNode)):(h.insertBefore(this.lis[e]),j.insertBefore(this.panels[e])),g.disabled=a.map(g.disabled,function(a,b){return a>=e?++a:a}),this._tabify(),this.anchors.length==1&&(g.selected=0,h.addClass("ui-tabs-selected ui-state-active"),j.removeClass("ui-tabs-hide"),this.element.queue("tabs",function(){f._trigger("show",null,f._ui(f.anchors[0],f.panels[0]))}),this.load(0)),this._trigger("add",null,this._ui(this.anchors[e],this.panels[e]));return this},remove:function(b){b=this._getIndex(b);var c=this.options,d=this.lis.eq(b).remove(),e=this.panels.eq(b).remove();d.hasClass("ui-tabs-selected")&&this.anchors.length>1&&this.select(b+(b+1<this.anchors.length?1:-1)),c.disabled=a.map(a.grep(c.disabled,function(a,c){return a!=b}),function(a,c){return a>=b?--a:a}),this._tabify(),this._trigger("remove",null,this._ui(d.find("a")[0],e[0]));return this},enable:function(b){b=this._getIndex(b);var c=this.options;if(a.inArray(b,c.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled"),c.disabled=a.grep(c.disabled,function(a,c){return a!=b}),this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(a){a=this._getIndex(a);var b=this,c=this.options;a!=c.selected&&(this.lis.eq(a).addClass("ui-state-disabled"),c.disabled.push(a),c.disabled.sort(),this._trigger("disable",null,this._ui(this.anchors[a],this.panels[a])));return this},select:function(a){a=this._getIndex(a);if(a==-1)if(this.options.collapsible&&this.options.selected!=-1)a=this.options.selected;else return this;this.anchors.eq(a).trigger(this.options.event+".tabs");return this},load:function(b){b=this._getIndex(b);var c=this,d=this.options,e=this.anchors.eq(b)[0],f=a.data(e,"load.tabs");this.abort();if(!f||this.element.queue("tabs").length!==0&&a.data(e,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(d.spinner){var g=a("span",e);g.data("label.tabs",g.html()).html(d.spinner)}this.xhr=a.ajax(a.extend({},d.ajaxOptions,{url:f,success:function(f,g){c.element.find(c._sanitizeSelector(e.hash)).html(f),c._cleanup(),d.cache&&a.data(e,"cache.tabs",!0),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.success(f,g)}catch(h){}},error:function(a,f,g){c._cleanup(),c._trigger("load",null,c._ui(c.anchors[b],c.panels[b]));try{d.ajaxOptions.error(a,f,b,e)}catch(g){}}})),c.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]),this.panels.stop(!1,!0),this.element.queue("tabs",this.element.queue("tabs").splice(-2,2)),this.xhr&&(this.xhr.abort(),delete this.xhr),this._cleanup();return this},url:function(a,b){this.anchors.eq(a).removeData("cache.tabs").data("load.tabs",b);return this},length:function(){return this.anchors.length}}),a.extend(a.ui.tabs,{version:"1.8.18"}),a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(a,b){var c=this,d=this.options,e=c._rotate||(c._rotate=function(b){clearTimeout(c.rotation),c.rotation=setTimeout(function(){var a=d.selected;c.select(++a<c.anchors.length?a:0)},a),b&&b.stopPropagation()}),f=c._unrotate||(c._unrotate=b?function(a){t=d.selected,e()}:function(a){a.clientX&&c.rotate(null)});a?(this.element.bind("tabsshow",e),this.anchors.bind(d.event+".tabs",f),e()):(clearTimeout(c.rotation),this.element.unbind("tabsshow",e),this.anchors.unbind(d.event+".tabs",f),delete this._rotate,delete this._unrotate);return this}})})(jQuery);/* + * jQuery UI Datepicker 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker + * + * Depends: + * jquery.ui.core.js + */(function($,undefined){function isArray(a){return a&&($.browser.safari&&typeof a=="object"&&a.length||a.constructor&&a.constructor.toString().match(/\Array\(\)/))}function extendRemove(a,b){$.extend(a,b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}function bindHover(a){var b="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return a.bind("mouseout",function(a){var c=$(a.target).closest(b);!c.length||c.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(c){var d=$(c.target).closest(b);!$.datepicker._isDisabledDatepicker(instActive.inline?a.parent()[0]:instActive.input[0])&&!!d.length&&(d.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),d.addClass("ui-state-hover"),d.hasClass("ui-datepicker-prev")&&d.addClass("ui-datepicker-prev-hover"),d.hasClass("ui-datepicker-next")&&d.addClass("ui-datepicker-next-hover"))})}function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}$.extend($.ui,{datepicker:{version:"1.8.18"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){extendRemove(this._defaults,a||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(a,b){var c=a[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:c,input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:b?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(a,b){var c=$(a);b.append=$([]),b.trigger=$([]);c.hasClass(this.markerClassName)||(this._attachments(c,b),c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),this._autoSize(b),$.data(a,PROP_NAME,b),b.settings.disabled&&this._disableDatepicker(a))},_attachments:function(a,b){var c=this._get(b,"appendText"),d=this._get(b,"isRTL");b.append&&b.append.remove(),c&&(b.append=$('<span class="'+this._appendClass+'">'+c+"</span>"),a[d?"before":"after"](b.append)),a.unbind("focus",this._showDatepicker),b.trigger&&b.trigger.remove();var e=this._get(b,"showOn");(e=="focus"||e=="both")&&a.focus(this._showDatepicker);if(e=="button"||e=="both"){var f=this._get(b,"buttonText"),g=this._get(b,"buttonImage");b.trigger=$(this._get(b,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:g,alt:f,title:f}):$('<button type="button"></button>').addClass(this._triggerClass).html(g==""?f:$("<img/>").attr({src:g,alt:f,title:f}))),a[d?"before":"after"](b.trigger),b.trigger.click(function(){$.datepicker._datepickerShowing&&$.datepicker._lastInput==a[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=a[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(a[0])):$.datepicker._showDatepicker(a[0]);return!1})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var d=function(a){var b=0,c=0;for(var d=0;d<a.length;d++)a[d].length>b&&(b=a[d].length,c=d);return c};b.setMonth(d(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort"))),b.setDate(d(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=$(a);c.hasClass(this.markerClassName)||(c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(a,c,d){b.settings[c]=d}).bind("getData.datepicker",function(a,c){return this._get(b,c)}),$.data(a,PROP_NAME,b),this._setDate(b,this._getDefaultDate(b),!0),this._updateDatepicker(b),this._updateAlternate(b),b.settings.disabled&&this._disableDatepicker(a),b.dpDiv.css("display","block"))},_dialogDatepicker:function(a,b,c,d,e){var f=this._dialogInst;if(!f){this.uuid+=1;var g="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+g+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),f=this._dialogInst=this._newInst(this._dialogInput,!1),f.settings={},$.data(this._dialogInput[0],PROP_NAME,f)}extendRemove(f.settings,d||{}),b=b&&b.constructor==Date?this._formatDate(f,b):b,this._dialogInput.val(b),this._pos=e?e.length?e:[e.pageX,e.pageY]:null;if(!this._pos){var h=document.documentElement.clientWidth,i=document.documentElement.clientHeight,j=document.documentElement.scrollLeft||document.body.scrollLeft,k=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[h/2-100+j,i/2-150+k]}this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),f.settings.onSelect=c,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,f);return this},_destroyDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();$.removeData(a,PROP_NAME),d=="input"?(c.append.remove(),c.trigger.remove(),b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(d=="div"||d=="span")&&b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!1,c.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().removeClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b})}},_disableDatepicker:function(a){var b=$(a),c=$.data(a,PROP_NAME);if(!!b.hasClass(this.markerClassName)){var d=a.nodeName.toLowerCase();if(d=="input")a.disabled=!0,c.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(d=="div"||d=="span"){var e=b.children("."+this._inlineClass);e.children().addClass("ui-state-disabled"),e.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=$.map(this._disabledInputs,function(b){return b==a?null:b}),this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return!1;for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return!0;return!1},_getInst:function(a){try{return $.data(a,PROP_NAME)}catch(b){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(a,b,c){var d=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?$.extend({},$.datepicker._defaults):d?b=="all"?$.extend({},d.settings):this._get(d,b):null;var e=b||{};typeof b=="string"&&(e={},e[b]=c);if(d){this._curInst==d&&this._hideDatepicker();var f=this._getDateDatepicker(a,!0),g=this._getMinMaxDate(d,"min"),h=this._getMinMaxDate(d,"max");extendRemove(d.settings,e),g!==null&&e.dateFormat!==undefined&&e.minDate===undefined&&(d.settings.minDate=this._formatDate(d,g)),h!==null&&e.dateFormat!==undefined&&e.maxDate===undefined&&(d.settings.maxDate=this._formatDate(d,h)),this._attachments($(a),d),this._autoSize(d),this._setDate(d,f),this._updateAlternate(d),this._updateDatepicker(d)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){var b=this._getInst(a);b&&this._updateDatepicker(b)},_setDateDatepicker:function(a,b){var c=this._getInst(a);c&&(this._setDate(c,b),this._updateDatepicker(c),this._updateAlternate(c))},_getDateDatepicker:function(a,b){var c=this._getInst(a);c&&!c.inline&&this._setDateFromField(c,b);return c?this._getDate(c):null},_doKeyDown:function(a){var b=$.datepicker._getInst(a.target),c=!0,d=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=!0;if($.datepicker._datepickerShowing)switch(a.keyCode){case 9:$.datepicker._hideDatepicker(),c=!1;break;case 13:var e=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",b.dpDiv);e[0]&&$.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,e[0]);var f=$.datepicker._get(b,"onSelect");if(f){var g=$.datepicker._formatDate(b);f.apply(b.input?b.input[0]:null,[g,b])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 35:(a.ctrlKey||a.metaKey)&&$.datepicker._clearDate(a.target),c=a.ctrlKey||a.metaKey;break;case 36:(a.ctrlKey||a.metaKey)&&$.datepicker._gotoToday(a.target),c=a.ctrlKey||a.metaKey;break;case 37:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?1:-1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?-$.datepicker._get(b,"stepBigMonths"):-$.datepicker._get(b,"stepMonths"),"M");break;case 38:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,-7,"D"),c=a.ctrlKey||a.metaKey;break;case 39:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,d?-1:1,"D"),c=a.ctrlKey||a.metaKey,a.originalEvent.altKey&&$.datepicker._adjustDate(a.target,a.ctrlKey?+$.datepicker._get(b,"stepBigMonths"):+$.datepicker._get(b,"stepMonths"),"M");break;case 40:(a.ctrlKey||a.metaKey)&&$.datepicker._adjustDate(a.target,7,"D"),c=a.ctrlKey||a.metaKey;break;default:c=!1}else a.keyCode==36&&a.ctrlKey?$.datepicker._showDatepicker(this):c=!1;c&&(a.preventDefault(),a.stopPropagation())},_doKeyPress:function(a){var b=$.datepicker._getInst(a.target);if($.datepicker._get(b,"constrainInput")){var c=$.datepicker._possibleChars($.datepicker._get(b,"dateFormat")),d=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||a.metaKey||d<" "||!c||c.indexOf(d)>-1}},_doKeyUp:function(a){var b=$.datepicker._getInst(a.target);if(b.input.val()!=b.lastVal)try{var c=$.datepicker.parseDate($.datepicker._get(b,"dateFormat"),b.input?b.input.val():null,$.datepicker._getFormatConfig(b));c&&($.datepicker._setDateFromField(b),$.datepicker._updateAlternate(b),$.datepicker._updateDatepicker(b))}catch(a){$.datepicker.log(a)}return!0},_showDatepicker:function(a){a=a.target||a,a.nodeName.toLowerCase()!="input"&&(a=$("input",a.parentNode)[0]);if(!$.datepicker._isDisabledDatepicker(a)&&$.datepicker._lastInput!=a){var b=$.datepicker._getInst(a);$.datepicker._curInst&&$.datepicker._curInst!=b&&($.datepicker._curInst.dpDiv.stop(!0,!0),b&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var c=$.datepicker._get(b,"beforeShow"),d=c?c.apply(a,[a,b]):{};if(d===!1)return;extendRemove(b.settings,d),b.lastVal=null,$.datepicker._lastInput=a,$.datepicker._setDateFromField(b),$.datepicker._inDialog&&(a.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(a),$.datepicker._pos[1]+=a.offsetHeight);var e=!1;$(a).parents().each(function(){e|=$(this).css("position")=="fixed";return!e}),e&&$.browser.opera&&($.datepicker._pos[0]-=document.documentElement.scrollLeft,$.datepicker._pos[1]-=document.documentElement.scrollTop);var f={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,b.dpDiv.empty(),b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(b),f=$.datepicker._checkOffset(b,f,e),b.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":e?"fixed":"absolute",display:"none",left:f.left+"px",top:f.top+"px"});if(!b.inline){var g=$.datepicker._get(b,"showAnim"),h=$.datepicker._get(b,"duration"),i=function(){var a=b.dpDiv.find("iframe.ui-datepicker-cover");if(!!a.length){var c=$.datepicker._getBorders(b.dpDiv);a.css({left:-c[0],top:-c[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex($(a).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&$.effects[g]?b.dpDiv.show(g,$.datepicker._get(b,"showOptions"),h,i):b.dpDiv[g||"show"](g?h:null,i),(!g||!h)&&i(),b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus(),$.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this;b.maxRows=4;var c=$.datepicker._getBorders(a.dpDiv);instActive=a,a.dpDiv.empty().append(this._generateHTML(a));var d=a.dpDiv.find("iframe.ui-datepicker-cover");!d.length||d.css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}),a.dpDiv.find("."+this._dayOverClass+" a").mouseover();var e=this._getNumberOfMonths(a),f=e[1],g=17;a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),f>1&&a.dpDiv.addClass("ui-datepicker-multi-"+f).css("width",g*f+"em"),a.dpDiv[(e[0]!=1||e[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),a==$.datepicker._curInst&&$.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var h=a.yearshtml;setTimeout(function(){h===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml),h=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(a){return{thin:1,medium:2,thick:3}[a]||a};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var d=a.dpDiv.outerWidth(),e=a.dpDiv.outerHeight(),f=a.input?a.input.outerWidth():0,g=a.input?a.input.outerHeight():0,h=document.documentElement.clientWidth+$(document).scrollLeft(),i=document.documentElement.clientHeight+$(document).scrollTop();b.left-=this._get(a,"isRTL")?d-f:0,b.left-=c&&b.left==a.input.offset().left?$(document).scrollLeft():0,b.top-=c&&b.top==a.input.offset().top+g?$(document).scrollTop():0,b.left-=Math.min(b.left,b.left+d>h&&h>d?Math.abs(b.left+d-h):0),b.top-=Math.min(b.top,b.top+e>i&&i>e?Math.abs(e+g):0);return b},_findPos:function(a){var b=this._getInst(a),c=this._get(b,"isRTL");while(a&&(a.type=="hidden"||a.nodeType!=1||$.expr.filters.hidden(a)))a=a[c?"previousSibling":"nextSibling"];var d=$(a).offset();return[d.left,d.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=$.data(a,PROP_NAME))&&this._datepickerShowing){var c=this._get(b,"showAnim"),d=this._get(b,"duration"),e=this,f=function(){$.datepicker._tidyDialog(b),e._curInst=null};$.effects&&$.effects[c]?b.dpDiv.hide(c,$.datepicker._get(b,"showOptions"),d,f):b.dpDiv[c=="slideDown"?"slideUp":c=="fadeIn"?"fadeOut":"hide"](c?d:null,f),c||f(),this._datepickerShowing=!1;var g=this._get(b,"onClose");g&&g.apply(b.input?b.input[0]:null,[b.input?b.input.val():"",b]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(!!$.datepicker._curInst){var b=$(a.target),c=$.datepicker._getInst(b[0]);(b[0].id!=$.datepicker._mainDivId&&b.parents("#"+$.datepicker._mainDivId).length==0&&!b.hasClass($.datepicker.markerClassName)&&!b.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||b.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=c)&&$.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){var d=$(a),e=this._getInst(d[0]);this._isDisabledDatepicker(d[0])||(this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c),this._updateDatepicker(e))},_gotoToday:function(a){var b=$(a),c=this._getInst(b[0]);if(this._get(c,"gotoCurrent")&&c.currentDay)c.selectedDay=c.currentDay,c.drawMonth=c.selectedMonth=c.currentMonth,c.drawYear=c.selectedYear=c.currentYear;else{var d=new Date;c.selectedDay=d.getDate(),c.drawMonth=c.selectedMonth=d.getMonth(),c.drawYear=c.selectedYear=d.getFullYear()}this._notifyChange(c),this._adjustDate(b)},_selectMonthYear:function(a,b,c){var d=$(a),e=this._getInst(d[0]);e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10),this._notifyChange(e),this._adjustDate(d)},_selectDay:function(a,b,c,d){var e=$(a);if(!$(d).hasClass(this._unselectableClass)&&!this._isDisabledDatepicker(e[0])){var f=this._getInst(e[0]);f.selectedDay=f.currentDay=$("a",d).html(),f.selectedMonth=f.currentMonth=b,f.selectedYear=f.currentYear=c,this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){var b=$(a),c=this._getInst(b[0]);this._selectDate(b,"")},_selectDate:function(a,b){var c=$(a),d=this._getInst(c[0]);b=b!=null?b:this._formatDate(d),d.input&&d.input.val(b),this._updateAlternate(d);var e=this._get(d,"onSelect");e?e.apply(d.input?d.input[0]:null,[b,d]):d.input&&d.input.trigger("change"),d.inline?this._updateDatepicker(d):(this._hideDatepicker(),this._lastInput=d.input[0],typeof d.input[0]!="object"&&d.input.focus(),this._lastInput=null)},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),d=this._getDate(a),e=this.formatDate(c,d,this._getFormatConfig(a));$(b).each(function(){$(this).val(e)})}},noWeekends:function(a){var b=a.getDay();return[b>0&&b<6,""]},iso8601Week:function(a){var b=new Date(a.getTime());b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();b.setMonth(0),b.setDate(1);return Math.floor(Math.round((c-b)/864e5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;var d=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;d=typeof d!="string"?d:(new Date).getFullYear()%100+parseInt(d,10);var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,g=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,h=(c?c.monthNames:null)||this._defaults.monthNames,i=-1,j=-1,k=-1,l=-1,m=!1,n=function(b){var c=s+1<a.length&&a.charAt(s+1)==b;c&&s++;return c},o=function(a){var c=n(a),d=a=="@"?14:a=="!"?20:a=="y"&&c?4:a=="o"?3:2,e=new RegExp("^\\d{1,"+d+"}"),f=b.substring(r).match(e);if(!f)throw"Missing number at position "+r;r+=f[0].length;return parseInt(f[0],10)},p=function(a,c,d){var e=$.map(n(a)?d:c,function(a,b){return[[b,a]]}).sort(function(a,b){return-(a[1].length-b[1].length)}),f=-1;$.each(e,function(a,c){var d=c[1];if(b.substr(r,d.length).toLowerCase()==d.toLowerCase()){f=c[0],r+=d.length;return!1}});if(f!=-1)return f+1;throw"Unknown name at position "+r},q=function(){if(b.charAt(r)!=a.charAt(s))throw"Unexpected literal at position "+r;r++},r=0;for(var s=0;s<a.length;s++)if(m)a.charAt(s)=="'"&&!n("'")?m=!1:q();else switch(a.charAt(s)){case"d":k=o("d");break;case"D":p("D",e,f);break;case"o":l=o("o");break;case"m":j=o("m");break;case"M":j=p("M",g,h);break;case"y":i=o("y");break;case"@":var t=new Date(o("@"));i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"!":var t=new Date((o("!")-this._ticksTo1970)/1e4);i=t.getFullYear(),j=t.getMonth()+1,k=t.getDate();break;case"'":n("'")?q():m=!0;break;default:q()}if(r<b.length)throw"Extra/unparsed characters found in date: "+b.substring(r);i==-1?i=(new Date).getFullYear():i<100&&(i+=(new Date).getFullYear()-(new Date).getFullYear()%100+(i<=d?0:-100));if(l>-1){j=1,k=l;for(;;){var u=this._getDaysInMonth(i,j-1);if(k<=u)break;j++,k-=u}}var t=this._daylightSavingAdjust(new Date(i,j-1,k));if(t.getFullYear()!=i||t.getMonth()+1!=j||t.getDate()!=k)throw"Invalid date";return t},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(a,b,c){if(!b)return"";var d=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,e=(c?c.dayNames:null)||this._defaults.dayNames,f=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,h=function(b){var c=m+1<a.length&&a.charAt(m+1)==b;c&&m++;return c},i=function(a,b,c){var d=""+b;if(h(a))while(d.length<c)d="0"+d;return d},j=function(a,b,c,d){return h(a)?d[b]:c[b]},k="",l=!1;if(b)for(var m=0;m<a.length;m++)if(l)a.charAt(m)=="'"&&!h("'")?l=!1:k+=a.charAt(m);else switch(a.charAt(m)){case"d":k+=i("d",b.getDate(),2);break;case"D":k+=j("D",b.getDay(),d,e);break;case"o":k+=i("o",Math.round(((new Date(b.getFullYear(),b.getMonth(),b.getDate())).getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":k+=i("m",b.getMonth()+1,2);break;case"M":k+=j("M",b.getMonth(),f,g);break;case"y":k+=h("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case"@":k+=b.getTime();break;case"!":k+=b.getTime()*1e4+this._ticksTo1970;break;case"'":h("'")?k+="'":l=!0;break;default:k+=a.charAt(m)}return k},_possibleChars:function(a){var b="",c=!1,d=function(b){var c=e+1<a.length&&a.charAt(e+1)==b;c&&e++;return c};for(var e=0;e<a.length;e++)if(c)a.charAt(e)=="'"&&!d("'")?c=!1:b+=a.charAt(e);else switch(a.charAt(e)){case"d":case"m":case"y":case"@":b+="0123456789";break;case"D":case"M":return null;case"'":d("'")?b+="'":c=!0;break;default:b+=a.charAt(e)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),d=a.lastVal=a.input?a.input.val():null,e,f;e=f=this._getDefaultDate(a);var g=this._getFormatConfig(a);try{e=this.parseDate(c,d,g)||f}catch(h){this.log(h),d=b?"":d}a.selectedDay=e.getDate(),a.drawMonth=a.selectedMonth=e.getMonth(),a.drawYear=a.selectedYear=e.getFullYear(),a.currentDay=d?e.getDate():0,a.currentMonth=d?e.getMonth():0,a.currentYear=d?e.getFullYear():0,this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var d=function(a){var b=new Date;b.setDate(b.getDate()+a);return b},e=function(b){try{return $.datepicker.parseDate($.datepicker._get(a,"dateFormat"),b,$.datepicker._getFormatConfig(a))}catch(c){}var d=(b.toLowerCase().match(/^c/)?$.datepicker._getDate(a):null)||new Date,e=d.getFullYear(),f=d.getMonth(),g=d.getDate(),h=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,i=h.exec(b);while(i){switch(i[2]||"d"){case"d":case"D":g+=parseInt(i[1],10);break;case"w":case"W":g+=parseInt(i[1],10)*7;break;case"m":case"M":f+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f));break;case"y":case"Y":e+=parseInt(i[1],10),g=Math.min(g,$.datepicker._getDaysInMonth(e,f))}i=h.exec(b)}return new Date(e,f,g)},f=b==null||b===""?c:typeof b=="string"?e(b):typeof b=="number"?isNaN(b)?c:d(b):new Date(b.getTime());f=f&&f.toString()=="Invalid Date"?c:f,f&&(f.setHours(0),f.setMinutes(0),f.setSeconds(0),f.setMilliseconds(0));return this._daylightSavingAdjust(f)},_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var d=!b,e=a.selectedMonth,f=a.selectedYear,g=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=g.getDate(),a.drawMonth=a.selectedMonth=a.currentMonth=g.getMonth(),a.drawYear=a.selectedYear=a.currentYear=g.getFullYear(),(e!=a.selectedMonth||f!=a.selectedYear)&&!c&&this._notifyChange(a),this._adjustInstDate(a),a.input&&a.input.val(d?"":this._formatDate(a))},_getDate:function(a){var b=!a.currentYear||a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return b},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),d=this._get(a,"showButtonPanel"),e=this._get(a,"hideIfNoPrevNext"),f=this._get(a,"navigationAsDateFormat"),g=this._getNumberOfMonths(a),h=this._get(a,"showCurrentAtPos"),i=this._get(a,"stepMonths"),j=g[0]!=1||g[1]!=1,k=this._daylightSavingAdjust(a.currentDay?new Date(a.currentYear,a.currentMonth,a.currentDay):new Date(9999,9,9)),l=this._getMinMaxDate(a,"min"),m=this._getMinMaxDate(a,"max"),n=a.drawMonth-h,o=a.drawYear;n<0&&(n+=12,o--);if(m){var p=this._daylightSavingAdjust(new Date(m.getFullYear(),m.getMonth()-g[0]*g[1]+1,m.getDate()));p=l&&p<l?l:p;while(this._daylightSavingAdjust(new Date(o,n,1))>p)n--,n<0&&(n=11,o--)}a.drawMonth=n,a.drawYear=o;var q=this._get(a,"prevText");q=f?this.formatDate(q,this._daylightSavingAdjust(new Date(o,n-i,1)),this._getFormatConfig(a)):q;var r=this._canAdjustMonth(a,-1,o,n)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._adjustDate('#"+a.id+"', -"+i+", 'M');\""+' title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>":e?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+q+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+q+"</span></a>",s=this._get(a,"nextText");s=f?this.formatDate(s,this._daylightSavingAdjust(new Date(o,n+i,1)),this._getFormatConfig(a)):s;var t=this._canAdjustMonth(a,1,o,n)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._adjustDate('#"+a.id+"', +"+i+", 'M');\""+' title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>":e?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>",u=this._get(a,"currentText"),v=this._get(a,"gotoCurrent")&&a.currentDay?k:b;u=f?this.formatDate(u,v,this._getFormatConfig(a)):u;var w=a.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+dpuuid+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>",x=d?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?w:"")+(this._isInRange(a,v)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+dpuuid+".datepicker._gotoToday('#"+a.id+"');\""+">"+u+"</button>":"")+(c?"":w)+"</div>":"",y=parseInt(this._get(a,"firstDay"),10);y=isNaN(y)?0:y;var z=this._get(a,"showWeek"),A=this._get(a,"dayNames"),B=this._get(a,"dayNamesShort"),C=this._get(a,"dayNamesMin"),D=this._get(a,"monthNames"),E=this._get(a,"monthNamesShort"),F=this._get(a,"beforeShowDay"),G=this._get(a,"showOtherMonths"),H=this._get(a,"selectOtherMonths"),I=this._get(a,"calculateWeek")||this.iso8601Week,J=this._getDefaultDate(a),K="";for(var L=0;L<g[0];L++){var M="";this.maxRows=4;for(var N=0;N<g[1];N++){var O=this._daylightSavingAdjust(new Date(o,n,a.selectedDay)),P=" ui-corner-all",Q="";if(j){Q+='<div class="ui-datepicker-group';if(g[1]>1)switch(N){case 0:Q+=" ui-datepicker-group-first",P=" ui-corner-"+(c?"right":"left");break;case g[1]-1:Q+=" ui-datepicker-group-last",P=" ui-corner-"+(c?"left":"right");break;default:Q+=" ui-datepicker-group-middle",P=""}Q+='">'}Q+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+P+'">'+(/all|left/.test(P)&&L==0?c?t:r:"")+(/all|right/.test(P)&&L==0?c?r:t:"")+this._generateMonthYearHeader(a,n,o,l,m,L>0||N>0,D,E)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var R=z?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(var S=0;S<7;S++){var T=(S+y)%7;R+="<th"+((S+y+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+A[T]+'">'+C[T]+"</span></th>"}Q+=R+"</tr></thead><tbody>";var U=this._getDaysInMonth(o,n);o==a.selectedYear&&n==a.selectedMonth&&(a.selectedDay=Math.min(a.selectedDay,U));var V=(this._getFirstDayOfMonth(o,n)-y+7)%7,W=Math.ceil((V+U)/7),X=j?this.maxRows>W?this.maxRows:W:W;this.maxRows=X;var Y=this._daylightSavingAdjust(new Date(o,n,1-V));for(var Z=0;Z<X;Z++){Q+="<tr>";var _=z?'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(Y)+"</td>":"";for(var S=0;S<7;S++){var ba=F?F.apply(a.input?a.input[0]:null,[Y]):[!0,""],bb=Y.getMonth()!=n,bc=bb&&!H||!ba[0]||l&&Y<l||m&&Y>m;_+='<td class="'+((S+y+6)%7>=5?" ui-datepicker-week-end":"")+(bb?" ui-datepicker-other-month":"")+(Y.getTime()==O.getTime()&&n==a.selectedMonth&&a._keyEvent||J.getTime()==Y.getTime()&&J.getTime()==O.getTime()?" "+this._dayOverClass:"")+(bc?" "+this._unselectableClass+" ui-state-disabled":"")+(bb&&!G?"":" "+ba[1]+(Y.getTime()==k.getTime()?" "+this._currentClass:"")+(Y.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!bb||G)&&ba[2]?' title="'+ba[2]+'"':"")+(bc?"":' onclick="DP_jQuery_'+dpuuid+".datepicker._selectDay('#"+a.id+"',"+Y.getMonth()+","+Y.getFullYear()+', this);return false;"')+">"+(bb&&!G?" ":bc?'<span class="ui-state-default">'+Y.getDate()+"</span>":'<a class="ui-state-default'+(Y.getTime()==b.getTime()?" ui-state-highlight":"")+(Y.getTime()==k.getTime()?" ui-state-active":"")+(bb?" ui-priority-secondary":"")+'" href="#">'+Y.getDate()+"</a>")+"</td>",Y.setDate(Y.getDate()+1),Y=this._daylightSavingAdjust(Y)}Q+=_+"</tr>"}n++,n>11&&(n=0,o++),Q+="</tbody></table>"+(j?"</div>"+(g[0]>0&&N==g[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),M+=Q}K+=M}K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""), +a._keyEvent=!1;return K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='<div class="ui-datepicker-title">',m="";if(f||!i)m+='<span class="ui-datepicker-month">'+g[b]+"</span>";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+dpuuid+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" "+">";for(var p=0;p<12;p++)(!n||p>=d.getMonth())&&(!o||p<=e.getMonth())&&(m+='<option value="'+p+'"'+(p==b?' selected="selected"':"")+">"+h[p]+"</option>");m+="</select>"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+='<span class="ui-datepicker-year">'+c+"</span>";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+dpuuid+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" "+">";for(;t<=u;t++)a.yearshtml+='<option value="'+t+'"'+(t==c?' selected="selected"':"")+">"+t+"</option>";a.yearshtml+="</select>",l+=a.yearshtml,a.yearshtml=null}}l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="</div>";return l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&b<c?c:b;e=d&&e>d?d:e;return e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth()));return this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return $.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return $.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b));return this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)})},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.18",window["DP_jQuery_"+dpuuid]=$})(jQuery);/* + * jQuery UI Progressbar 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===b)return this._value();this._setOption("value",a);return this},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;typeof a!="number"&&(a=0);return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.18"})})(jQuery);/* + * jQuery UI Effects 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */jQuery.effects||function(a,b){function l(b){if(!b||typeof b=="number"||a.fx.speeds[b])return!0;if(typeof b=="string"&&!a.effects[b])return!0;return!1}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete;return[b,c,d,e]}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function d(b,d){var e;do{e=a.curCSS(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function c(b){var c;if(b&&b.constructor==Array&&b.length==3)return b;if(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)];if(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55];if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)];if(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)];if(c=/rgba\(0, 0, 0, 0\)/.exec(b))return e.transparent;return e[a.trim(b).toLowerCase()]}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){a.isFunction(d)&&(e=d,d=null);return this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class");a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.18",save:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.data("ec.storage."+b[c],a[0].style[b[c]])},restore:function(a,b){for(var c=0;c<b.length;c++)b[c]!==null&&a.css(b[c],a.data("ec.storage."+b[c]))},setMode:function(a,b){b=="toggle"&&(b=a.is(":hidden")?"show":"hide");return b},getBaseline:function(a,b){var c,d;switch(a[0]){case"top":c=0;break;case"middle":c=.5;break;case"bottom":c=1;break;default:c=a[0]/b.height}switch(a[1]){case"left":d=0;break;case"center":d=.5;break;case"right":d=1;break;default:d=a[1]/b.width}return{x:d,y:c}},createWrapper:function(b){if(b.parent().is(".ui-effects-wrapper"))return b.parent();var c={width:b.outerWidth(!0),height:b.outerHeight(!0),"float":b.css("float")},d=a("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"}));return d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;if(b.parent().is(".ui-effects-wrapper")){c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus();return c}return b},setTransition:function(b,c,d,e){e=e||{},a.each(c,function(a,c){unit=b.cssUnit(c),unit[0]>0&&(e[c]=unit[0]*d+unit[1])});return e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];if(a.fx.off||!i)return h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)});return i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="show";return this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="hide";return this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);c[1].mode="toggle";return this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])});return d}}),a.easing.jswing=a.easing.swing,a.extend(a.easing,{def:"easeOutQuad",swing:function(b,c,d,e,f){return a.easing[a.easing.def](b,c,d,e,f)},easeInQuad:function(a,b,c,d,e){return d*(b/=e)*b+c},easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c},easeInOutQuad:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b+c;return-d/2*(--b*(b-2)-1)+c},easeInCubic:function(a,b,c,d,e){return d*(b/=e)*b*b+c},easeOutCubic:function(a,b,c,d,e){return d*((b=b/e-1)*b*b+1)+c},easeInOutCubic:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b+c;return d/2*((b-=2)*b*b+2)+c},easeInQuart:function(a,b,c,d,e){return d*(b/=e)*b*b*b+c},easeOutQuart:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c},easeInOutQuart:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b+c;return-d/2*((b-=2)*b*b*b-2)+c},easeInQuint:function(a,b,c,d,e){return d*(b/=e)*b*b*b*b+c},easeOutQuint:function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},easeInOutQuint:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b*b+c;return d/2*((b-=2)*b*b*b*b+2)+c},easeInSine:function(a,b,c,d,e){return-d*Math.cos(b/e*(Math.PI/2))+d+c},easeOutSine:function(a,b,c,d,e){return d*Math.sin(b/e*(Math.PI/2))+c},easeInOutSine:function(a,b,c,d,e){return-d/2*(Math.cos(Math.PI*b/e)-1)+c},easeInExpo:function(a,b,c,d,e){return b==0?c:d*Math.pow(2,10*(b/e-1))+c},easeOutExpo:function(a,b,c,d,e){return b==e?c+d:d*(-Math.pow(2,-10*b/e)+1)+c},easeInOutExpo:function(a,b,c,d,e){if(b==0)return c;if(b==e)return c+d;if((b/=e/2)<1)return d/2*Math.pow(2,10*(b-1))+c;return d/2*(-Math.pow(2,-10*--b)+2)+c},easeInCirc:function(a,b,c,d,e){return-d*(Math.sqrt(1-(b/=e)*b)-1)+c},easeOutCirc:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c},easeInOutCirc:function(a,b,c,d,e){if((b/=e/2)<1)return-d/2*(Math.sqrt(1-b*b)-1)+c;return d/2*(Math.sqrt(1-(b-=2)*b)+1)+c},easeInElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g))+c},easeOutElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*b)*Math.sin((b*e-f)*2*Math.PI/g)+d+c},easeInOutElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e/2)==2)return c+d;g||(g=e*.3*1.5);if(h<Math.abs(d)){h=d;var f=g/4}else var f=g/(2*Math.PI)*Math.asin(d/h);if(b<1)return-0.5*h*Math.pow(2,10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g)+c;return h*Math.pow(2,-10*(b-=1))*Math.sin((b*e-f)*2*Math.PI/g)*.5+d+c},easeInBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);return e*(c/=f)*c*((g+1)*c-g)+d},easeOutBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);return e*((c=c/f-1)*c*((g+1)*c+g)+1)+d},easeInOutBack:function(a,c,d,e,f,g){g==b&&(g=1.70158);if((c/=f/2)<1)return e/2*c*c*(((g*=1.525)+1)*c-g)+d;return e/2*((c-=2)*c*(((g*=1.525)+1)*c+g)+2)+d},easeInBounce:function(b,c,d,e,f){return e-a.easing.easeOutBounce(b,f-c,0,e,f)+d},easeOutBounce:function(a,b,c,d,e){return(b/=e)<1/2.75?d*7.5625*b*b+c:b<2/2.75?d*(7.5625*(b-=1.5/2.75)*b+.75)+c:b<2.5/2.75?d*(7.5625*(b-=2.25/2.75)*b+.9375)+c:d*(7.5625*(b-=2.625/2.75)*b+.984375)+c},easeInOutBounce:function(b,c,d,e,f){if(c<f/2)return a.easing.easeInBounce(b,c*2,0,e,f)*.5+d;return a.easing.easeOutBounce(b,c*2-f,0,e,f)*.5+e*.5+d}})}(jQuery);/* + * jQuery UI Effects Blind 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Blind + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);/* + * jQuery UI Effects Bounce 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Bounce + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight({margin:!0})/3:c.outerWidth({margin:!0})/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m<h;m++){var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing),g=e=="hide"?g*2:g/2}if(e=="hide"){var l={opacity:0};l[j]=(k=="pos"?"-=":"+=")+g,c.animate(l,i/2,b.options.easing,function(){c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}else{var n={},p={};n[j]=(k=="pos"?"-=":"+=")+g,p[j]=(k=="pos"?"+=":"-=")+g,c.animate(n,i/2,b.options.easing).animate(p,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)})}c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);/* + * jQuery UI Effects Clip 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Clip + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.clip=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","height","width"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=c[0].tagName=="IMG"?g:c,i={size:f=="vertical"?"height":"width",position:f=="vertical"?"top":"left"},j=f=="vertical"?h.height():h.width();e=="show"&&(h.css(i.size,0),h.css(i.position,j/2));var k={};k[i.size]=e=="show"?j:0,k[i.position]=e=="show"?0:j/2,h.animate(k,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Drop 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Drop + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.drop=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","opacity"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight({margin:!0})/2:c.outerWidth({margin:!0})/2);e=="show"&&c.css("opacity",0).css(g,h=="pos"?-i:i);var j={opacity:e=="show"?1:0};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Explode 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Explode + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.explode=function(b){return this.queue(function(){var c=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3,d=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?a(this).is(":visible")?"hide":"show":b.options.mode;var e=a(this).show().css("visibility","hidden"),f=e.offset();f.top-=parseInt(e.css("marginTop"),10)||0,f.left-=parseInt(e.css("marginLeft"),10)||0;var g=e.outerWidth(!0),h=e.outerHeight(!0);for(var i=0;i<c;i++)for(var j=0;j<d;j++)e.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);/* + * jQuery UI Effects Fade 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Fold 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);/* + * jQuery UI Effects Highlight 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Pulsate 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show");times=(b.options.times||5)*2-1,duration=b.duration?b.duration/2:a.fx.speeds._default/2,isVisible=c.is(":visible"),animateTo=0,isVisible||(c.css("opacity",0).show(),animateTo=1),(d=="hide"&&isVisible||d=="show"&&!isVisible)&×--;for(var e=0;e<times;e++)c.animate({opacity:animateTo},duration,b.options.easing),animateTo=(animateTo+1)%2;c.animate({opacity:animateTo},duration,b.options.easing,function(){animateTo==0&&c.hide(),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}).dequeue()})}})(jQuery);/* + * jQuery UI Effects Scale 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Scale + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.puff=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide"),e=parseInt(b.options.percent,10)||150,f=e/100,g={height:c.height(),width:c.width()};a.extend(b.options,{fade:!0,mode:d,percent:d=="hide"?e:100,from:d=="hide"?g:{height:g.height*f,width:g.width*f}}),c.effect("scale",b.options,b.duration,b.callback),c.dequeue()})},a.effects.scale=function(b){return this.queue(function(){var c=a(this),d=a.extend(!0,{},b.options),e=a.effects.setMode(c,b.options.mode||"effect"),f=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:e=="hide"?0:100),g=b.options.direction||"both",h=b.options.origin;e!="effect"&&(d.origin=h||["middle","center"],d.restore=!0);var i={height:c.height(),width:c.width()};c.from=b.options.from||(e=="show"?{height:0,width:0}:i);var j={y:g!="horizontal"?f/100:1,x:g!="vertical"?f/100:1};c.to={height:i.height*j.y,width:i.width*j.x},b.options.fade&&(e=="show"&&(c.from.opacity=0,c.to.opacity=1),e=="hide"&&(c.from.opacity=1,c.to.opacity=0)),d.from=c.from,d.to=c.to,d.mode=e,c.effect("size",d,b.duration,b.callback),c.dequeue()})},a.effects.size=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right","width","height","overflow","opacity"],e=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],g=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],i=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],j=a.effects.setMode(c,b.options.mode||"effect"),k=b.options.restore||!1,l=b.options.scale||"both",m=b.options.origin,n={height:c.height(),width:c.width()};c.from=b.options.from||n,c.to=b.options.to||n;if(m){var p=a.effects.getBaseline(m,n);c.from.top=(n.height-c.from.height)*p.y,c.from.left=(n.width-c.from.width)*p.x,c.to.top=(n.height-c.to.height)*p.y,c.to.left=(n.width-c.to.width)*p.x}var q={from:{y:c.from.height/n.height,x:c.from.width/n.width},to:{y:c.to.height/n.height,x:c.to.width/n.width}};if(l=="box"||l=="both")q.from.y!=q.to.y&&(d=d.concat(h),c.from=a.effects.setTransition(c,h,q.from.y,c.from),c.to=a.effects.setTransition(c,h,q.to.y,c.to)),q.from.x!=q.to.x&&(d=d.concat(i),c.from=a.effects.setTransition(c,i,q.from.x,c.from),c.to=a.effects.setTransition(c,i,q.to.x,c.to));(l=="content"||l=="both")&&q.from.y!=q.to.y&&(d=d.concat(g),c.from=a.effects.setTransition(c,g,q.from.y,c.from),c.to=a.effects.setTransition(c,g,q.to.y,c.to)),a.effects.save(c,k?d:e),c.show(),a.effects.createWrapper(c),c.css("overflow","hidden").css(c.from);if(l=="content"||l=="both")h=h.concat(["marginTop","marginBottom"]).concat(g),i=i.concat(["marginLeft","marginRight"]),f=d.concat(h).concat(i),c.find("*[width]").each(function(){child=a(this),k&&a.effects.save(child,f);var c={height:child.height(),width:child.width()};child.from={height:c.height*q.from.y,width:c.width*q.from.x},child.to={height:c.height*q.to.y,width:c.width*q.to.x},q.from.y!=q.to.y&&(child.from=a.effects.setTransition(child,h,q.from.y,child.from),child.to=a.effects.setTransition(child,h,q.to.y,child.to)),q.from.x!=q.to.x&&(child.from=a.effects.setTransition(child,i,q.from.x,child.from),child.to=a.effects.setTransition(child,i,q.to.x,child.to)),child.css(child.from),child.animate(child.to,b.duration,b.options.easing,function(){k&&a.effects.restore(child,f)})});c.animate(c.to,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){c.to.opacity===0&&c.css("opacity",c.from.opacity),j=="hide"&&c.hide(),a.effects.restore(c,k?d:e),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Shake 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Shake + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.shake=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"left",g=b.options.distance||20,h=b.options.times||3,i=b.duration||b.options.duration||140;a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",l={},m={},n={};l[j]=(k=="pos"?"-=":"+=")+g,m[j]=(k=="pos"?"+=":"-=")+g*2,n[j]=(k=="pos"?"-=":"+=")+g*2,c.animate(l,i,b.options.easing);for(var p=1;p<h;p++)c.animate(m,i,b.options.easing).animate(n,i,b.options.easing);c.animate(m,i,b.options.easing).animate(l,i/2,b.options.easing,function(){a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments)}),c.queue("fx",function(){c.dequeue()}),c.dequeue()})}})(jQuery);/* + * jQuery UI Effects Slide 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Slide + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.slide=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"show"),f=b.options.direction||"left";a.effects.save(c,d),c.show(),a.effects.createWrapper(c).css({overflow:"hidden"});var g=f=="up"||f=="down"?"top":"left",h=f=="up"||f=="left"?"pos":"neg",i=b.options.distance||(g=="top"?c.outerHeight({margin:!0}):c.outerWidth({margin:!0}));e=="show"&&c.css(g,h=="pos"?isNaN(i)?"-"+i:-i:i);var j={};j[g]=(e=="show"?h=="pos"?"+=":"-=":h=="pos"?"-=":"+=")+i,c.animate(j,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);/* + * jQuery UI Effects Transfer 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Transfer + * + * Depends: + * jquery.effects.core.js + */(function(a,b){a.effects.transfer=function(b){return this.queue(function(){var c=a(this),d=a(b.options.to),e=d.offset(),f={top:e.top,left:e.left,height:d.innerHeight(),width:d.innerWidth()},g=c.offset(),h=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);
\ No newline at end of file diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/init-db.sh b/storage/mroonga/vendor/groonga/examples/dictionary/init-db.sh new file mode 100755 index 00000000000..351d90e7b30 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/init-db.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +if [ 1 != $# ]; then + echo "usage: $0 db_path" + exit 1 +fi + +if groonga-suggest-create-dataset $1 dictionary > /dev/null; then + echo "db initialized." +fi diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am new file mode 100644 index 00000000000..70b4a5bc010 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/Makefile.am @@ -0,0 +1,3 @@ +jmdictdir = $(examples_dictionarydir)/jmdict +dist_jmdict_SCRIPTS = \ + jmdict.rb diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb new file mode 100755 index 00000000000..bf8926783cb --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/jmdict/jmdict.rb @@ -0,0 +1,42 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- + +require 'rexml/document' +require 'rexml/parsers/streamparser' +require 'rexml/parsers/baseparser' +require 'rexml/streamlistener' + +#REXML::Document.new(STDIN) + +class MyListener + include REXML::StreamListener + def tag_start(name, attrs) + # p name, attrs + case name + when 'entry' + @n = 0 + end + end + def tag_end name + # p "tag_end: #{x}" + case name + when 'sense' + @n += 1 + when 'entry' + @n_ents += 1 + puts "#{@ent}:#{@n}" if (@n > 8) + when 'ent_seq' + @ent = @text + end + end + + def text(text) + @text = text + end + + def xmldecl(version, encoding, standalone) + @n_ents = 0 + end +end + +REXML::Parsers::StreamParser.new(STDIN, MyListener.new).parse diff --git a/storage/mroonga/vendor/groonga/examples/dictionary/readme.txt b/storage/mroonga/vendor/groonga/examples/dictionary/readme.txt new file mode 100644 index 00000000000..555706e0061 --- /dev/null +++ b/storage/mroonga/vendor/groonga/examples/dictionary/readme.txt @@ -0,0 +1,71 @@ +.. highlightlang:: none + +辞書検索ツール +============== + +名前 +---- + +groonga辞書検索ツール + +説明 +---- + +様々な商用・非商用の辞書ファイルをインポートしてgroongaで検索できるようにします。 + +対応している辞書 +++++++++++++++++ + +現状では下記の辞書に対応しています。 + +* EDICT + +EDICTは、Monash大学Jim Breen教授が提供している和英辞書です。下記から入手できます。 + +http://ftp.monash.edu.au/pub/nihongo/edict.gz + +* GENE95 + +GENE95は、Kurumiさん(NiftyID: GGD00145)が作成された英和辞書です。下記から入手できます。 + +http://www.namazu.org/~tsuchiya/sdic/data/gene95.tar.gz + +* 英辞郎 + +英辞郎は、EDPという団体によって編纂されている英和・和英辞書です。 + +http://www.eijiro.jp/ + +書店やオンラインショップなどで購入できます。 + +データベースの初期化 +++++++++++++++++++++ + +本ディレクトリで下記のように実行し、辞書データを格納するデータベースファイルを下記のようにして初期化します。 + + ./init-db.sh データベースパス名 + +このようにして作成したデータベースについて、様々な辞書のデータをインポートすることができます。 + +インポートの方法 +++++++++++++++++ + +* EDICT + +edictディレクトリ配下で以下のように実行します。 edict.gzは自動でダウンロードします。 + + ./edict-import.sh データベースパス名 + +* GENE95 + +gene95ディレクトリ配下で下記のように実行します。 gene95.tar.gzは自動でダウンロードします。 + + ./gene-import.sh データベースパス名 + +* 英辞郎 + +英辞郎に付属のPDICツールを用いてCSVファイル形式に辞書をエクスポートします。(このとき「登録項目」ですべての項目を出力するようにします) eijiroディレクトリ配下で下記のように実行します。 + + ./eijiro-import.sh データベースパス名 出力したCSVファイルのパス名 + +(英辞郎第四版で動作を確認しています) diff --git a/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in b/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in index 22a90d82430..380495bb391 100644 --- a/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in +++ b/storage/mroonga/vendor/groonga/groonga-httpd-conf.sh.in @@ -6,13 +6,15 @@ sysconfdir="@sysconfdir@" pkgsysconfdir="@pkgsysconfdir@" localstatedir="@localstatedir@" +EXEEXT="@EXEEXT@" + SED="@SED@" export GROONGA_HTTPD_MODULE_PATH="@abs_top_srcdir@/src/httpd/nginx-module" export GROONGA_HTTPD_IN_TREE_INCLUDE_PATH="@abs_top_srcdir@/include" export GROONGA_HTTPD_IN_TREE_LINK_PATH="@abs_top_builddir@/lib/.libs" export GROONGA_HTTPD_PREFIX="${pkgsysconfdir}/httpd" -export GROONGA_HTTPD_BIN_PATH="${sbindir}/groonga-httpd" +export GROONGA_HTTPD_BIN_PATH="${sbindir}/groonga-httpd${EXEEXT}" export GROONGA_HTTPD_CONF_PATH="${pkgsysconfdir}/httpd/groonga-httpd.conf" export GROONGA_HTTPD_ERROR_LOG_PATH="${localstatedir}/log/groonga/httpd/error.log" export GROONGA_HTTPD_HTTP_LOG_PATH="${localstatedir}/log/groonga/httpd/access.log" diff --git a/storage/mroonga/vendor/groonga/include/CMakeLists.txt b/storage/mroonga/vendor/groonga/include/CMakeLists.txt index 96e22474cbf..7594c6e6c66 100644 --- a/storage/mroonga/vendor/groonga/include/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/include/CMakeLists.txt @@ -13,8 +13,6 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -if(NOT MRN_GROONGA_BUNDLED) - install(FILES groonga.h DESTINATION "${GRN_INCLUDE_DIR}") - install(DIRECTORY groonga DESTINATION "${GRN_INCLUDE_DIR}" - FILES_MATCHING PATTERN "*.h") -endif() +install(FILES groonga.h DESTINATION "${GRN_INCLUDE_DIR}") +install(DIRECTORY groonga DESTINATION "${GRN_INCLUDE_DIR}" + FILES_MATCHING PATTERN "*.h") diff --git a/storage/mroonga/vendor/groonga/include/groonga.h b/storage/mroonga/vendor/groonga/include/groonga.h index d1cf1e24a56..96384287270 100644 --- a/storage/mroonga/vendor/groonga/include/groonga.h +++ b/storage/mroonga/vendor/groonga/include/groonga.h @@ -1,5 +1,5 @@ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2014-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -18,2089 +18,12 @@ #ifndef GROONGA_H #define GROONGA_H -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdarg.h> - -#ifndef GRN_API -#if defined(_WIN32) || defined(_WIN64) -#define GRN_API __declspec(dllimport) -#else -#define GRN_API -#endif /* defined(_WIN32) || defined(_WIN64) */ -#endif /* GRN_API */ - -typedef unsigned int grn_id; -typedef unsigned char grn_bool; - -#define GRN_ID_NIL (0x00) -#define GRN_ID_MAX (0x3fffffff) - -#define GRN_TRUE (1) -#define GRN_FALSE (0) - -typedef enum { - GRN_SUCCESS = 0, - GRN_END_OF_DATA = 1, - GRN_UNKNOWN_ERROR = -1, - GRN_OPERATION_NOT_PERMITTED = -2, - GRN_NO_SUCH_FILE_OR_DIRECTORY = -3, - GRN_NO_SUCH_PROCESS = -4, - GRN_INTERRUPTED_FUNCTION_CALL = -5, - GRN_INPUT_OUTPUT_ERROR = -6, - GRN_NO_SUCH_DEVICE_OR_ADDRESS = -7, - GRN_ARG_LIST_TOO_LONG = -8, - GRN_EXEC_FORMAT_ERROR = -9, - GRN_BAD_FILE_DESCRIPTOR = -10, - GRN_NO_CHILD_PROCESSES = -11, - GRN_RESOURCE_TEMPORARILY_UNAVAILABLE = -12, - GRN_NOT_ENOUGH_SPACE = -13, - GRN_PERMISSION_DENIED = -14, - GRN_BAD_ADDRESS = -15, - GRN_RESOURCE_BUSY = -16, - GRN_FILE_EXISTS = -17, - GRN_IMPROPER_LINK = -18, - GRN_NO_SUCH_DEVICE = -19, - GRN_NOT_A_DIRECTORY = -20, - GRN_IS_A_DIRECTORY = -21, - GRN_INVALID_ARGUMENT = -22, - GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM = -23, - GRN_TOO_MANY_OPEN_FILES = -24, - GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION = -25, - GRN_FILE_TOO_LARGE = -26, - GRN_NO_SPACE_LEFT_ON_DEVICE = -27, - GRN_INVALID_SEEK = -28, - GRN_READ_ONLY_FILE_SYSTEM = -29, - GRN_TOO_MANY_LINKS = -30, - GRN_BROKEN_PIPE = -31, - GRN_DOMAIN_ERROR = -32, - GRN_RESULT_TOO_LARGE = -33, - GRN_RESOURCE_DEADLOCK_AVOIDED = -34, - GRN_NO_MEMORY_AVAILABLE = -35, - GRN_FILENAME_TOO_LONG = -36, - GRN_NO_LOCKS_AVAILABLE = -37, - GRN_FUNCTION_NOT_IMPLEMENTED = -38, - GRN_DIRECTORY_NOT_EMPTY = -39, - GRN_ILLEGAL_BYTE_SEQUENCE = -40, - GRN_SOCKET_NOT_INITIALIZED = -41, - GRN_OPERATION_WOULD_BLOCK = -42, - GRN_ADDRESS_IS_NOT_AVAILABLE = -43, - GRN_NETWORK_IS_DOWN = -44, - GRN_NO_BUFFER = -45, - GRN_SOCKET_IS_ALREADY_CONNECTED = -46, - GRN_SOCKET_IS_NOT_CONNECTED = -47, - GRN_SOCKET_IS_ALREADY_SHUTDOWNED = -48, - GRN_OPERATION_TIMEOUT = -49, - GRN_CONNECTION_REFUSED = -50, - GRN_RANGE_ERROR = -51, - GRN_TOKENIZER_ERROR = -52, - GRN_FILE_CORRUPT = -53, - GRN_INVALID_FORMAT = -54, - GRN_OBJECT_CORRUPT = -55, - GRN_TOO_MANY_SYMBOLIC_LINKS = -56, - GRN_NOT_SOCKET = -57, - GRN_OPERATION_NOT_SUPPORTED = -58, - GRN_ADDRESS_IS_IN_USE = -59, - GRN_ZLIB_ERROR = -60, - GRN_LZO_ERROR = -61, - GRN_STACK_OVER_FLOW = -62, - GRN_SYNTAX_ERROR = -63, - GRN_RETRY_MAX = -64, - GRN_INCOMPATIBLE_FILE_FORMAT = -65, - GRN_UPDATE_NOT_ALLOWED = -66, - GRN_TOO_SMALL_OFFSET = -67, - GRN_TOO_LARGE_OFFSET = -68, - GRN_TOO_SMALL_LIMIT = -69, - GRN_CAS_ERROR = -70, - GRN_UNSUPPORTED_COMMAND_VERSION = -71, - GRN_NORMALIZER_ERROR = -72, - GRN_TOKEN_FILTER_ERROR = -73, -} grn_rc; - -GRN_API grn_rc grn_init(void); -GRN_API grn_rc grn_fin(void); - -typedef enum { - GRN_ENC_DEFAULT = 0, - GRN_ENC_NONE, - GRN_ENC_EUC_JP, - GRN_ENC_UTF8, - GRN_ENC_SJIS, - GRN_ENC_LATIN1, - GRN_ENC_KOI8R -} grn_encoding; - -typedef enum { - GRN_COMMAND_VERSION_DEFAULT = 0, - GRN_COMMAND_VERSION_1, - GRN_COMMAND_VERSION_2 -} grn_command_version; - -#define GRN_COMMAND_VERSION_MIN GRN_COMMAND_VERSION_1 -#define GRN_COMMAND_VERSION_STABLE GRN_COMMAND_VERSION_1 -#define GRN_COMMAND_VERSION_MAX GRN_COMMAND_VERSION_2 - -typedef enum { - GRN_LOG_NONE = 0, - GRN_LOG_EMERG, - GRN_LOG_ALERT, - GRN_LOG_CRIT, - GRN_LOG_ERROR, - GRN_LOG_WARNING, - GRN_LOG_NOTICE, - GRN_LOG_INFO, - GRN_LOG_DEBUG, - GRN_LOG_DUMP -} grn_log_level; - -/* query log flags */ -#define GRN_QUERY_LOG_NONE (0x00) -#define GRN_QUERY_LOG_COMMAND (0x01<<0) -#define GRN_QUERY_LOG_RESULT_CODE (0x01<<1) -#define GRN_QUERY_LOG_DESTINATION (0x01<<2) -#define GRN_QUERY_LOG_CACHE (0x01<<3) -#define GRN_QUERY_LOG_SIZE (0x01<<4) -#define GRN_QUERY_LOG_SCORE (0x01<<5) -#define GRN_QUERY_LOG_ALL\ - (GRN_QUERY_LOG_COMMAND |\ - GRN_QUERY_LOG_RESULT_CODE |\ - GRN_QUERY_LOG_DESTINATION |\ - GRN_QUERY_LOG_CACHE |\ - GRN_QUERY_LOG_SIZE |\ - GRN_QUERY_LOG_SCORE) -#define GRN_QUERY_LOG_DEFAULT GRN_QUERY_LOG_ALL - -typedef enum { - GRN_CONTENT_NONE = 0, - GRN_CONTENT_TSV, - GRN_CONTENT_JSON, - GRN_CONTENT_XML, - GRN_CONTENT_MSGPACK -} grn_content_type; - -typedef struct _grn_obj grn_obj; -typedef struct _grn_ctx grn_ctx; - -#define GRN_CTX_MSGSIZE (0x80) -#define GRN_CTX_FIN (0xff) - -typedef union { - int int_value; - grn_id id; - void *ptr; -} grn_user_data; - -typedef grn_obj *grn_proc_func(grn_ctx *ctx, int nargs, grn_obj **args, - grn_user_data *user_data); - -struct _grn_ctx { - grn_rc rc; - int flags; - grn_encoding encoding; - unsigned char ntrace; - unsigned char errlvl; - unsigned char stat; - unsigned int seqno; - unsigned int subno; - unsigned int seqno2; - unsigned int errline; - grn_user_data user_data; - grn_ctx *prev; - grn_ctx *next; - const char *errfile; - const char *errfunc; - struct _grn_ctx_impl *impl; - void *trace[16]; - char errbuf[GRN_CTX_MSGSIZE]; -}; - -#define GRN_CTX_USER_DATA(ctx) (&((ctx)->user_data)) - -/* Deprecated since 4.0.3. Don't use it. */ -#define GRN_CTX_USE_QL (0x03) -/* Deprecated since 4.0.3. Don't use it. */ -#define GRN_CTX_BATCH_MODE (0x04) -#define GRN_CTX_PER_DB (0x08) - -GRN_API grn_rc grn_ctx_init(grn_ctx *ctx, int flags); -GRN_API grn_rc grn_ctx_fin(grn_ctx *ctx); -GRN_API grn_ctx *grn_ctx_open(int flags); -GRN_API grn_rc grn_ctx_close(grn_ctx *ctx); -GRN_API grn_rc grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *func); - -GRN_API grn_encoding grn_get_default_encoding(void); -GRN_API grn_rc grn_set_default_encoding(grn_encoding encoding); - -#define GRN_CTX_GET_ENCODING(ctx) ((ctx)->encoding) -#define GRN_CTX_SET_ENCODING(ctx,enc) \ - ((ctx)->encoding = (enc == GRN_ENC_DEFAULT) ? grn_get_default_encoding() : enc) - -GRN_API const char *grn_get_version(void); -GRN_API const char *grn_get_package(void); - -GRN_API grn_command_version grn_get_default_command_version(void); -GRN_API grn_rc grn_set_default_command_version(grn_command_version version); -GRN_API grn_command_version grn_ctx_get_command_version(grn_ctx *ctx); -GRN_API grn_rc grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version); -GRN_API long long int grn_ctx_get_match_escalation_threshold(grn_ctx *ctx); -GRN_API grn_rc grn_ctx_set_match_escalation_threshold(grn_ctx *ctx, long long int threshold); -GRN_API long long int grn_get_default_match_escalation_threshold(void); -GRN_API grn_rc grn_set_default_match_escalation_threshold(long long int threshold); - -GRN_API int grn_get_lock_timeout(void); -GRN_API grn_rc grn_set_lock_timeout(int timeout); - -/* cache */ -#define GRN_CACHE_DEFAULT_MAX_N_ENTRIES 100 -typedef struct _grn_cache grn_cache; - -GRN_API grn_cache *grn_cache_open(grn_ctx *ctx); -GRN_API grn_rc grn_cache_close(grn_ctx *ctx, grn_cache *cache); - -GRN_API grn_rc grn_cache_current_set(grn_ctx *ctx, grn_cache *cache); -GRN_API grn_cache *grn_cache_current_get(grn_ctx *ctx); - -GRN_API grn_rc grn_cache_set_max_n_entries(grn_ctx *ctx, - grn_cache *cache, - unsigned int n); -GRN_API unsigned int grn_cache_get_max_n_entries(grn_ctx *ctx, - grn_cache *cache); - -/* grn_encoding */ - -GRN_API const char *grn_encoding_to_string(grn_encoding encoding); -GRN_API grn_encoding grn_encoding_parse(const char *name); - -/* obj */ - -typedef unsigned short int grn_obj_flags; - -#define GRN_OBJ_TABLE_TYPE_MASK (0x07) -#define GRN_OBJ_TABLE_HASH_KEY (0x00) -#define GRN_OBJ_TABLE_PAT_KEY (0x01) -#define GRN_OBJ_TABLE_DAT_KEY (0x02) -#define GRN_OBJ_TABLE_NO_KEY (0x03) - -#define GRN_OBJ_KEY_MASK (0x07<<3) -#define GRN_OBJ_KEY_UINT (0x00<<3) -#define GRN_OBJ_KEY_INT (0x01<<3) -#define GRN_OBJ_KEY_FLOAT (0x02<<3) -#define GRN_OBJ_KEY_GEO_POINT (0x03<<3) - -#define GRN_OBJ_KEY_WITH_SIS (0x01<<6) -#define GRN_OBJ_KEY_NORMALIZE (0x01<<7) - -#define GRN_OBJ_COLUMN_TYPE_MASK (0x07) -#define GRN_OBJ_COLUMN_SCALAR (0x00) -#define GRN_OBJ_COLUMN_VECTOR (0x01) -#define GRN_OBJ_COLUMN_INDEX (0x02) - -#define GRN_OBJ_COMPRESS_MASK (0x07<<4) -#define GRN_OBJ_COMPRESS_NONE (0x00<<4) -#define GRN_OBJ_COMPRESS_ZLIB (0x01<<4) -#define GRN_OBJ_COMPRESS_LZO (0x02<<4) - -#define GRN_OBJ_WITH_SECTION (0x01<<7) -#define GRN_OBJ_WITH_WEIGHT (0x01<<8) -#define GRN_OBJ_WITH_POSITION (0x01<<9) -#define GRN_OBJ_RING_BUFFER (0x01<<10) - -#define GRN_OBJ_UNIT_MASK (0x0f<<8) -#define GRN_OBJ_UNIT_DOCUMENT_NONE (0x00<<8) -#define GRN_OBJ_UNIT_DOCUMENT_SECTION (0x01<<8) -#define GRN_OBJ_UNIT_DOCUMENT_POSITION (0x02<<8) -#define GRN_OBJ_UNIT_SECTION_NONE (0x03<<8) -#define GRN_OBJ_UNIT_SECTION_POSITION (0x04<<8) -#define GRN_OBJ_UNIT_POSITION_NONE (0x05<<8) -#define GRN_OBJ_UNIT_USERDEF_DOCUMENT (0x06<<8) -#define GRN_OBJ_UNIT_USERDEF_SECTION (0x07<<8) -#define GRN_OBJ_UNIT_USERDEF_POSITION (0x08<<8) - -#define GRN_OBJ_NO_SUBREC (0x00<<13) -#define GRN_OBJ_WITH_SUBREC (0x01<<13) - -#define GRN_OBJ_KEY_VAR_SIZE (0x01<<14) - -#define GRN_OBJ_TEMPORARY (0x00<<15) -#define GRN_OBJ_PERSISTENT (0x01<<15) - -/* obj types */ - -#define GRN_VOID (0x00) -#define GRN_BULK (0x02) -#define GRN_PTR (0x03) -#define GRN_UVECTOR (0x04) /* vector of grn_id */ -#define GRN_PVECTOR (0x05) /* vector of grn_obj* */ -#define GRN_VECTOR (0x06) /* vector of arbitrary data */ -#define GRN_MSG (0x07) -#define GRN_QUERY (0x08) -#define GRN_ACCESSOR (0x09) -#define GRN_SNIP (0x0b) -#define GRN_PATSNIP (0x0c) -#define GRN_STRING (0x0d) -#define GRN_CURSOR_TABLE_HASH_KEY (0x10) -#define GRN_CURSOR_TABLE_PAT_KEY (0x11) -#define GRN_CURSOR_TABLE_DAT_KEY (0x12) -#define GRN_CURSOR_TABLE_NO_KEY (0x13) -#define GRN_CURSOR_COLUMN_INDEX (0x18) -#define GRN_CURSOR_COLUMN_GEO_INDEX (0x1a) -#define GRN_TYPE (0x20) -#define GRN_PROC (0x21) -#define GRN_EXPR (0x22) -#define GRN_TABLE_HASH_KEY (0x30) -#define GRN_TABLE_PAT_KEY (0x31) -#define GRN_TABLE_DAT_KEY (0x32) -#define GRN_TABLE_NO_KEY (0x33) -#define GRN_DB (0x37) -#define GRN_COLUMN_FIX_SIZE (0x40) -#define GRN_COLUMN_VAR_SIZE (0x41) -#define GRN_COLUMN_INDEX (0x48) - -typedef struct _grn_section grn_section; -typedef struct _grn_obj_header grn_obj_header; - -struct _grn_section { - unsigned int offset; - unsigned int length; - unsigned int weight; - grn_id domain; -}; - -struct _grn_obj_header { - unsigned char type; - unsigned char impl_flags; - grn_obj_flags flags; - grn_id domain; -}; - -struct _grn_obj { - grn_obj_header header; - union { - struct { - char *head; - char *curr; - char *tail; - } b; - struct { - grn_obj *body; - grn_section *sections; - int n_sections; - } v; - } u; -}; - -#define GRN_OBJ_REFER (0x01<<0) -#define GRN_OBJ_OUTPLACE (0x01<<1) - -#define GRN_OBJ_INIT(obj,obj_type,obj_flags,obj_domain) do { \ - (obj)->header.type = (obj_type);\ - (obj)->header.impl_flags = (obj_flags);\ - (obj)->header.flags = 0;\ - (obj)->header.domain = (obj_domain);\ - (obj)->u.b.head = NULL;\ - (obj)->u.b.curr = NULL;\ - (obj)->u.b.tail = NULL;\ -} while (0) - -#define GRN_OBJ_FIN(ctx,obj) (grn_obj_close((ctx), (obj))) - -typedef struct _grn_db_create_optarg grn_db_create_optarg; - -struct _grn_db_create_optarg { - char **builtin_type_names; - int n_builtin_type_names; -}; - -GRN_API grn_obj *grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg); - -#define GRN_DB_OPEN_OR_CREATE(ctx,path,optarg,db) \ - (((db) = grn_db_open((ctx), (path))) || (db = grn_db_create((ctx), (path), (optarg)))) - -GRN_API grn_obj *grn_db_open(grn_ctx *ctx, const char *path); -GRN_API void grn_db_touch(grn_ctx *ctx, grn_obj *db); - -GRN_API grn_rc grn_ctx_use(grn_ctx *ctx, grn_obj *db); -GRN_API grn_obj *grn_ctx_db(grn_ctx *ctx); -GRN_API grn_obj *grn_ctx_get(grn_ctx *ctx, const char *name, int name_size); - -typedef enum { - GRN_DB_VOID = 0, - GRN_DB_DB, - GRN_DB_OBJECT, - GRN_DB_BOOL, - GRN_DB_INT8, - GRN_DB_UINT8, - GRN_DB_INT16, - GRN_DB_UINT16, - GRN_DB_INT32, - GRN_DB_UINT32, - GRN_DB_INT64, - GRN_DB_UINT64, - GRN_DB_FLOAT, - GRN_DB_TIME, - GRN_DB_SHORT_TEXT, - GRN_DB_TEXT, - GRN_DB_LONG_TEXT, - GRN_DB_TOKYO_GEO_POINT, - GRN_DB_WGS84_GEO_POINT -} grn_builtin_type; - -typedef enum { - GRN_DB_MECAB = 64, - GRN_DB_DELIMIT, - GRN_DB_UNIGRAM, - GRN_DB_BIGRAM, - GRN_DB_TRIGRAM -} grn_builtin_tokenizer; - -GRN_API grn_obj *grn_ctx_at(grn_ctx *ctx, grn_id id); - -GRN_API grn_obj *grn_type_create(grn_ctx *ctx, const char *name, unsigned int name_size, - grn_obj_flags flags, unsigned int size); - -GRN_API grn_rc grn_plugin_register(grn_ctx *ctx, const char *name); -GRN_API grn_rc grn_plugin_register_by_path(grn_ctx *ctx, const char *path); -GRN_API const char *grn_plugin_get_system_plugins_dir(void); -GRN_API const char *grn_plugin_get_suffix(void); - -typedef struct { - const char *name; - unsigned int name_size; - grn_obj value; -} grn_expr_var; - -typedef grn_rc (*grn_plugin_func)(grn_ctx *ctx); - -typedef enum { - GRN_PROC_INVALID = 0, - GRN_PROC_TOKENIZER, - GRN_PROC_COMMAND, - GRN_PROC_FUNCTION, - GRN_PROC_HOOK, - GRN_PROC_NORMALIZER, - GRN_PROC_TOKEN_FILTER -} grn_proc_type; - -GRN_API grn_obj *grn_proc_create(grn_ctx *ctx, - const char *name, int name_size, grn_proc_type type, - grn_proc_func *init, grn_proc_func *next, grn_proc_func *fin, - unsigned int nvars, grn_expr_var *vars); -GRN_API grn_obj *grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data, - grn_expr_var **vars, unsigned int *nvars, grn_obj **caller); -GRN_API grn_proc_type grn_proc_get_type(grn_ctx *ctx, grn_obj *proc); - -/*------------------------------------------------------------- - * API for table - */ - -#define GRN_TABLE_MAX_KEY_SIZE (0x1000) - -GRN_API grn_obj *grn_table_create(grn_ctx *ctx, - const char *name, unsigned int name_size, - const char *path, grn_obj_flags flags, - grn_obj *key_type, grn_obj *value_type); - -#define GRN_TABLE_OPEN_OR_CREATE(ctx,name,name_size,path,flags,key_type,value_type,table) \ - (((table) = grn_ctx_get((ctx), (name), (name_size))) ||\ - ((table) = grn_table_create((ctx), (name), (name_size), (path), (flags), (key_type), (value_type)))) - -/* TODO: int *added -> grn_bool *added */ -GRN_API grn_id grn_table_add(grn_ctx *ctx, grn_obj *table, - const void *key, unsigned int key_size, int *added); -GRN_API grn_id grn_table_get(grn_ctx *ctx, grn_obj *table, - const void *key, unsigned int key_size); -GRN_API grn_id grn_table_at(grn_ctx *ctx, grn_obj *table, grn_id id); -GRN_API grn_id grn_table_lcp_search(grn_ctx *ctx, grn_obj *table, - const void *key, unsigned int key_size); -GRN_API int grn_table_get_key(grn_ctx *ctx, grn_obj *table, - grn_id id, void *keybuf, int buf_size); -GRN_API grn_rc grn_table_delete(grn_ctx *ctx, grn_obj *table, - const void *key, unsigned int key_size); -GRN_API grn_rc grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id); -GRN_API grn_rc grn_table_update_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, - const void *dest_key, unsigned int dest_key_size); -GRN_API grn_rc grn_table_update(grn_ctx *ctx, grn_obj *table, - const void *src_key, unsigned int src_key_size, - const void *dest_key, unsigned int dest_key_size); -GRN_API grn_rc grn_table_truncate(grn_ctx *ctx, grn_obj *table); - -typedef grn_obj grn_table_cursor; - -#define GRN_CURSOR_ASCENDING (0x00<<0) -#define GRN_CURSOR_DESCENDING (0x01<<0) -#define GRN_CURSOR_GE (0x00<<1) -#define GRN_CURSOR_GT (0x01<<1) -#define GRN_CURSOR_LE (0x00<<2) -#define GRN_CURSOR_LT (0x01<<2) -#define GRN_CURSOR_BY_KEY (0x00<<3) -#define GRN_CURSOR_BY_ID (0x01<<3) -#define GRN_CURSOR_PREFIX (0x01<<4) -#define GRN_CURSOR_SIZE_BY_BIT (0x01<<5) -#define GRN_CURSOR_RK (0x01<<6) - -GRN_API grn_table_cursor *grn_table_cursor_open(grn_ctx *ctx, grn_obj *table, - const void *min, unsigned int min_size, - const void *max, unsigned int max_size, - int offset, int limit, int flags); -GRN_API grn_rc grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc); -GRN_API grn_id grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc); -GRN_API int grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key); -GRN_API int grn_table_cursor_get_value(grn_ctx *ctx, grn_table_cursor *tc, void **value); -GRN_API grn_rc grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc, - const void *value, int flags); -GRN_API grn_rc grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc); -GRN_API grn_obj *grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc); - -typedef struct { - grn_id rid; - grn_id sid; - unsigned int pos; - unsigned int tf; - unsigned int weight; - unsigned int rest; -} grn_posting; - -GRN_API grn_obj *grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc, grn_obj *index, - grn_id rid_min, grn_id rid_max, int flags); -GRN_API grn_posting *grn_index_cursor_next(grn_ctx *ctx, grn_obj *ic, grn_id *tid); - -#define GRN_TABLE_EACH(ctx,table,head,tail,id,key,key_size,value,block) do {\ - (ctx)->errlvl = GRN_LOG_NOTICE;\ - (ctx)->rc = GRN_SUCCESS;\ - if ((ctx)->seqno & 1) {\ - (ctx)->subno++;\ - } else {\ - (ctx)->seqno++;\ - }\ - if (table) {\ - switch ((table)->header.type) {\ - case GRN_TABLE_PAT_KEY :\ - GRN_PAT_EACH((ctx), (grn_pat *)(table), (id), (key), (key_size), (value), block);\ - break;\ - case GRN_TABLE_DAT_KEY :\ - GRN_DAT_EACH((ctx), (grn_dat *)(table), (id), (key), (key_size), block);\ - break;\ - case GRN_TABLE_HASH_KEY :\ - GRN_HASH_EACH((ctx), (grn_hash *)(table), (id), (key), (key_size), (value), block);\ - break;\ - case GRN_TABLE_NO_KEY :\ - GRN_ARRAY_EACH((ctx), (grn_array *)(table), (head), (tail), (id), (value), block);\ - break;\ - }\ - }\ - if ((ctx)->subno) {\ - (ctx)->subno--;\ - } else {\ - (ctx)->seqno++;\ - }\ -} while (0) - -typedef struct _grn_table_sort_key grn_table_sort_key; -typedef unsigned char grn_table_sort_flags; - -#define GRN_TABLE_SORT_ASC (0x00<<0) -#define GRN_TABLE_SORT_DESC (0x01<<0) - -struct _grn_table_sort_key { - grn_obj *key; - grn_table_sort_flags flags; - int offset; -}; - -GRN_API int grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, - grn_obj *result, grn_table_sort_key *keys, int n_keys); - -typedef struct _grn_table_group_result grn_table_group_result; -typedef unsigned int grn_table_group_flags; - -#define GRN_TABLE_GROUP_CALC_COUNT (0x01<<3) -#define GRN_TABLE_GROUP_CALC_MAX (0x01<<4) -#define GRN_TABLE_GROUP_CALC_MIN (0x01<<5) -#define GRN_TABLE_GROUP_CALC_SUM (0x01<<6) -#define GRN_TABLE_GROUP_CALC_AVG (0x01<<7) - -typedef enum { - GRN_OP_PUSH = 0, - GRN_OP_POP, - GRN_OP_NOP, - GRN_OP_CALL, - GRN_OP_INTERN, - GRN_OP_GET_REF, - GRN_OP_GET_VALUE, - GRN_OP_AND, - GRN_OP_AND_NOT, - /* Deprecated. Just for backward compatibility. */ -#define GRN_OP_BUT GRN_OP_AND_NOT - GRN_OP_OR, - GRN_OP_ASSIGN, - GRN_OP_STAR_ASSIGN, - GRN_OP_SLASH_ASSIGN, - GRN_OP_MOD_ASSIGN, - GRN_OP_PLUS_ASSIGN, - GRN_OP_MINUS_ASSIGN, - GRN_OP_SHIFTL_ASSIGN, - GRN_OP_SHIFTR_ASSIGN, - GRN_OP_SHIFTRR_ASSIGN, - GRN_OP_AND_ASSIGN, - GRN_OP_XOR_ASSIGN, - GRN_OP_OR_ASSIGN, - GRN_OP_JUMP, - GRN_OP_CJUMP, - GRN_OP_COMMA, - GRN_OP_BITWISE_OR, - GRN_OP_BITWISE_XOR, - GRN_OP_BITWISE_AND, - GRN_OP_BITWISE_NOT, - GRN_OP_EQUAL, - GRN_OP_NOT_EQUAL, - GRN_OP_LESS, - GRN_OP_GREATER, - GRN_OP_LESS_EQUAL, - GRN_OP_GREATER_EQUAL, - GRN_OP_IN, - GRN_OP_MATCH, - GRN_OP_NEAR, - GRN_OP_NEAR2, - GRN_OP_SIMILAR, - GRN_OP_TERM_EXTRACT, - GRN_OP_SHIFTL, - GRN_OP_SHIFTR, - GRN_OP_SHIFTRR, - GRN_OP_PLUS, - GRN_OP_MINUS, - GRN_OP_STAR, - GRN_OP_SLASH, - GRN_OP_MOD, - GRN_OP_DELETE, - GRN_OP_INCR, - GRN_OP_DECR, - GRN_OP_INCR_POST, - GRN_OP_DECR_POST, - GRN_OP_NOT, - GRN_OP_ADJUST, - GRN_OP_EXACT, - GRN_OP_LCP, - GRN_OP_PARTIAL, - GRN_OP_UNSPLIT, - GRN_OP_PREFIX, - GRN_OP_SUFFIX, - GRN_OP_GEO_DISTANCE1, - GRN_OP_GEO_DISTANCE2, - GRN_OP_GEO_DISTANCE3, - GRN_OP_GEO_DISTANCE4, - GRN_OP_GEO_WITHINP5, - GRN_OP_GEO_WITHINP6, - GRN_OP_GEO_WITHINP8, - GRN_OP_OBJ_SEARCH, - GRN_OP_EXPR_GET_VAR, - GRN_OP_TABLE_CREATE, - GRN_OP_TABLE_SELECT, - GRN_OP_TABLE_SORT, - GRN_OP_TABLE_GROUP, - GRN_OP_JSON_PUT, - GRN_OP_GET_MEMBER -} grn_operator; - -struct _grn_table_group_result { - grn_obj *table; - unsigned char key_begin; - unsigned char key_end; - int limit; - grn_table_group_flags flags; - grn_operator op; -}; - -GRN_API grn_rc grn_table_group(grn_ctx *ctx, grn_obj *table, - grn_table_sort_key *keys, int n_keys, - grn_table_group_result *results, int n_results); -GRN_API grn_rc grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, - grn_obj *res, grn_operator op); -GRN_API grn_rc grn_table_difference(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, - grn_obj *res1, grn_obj *res2); -GRN_API int grn_table_columns(grn_ctx *ctx, grn_obj *table, - const char *name, unsigned int name_size, - grn_obj *res); - -GRN_API grn_obj *grn_obj_column(grn_ctx *ctx, grn_obj *table, - const char *name, unsigned int name_size); - -GRN_API unsigned int grn_table_size(grn_ctx *ctx, grn_obj *table); - -/*------------------------------------------------------------- - * API for column - */ - -#define GRN_COLUMN_NAME_ID "_id" -#define GRN_COLUMN_NAME_ID_LEN (sizeof(GRN_COLUMN_NAME_ID) - 1) -#define GRN_COLUMN_NAME_KEY "_key" -#define GRN_COLUMN_NAME_KEY_LEN (sizeof(GRN_COLUMN_NAME_KEY) - 1) -#define GRN_COLUMN_NAME_VALUE "_value" -#define GRN_COLUMN_NAME_VALUE_LEN (sizeof(GRN_COLUMN_NAME_VALUE) - 1) -#define GRN_COLUMN_NAME_SCORE "_score" -#define GRN_COLUMN_NAME_SCORE_LEN (sizeof(GRN_COLUMN_NAME_SCORE) - 1) -#define GRN_COLUMN_NAME_NSUBRECS "_nsubrecs" -#define GRN_COLUMN_NAME_NSUBRECS_LEN (sizeof(GRN_COLUMN_NAME_NSUBRECS) - 1) - -GRN_API grn_obj *grn_column_create(grn_ctx *ctx, grn_obj *table, - const char *name, unsigned int name_size, - const char *path, grn_obj_flags flags, grn_obj *type); - -#define GRN_COLUMN_OPEN_OR_CREATE(ctx,table,name,name_size,path,flags,type,column) \ - (((column) = grn_obj_column((ctx), (table), (name), (name_size))) ||\ - ((column) = grn_column_create((ctx), (table), (name), (name_size), (path), (flags), (type)))) - -GRN_API grn_rc grn_column_index_update(grn_ctx *ctx, grn_obj *column, - grn_id id, unsigned int section, - grn_obj *oldvalue, grn_obj *newvalue); -GRN_API grn_obj *grn_column_table(grn_ctx *ctx, grn_obj *column); - -/*------------------------------------------------------------- - * API for db, table and/or column - */ - -typedef enum { - GRN_INFO_ENCODING = 0, - GRN_INFO_SOURCE, - GRN_INFO_DEFAULT_TOKENIZER, - GRN_INFO_ELEMENT_SIZE, - GRN_INFO_CURR_MAX, - GRN_INFO_MAX_ELEMENT_SIZE, - GRN_INFO_SEG_SIZE, - GRN_INFO_CHUNK_SIZE, - GRN_INFO_MAX_SECTION, - GRN_INFO_HOOK_LOCAL_DATA, - GRN_INFO_ELEMENT_A, - GRN_INFO_ELEMENT_CHUNK, - GRN_INFO_ELEMENT_CHUNK_SIZE, - GRN_INFO_ELEMENT_BUFFER_FREE, - GRN_INFO_ELEMENT_NTERMS, - GRN_INFO_ELEMENT_NTERMS_VOID, - GRN_INFO_ELEMENT_SIZE_IN_CHUNK, - GRN_INFO_ELEMENT_POS_IN_CHUNK, - GRN_INFO_ELEMENT_SIZE_IN_BUFFER, - GRN_INFO_ELEMENT_POS_IN_BUFFER, - GRN_INFO_ELEMENT_ESTIMATE_SIZE, - GRN_INFO_NGRAM_UNIT_SIZE, - /* - GRN_INFO_VERSION, - GRN_INFO_CONFIGURE_OPTIONS, - GRN_INFO_CONFIG_PATH, - */ - GRN_INFO_PARTIAL_MATCH_THRESHOLD, - GRN_INFO_II_SPLIT_THRESHOLD, - GRN_INFO_SUPPORT_ZLIB, - GRN_INFO_SUPPORT_LZO, - GRN_INFO_NORMALIZER, - GRN_INFO_TOKEN_FILTERS -} grn_info_type; - -GRN_API grn_obj *grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valuebuf); -GRN_API grn_rc grn_obj_set_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *value); -GRN_API grn_obj *grn_obj_get_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, - grn_info_type type, grn_obj *value); -GRN_API grn_rc grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, - grn_info_type type, grn_obj *value); - -GRN_API grn_bool grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj); - -GRN_API grn_obj *grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value); -GRN_API int grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values); - -#define GRN_COLUMN_EACH(ctx,column,id,value,block) do {\ - int _n;\ - grn_id id = 1;\ - while ((_n = grn_obj_get_values(ctx, column, id, (void **)&value)) > 0) {\ - for (; _n; _n--, id++, value++) {\ - block\ - }\ - }\ -} while (0) - -#define GRN_OBJ_SET_MASK (0x07) -#define GRN_OBJ_SET (0x01) -#define GRN_OBJ_INCR (0x02) -#define GRN_OBJ_DECR (0x03) -#define GRN_OBJ_APPEND (0x04) -#define GRN_OBJ_PREPEND (0x05) -#define GRN_OBJ_GET (0x01<<4) -#define GRN_OBJ_COMPARE (0x01<<5) -#define GRN_OBJ_LOCK (0x01<<6) -#define GRN_OBJ_UNLOCK (0x01<<7) - -GRN_API grn_rc grn_obj_set_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags); -GRN_API grn_rc grn_obj_remove(grn_ctx *ctx, grn_obj *obj); -GRN_API grn_rc grn_obj_rename(grn_ctx *ctx, grn_obj *obj, - const char *name, unsigned int name_size); -GRN_API grn_rc grn_table_rename(grn_ctx *ctx, grn_obj *table, - const char *name, unsigned int name_size); - -GRN_API grn_rc grn_column_rename(grn_ctx *ctx, grn_obj *column, - const char *name, unsigned int name_size); - -GRN_API grn_rc grn_obj_close(grn_ctx *ctx, grn_obj *obj); -GRN_API grn_rc grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags); -GRN_API void grn_obj_unlink(grn_ctx *ctx, grn_obj *obj); - -GRN_API grn_user_data *grn_obj_user_data(grn_ctx *ctx, grn_obj *obj); - -GRN_API grn_rc grn_obj_set_finalizer(grn_ctx *ctx, grn_obj *obj, grn_proc_func *func); - -GRN_API const char *grn_obj_path(grn_ctx *ctx, grn_obj *obj); -GRN_API int grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size); - -GRN_API int grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size); - -GRN_API grn_id grn_obj_get_range(grn_ctx *ctx, grn_obj *obj); - -#define GRN_OBJ_GET_DOMAIN(obj) \ - ((obj)->header.type == GRN_TABLE_NO_KEY ? GRN_ID_NIL : (obj)->header.domain) - -GRN_API int grn_obj_expire(grn_ctx *ctx, grn_obj *obj, int threshold); -GRN_API int grn_obj_check(grn_ctx *ctx, grn_obj *obj); -GRN_API grn_rc grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout); -GRN_API grn_rc grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id); -GRN_API grn_rc grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj); -GRN_API unsigned int grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj); -GRN_API int grn_obj_defrag(grn_ctx *ctx, grn_obj *obj, int threshold); - -GRN_API grn_obj *grn_obj_db(grn_ctx *ctx, grn_obj *obj); - -GRN_API grn_id grn_obj_id(grn_ctx *ctx, grn_obj *obj); - -typedef struct _grn_search_optarg grn_search_optarg; - -struct _grn_search_optarg { - grn_operator mode; - int similarity_threshold; - int max_interval; - int *weight_vector; - int vector_size; - grn_obj *proc; - int max_size; -}; - -GRN_API grn_rc grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query, - grn_obj *res, grn_operator op, grn_search_optarg *optarg); - -typedef grn_rc grn_selector_func(grn_ctx *ctx, grn_obj *table, grn_obj *index, - int nargs, grn_obj **args, - grn_obj *res, grn_operator op); - -GRN_API grn_rc grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, - grn_selector_func selector); - -/*------------------------------------------------------------- - * grn_vector -*/ - -GRN_API unsigned int grn_vector_size(grn_ctx *ctx, grn_obj *vector); - -GRN_API grn_rc grn_vector_add_element(grn_ctx *ctx, grn_obj *vector, - const char *str, unsigned int str_len, - unsigned int weight, grn_id domain); - -GRN_API unsigned int grn_vector_get_element(grn_ctx *ctx, grn_obj *vector, - unsigned int offset, const char **str, - unsigned int *weight, grn_id *domain); - -/*------------------------------------------------------------- - * grn_uvector -*/ - -GRN_API unsigned int grn_uvector_size(grn_ctx *ctx, grn_obj *uvector); - -GRN_API grn_rc grn_uvector_add_element(grn_ctx *ctx, grn_obj *vector, - grn_id id, unsigned int weight); - -GRN_API grn_id grn_uvector_get_element(grn_ctx *ctx, grn_obj *uvector, - unsigned int offset, - unsigned int *weight); - -/*------------------------------------------------------------- - * API for hook - */ - -GRN_API int grn_proc_call_next(grn_ctx *ctx, grn_obj *exec_info, grn_obj *in, grn_obj *out); -GRN_API void *grn_proc_get_ctx_local_data(grn_ctx *ctx, grn_obj *exec_info); -GRN_API void *grn_proc_get_hook_local_data(grn_ctx *ctx, grn_obj *exec_info); - -typedef enum { - GRN_HOOK_SET = 0, - GRN_HOOK_GET, - GRN_HOOK_INSERT, - GRN_HOOK_DELETE, - GRN_HOOK_SELECT -} grn_hook_entry; - -GRN_API grn_rc grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, - int offset, grn_obj *proc, grn_obj *data); -GRN_API int grn_obj_get_nhooks(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry); -GRN_API grn_obj *grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, - int offset, grn_obj *data); -GRN_API grn_rc grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset); - -GRN_API grn_obj *grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain); - -GRN_API int grn_column_index(grn_ctx *ctx, grn_obj *column, grn_operator op, - grn_obj **indexbuf, int buf_size, int *section); - -GRN_API grn_rc grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep); -GRN_API grn_rc grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer); - -/* geo */ - -typedef struct { - int latitude; - int longitude; -} grn_geo_point; - -GRN_API grn_rc grn_geo_select_in_rectangle(grn_ctx *ctx, - grn_obj *index, - grn_obj *top_left_point, - grn_obj *bottom_right_point, - grn_obj *res, - grn_operator op); -GRN_API int grn_geo_estimate_in_rectangle(grn_ctx *ctx, - grn_obj *index, - grn_obj *top_left_point, - grn_obj *bottom_right_point); -GRN_API grn_obj *grn_geo_cursor_open_in_rectangle(grn_ctx *ctx, - grn_obj *index, - grn_obj *top_left_point, - grn_obj *bottom_right_point, - int offset, - int limit); -GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor); - - -/* query & snippet */ - -#ifndef GRN_QUERY_AND -#define GRN_QUERY_AND '+' -#endif /* GRN_QUERY_AND */ -#ifndef GRN_QUERY_AND_NOT -# ifdef GRN_QUERY_BUT - /* Deprecated. Just for backward compatibility. */ -# define GRN_QUERY_AND_NOT GRN_QUERY_BUT -# else -# define GRN_QUERY_AND_NOT '-' -# endif /* GRN_QUERY_BUT */ -#endif /* GRN_QUERY_AND_NOT */ -#ifndef GRN_QUERY_ADJ_INC -#define GRN_QUERY_ADJ_INC '>' -#endif /* GRN_QUERY_ADJ_POS2 */ -#ifndef GRN_QUERY_ADJ_DEC -#define GRN_QUERY_ADJ_DEC '<' -#endif /* GRN_QUERY_ADJ_POS1 */ -#ifndef GRN_QUERY_ADJ_NEG -#define GRN_QUERY_ADJ_NEG '~' -#endif /* GRN_QUERY_ADJ_NEG */ -#ifndef GRN_QUERY_PREFIX -#define GRN_QUERY_PREFIX '*' -#endif /* GRN_QUERY_PREFIX */ -#ifndef GRN_QUERY_PARENL -#define GRN_QUERY_PARENL '(' -#endif /* GRN_QUERY_PARENL */ -#ifndef GRN_QUERY_PARENR -#define GRN_QUERY_PARENR ')' -#endif /* GRN_QUERY_PARENR */ -#ifndef GRN_QUERY_QUOTEL -#define GRN_QUERY_QUOTEL '"' -#endif /* GRN_QUERY_QUOTEL */ -#ifndef GRN_QUERY_QUOTER -#define GRN_QUERY_QUOTER '"' -#endif /* GRN_QUERY_QUOTER */ -#ifndef GRN_QUERY_ESCAPE -#define GRN_QUERY_ESCAPE '\\' -#endif /* GRN_QUERY_ESCAPE */ -#ifndef GRN_QUERY_COLUMN -#define GRN_QUERY_COLUMN ':' -#endif /* GRN_QUERY_COLUMN */ - -typedef struct _grn_snip_mapping grn_snip_mapping; - -struct _grn_snip_mapping { - void *dummy; -}; - -#define GRN_SNIP_NORMALIZE (0x01<<0) -#define GRN_SNIP_COPY_TAG (0x01<<1) -#define GRN_SNIP_SKIP_LEADING_SPACES (0x01<<2) - -#define GRN_SNIP_MAPPING_HTML_ESCAPE ((grn_snip_mapping *)-1) - -GRN_API grn_obj *grn_snip_open(grn_ctx *ctx, int flags, unsigned int width, - unsigned int max_results, - const char *defaultopentag, unsigned int defaultopentag_len, - const char *defaultclosetag, unsigned int defaultclosetag_len, - grn_snip_mapping *mapping); -GRN_API grn_rc grn_snip_add_cond(grn_ctx *ctx, grn_obj *snip, - const char *keyword, unsigned int keyword_len, - const char *opentag, unsigned int opentag_len, - const char *closetag, unsigned int closetag_len); -GRN_API grn_rc grn_snip_set_normalizer(grn_ctx *ctx, grn_obj *snip, - grn_obj *normalizer); -GRN_API grn_obj *grn_snip_get_normalizer(grn_ctx *ctx, grn_obj *snip); -GRN_API grn_rc grn_snip_exec(grn_ctx *ctx, grn_obj *snip, - const char *string, unsigned int string_len, - unsigned int *nresults, unsigned int *max_tagged_len); -GRN_API grn_rc grn_snip_get_result(grn_ctx *ctx, grn_obj *snip, const unsigned int index, - char *result, unsigned int *result_len); - -/* log */ - -#define GRN_LOG_TIME (0x01<<0) -#define GRN_LOG_TITLE (0x01<<1) -#define GRN_LOG_MESSAGE (0x01<<2) -#define GRN_LOG_LOCATION (0x01<<3) - -/* Deprecated since 2.1.2. Use grn_logger instead. */ -typedef struct _grn_logger_info grn_logger_info; - -/* Deprecated since 2.1.2. Use grn_logger instead. */ -struct _grn_logger_info { - grn_log_level max_level; - int flags; - void (*func)(int, const char *, const char *, const char *, const char *, void *); - void *func_arg; -}; - -/* Deprecated since 2.1.2. Use grn_logger_set() instead. */ -GRN_API grn_rc grn_logger_info_set(grn_ctx *ctx, const grn_logger_info *info); - -typedef struct _grn_logger grn_logger; - -struct _grn_logger { - grn_log_level max_level; - int flags; - void *user_data; - void (*log)(grn_ctx *ctx, grn_log_level level, - const char *timestamp, const char *title, const char *message, - const char *location, void *user_data); - void (*reopen)(grn_ctx *ctx, void *user_data); - void (*fin)(grn_ctx *ctx, void *user_data); -}; - -GRN_API grn_rc grn_logger_set(grn_ctx *ctx, const grn_logger *logger); - -GRN_API void grn_logger_set_max_level(grn_ctx *ctx, grn_log_level max_level); -GRN_API grn_log_level grn_logger_get_max_level(grn_ctx *ctx); - -#ifdef __GNUC__ -#define GRN_ATTRIBUTE_PRINTF(fmt_pos) \ - __attribute__ ((format(printf, fmt_pos, fmt_pos + 1))) -#else -#define GRN_ATTRIBUTE_PRINTF(fmt_pos) -#endif /* __GNUC__ */ - -GRN_API void grn_logger_put(grn_ctx *ctx, grn_log_level level, - const char *file, int line, const char *func, const char *fmt, ...) GRN_ATTRIBUTE_PRINTF(6); -GRN_API void grn_logger_reopen(grn_ctx *ctx); - -GRN_API grn_bool grn_logger_pass(grn_ctx *ctx, grn_log_level level); - -#ifndef GRN_LOG_DEFAULT_LEVEL -#define GRN_LOG_DEFAULT_LEVEL GRN_LOG_NOTICE -#endif /* GRN_LOG_DEFAULT_LEVEL */ - -GRN_API void grn_default_logger_set_max_level(grn_log_level level); -GRN_API grn_log_level grn_default_logger_get_max_level(void); -GRN_API void grn_default_logger_set_path(const char *path); -GRN_API const char *grn_default_logger_get_path(void); - -#define GRN_LOG(ctx,level,...) do {\ - if (grn_logger_pass(ctx, level)) {\ - grn_logger_put(ctx, (level), __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \ - }\ -} while (0) - -typedef struct _grn_query_logger grn_query_logger; - -struct _grn_query_logger { - unsigned int flags; - void *user_data; - void (*log)(grn_ctx *ctx, unsigned int flag, - const char *timestamp, const char *info, const char *message, - void *user_data); - void (*reopen)(grn_ctx *ctx, void *user_data); - void (*fin)(grn_ctx *ctx, void *user_data); -}; - -GRN_API grn_rc grn_query_logger_set(grn_ctx *ctx, const grn_query_logger *logger); - -GRN_API void grn_query_logger_put(grn_ctx *ctx, unsigned int flag, - const char *mark, - const char *format, ...) GRN_ATTRIBUTE_PRINTF(4); -GRN_API void grn_query_logger_reopen(grn_ctx *ctx); - -GRN_API grn_bool grn_query_logger_pass(grn_ctx *ctx, unsigned int flag); - -GRN_API void grn_default_query_logger_set_flags(unsigned int flags); -GRN_API unsigned int grn_default_query_logger_get_flags(void); -GRN_API void grn_default_query_logger_set_path(const char *path); -GRN_API const char *grn_default_query_logger_get_path(void); - -#define GRN_QUERY_LOG(ctx, flag, mark, format, ...) do {\ - if (grn_query_logger_pass(ctx, flag)) {\ - grn_query_logger_put(ctx, (flag), (mark), format, __VA_ARGS__);\ - }\ -} while (0) - -/* grn_bulk */ - -#define GRN_BULK_BUFSIZE (sizeof(grn_obj) - sizeof(grn_obj_header)) -/* This assumes that GRN_BULK_BUFSIZE is less than 32 (= 0x20). */ -#define GRN_BULK_BUFSIZE_MAX 0x1f -#define GRN_BULK_SIZE_IN_FLAGS(flags) ((flags) & GRN_BULK_BUFSIZE_MAX) -#define GRN_BULK_OUTP(bulk) ((bulk)->header.impl_flags & GRN_OBJ_OUTPLACE) -#define GRN_BULK_REWIND(bulk) do {\ - if ((bulk)->header.type == GRN_VECTOR) {\ - grn_obj *_body = (bulk)->u.v.body;\ - if (_body) {\ - if (GRN_BULK_OUTP(_body)) {\ - (_body)->u.b.curr = (_body)->u.b.head;\ - } else {\ - (_body)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\ - }\ - }\ - (bulk)->u.v.n_sections = 0;\ - } else {\ - if (GRN_BULK_OUTP(bulk)) {\ - (bulk)->u.b.curr = (bulk)->u.b.head;\ - } else {\ - (bulk)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\ - }\ - }\ -} while (0) -#define GRN_BULK_WSIZE(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.tail - (bulk)->u.b.head)\ - : GRN_BULK_BUFSIZE) -#define GRN_BULK_REST(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.tail - (bulk)->u.b.curr)\ - : GRN_BULK_BUFSIZE - (bulk)->header.flags) -#define GRN_BULK_VSIZE(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.curr - (bulk)->u.b.head)\ - : GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)) -#define GRN_BULK_EMPTYP(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.curr == (bulk)->u.b.head)\ - : !(GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))) -#define GRN_BULK_HEAD(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.head)\ - : (char *)&((bulk)->u.b.head)) -#define GRN_BULK_CURR(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.curr)\ - : (char *)&((bulk)->u.b.head) + GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)) -#define GRN_BULK_TAIL(bulk) \ - (GRN_BULK_OUTP(bulk)\ - ? ((bulk)->u.b.tail)\ - : (char *)&((bulk)[1])) - -GRN_API grn_rc grn_bulk_reinit(grn_ctx *ctx, grn_obj *bulk, unsigned int size); -GRN_API grn_rc grn_bulk_resize(grn_ctx *ctx, grn_obj *bulk, unsigned int newsize); -GRN_API grn_rc grn_bulk_write(grn_ctx *ctx, grn_obj *bulk, - const char *str, unsigned int len); -GRN_API grn_rc grn_bulk_write_from(grn_ctx *ctx, grn_obj *bulk, - const char *str, unsigned int from, unsigned int len); -GRN_API grn_rc grn_bulk_reserve(grn_ctx *ctx, grn_obj *bulk, unsigned int len); -GRN_API grn_rc grn_bulk_space(grn_ctx *ctx, grn_obj *bulk, unsigned int len); -GRN_API grn_rc grn_bulk_truncate(grn_ctx *ctx, grn_obj *bulk, unsigned int len); -GRN_API grn_rc grn_bulk_fin(grn_ctx *ctx, grn_obj *bulk); - -/* grn_text */ - -GRN_API grn_rc grn_text_itoa(grn_ctx *ctx, grn_obj *bulk, int i); -GRN_API grn_rc grn_text_itoa_padded(grn_ctx *ctx, grn_obj *bulk, int i, char ch, unsigned int len); -GRN_API grn_rc grn_text_lltoa(grn_ctx *ctx, grn_obj *bulk, long long int i); -GRN_API grn_rc grn_text_ftoa(grn_ctx *ctx, grn_obj *bulk, double d); -GRN_API grn_rc grn_text_itoh(grn_ctx *ctx, grn_obj *bulk, int i, unsigned int len); -GRN_API grn_rc grn_text_itob(grn_ctx *ctx, grn_obj *bulk, grn_id id); -GRN_API grn_rc grn_text_lltob32h(grn_ctx *ctx, grn_obj *bulk, long long int i); -GRN_API grn_rc grn_text_benc(grn_ctx *ctx, grn_obj *bulk, unsigned int v); -GRN_API grn_rc grn_text_esc(grn_ctx *ctx, grn_obj *bulk, const char *s, unsigned int len); -GRN_API grn_rc grn_text_urlenc(grn_ctx *ctx, grn_obj *buf, - const char *str, unsigned int len); -GRN_API const char *grn_text_urldec(grn_ctx *ctx, grn_obj *buf, - const char *s, const char *e, char d); -GRN_API grn_rc grn_text_escape_xml(grn_ctx *ctx, grn_obj *buf, - const char *s, unsigned int len); -GRN_API grn_rc grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec); -GRN_API grn_rc grn_text_printf(grn_ctx *ctx, grn_obj *bulk, - const char *format, ...) GRN_ATTRIBUTE_PRINTF(3); -GRN_API grn_rc grn_text_vprintf(grn_ctx *ctx, grn_obj *bulk, - const char *format, va_list args); - -typedef struct _grn_obj_format grn_obj_format; - -#define GRN_OBJ_FORMAT_WITH_COLUMN_NAMES (0x01<<0) -#define GRN_OBJ_FORMAT_AS_ARRAY (0x01<<3) -/* Deprecated since 4.0.1. It will be removed at 5.0.0. - Use GRN_OBJ_FORMAT_AS_ARRAY instead.*/ -#define GRN_OBJ_FORMAT_ASARRAY GRN_OBJ_FORMAT_AS_ARRAY -#define GRN_OBJ_FORMAT_WITH_WEIGHT (0x01<<4) - -struct _grn_obj_format { - grn_obj columns; - const void *min; - const void *max; - unsigned int min_size; - unsigned int max_size; - int nhits; - int offset; - int limit; - int hits_offset; - int flags; - grn_obj *expression; -}; - -#define GRN_OBJ_FORMAT_INIT(format,format_nhits,format_offset,format_limit,format_hits_offset) do { \ - GRN_PTR_INIT(&(format)->columns, GRN_OBJ_VECTOR, GRN_ID_NIL);\ - (format)->nhits = (format_nhits);\ - (format)->offset = (format_offset);\ - (format)->limit = (format_limit);\ - (format)->hits_offset = (format_hits_offset);\ - (format)->flags = 0;\ - (format)->expression = NULL;\ -} while (0) - -#define GRN_OBJ_FORMAT_FIN(ctx,format) do {\ - int ncolumns = GRN_BULK_VSIZE(&(format)->columns) / sizeof(grn_obj *);\ - grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&(format)->columns);\ - while (ncolumns--) { grn_obj_unlink((ctx), *columns++); }\ - GRN_OBJ_FIN((ctx), &(format)->columns);\ - if ((format)->expression) { GRN_OBJ_FIN((ctx), (format)->expression); } \ -} while (0) - -GRN_API void grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, - grn_obj *obj, grn_obj_format *format); -GRN_API void grn_output_envelope(grn_ctx *ctx, grn_rc rc, - grn_obj *head, grn_obj *body, grn_obj *foot, - const char *file, int line); - -GRN_API void grn_ctx_output_array_open(grn_ctx *ctx, - const char *name, int nelements); -GRN_API void grn_ctx_output_array_close(grn_ctx *ctx); -GRN_API void grn_ctx_output_map_open(grn_ctx *ctx, - const char *name, int nelements); -GRN_API void grn_ctx_output_map_close(grn_ctx *ctx); -GRN_API void grn_ctx_output_int32(grn_ctx *ctx, int value); -GRN_API void grn_ctx_output_int64(grn_ctx *ctx, long long int value); -GRN_API void grn_ctx_output_float(grn_ctx *ctx, double value); -GRN_API void grn_ctx_output_cstr(grn_ctx *ctx, const char *value); -GRN_API void grn_ctx_output_str(grn_ctx *ctx, - const char *value, unsigned int value_len); -GRN_API void grn_ctx_output_bool(grn_ctx *ctx, grn_bool value); -GRN_API void grn_ctx_output_obj(grn_ctx *ctx, - grn_obj *value, grn_obj_format *format); - - -GRN_API const char *grn_ctx_get_mime_type(grn_ctx *ctx); -GRN_API void grn_ctx_recv_handler_set(grn_ctx *, - void (*func)(grn_ctx *, int, void *), - void *func_arg); - -/* obsolete */ -GRN_API grn_rc grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, - grn_obj_format *format); - -/* various values exchanged via grn_obj */ - -#define GRN_OBJ_DO_SHALLOW_COPY (GRN_OBJ_REFER|GRN_OBJ_OUTPLACE) -#define GRN_OBJ_VECTOR (0x01<<7) - -#define GRN_OBJ_MUTABLE(obj) ((obj) && (obj)->header.type <= GRN_VECTOR) - -#define GRN_VALUE_FIX_SIZE_INIT(obj,flags,domain)\ - GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK,\ - ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain)) -#define GRN_VALUE_VAR_SIZE_INIT(obj,flags,domain)\ - GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_VECTOR : GRN_BULK,\ - ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain)) - -#define GRN_VOID_INIT(obj) GRN_OBJ_INIT((obj), GRN_VOID, 0, GRN_DB_VOID) -#define GRN_TEXT_INIT(obj,flags) \ - GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_TEXT) -#define GRN_SHORT_TEXT_INIT(obj,flags) \ - GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_SHORT_TEXT) -#define GRN_LONG_TEXT_INIT(obj,flags) \ - GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_LONG_TEXT) -#define GRN_TEXT_SET_REF(obj,str,len) do {\ - (obj)->u.b.head = (char *)(str);\ - (obj)->u.b.curr = (char *)(str) + (len);\ -} while (0) -#define GRN_TEXT_SET(ctx,obj,str,len) do {\ - if ((obj)->header.impl_flags & GRN_OBJ_REFER) {\ - GRN_TEXT_SET_REF((obj), (str), (len));\ - } else {\ - grn_bulk_write_from((ctx), (obj), (const char *)(str), 0, (unsigned int)(len));\ - }\ -} while (0) -#define GRN_TEXT_PUT(ctx,obj,str,len) \ - grn_bulk_write((ctx), (obj), (const char *)(str), (unsigned int)(len)) -#define GRN_TEXT_PUTC(ctx,obj,c) do {\ - char _c = (c); grn_bulk_write((ctx), (obj), &_c, 1);\ -} while (0) - -#define GRN_TEXT_PUTS(ctx,obj,str) GRN_TEXT_PUT((ctx), (obj), (str), strlen(str)) -#define GRN_TEXT_SETS(ctx,obj,str) GRN_TEXT_SET((ctx), (obj), (str), strlen(str)) -#define GRN_TEXT_VALUE(obj) GRN_BULK_HEAD(obj) -#define GRN_TEXT_LEN(obj) GRN_BULK_VSIZE(obj) - -#define GRN_BOOL_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_BOOL) -#define GRN_INT8_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT8) -#define GRN_UINT8_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT8) -#define GRN_INT16_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT16) -#define GRN_UINT16_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT16) -#define GRN_INT32_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT32) -#define GRN_UINT32_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT32) -#define GRN_INT64_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT64) -#define GRN_UINT64_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT64) -#define GRN_FLOAT_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_FLOAT) -#define GRN_TIME_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TIME) -#define GRN_RECORD_INIT GRN_VALUE_FIX_SIZE_INIT -#define GRN_PTR_INIT(obj,flags,domain)\ - GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_PVECTOR : GRN_PTR,\ - ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain)) -#define GRN_TOKYO_GEO_POINT_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TOKYO_GEO_POINT) -#define GRN_WGS84_GEO_POINT_INIT(obj,flags) \ - GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_WGS84_GEO_POINT) - -#define GRN_BOOL_SET(ctx,obj,val) do {\ - unsigned char _val = (unsigned char)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\ -} while (0) -#define GRN_INT8_SET(ctx,obj,val) do {\ - signed char _val = (signed char)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed char));\ -} while (0) -#define GRN_UINT8_SET(ctx,obj,val) do {\ - unsigned char _val = (unsigned char)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\ -} while (0) -#define GRN_INT16_SET(ctx,obj,val) do {\ - signed short _val = (signed short)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed short));\ -} while (0) -#define GRN_UINT16_SET(ctx,obj,val) do {\ - unsigned short _val = (unsigned short)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned short));\ -} while (0) -#define GRN_INT32_SET(ctx,obj,val) do {\ - int _val = (int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(int));\ -} while (0) -#define GRN_UINT32_SET(ctx,obj,val) do {\ - unsigned int _val = (unsigned int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned int));\ -} while (0) -#define GRN_INT64_SET(ctx,obj,val) do {\ - long long int _val = (long long int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long int));\ -} while (0) -#define GRN_UINT64_SET(ctx,obj,val) do {\ - long long unsigned int _val = (long long unsigned int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long unsigned int));\ -} while (0) -#define GRN_FLOAT_SET(ctx,obj,val) do {\ - double _val = (double)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(double));\ -} while (0) -#define GRN_TIME_SET GRN_INT64_SET -#define GRN_RECORD_SET(ctx,obj,val) do {\ - grn_id _val = (grn_id)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_id));\ -} while (0) -#define GRN_PTR_SET(ctx,obj,val) do {\ - grn_obj *_val = (grn_obj *)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_obj *));\ -} while (0) - -#define GRN_GEO_DEGREE2MSEC(degree)\ - ((int)((degree) * 3600 * 1000 + ((degree) > 0 ? 0.5 : -0.5))) -#define GRN_GEO_MSEC2DEGREE(msec)\ - ((((int)(msec)) / 3600.0) * 0.001) - -#define GRN_GEO_POINT_SET(ctx,obj,_latitude,_longitude) do {\ - grn_geo_point _val;\ - _val.latitude = (int)(_latitude);\ - _val.longitude = (int)(_longitude);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_geo_point));\ -} while (0) - -#define GRN_BOOL_SET_AT(ctx,obj,offset,val) do {\ - unsigned char _val = (unsigned char)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset), sizeof(unsigned char));\ -} while (0) -#define GRN_INT8_SET_AT(ctx,obj,offset,val) do {\ - signed char _val = (signed char)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(signed char), sizeof(signed char));\ -} while (0) -#define GRN_UINT8_SET_AT(ctx,obj,offset,val) do { \ - unsigned char _val = (unsigned char)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(unsigned char), sizeof(unsigned char));\ -} while (0) -#define GRN_INT16_SET_AT(ctx,obj,offset,val) do {\ - signed short _val = (signed short)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(signed short), sizeof(signed short));\ -} while (0) -#define GRN_UINT16_SET_AT(ctx,obj,offset,val) do { \ - unsigned short _val = (unsigned short)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(unsigned short), sizeof(unsigned short));\ -} while (0) -#define GRN_INT32_SET_AT(ctx,obj,offset,val) do {\ - int _val = (int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(int), sizeof(int));\ -} while (0) -#define GRN_UINT32_SET_AT(ctx,obj,offset,val) do { \ - unsigned int _val = (unsigned int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(unsigned int), sizeof(unsigned int));\ -} while (0) -#define GRN_INT64_SET_AT(ctx,obj,offset,val) do {\ - long long int _val = (long long int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(long long int), sizeof(long long int));\ -} while (0) -#define GRN_UINT64_SET_AT(ctx,obj,offset,val) do {\ - long long unsigned int _val = (long long unsigned int)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(long long unsigned int),\ - sizeof(long long unsigned int));\ -} while (0) -#define GRN_FLOAT_SET_AT(ctx,obj,offset,val) do {\ - double _val = (double)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(double), sizeof(double));\ -} while (0) -#define GRN_TIME_SET_AT GRN_INT64_SET_AT -#define GRN_RECORD_SET_AT(ctx,obj,offset,val) do {\ - grn_id _val = (grn_id)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(grn_id), sizeof(grn_id));\ -} while (0) -#define GRN_PTR_SET_AT(ctx,obj,offset,val) do {\ - grn_obj *_val = (grn_obj *)(val);\ - grn_bulk_write_from((ctx), (obj), (char *)&_val,\ - (offset) * sizeof(grn_obj *), sizeof(grn_obj *));\ -} while (0) - -#define GRN_TIME_USEC_PER_SEC 1000000 -#define GRN_TIME_PACK(sec, usec) ((long long int)(sec) * GRN_TIME_USEC_PER_SEC + (usec)) -#define GRN_TIME_UNPACK(time_value, sec, usec) do {\ - sec = (time_value) / GRN_TIME_USEC_PER_SEC;\ - usec = (time_value) % GRN_TIME_USEC_PER_SEC;\ -} while (0) - -GRN_API void grn_time_now(grn_ctx *ctx, grn_obj *obj); - -#define GRN_TIME_NOW(ctx,obj) (grn_time_now((ctx), (obj))) - -#define GRN_BOOL_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj))) -#define GRN_INT8_VALUE(obj) (*((signed char *)GRN_BULK_HEAD(obj))) -#define GRN_UINT8_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj))) -#define GRN_INT16_VALUE(obj) (*((signed short *)GRN_BULK_HEAD(obj))) -#define GRN_UINT16_VALUE(obj) (*((unsigned short *)GRN_BULK_HEAD(obj))) -#define GRN_INT32_VALUE(obj) (*((int *)GRN_BULK_HEAD(obj))) -#define GRN_UINT32_VALUE(obj) (*((unsigned int *)GRN_BULK_HEAD(obj))) -#define GRN_INT64_VALUE(obj) (*((long long int *)GRN_BULK_HEAD(obj))) -#define GRN_UINT64_VALUE(obj) (*((long long unsigned int *)GRN_BULK_HEAD(obj))) -#define GRN_FLOAT_VALUE(obj) (*((double *)GRN_BULK_HEAD(obj))) -#define GRN_TIME_VALUE GRN_INT64_VALUE -#define GRN_RECORD_VALUE(obj) (*((grn_id *)GRN_BULK_HEAD(obj))) -#define GRN_PTR_VALUE(obj) (*((grn_obj **)GRN_BULK_HEAD(obj))) -#define GRN_GEO_POINT_VALUE(obj,_latitude,_longitude) do {\ - grn_geo_point *_val = (grn_geo_point *)GRN_BULK_HEAD(obj);\ - _latitude = _val->latitude;\ - _longitude = _val->longitude;\ -} while (0) - -#define GRN_BOOL_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_INT8_VALUE_AT(obj,offset) (((signed char *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_UINT8_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_INT16_VALUE_AT(obj,offset) (((signed short *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_UINT16_VALUE_AT(obj,offset) (((unsigned short *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_INT32_VALUE_AT(obj,offset) (((int *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_UINT32_VALUE_AT(obj,offset) (((unsigned int *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_INT64_VALUE_AT(obj,offset) (((long long int *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_UINT64_VALUE_AT(obj,offset) (((long long unsigned int *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_FLOAT_VALUE_AT(obj,offset) (((double *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_TIME_VALUE_AT GRN_INT64_VALUE_AT -#define GRN_RECORD_VALUE_AT(obj,offset) (((grn_id *)GRN_BULK_HEAD(obj))[offset]) -#define GRN_PTR_VALUE_AT(obj,offset) (((grn_obj **)GRN_BULK_HEAD(obj))[offset]) - -#define GRN_BOOL_PUT(ctx,obj,val) do {\ - unsigned char _val = (unsigned char)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\ -} while (0) -#define GRN_INT8_PUT(ctx,obj,val) do {\ - signed char _val = (signed char)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed char));\ -} while (0) -#define GRN_UINT8_PUT(ctx,obj,val) do {\ - unsigned char _val = (unsigned char)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\ -} while (0) -#define GRN_INT16_PUT(ctx,obj,val) do {\ - signed short _val = (signed short)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed short));\ -} while (0) -#define GRN_UINT16_PUT(ctx,obj,val) do {\ - unsigned short _val = (unsigned short)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned short));\ -} while (0) -#define GRN_INT32_PUT(ctx,obj,val) do {\ - int _val = (int)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(int));\ -} while (0) -#define GRN_UINT32_PUT(ctx,obj,val) do {\ - unsigned int _val = (unsigned int)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned int));\ -} while (0) -#define GRN_INT64_PUT(ctx,obj,val) do {\ - long long int _val = (long long int)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long int));\ -} while (0) -#define GRN_UINT64_PUT(ctx,obj,val) do {\ - long long unsigned int _val = (long long unsigned int)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long unsigned int));\ -} while (0) -#define GRN_FLOAT_PUT(ctx,obj,val) do {\ - double _val = (double)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(double));\ -} while (0) -#define GRN_TIME_PUT GRN_INT64_PUT -#define GRN_RECORD_PUT(ctx,obj,val) do {\ - grn_id _val = (grn_id)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_id));\ -} while (0) -#define GRN_PTR_PUT(ctx,obj,val) do {\ - grn_obj *_val = (grn_obj *)(val);\ - grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_obj *));\ -} while (0) - -/* grn_str: deprecated. use grn_string instead. */ - -typedef struct { - const char *orig; - char *norm; - short *checks; - unsigned char *ctypes; - int flags; - unsigned int orig_blen; - unsigned int norm_blen; - unsigned int length; - grn_encoding encoding; -} grn_str; - -#define GRN_STR_REMOVEBLANK (0x01<<0) -#define GRN_STR_WITH_CTYPES (0x01<<1) -#define GRN_STR_WITH_CHECKS (0x01<<2) -#define GRN_STR_NORMALIZE GRN_OBJ_KEY_NORMALIZE - -GRN_API grn_str *grn_str_open(grn_ctx *ctx, const char *str, unsigned int str_len, - int flags); -GRN_API grn_rc grn_str_close(grn_ctx *ctx, grn_str *nstr); - -/* grn_string */ - -#define GRN_STRING_REMOVE_BLANK (0x01<<0) -#define GRN_STRING_WITH_TYPES (0x01<<1) -#define GRN_STRING_WITH_CHECKS (0x01<<2) -#define GRN_STRING_REMOVE_TOKENIZED_DELIMITER (0x01<<3) - -#define GRN_NORMALIZER_AUTO ((grn_obj *)1) - -#define GRN_CHAR_BLANK 0x80 -#define GRN_CHAR_IS_BLANK(c) ((c) & (GRN_CHAR_BLANK)) -#define GRN_CHAR_TYPE(c) ((c) & 0x7f) - -typedef enum { - GRN_CHAR_NULL = 0, - GRN_CHAR_ALPHA, - GRN_CHAR_DIGIT, - GRN_CHAR_SYMBOL, - GRN_CHAR_HIRAGANA, - GRN_CHAR_KATAKANA, - GRN_CHAR_KANJI, - GRN_CHAR_OTHERS -} grn_char_type; - -GRN_API grn_obj *grn_string_open(grn_ctx *ctx, - const char *string, - unsigned int length_in_bytes, - grn_obj *normalizer, int flags); -GRN_API grn_rc grn_string_get_original(grn_ctx *ctx, grn_obj *string, - const char **original, - unsigned int *length_in_bytes); -GRN_API int grn_string_get_flags(grn_ctx *ctx, grn_obj *string); -GRN_API grn_rc grn_string_get_normalized(grn_ctx *ctx, grn_obj *string, - const char **normalized, - unsigned int *length_in_bytes, - unsigned int *n_characters); -GRN_API grn_rc grn_string_set_normalized(grn_ctx *ctx, grn_obj *string, - char *normalized, - unsigned int length_in_bytes, - unsigned int n_characters); -GRN_API const short *grn_string_get_checks(grn_ctx *ctx, grn_obj *string); -GRN_API grn_rc grn_string_set_checks(grn_ctx *ctx, - grn_obj *string, - short *checks); -GRN_API const unsigned char *grn_string_get_types(grn_ctx *ctx, grn_obj *string); -GRN_API grn_rc grn_string_set_types(grn_ctx *ctx, - grn_obj *string, - unsigned char *types); -GRN_API grn_encoding grn_string_get_encoding(grn_ctx *ctx, grn_obj *string); - - -GRN_API int grn_charlen(grn_ctx *ctx, const char *str, const char *end); - -/* expr */ - -GRN_API grn_obj *grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size); -GRN_API grn_rc grn_expr_close(grn_ctx *ctx, grn_obj *expr); -GRN_API grn_obj *grn_expr_add_var(grn_ctx *ctx, grn_obj *expr, - const char *name, unsigned int name_size); -GRN_API grn_obj *grn_expr_get_var(grn_ctx *ctx, grn_obj *expr, - const char *name, unsigned int name_size); -GRN_API grn_obj *grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset); - -GRN_API grn_obj *grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, - grn_operator op, int nargs); -GRN_API grn_obj *grn_expr_append_const(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, - grn_operator op, int nargs); -GRN_API grn_obj *grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr, - const char *str, unsigned int str_size, - grn_operator op, int nargs); -GRN_API grn_obj *grn_expr_append_const_int(grn_ctx *ctx, grn_obj *expr, int i, - grn_operator op, int nargs); -GRN_API grn_rc grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs); - -GRN_API grn_rc grn_expr_get_keywords(grn_ctx *ctx, grn_obj *expr, grn_obj *keywords); - -GRN_API grn_rc grn_expr_syntax_escape(grn_ctx *ctx, - const char *query, int query_size, - const char *target_characters, - char escape_character, - grn_obj *escaped_query); -GRN_API grn_rc grn_expr_syntax_escape_query(grn_ctx *ctx, - const char *query, int query_size, - grn_obj *escaped_query); - -GRN_API grn_rc grn_expr_compile(grn_ctx *ctx, grn_obj *expr); -GRN_API grn_obj *grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs); -GRN_API grn_rc grn_ctx_push(grn_ctx *ctx, grn_obj *obj); -GRN_API grn_obj *grn_ctx_pop(grn_ctx *ctx); - -GRN_API grn_obj *grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, - grn_id domain, grn_obj_flags flags); - -GRN_API grn_obj *grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, - grn_obj *res, grn_operator op); - -GRN_API int grn_obj_columns(grn_ctx *ctx, grn_obj *table, - const char *str, unsigned int str_size, grn_obj *res); - -#define GRN_EXPR_CREATE_FOR_QUERY(ctx,table,expr,var) do {\ - if (((expr) = grn_expr_create((ctx), NULL, 0)) &&\ - ((var) = grn_expr_add_var((ctx), (expr), NULL, 0))) {\ - GRN_RECORD_INIT((var), 0, grn_obj_id((ctx), (table)));\ - } else {\ - (var) = NULL;\ - }\ -} while (0) - -typedef unsigned int grn_expr_flags; - -#define GRN_EXPR_SYNTAX_QUERY (0x00) -#define GRN_EXPR_SYNTAX_SCRIPT (0x01) -#define GRN_EXPR_SYNTAX_OUTPUT_COLUMNS (0x20) -#define GRN_EXPR_SYNTAX_ADJUSTER (0x40) -#define GRN_EXPR_ALLOW_PRAGMA (0x02) -#define GRN_EXPR_ALLOW_COLUMN (0x04) -#define GRN_EXPR_ALLOW_UPDATE (0x08) -#define GRN_EXPR_ALLOW_LEADING_NOT (0x10) - -GRN_API grn_rc grn_expr_parse(grn_ctx *ctx, grn_obj *expr, - const char *str, unsigned int str_size, - grn_obj *default_column, grn_operator default_mode, - grn_operator default_op, grn_expr_flags flags); - -GRN_API grn_obj *grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags, - unsigned int width, unsigned int max_results, - unsigned int n_tags, - const char **opentags, unsigned int *opentag_lens, - const char **closetags, unsigned int *closetag_lens, - grn_snip_mapping *mapping); -GRN_API grn_rc grn_expr_snip_add_conditions(grn_ctx *ctx, - grn_obj *expr, - grn_obj *snip, - unsigned int n_tags, - const char **opentags, - unsigned int *opentag_lens, - const char **closetags, - unsigned int *closetag_lens); - -GRN_API grn_table_sort_key *grn_table_sort_key_from_str(grn_ctx *ctx, - const char *str, unsigned int str_size, - grn_obj *table, unsigned int *nkeys); -GRN_API grn_rc grn_table_sort_key_close(grn_ctx *ctx, - grn_table_sort_key *keys, unsigned int nkeys); - -GRN_API grn_bool grn_table_is_grouped(grn_ctx *ctx, grn_obj *table); - -GRN_API unsigned int grn_table_max_n_subrecs(grn_ctx *ctx, grn_obj *table); - -GRN_API grn_obj *grn_table_create_for_group(grn_ctx *ctx, - const char *name, - unsigned int name_size, - const char *path, - grn_obj *group_key, - grn_obj *value_type, - unsigned int max_n_subrecs); - -GRN_API unsigned int grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, - grn_id id, grn_id *subrecbuf, - int *scorebuf, int buf_size); - -GRN_API grn_obj *grn_table_tokenize(grn_ctx *ctx, grn_obj *table, - const char *str, unsigned int str_len, - grn_obj *buf, grn_bool addp); - -GRN_API grn_rc grn_load(grn_ctx *ctx, grn_content_type input_type, - const char *table, unsigned int table_len, - const char *columns, unsigned int columns_len, - const char *values, unsigned int values_len, - const char *ifexists, unsigned int ifexists_len, - const char *each, unsigned int each_len); - -#define GRN_CTX_MORE (0x01<<0) -#define GRN_CTX_TAIL (0x01<<1) -#define GRN_CTX_HEAD (0x01<<2) -#define GRN_CTX_QUIET (0x01<<3) -#define GRN_CTX_QUIT (0x01<<4) - -GRN_API grn_rc grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags); -GRN_API unsigned int grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags); -GRN_API unsigned int grn_ctx_recv(grn_ctx *ctx, char **str, unsigned int *str_len, int *flags); - -typedef struct _grn_ctx_info grn_ctx_info; - -struct _grn_ctx_info { - int fd; - unsigned int com_status; - grn_obj *outbuf; - unsigned char stat; -}; - -GRN_API grn_rc grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info); - -GRN_API grn_rc grn_set_segv_handler(void); -GRN_API grn_rc grn_set_int_handler(void); -GRN_API grn_rc grn_set_term_handler(void); - -/* hash */ - -typedef struct _grn_hash grn_hash; -typedef struct _grn_hash_cursor grn_hash_cursor; - -GRN_API grn_hash *grn_hash_create(grn_ctx *ctx, const char *path, unsigned int key_size, - unsigned int value_size, unsigned int flags); - -GRN_API grn_hash *grn_hash_open(grn_ctx *ctx, const char *path); - -GRN_API grn_rc grn_hash_close(grn_ctx *ctx, grn_hash *hash); - -GRN_API grn_id grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, - unsigned int key_size, void **value, int *added); -GRN_API grn_id grn_hash_get(grn_ctx *ctx, grn_hash *hash, const void *key, - unsigned int key_size, void **value); - -GRN_API int grn_hash_get_key(grn_ctx *ctx, grn_hash *hash, grn_id id, void *keybuf, int bufsize); -GRN_API int grn_hash_get_key2(grn_ctx *ctx, grn_hash *hash, grn_id id, grn_obj *bulk); -GRN_API int grn_hash_get_value(grn_ctx *ctx, grn_hash *hash, grn_id id, void *valuebuf); -GRN_API grn_rc grn_hash_set_value(grn_ctx *ctx, grn_hash *hash, grn_id id, - const void *value, int flags); - -typedef struct _grn_table_delete_optarg grn_table_delete_optarg; - -struct _grn_table_delete_optarg { - int flags; - int (*func)(grn_ctx *ctx, grn_obj *, grn_id, void *); - void *func_arg; -}; - -GRN_API grn_rc grn_hash_delete_by_id(grn_ctx *ctx, grn_hash *hash, grn_id id, - grn_table_delete_optarg *optarg); -GRN_API grn_rc grn_hash_delete(grn_ctx *ctx, grn_hash *hash, - const void *key, unsigned int key_size, - grn_table_delete_optarg *optarg); - -GRN_API grn_hash_cursor *grn_hash_cursor_open(grn_ctx *ctx, grn_hash *hash, - const void *min, unsigned int min_size, - const void *max, unsigned int max_size, - int offset, int limit, int flags); -GRN_API grn_id grn_hash_cursor_next(grn_ctx *ctx, grn_hash_cursor *c); -GRN_API void grn_hash_cursor_close(grn_ctx *ctx, grn_hash_cursor *c); - -GRN_API int grn_hash_cursor_get_key(grn_ctx *ctx, grn_hash_cursor *c, void **key); -GRN_API int grn_hash_cursor_get_value(grn_ctx *ctx, grn_hash_cursor *c, void **value); -GRN_API grn_rc grn_hash_cursor_set_value(grn_ctx *ctx, grn_hash_cursor *c, - const void *value, int flags); - -GRN_API int grn_hash_cursor_get_key_value(grn_ctx *ctx, grn_hash_cursor *c, - void **key, unsigned int *key_size, void **value); - -GRN_API grn_rc grn_hash_cursor_delete(grn_ctx *ctx, grn_hash_cursor *c, - grn_table_delete_optarg *optarg); - -#define GRN_HASH_EACH(ctx,hash,id,key,key_size,value,block) do {\ - grn_hash_cursor *_sc = grn_hash_cursor_open(ctx, hash, NULL, 0, NULL, 0, 0, -1, 0); \ - if (_sc) {\ - grn_id id;\ - while ((id = grn_hash_cursor_next(ctx, _sc))) {\ - grn_hash_cursor_get_key_value(ctx, _sc, (void **)(key),\ - (key_size), (void **)(value));\ - block\ - }\ - grn_hash_cursor_close(ctx, _sc);\ - }\ -} while (0) - -/* array */ - -typedef struct _grn_array grn_array; -typedef struct _grn_array_cursor grn_array_cursor; - -GRN_API grn_array *grn_array_create(grn_ctx *ctx, const char *path, - unsigned int value_size, unsigned int flags); -GRN_API grn_array *grn_array_open(grn_ctx *ctx, const char *path); -GRN_API grn_rc grn_array_close(grn_ctx *ctx, grn_array *array); -GRN_API grn_id grn_array_add(grn_ctx *ctx, grn_array *array, void **value); -GRN_API grn_id grn_array_push(grn_ctx *ctx, grn_array *array, - void (*func)(grn_ctx *ctx, grn_array *array, - grn_id id, void *func_arg), - void *func_arg); -GRN_API grn_id grn_array_pull(grn_ctx *ctx, grn_array *array, grn_bool blockp, - void (*func)(grn_ctx *ctx, grn_array *array, - grn_id id, void *func_arg), - void *func_arg); -GRN_API void grn_array_unblock(grn_ctx *ctx, grn_array *array); -GRN_API int grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf); -GRN_API grn_rc grn_array_set_value(grn_ctx *ctx, grn_array *array, grn_id id, - const void *value, int flags); -GRN_API grn_array_cursor *grn_array_cursor_open(grn_ctx *ctx, grn_array *array, - grn_id min, grn_id max, - int offset, int limit, int flags); -GRN_API grn_id grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor); -GRN_API int grn_array_cursor_get_value(grn_ctx *ctx, grn_array_cursor *cursor, void **value); -GRN_API grn_rc grn_array_cursor_set_value(grn_ctx *ctx, grn_array_cursor *cursor, - const void *value, int flags); -GRN_API grn_rc grn_array_cursor_delete(grn_ctx *ctx, grn_array_cursor *cursor, - grn_table_delete_optarg *optarg); -GRN_API void grn_array_cursor_close(grn_ctx *ctx, grn_array_cursor *cursor); -GRN_API grn_rc grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id, - grn_table_delete_optarg *optarg); - -GRN_API grn_id grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id); - -GRN_API void *_grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id); - -#define GRN_ARRAY_EACH(ctx,array,head,tail,id,value,block) do {\ - grn_array_cursor *_sc = grn_array_cursor_open(ctx, array, head, tail, 0, -1, 0); \ - if (_sc) {\ - grn_id id;\ - while ((id = grn_array_cursor_next(ctx, _sc))) {\ - grn_array_cursor_get_value(ctx, _sc, (void **)(value));\ - block\ - }\ - grn_array_cursor_close(ctx, _sc); \ - }\ -} while (0) - -/* pat */ - -typedef struct _grn_pat grn_pat; -typedef struct _grn_pat_cursor grn_pat_cursor; - -GRN_API grn_pat *grn_pat_create(grn_ctx *ctx, const char *path, unsigned int key_size, - unsigned int value_size, unsigned int flags); - -GRN_API grn_pat *grn_pat_open(grn_ctx *ctx, const char *path); - -GRN_API grn_rc grn_pat_close(grn_ctx *ctx, grn_pat *pat); - -GRN_API grn_rc grn_pat_remove(grn_ctx *ctx, const char *path); - -GRN_API grn_id grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key, - unsigned int key_size, void **value); -GRN_API grn_id grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key, - unsigned int key_size, void **value, int *added); - -GRN_API int grn_pat_get_key(grn_ctx *ctx, grn_pat *pat, grn_id id, void *keybuf, int bufsize); -GRN_API int grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk); -GRN_API int grn_pat_get_value(grn_ctx *ctx, grn_pat *pat, grn_id id, void *valuebuf); -GRN_API grn_rc grn_pat_set_value(grn_ctx *ctx, grn_pat *pat, grn_id id, - const void *value, int flags); - -GRN_API grn_rc grn_pat_delete_by_id(grn_ctx *ctx, grn_pat *pat, grn_id id, - grn_table_delete_optarg *optarg); -GRN_API grn_rc grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, unsigned int key_size, - grn_table_delete_optarg *optarg); -GRN_API int grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id, - grn_table_delete_optarg *optarg); - -typedef struct _grn_pat_scan_hit grn_pat_scan_hit; - -struct _grn_pat_scan_hit { - grn_id id; - unsigned int offset; - unsigned int length; -}; - -GRN_API int grn_pat_scan(grn_ctx *ctx, grn_pat *pat, const char *str, unsigned int str_len, - grn_pat_scan_hit *sh, unsigned int sh_size, const char **rest); - -GRN_API grn_rc grn_pat_prefix_search(grn_ctx *ctx, grn_pat *pat, - const void *key, unsigned int key_size, grn_hash *h); -GRN_API grn_rc grn_pat_suffix_search(grn_ctx *ctx, grn_pat *pat, - const void *key, unsigned int key_size, grn_hash *h); -GRN_API grn_id grn_pat_lcp_search(grn_ctx *ctx, grn_pat *pat, - const void *key, unsigned int key_size); - -GRN_API unsigned int grn_pat_size(grn_ctx *ctx, grn_pat *pat); - -GRN_API grn_pat_cursor *grn_pat_cursor_open(grn_ctx *ctx, grn_pat *pat, - const void *min, unsigned int min_size, - const void *max, unsigned int max_size, - int offset, int limit, int flags); -GRN_API grn_id grn_pat_cursor_next(grn_ctx *ctx, grn_pat_cursor *c); -GRN_API void grn_pat_cursor_close(grn_ctx *ctx, grn_pat_cursor *c); - -GRN_API int grn_pat_cursor_get_key(grn_ctx *ctx, grn_pat_cursor *c, void **key); -GRN_API int grn_pat_cursor_get_value(grn_ctx *ctx, grn_pat_cursor *c, void **value); - -GRN_API int grn_pat_cursor_get_key_value(grn_ctx *ctx, grn_pat_cursor *c, - void **key, unsigned int *key_size, void **value); -GRN_API grn_rc grn_pat_cursor_set_value(grn_ctx *ctx, grn_pat_cursor *c, - const void *value, int flags); -GRN_API grn_rc grn_pat_cursor_delete(grn_ctx *ctx, grn_pat_cursor *c, - grn_table_delete_optarg *optarg); - -#define GRN_PAT_EACH(ctx,pat,id,key,key_size,value,block) do { \ - grn_pat_cursor *_sc = grn_pat_cursor_open(ctx, pat, NULL, 0, NULL, 0, 0, -1, 0); \ - if (_sc) {\ - grn_id id;\ - while ((id = grn_pat_cursor_next(ctx, _sc))) {\ - grn_pat_cursor_get_key_value(ctx, _sc, (void **)(key),\ - (key_size), (void **)(value));\ - block\ - }\ - grn_pat_cursor_close(ctx, _sc);\ - }\ -} while (0) - -/* dat */ - -typedef struct _grn_dat grn_dat; -typedef struct _grn_dat_cursor grn_dat_cursor; - -GRN_API grn_dat *grn_dat_create(grn_ctx *ctx, const char *path, unsigned int key_size, - unsigned int value_size, unsigned int flags); - -GRN_API grn_dat *grn_dat_open(grn_ctx *ctx, const char *path); - -GRN_API grn_rc grn_dat_close(grn_ctx *ctx, grn_dat *dat); - -GRN_API grn_rc grn_dat_remove(grn_ctx *ctx, const char *path); - -GRN_API grn_id grn_dat_get(grn_ctx *ctx, grn_dat *dat, const void *key, - unsigned int key_size, void **value); -GRN_API grn_id grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key, - unsigned int key_size, void **value, int *added); - -GRN_API int grn_dat_get_key(grn_ctx *ctx, grn_dat *dat, grn_id id, void *keybuf, int bufsize); -GRN_API int grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk); - -GRN_API grn_rc grn_dat_delete_by_id(grn_ctx *ctx, grn_dat *dat, grn_id id, - grn_table_delete_optarg *optarg); -GRN_API grn_rc grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_size, - grn_table_delete_optarg *optarg); - -GRN_API grn_rc grn_dat_update_by_id(grn_ctx *ctx, grn_dat *dat, grn_id src_key_id, - const void *dest_key, unsigned int dest_key_size); -GRN_API grn_rc grn_dat_update(grn_ctx *ctx, grn_dat *dat, - const void *src_key, unsigned int src_key_size, - const void *dest_key, unsigned int dest_key_size); - -GRN_API unsigned int grn_dat_size(grn_ctx *ctx, grn_dat *dat); - -GRN_API grn_dat_cursor *grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat, - const void *min, unsigned int min_size, - const void *max, unsigned int max_size, - int offset, int limit, int flags); -GRN_API grn_id grn_dat_cursor_next(grn_ctx *ctx, grn_dat_cursor *c); -GRN_API void grn_dat_cursor_close(grn_ctx *ctx, grn_dat_cursor *c); - -GRN_API int grn_dat_cursor_get_key(grn_ctx *ctx, grn_dat_cursor *c, const void **key); -GRN_API grn_rc grn_dat_cursor_delete(grn_ctx *ctx, grn_dat_cursor *c, - grn_table_delete_optarg *optarg); - -#define GRN_DAT_EACH(ctx,dat,id,key,key_size,block) do {\ - grn_dat_cursor *_sc = grn_dat_cursor_open(ctx, dat, NULL, 0, NULL, 0, 0, -1, 0);\ - if (_sc) {\ - grn_id id;\ - unsigned int *_ks = (key_size);\ - if (_ks) {\ - while ((id = grn_dat_cursor_next(ctx, _sc))) {\ - int _ks_raw = grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\ - *(_ks) = (unsigned int)_ks_raw;\ - block\ - }\ - } else {\ - while ((id = grn_dat_cursor_next(ctx, _sc))) {\ - grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\ - block\ - }\ - }\ - grn_dat_cursor_close(ctx, _sc);\ - }\ -} while (0) - -/* buffered index builder */ - -typedef struct _grn_ii grn_ii; -typedef struct _grn_ii_buffer grn_ii_buffer; - -grn_ii_buffer *grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii, - long long unsigned int update_buffer_size); -grn_rc grn_ii_buffer_append(grn_ctx *ctx, grn_ii_buffer *ii_buffer, - grn_id rid, unsigned int section, grn_obj *value); -grn_rc grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer); -grn_rc grn_ii_buffer_close(grn_ctx *ctx, grn_ii_buffer *ii_buffer); - - -#ifdef __cplusplus -} -#endif +#include "groonga/groonga.h" +#include "groonga/obj.h" +#include "groonga/ii.h" +#include "groonga/expr.h" +#include "groonga/output.h" +#include "groonga/util.h" +#include "groonga/request_canceler.h" #endif /* GROONGA_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/Makefile.am b/storage/mroonga/vendor/groonga/include/groonga/Makefile.am index 5cfb61937fb..63dcc1e7ba9 100644 --- a/storage/mroonga/vendor/groonga/include/groonga/Makefile.am +++ b/storage/mroonga/vendor/groonga/include/groonga/Makefile.am @@ -1,7 +1,16 @@ groonga_includedir = $(pkgincludedir)/groonga groonga_include_HEADERS = \ + command.h \ + expr.h \ + groonga.h \ + ii.h \ + obj.h \ + output.h \ plugin.h \ + request_canceler.h \ + token.h \ tokenizer.h \ token_filter.h \ nfkc.h \ - normalizer.h + normalizer.h \ + util.h diff --git a/storage/mroonga/vendor/groonga/include/groonga/command.h b/storage/mroonga/vendor/groonga/include/groonga/command.h new file mode 100644 index 00000000000..101956a04f9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/command.h @@ -0,0 +1,79 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_COMMAND_H +#define GROONGA_COMMAND_H + +#include <groonga/plugin.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _grn_command_input grn_command_input; + +GRN_PLUGIN_EXPORT grn_command_input *grn_command_input_open(grn_ctx *ctx, + grn_obj *command); +GRN_PLUGIN_EXPORT grn_rc grn_command_input_close(grn_ctx *ctx, + grn_command_input *input); + +GRN_PLUGIN_EXPORT grn_obj *grn_command_input_add(grn_ctx *ctx, + grn_command_input *input, + const char *name, + int name_size, + grn_bool *added); +GRN_PLUGIN_EXPORT grn_obj *grn_command_input_get(grn_ctx *ctx, + grn_command_input *input, + const char *name, + int name_size); +GRN_PLUGIN_EXPORT grn_obj *grn_command_input_at(grn_ctx *ctx, + grn_command_input *input, + unsigned int offset); + +typedef void grn_command_run_func(grn_ctx *ctx, + grn_obj *command, + grn_command_input *input, + void *user_data); + +/* + grn_command_register() registers a command to the database which is + associated with `ctx'. `command_name' and `command_name_size' + specify the command name. Alphabetic letters ('A'-'Z' and 'a'-'z'), + digits ('0'-'9') and an underscore ('_') are capable characters. + + `run' is called for running the command. + + grn_command_register() returns GRN_SUCCESS on success, an error + code on failure. + */ +GRN_PLUGIN_EXPORT grn_rc grn_command_register(grn_ctx *ctx, + const char *command_name, + int command_name_size, + grn_command_run_func *run, + grn_expr_var *vars, + unsigned int n_vars, + void *user_data); + +GRN_PLUGIN_EXPORT grn_rc grn_command_run(grn_ctx *ctx, + grn_obj *command, + grn_command_input *input); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* GROONGA_COMMAND_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/expr.h b/storage/mroonga/vendor/groonga/include/groonga/expr.h new file mode 100644 index 00000000000..cf8fb3519ca --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/expr.h @@ -0,0 +1,108 @@ +/* + Copyright(C) 2009-2014 Brazil + + This library 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 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_EXPR_H +#define GROONGA_EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API grn_obj *grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size); +GRN_API grn_rc grn_expr_close(grn_ctx *ctx, grn_obj *expr); +GRN_API grn_obj *grn_expr_add_var(grn_ctx *ctx, grn_obj *expr, + const char *name, unsigned int name_size); +GRN_API grn_obj *grn_expr_get_var(grn_ctx *ctx, grn_obj *expr, + const char *name, unsigned int name_size); +GRN_API grn_obj *grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset); +GRN_API grn_rc grn_expr_clear_vars(grn_ctx *ctx, grn_obj *expr); + + +GRN_API grn_obj *grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, + grn_operator op, int nargs); +GRN_API grn_obj *grn_expr_append_const(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, + grn_operator op, int nargs); +GRN_API grn_obj *grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr, + const char *str, unsigned int str_size, + grn_operator op, int nargs); +GRN_API grn_obj *grn_expr_append_const_int(grn_ctx *ctx, grn_obj *expr, int i, + grn_operator op, int nargs); +GRN_API grn_rc grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs); + +GRN_API grn_rc grn_expr_get_keywords(grn_ctx *ctx, grn_obj *expr, grn_obj *keywords); + +GRN_API grn_rc grn_expr_syntax_escape(grn_ctx *ctx, + const char *query, int query_size, + const char *target_characters, + char escape_character, + grn_obj *escaped_query); +GRN_API grn_rc grn_expr_syntax_escape_query(grn_ctx *ctx, + const char *query, int query_size, + grn_obj *escaped_query); + +GRN_API grn_rc grn_expr_compile(grn_ctx *ctx, grn_obj *expr); +GRN_API grn_rc grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer); +GRN_API grn_obj *grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs); + +GRN_API grn_obj *grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, + grn_id domain, grn_obj_flags flags); + +#define GRN_EXPR_CREATE_FOR_QUERY(ctx,table,expr,var) do {\ + if (((expr) = grn_expr_create((ctx), NULL, 0)) &&\ + ((var) = grn_expr_add_var((ctx), (expr), NULL, 0))) {\ + GRN_RECORD_INIT((var), 0, grn_obj_id((ctx), (table)));\ + } else {\ + (var) = NULL;\ + }\ +} while (0) + +typedef unsigned int grn_expr_flags; + +#define GRN_EXPR_SYNTAX_QUERY (0x00) +#define GRN_EXPR_SYNTAX_SCRIPT (0x01) +#define GRN_EXPR_SYNTAX_OUTPUT_COLUMNS (0x20) +#define GRN_EXPR_SYNTAX_ADJUSTER (0x40) +#define GRN_EXPR_ALLOW_PRAGMA (0x02) +#define GRN_EXPR_ALLOW_COLUMN (0x04) +#define GRN_EXPR_ALLOW_UPDATE (0x08) +#define GRN_EXPR_ALLOW_LEADING_NOT (0x10) + +GRN_API grn_rc grn_expr_parse(grn_ctx *ctx, grn_obj *expr, + const char *str, unsigned int str_size, + grn_obj *default_column, grn_operator default_mode, + grn_operator default_op, grn_expr_flags flags); + +GRN_API grn_obj *grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags, + unsigned int width, unsigned int max_results, + unsigned int n_tags, + const char **opentags, unsigned int *opentag_lens, + const char **closetags, unsigned int *closetag_lens, + grn_snip_mapping *mapping); +GRN_API grn_rc grn_expr_snip_add_conditions(grn_ctx *ctx, + grn_obj *expr, + grn_obj *snip, + unsigned int n_tags, + const char **opentags, + unsigned int *opentag_lens, + const char **closetags, + unsigned int *closetag_lens); + +#ifdef __cplusplus +} +#endif + +#endif /* GROONGA_EXPR_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/groonga.h b/storage/mroonga/vendor/groonga/include/groonga/groonga.h new file mode 100644 index 00000000000..16bc424b8c1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/groonga.h @@ -0,0 +1,1994 @@ +/* + Copyright(C) 2009-2015 Brazil + + This library 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 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_GROONGA_H +#define GROONGA_GROONGA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> + +#ifndef GRN_API +# if defined(_WIN32) || defined(_WIN64) +# define GRN_API __declspec(dllimport) +# else +# define GRN_API +# endif /* defined(_WIN32) || defined(_WIN64) */ +#endif /* GRN_API */ + +typedef unsigned int grn_id; +typedef unsigned char grn_bool; + +#define GRN_ID_NIL (0x00) +#define GRN_ID_MAX (0x3fffffff) + +#define GRN_TRUE (1) +#define GRN_FALSE (0) + +typedef enum { + GRN_SUCCESS = 0, + GRN_END_OF_DATA = 1, + GRN_UNKNOWN_ERROR = -1, + GRN_OPERATION_NOT_PERMITTED = -2, + GRN_NO_SUCH_FILE_OR_DIRECTORY = -3, + GRN_NO_SUCH_PROCESS = -4, + GRN_INTERRUPTED_FUNCTION_CALL = -5, + GRN_INPUT_OUTPUT_ERROR = -6, + GRN_NO_SUCH_DEVICE_OR_ADDRESS = -7, + GRN_ARG_LIST_TOO_LONG = -8, + GRN_EXEC_FORMAT_ERROR = -9, + GRN_BAD_FILE_DESCRIPTOR = -10, + GRN_NO_CHILD_PROCESSES = -11, + GRN_RESOURCE_TEMPORARILY_UNAVAILABLE = -12, + GRN_NOT_ENOUGH_SPACE = -13, + GRN_PERMISSION_DENIED = -14, + GRN_BAD_ADDRESS = -15, + GRN_RESOURCE_BUSY = -16, + GRN_FILE_EXISTS = -17, + GRN_IMPROPER_LINK = -18, + GRN_NO_SUCH_DEVICE = -19, + GRN_NOT_A_DIRECTORY = -20, + GRN_IS_A_DIRECTORY = -21, + GRN_INVALID_ARGUMENT = -22, + GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM = -23, + GRN_TOO_MANY_OPEN_FILES = -24, + GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION = -25, + GRN_FILE_TOO_LARGE = -26, + GRN_NO_SPACE_LEFT_ON_DEVICE = -27, + GRN_INVALID_SEEK = -28, + GRN_READ_ONLY_FILE_SYSTEM = -29, + GRN_TOO_MANY_LINKS = -30, + GRN_BROKEN_PIPE = -31, + GRN_DOMAIN_ERROR = -32, + GRN_RESULT_TOO_LARGE = -33, + GRN_RESOURCE_DEADLOCK_AVOIDED = -34, + GRN_NO_MEMORY_AVAILABLE = -35, + GRN_FILENAME_TOO_LONG = -36, + GRN_NO_LOCKS_AVAILABLE = -37, + GRN_FUNCTION_NOT_IMPLEMENTED = -38, + GRN_DIRECTORY_NOT_EMPTY = -39, + GRN_ILLEGAL_BYTE_SEQUENCE = -40, + GRN_SOCKET_NOT_INITIALIZED = -41, + GRN_OPERATION_WOULD_BLOCK = -42, + GRN_ADDRESS_IS_NOT_AVAILABLE = -43, + GRN_NETWORK_IS_DOWN = -44, + GRN_NO_BUFFER = -45, + GRN_SOCKET_IS_ALREADY_CONNECTED = -46, + GRN_SOCKET_IS_NOT_CONNECTED = -47, + GRN_SOCKET_IS_ALREADY_SHUTDOWNED = -48, + GRN_OPERATION_TIMEOUT = -49, + GRN_CONNECTION_REFUSED = -50, + GRN_RANGE_ERROR = -51, + GRN_TOKENIZER_ERROR = -52, + GRN_FILE_CORRUPT = -53, + GRN_INVALID_FORMAT = -54, + GRN_OBJECT_CORRUPT = -55, + GRN_TOO_MANY_SYMBOLIC_LINKS = -56, + GRN_NOT_SOCKET = -57, + GRN_OPERATION_NOT_SUPPORTED = -58, + GRN_ADDRESS_IS_IN_USE = -59, + GRN_ZLIB_ERROR = -60, + GRN_LZ4_ERROR = -61, +/* Just for backward compatibility. We'll remove it at 5.0.0. */ +#define GRN_LZO_ERROR GRN_LZ4_ERROR + GRN_STACK_OVER_FLOW = -62, + GRN_SYNTAX_ERROR = -63, + GRN_RETRY_MAX = -64, + GRN_INCOMPATIBLE_FILE_FORMAT = -65, + GRN_UPDATE_NOT_ALLOWED = -66, + GRN_TOO_SMALL_OFFSET = -67, + GRN_TOO_LARGE_OFFSET = -68, + GRN_TOO_SMALL_LIMIT = -69, + GRN_CAS_ERROR = -70, + GRN_UNSUPPORTED_COMMAND_VERSION = -71, + GRN_NORMALIZER_ERROR = -72, + GRN_TOKEN_FILTER_ERROR = -73, + GRN_COMMAND_ERROR = -74, + GRN_PLUGIN_ERROR = -75, + GRN_SCORER_ERROR = -76 +} grn_rc; + +GRN_API grn_rc grn_init(void); +GRN_API grn_rc grn_fin(void); + +typedef enum { + GRN_ENC_DEFAULT = 0, + GRN_ENC_NONE, + GRN_ENC_EUC_JP, + GRN_ENC_UTF8, + GRN_ENC_SJIS, + GRN_ENC_LATIN1, + GRN_ENC_KOI8R +} grn_encoding; + +typedef enum { + GRN_COMMAND_VERSION_DEFAULT = 0, + GRN_COMMAND_VERSION_1, + GRN_COMMAND_VERSION_2 +} grn_command_version; + +#define GRN_COMMAND_VERSION_MIN GRN_COMMAND_VERSION_1 +#define GRN_COMMAND_VERSION_STABLE GRN_COMMAND_VERSION_1 +#define GRN_COMMAND_VERSION_MAX GRN_COMMAND_VERSION_2 + +typedef enum { + GRN_LOG_NONE = 0, + GRN_LOG_EMERG, + GRN_LOG_ALERT, + GRN_LOG_CRIT, + GRN_LOG_ERROR, + GRN_LOG_WARNING, + GRN_LOG_NOTICE, + GRN_LOG_INFO, + GRN_LOG_DEBUG, + GRN_LOG_DUMP +} grn_log_level; + +/* query log flags */ +#define GRN_QUERY_LOG_NONE (0x00) +#define GRN_QUERY_LOG_COMMAND (0x01<<0) +#define GRN_QUERY_LOG_RESULT_CODE (0x01<<1) +#define GRN_QUERY_LOG_DESTINATION (0x01<<2) +#define GRN_QUERY_LOG_CACHE (0x01<<3) +#define GRN_QUERY_LOG_SIZE (0x01<<4) +#define GRN_QUERY_LOG_SCORE (0x01<<5) +#define GRN_QUERY_LOG_ALL\ + (GRN_QUERY_LOG_COMMAND |\ + GRN_QUERY_LOG_RESULT_CODE |\ + GRN_QUERY_LOG_DESTINATION |\ + GRN_QUERY_LOG_CACHE |\ + GRN_QUERY_LOG_SIZE |\ + GRN_QUERY_LOG_SCORE) +#define GRN_QUERY_LOG_DEFAULT GRN_QUERY_LOG_ALL + +typedef enum { + GRN_CONTENT_NONE = 0, + GRN_CONTENT_TSV, + GRN_CONTENT_JSON, + GRN_CONTENT_XML, + GRN_CONTENT_MSGPACK +} grn_content_type; + +typedef struct _grn_obj grn_obj; +typedef struct _grn_ctx grn_ctx; + +#define GRN_CTX_MSGSIZE (0x80) +#define GRN_CTX_FIN (0xff) + +typedef union { + int int_value; + grn_id id; + void *ptr; +} grn_user_data; + +typedef grn_obj *grn_proc_func(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data); + +struct _grn_ctx { + grn_rc rc; + int flags; + grn_encoding encoding; + unsigned char ntrace; + unsigned char errlvl; + unsigned char stat; + unsigned int seqno; + unsigned int subno; + unsigned int seqno2; + unsigned int errline; + grn_user_data user_data; + grn_ctx *prev; + grn_ctx *next; + const char *errfile; + const char *errfunc; + struct _grn_ctx_impl *impl; + void *trace[16]; + char errbuf[GRN_CTX_MSGSIZE]; +}; + +#define GRN_CTX_USER_DATA(ctx) (&((ctx)->user_data)) + +/* Deprecated since 4.0.3. Don't use it. */ +#define GRN_CTX_USE_QL (0x03) +/* Deprecated since 4.0.3. Don't use it. */ +#define GRN_CTX_BATCH_MODE (0x04) +#define GRN_CTX_PER_DB (0x08) + +GRN_API grn_rc grn_ctx_init(grn_ctx *ctx, int flags); +GRN_API grn_rc grn_ctx_fin(grn_ctx *ctx); +GRN_API grn_ctx *grn_ctx_open(int flags); +GRN_API grn_rc grn_ctx_close(grn_ctx *ctx); +GRN_API grn_rc grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *func); + +GRN_API grn_encoding grn_get_default_encoding(void); +GRN_API grn_rc grn_set_default_encoding(grn_encoding encoding); + +#define GRN_CTX_GET_ENCODING(ctx) ((ctx)->encoding) +#define GRN_CTX_SET_ENCODING(ctx,enc) \ + ((ctx)->encoding = (enc == GRN_ENC_DEFAULT) ? grn_get_default_encoding() : enc) + +GRN_API const char *grn_get_version(void); +GRN_API const char *grn_get_package(void); + +GRN_API grn_command_version grn_get_default_command_version(void); +GRN_API grn_rc grn_set_default_command_version(grn_command_version version); +GRN_API grn_command_version grn_ctx_get_command_version(grn_ctx *ctx); +GRN_API grn_rc grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version); +GRN_API long long int grn_ctx_get_match_escalation_threshold(grn_ctx *ctx); +GRN_API grn_rc grn_ctx_set_match_escalation_threshold(grn_ctx *ctx, long long int threshold); +GRN_API long long int grn_get_default_match_escalation_threshold(void); +GRN_API grn_rc grn_set_default_match_escalation_threshold(long long int threshold); + +GRN_API int grn_get_lock_timeout(void); +GRN_API grn_rc grn_set_lock_timeout(int timeout); + +/* cache */ +#define GRN_CACHE_DEFAULT_MAX_N_ENTRIES 100 +typedef struct _grn_cache grn_cache; + +GRN_API grn_cache *grn_cache_open(grn_ctx *ctx); +GRN_API grn_rc grn_cache_close(grn_ctx *ctx, grn_cache *cache); + +GRN_API grn_rc grn_cache_current_set(grn_ctx *ctx, grn_cache *cache); +GRN_API grn_cache *grn_cache_current_get(grn_ctx *ctx); + +GRN_API grn_rc grn_cache_set_max_n_entries(grn_ctx *ctx, + grn_cache *cache, + unsigned int n); +GRN_API unsigned int grn_cache_get_max_n_entries(grn_ctx *ctx, + grn_cache *cache); + +/* grn_encoding */ + +GRN_API const char *grn_encoding_to_string(grn_encoding encoding); +GRN_API grn_encoding grn_encoding_parse(const char *name); + +/* obj */ + +typedef unsigned short int grn_obj_flags; + +#define GRN_OBJ_TABLE_TYPE_MASK (0x07) +#define GRN_OBJ_TABLE_HASH_KEY (0x00) +#define GRN_OBJ_TABLE_PAT_KEY (0x01) +#define GRN_OBJ_TABLE_DAT_KEY (0x02) +#define GRN_OBJ_TABLE_NO_KEY (0x03) + +#define GRN_OBJ_KEY_MASK (0x07<<3) +#define GRN_OBJ_KEY_UINT (0x00<<3) +#define GRN_OBJ_KEY_INT (0x01<<3) +#define GRN_OBJ_KEY_FLOAT (0x02<<3) +#define GRN_OBJ_KEY_GEO_POINT (0x03<<3) + +#define GRN_OBJ_KEY_WITH_SIS (0x01<<6) +#define GRN_OBJ_KEY_NORMALIZE (0x01<<7) + +#define GRN_OBJ_COLUMN_TYPE_MASK (0x07) +#define GRN_OBJ_COLUMN_SCALAR (0x00) +#define GRN_OBJ_COLUMN_VECTOR (0x01) +#define GRN_OBJ_COLUMN_INDEX (0x02) + +#define GRN_OBJ_COMPRESS_MASK (0x07<<4) +#define GRN_OBJ_COMPRESS_NONE (0x00<<4) +#define GRN_OBJ_COMPRESS_ZLIB (0x01<<4) +#define GRN_OBJ_COMPRESS_LZ4 (0x02<<4) +/* Just for backward compatibility. We'll remove it at 5.0.0. */ +#define GRN_OBJ_COMPRESS_LZO GRN_OBJ_COMPRESS_LZ4 + +#define GRN_OBJ_WITH_SECTION (0x01<<7) +#define GRN_OBJ_WITH_WEIGHT (0x01<<8) +#define GRN_OBJ_WITH_POSITION (0x01<<9) +#define GRN_OBJ_RING_BUFFER (0x01<<10) + +#define GRN_OBJ_UNIT_MASK (0x0f<<8) +#define GRN_OBJ_UNIT_DOCUMENT_NONE (0x00<<8) +#define GRN_OBJ_UNIT_DOCUMENT_SECTION (0x01<<8) +#define GRN_OBJ_UNIT_DOCUMENT_POSITION (0x02<<8) +#define GRN_OBJ_UNIT_SECTION_NONE (0x03<<8) +#define GRN_OBJ_UNIT_SECTION_POSITION (0x04<<8) +#define GRN_OBJ_UNIT_POSITION_NONE (0x05<<8) +#define GRN_OBJ_UNIT_USERDEF_DOCUMENT (0x06<<8) +#define GRN_OBJ_UNIT_USERDEF_SECTION (0x07<<8) +#define GRN_OBJ_UNIT_USERDEF_POSITION (0x08<<8) + +#define GRN_OBJ_NO_SUBREC (0x00<<13) +#define GRN_OBJ_WITH_SUBREC (0x01<<13) + +#define GRN_OBJ_KEY_VAR_SIZE (0x01<<14) + +#define GRN_OBJ_TEMPORARY (0x00<<15) +#define GRN_OBJ_PERSISTENT (0x01<<15) + +/* obj types */ + +#define GRN_VOID (0x00) +#define GRN_BULK (0x02) +#define GRN_PTR (0x03) +#define GRN_UVECTOR (0x04) /* vector of fixed size data especially grn_id */ +#define GRN_PVECTOR (0x05) /* vector of grn_obj* */ +#define GRN_VECTOR (0x06) /* vector of arbitrary data */ +#define GRN_MSG (0x07) +#define GRN_QUERY (0x08) +#define GRN_ACCESSOR (0x09) +#define GRN_SNIP (0x0b) +#define GRN_PATSNIP (0x0c) +#define GRN_STRING (0x0d) +#define GRN_CURSOR_TABLE_HASH_KEY (0x10) +#define GRN_CURSOR_TABLE_PAT_KEY (0x11) +#define GRN_CURSOR_TABLE_DAT_KEY (0x12) +#define GRN_CURSOR_TABLE_NO_KEY (0x13) +#define GRN_CURSOR_COLUMN_INDEX (0x18) +#define GRN_CURSOR_COLUMN_GEO_INDEX (0x1a) +#define GRN_TYPE (0x20) +#define GRN_PROC (0x21) +#define GRN_EXPR (0x22) +#define GRN_TABLE_HASH_KEY (0x30) +#define GRN_TABLE_PAT_KEY (0x31) +#define GRN_TABLE_DAT_KEY (0x32) +#define GRN_TABLE_NO_KEY (0x33) +#define GRN_DB (0x37) +#define GRN_COLUMN_FIX_SIZE (0x40) +#define GRN_COLUMN_VAR_SIZE (0x41) +#define GRN_COLUMN_INDEX (0x48) + +typedef struct _grn_section grn_section; +typedef struct _grn_obj_header grn_obj_header; + +struct _grn_section { + unsigned int offset; + unsigned int length; + unsigned int weight; + grn_id domain; +}; + +struct _grn_obj_header { + unsigned char type; + unsigned char impl_flags; + grn_obj_flags flags; + grn_id domain; +}; + +struct _grn_obj { + grn_obj_header header; + union { + struct { + char *head; + char *curr; + char *tail; + } b; + struct { + grn_obj *body; + grn_section *sections; + int n_sections; + } v; + } u; +}; + +#define GRN_OBJ_REFER (0x01<<0) +#define GRN_OBJ_OUTPLACE (0x01<<1) + +#define GRN_OBJ_INIT(obj,obj_type,obj_flags,obj_domain) do { \ + (obj)->header.type = (obj_type);\ + (obj)->header.impl_flags = (obj_flags);\ + (obj)->header.flags = 0;\ + (obj)->header.domain = (obj_domain);\ + (obj)->u.b.head = NULL;\ + (obj)->u.b.curr = NULL;\ + (obj)->u.b.tail = NULL;\ +} while (0) + +#define GRN_OBJ_FIN(ctx,obj) (grn_obj_close((ctx), (obj))) + +typedef struct _grn_db_create_optarg grn_db_create_optarg; + +struct _grn_db_create_optarg { + char **builtin_type_names; + int n_builtin_type_names; +}; + +GRN_API grn_obj *grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg); + +#define GRN_DB_OPEN_OR_CREATE(ctx,path,optarg,db) \ + (((db) = grn_db_open((ctx), (path))) || (db = grn_db_create((ctx), (path), (optarg)))) + +GRN_API grn_obj *grn_db_open(grn_ctx *ctx, const char *path); +GRN_API void grn_db_touch(grn_ctx *ctx, grn_obj *db); +GRN_API grn_rc grn_db_recover(grn_ctx *ctx, grn_obj *db); + +GRN_API grn_rc grn_ctx_use(grn_ctx *ctx, grn_obj *db); +GRN_API grn_obj *grn_ctx_db(grn_ctx *ctx); +GRN_API grn_obj *grn_ctx_get(grn_ctx *ctx, const char *name, int name_size); +GRN_API grn_rc grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer); + +typedef enum { + GRN_DB_VOID = 0, + GRN_DB_DB, + GRN_DB_OBJECT, + GRN_DB_BOOL, + GRN_DB_INT8, + GRN_DB_UINT8, + GRN_DB_INT16, + GRN_DB_UINT16, + GRN_DB_INT32, + GRN_DB_UINT32, + GRN_DB_INT64, + GRN_DB_UINT64, + GRN_DB_FLOAT, + GRN_DB_TIME, + GRN_DB_SHORT_TEXT, + GRN_DB_TEXT, + GRN_DB_LONG_TEXT, + GRN_DB_TOKYO_GEO_POINT, + GRN_DB_WGS84_GEO_POINT +} grn_builtin_type; + +typedef enum { + GRN_DB_MECAB = 64, + GRN_DB_DELIMIT, + GRN_DB_UNIGRAM, + GRN_DB_BIGRAM, + GRN_DB_TRIGRAM +} grn_builtin_tokenizer; + +GRN_API grn_obj *grn_ctx_at(grn_ctx *ctx, grn_id id); + +GRN_API grn_obj *grn_type_create(grn_ctx *ctx, const char *name, unsigned int name_size, + grn_obj_flags flags, unsigned int size); + +GRN_API grn_rc grn_plugin_register(grn_ctx *ctx, const char *name); +GRN_API grn_rc grn_plugin_register_by_path(grn_ctx *ctx, const char *path); +GRN_API const char *grn_plugin_get_system_plugins_dir(void); +GRN_API const char *grn_plugin_get_suffix(void); + +typedef struct { + const char *name; + unsigned int name_size; + grn_obj value; +} grn_expr_var; + +typedef grn_rc (*grn_plugin_func)(grn_ctx *ctx); + +typedef enum { + GRN_PROC_INVALID = 0, + GRN_PROC_TOKENIZER, + GRN_PROC_COMMAND, + GRN_PROC_FUNCTION, + GRN_PROC_HOOK, + GRN_PROC_NORMALIZER, + GRN_PROC_TOKEN_FILTER, + GRN_PROC_SCORER +} grn_proc_type; + +GRN_API grn_obj *grn_proc_create(grn_ctx *ctx, + const char *name, int name_size, grn_proc_type type, + grn_proc_func *init, grn_proc_func *next, grn_proc_func *fin, + unsigned int nvars, grn_expr_var *vars); +GRN_API grn_obj *grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data, + grn_expr_var **vars, unsigned int *nvars, grn_obj **caller); +GRN_API grn_proc_type grn_proc_get_type(grn_ctx *ctx, grn_obj *proc); + +/*------------------------------------------------------------- + * API for table + */ + +#define GRN_TABLE_MAX_KEY_SIZE (0x1000) + +GRN_API grn_obj *grn_table_create(grn_ctx *ctx, + const char *name, unsigned int name_size, + const char *path, grn_obj_flags flags, + grn_obj *key_type, grn_obj *value_type); + +#define GRN_TABLE_OPEN_OR_CREATE(ctx,name,name_size,path,flags,key_type,value_type,table) \ + (((table) = grn_ctx_get((ctx), (name), (name_size))) ||\ + ((table) = grn_table_create((ctx), (name), (name_size), (path), (flags), (key_type), (value_type)))) + +/* TODO: int *added -> grn_bool *added */ +GRN_API grn_id grn_table_add(grn_ctx *ctx, grn_obj *table, + const void *key, unsigned int key_size, int *added); +GRN_API grn_id grn_table_get(grn_ctx *ctx, grn_obj *table, + const void *key, unsigned int key_size); +GRN_API grn_id grn_table_at(grn_ctx *ctx, grn_obj *table, grn_id id); +GRN_API grn_id grn_table_lcp_search(grn_ctx *ctx, grn_obj *table, + const void *key, unsigned int key_size); +GRN_API int grn_table_get_key(grn_ctx *ctx, grn_obj *table, + grn_id id, void *keybuf, int buf_size); +GRN_API grn_rc grn_table_delete(grn_ctx *ctx, grn_obj *table, + const void *key, unsigned int key_size); +GRN_API grn_rc grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id); +GRN_API grn_rc grn_table_update_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, + const void *dest_key, unsigned int dest_key_size); +GRN_API grn_rc grn_table_update(grn_ctx *ctx, grn_obj *table, + const void *src_key, unsigned int src_key_size, + const void *dest_key, unsigned int dest_key_size); +GRN_API grn_rc grn_table_truncate(grn_ctx *ctx, grn_obj *table); + +typedef grn_obj grn_table_cursor; + +#define GRN_CURSOR_ASCENDING (0x00<<0) +#define GRN_CURSOR_DESCENDING (0x01<<0) +#define GRN_CURSOR_GE (0x00<<1) +#define GRN_CURSOR_GT (0x01<<1) +#define GRN_CURSOR_LE (0x00<<2) +#define GRN_CURSOR_LT (0x01<<2) +#define GRN_CURSOR_BY_KEY (0x00<<3) +#define GRN_CURSOR_BY_ID (0x01<<3) +#define GRN_CURSOR_PREFIX (0x01<<4) +#define GRN_CURSOR_SIZE_BY_BIT (0x01<<5) +#define GRN_CURSOR_RK (0x01<<6) + +GRN_API grn_table_cursor *grn_table_cursor_open(grn_ctx *ctx, grn_obj *table, + const void *min, unsigned int min_size, + const void *max, unsigned int max_size, + int offset, int limit, int flags); +GRN_API grn_rc grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc); +GRN_API grn_id grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc); +GRN_API int grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key); +GRN_API int grn_table_cursor_get_value(grn_ctx *ctx, grn_table_cursor *tc, void **value); +GRN_API grn_rc grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc, + const void *value, int flags); +GRN_API grn_rc grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc); +GRN_API grn_obj *grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc); + +typedef struct { + grn_id rid; + grn_id sid; + unsigned int pos; + unsigned int tf; + unsigned int weight; + unsigned int rest; +} grn_posting; + +GRN_API grn_obj *grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc, grn_obj *index, + grn_id rid_min, grn_id rid_max, int flags); +GRN_API grn_posting *grn_index_cursor_next(grn_ctx *ctx, grn_obj *ic, grn_id *tid); + +#define GRN_TABLE_EACH(ctx,table,head,tail,id,key,key_size,value,block) do {\ + (ctx)->errlvl = GRN_LOG_NOTICE;\ + (ctx)->rc = GRN_SUCCESS;\ + if ((ctx)->seqno & 1) {\ + (ctx)->subno++;\ + } else {\ + (ctx)->seqno++;\ + }\ + if (table) {\ + switch ((table)->header.type) {\ + case GRN_TABLE_PAT_KEY :\ + GRN_PAT_EACH((ctx), (grn_pat *)(table), (id), (key), (key_size), (value), block);\ + break;\ + case GRN_TABLE_DAT_KEY :\ + GRN_DAT_EACH((ctx), (grn_dat *)(table), (id), (key), (key_size), block);\ + break;\ + case GRN_TABLE_HASH_KEY :\ + GRN_HASH_EACH((ctx), (grn_hash *)(table), (id), (key), (key_size), (value), block);\ + break;\ + case GRN_TABLE_NO_KEY :\ + GRN_ARRAY_EACH((ctx), (grn_array *)(table), (head), (tail), (id), (value), block);\ + break;\ + }\ + }\ + if ((ctx)->subno) {\ + (ctx)->subno--;\ + } else {\ + (ctx)->seqno++;\ + }\ +} while (0) + +typedef struct _grn_table_sort_key grn_table_sort_key; +typedef unsigned char grn_table_sort_flags; + +#define GRN_TABLE_SORT_ASC (0x00<<0) +#define GRN_TABLE_SORT_DESC (0x01<<0) + +struct _grn_table_sort_key { + grn_obj *key; + grn_table_sort_flags flags; + int offset; +}; + +GRN_API int grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, + grn_obj *result, grn_table_sort_key *keys, int n_keys); + +typedef struct _grn_table_group_result grn_table_group_result; +typedef unsigned int grn_table_group_flags; + +#define GRN_TABLE_GROUP_CALC_COUNT (0x01<<3) +#define GRN_TABLE_GROUP_CALC_MAX (0x01<<4) +#define GRN_TABLE_GROUP_CALC_MIN (0x01<<5) +#define GRN_TABLE_GROUP_CALC_SUM (0x01<<6) +#define GRN_TABLE_GROUP_CALC_AVG (0x01<<7) + +typedef enum { + GRN_OP_PUSH = 0, + GRN_OP_POP, + GRN_OP_NOP, + GRN_OP_CALL, + GRN_OP_INTERN, + GRN_OP_GET_REF, + GRN_OP_GET_VALUE, + GRN_OP_AND, + GRN_OP_AND_NOT, + /* Deprecated. Just for backward compatibility. */ +#define GRN_OP_BUT GRN_OP_AND_NOT + GRN_OP_OR, + GRN_OP_ASSIGN, + GRN_OP_STAR_ASSIGN, + GRN_OP_SLASH_ASSIGN, + GRN_OP_MOD_ASSIGN, + GRN_OP_PLUS_ASSIGN, + GRN_OP_MINUS_ASSIGN, + GRN_OP_SHIFTL_ASSIGN, + GRN_OP_SHIFTR_ASSIGN, + GRN_OP_SHIFTRR_ASSIGN, + GRN_OP_AND_ASSIGN, + GRN_OP_XOR_ASSIGN, + GRN_OP_OR_ASSIGN, + GRN_OP_JUMP, + GRN_OP_CJUMP, + GRN_OP_COMMA, + GRN_OP_BITWISE_OR, + GRN_OP_BITWISE_XOR, + GRN_OP_BITWISE_AND, + GRN_OP_BITWISE_NOT, + GRN_OP_EQUAL, + GRN_OP_NOT_EQUAL, + GRN_OP_LESS, + GRN_OP_GREATER, + GRN_OP_LESS_EQUAL, + GRN_OP_GREATER_EQUAL, + GRN_OP_IN, + GRN_OP_MATCH, + GRN_OP_NEAR, + GRN_OP_NEAR2, + GRN_OP_SIMILAR, + GRN_OP_TERM_EXTRACT, + GRN_OP_SHIFTL, + GRN_OP_SHIFTR, + GRN_OP_SHIFTRR, + GRN_OP_PLUS, + GRN_OP_MINUS, + GRN_OP_STAR, + GRN_OP_SLASH, + GRN_OP_MOD, + GRN_OP_DELETE, + GRN_OP_INCR, + GRN_OP_DECR, + GRN_OP_INCR_POST, + GRN_OP_DECR_POST, + GRN_OP_NOT, + GRN_OP_ADJUST, + GRN_OP_EXACT, + GRN_OP_LCP, + GRN_OP_PARTIAL, + GRN_OP_UNSPLIT, + GRN_OP_PREFIX, + GRN_OP_SUFFIX, + GRN_OP_GEO_DISTANCE1, + GRN_OP_GEO_DISTANCE2, + GRN_OP_GEO_DISTANCE3, + GRN_OP_GEO_DISTANCE4, + GRN_OP_GEO_WITHINP5, + GRN_OP_GEO_WITHINP6, + GRN_OP_GEO_WITHINP8, + GRN_OP_OBJ_SEARCH, + GRN_OP_EXPR_GET_VAR, + GRN_OP_TABLE_CREATE, + GRN_OP_TABLE_SELECT, + GRN_OP_TABLE_SORT, + GRN_OP_TABLE_GROUP, + GRN_OP_JSON_PUT, + GRN_OP_GET_MEMBER +} grn_operator; + +GRN_API const char *grn_operator_to_string(grn_operator op); +GRN_API grn_bool grn_operator_exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y); +GRN_API grn_bool grn_operator_exec_not_equal(grn_ctx *ctx, + grn_obj *x, grn_obj *y); +GRN_API grn_bool grn_operator_exec_less(grn_ctx *ctx, grn_obj *x, grn_obj *y); +GRN_API grn_bool grn_operator_exec_greater(grn_ctx *ctx, grn_obj *x, grn_obj *y); +GRN_API grn_bool grn_operator_exec_less_equal(grn_ctx *ctx, + grn_obj *x, grn_obj *y); +GRN_API grn_bool grn_operator_exec_greater_equal(grn_ctx *ctx, + grn_obj *x, grn_obj *y); + +struct _grn_table_group_result { + grn_obj *table; + unsigned char key_begin; + unsigned char key_end; + int limit; + grn_table_group_flags flags; + grn_operator op; + unsigned int max_n_subrecs; + grn_obj *calc_target; +}; + +GRN_API grn_rc grn_table_group(grn_ctx *ctx, grn_obj *table, + grn_table_sort_key *keys, int n_keys, + grn_table_group_result *results, int n_results); +GRN_API grn_rc grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, + grn_obj *res, grn_operator op); +GRN_API grn_rc grn_table_difference(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, + grn_obj *res1, grn_obj *res2); +GRN_API int grn_table_columns(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size, + grn_obj *res); + +GRN_API grn_obj *grn_obj_column(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size); + +GRN_API unsigned int grn_table_size(grn_ctx *ctx, grn_obj *table); + +/*------------------------------------------------------------- + * API for column + */ + +#define GRN_COLUMN_NAME_ID "_id" +#define GRN_COLUMN_NAME_ID_LEN (sizeof(GRN_COLUMN_NAME_ID) - 1) +#define GRN_COLUMN_NAME_KEY "_key" +#define GRN_COLUMN_NAME_KEY_LEN (sizeof(GRN_COLUMN_NAME_KEY) - 1) +#define GRN_COLUMN_NAME_VALUE "_value" +#define GRN_COLUMN_NAME_VALUE_LEN (sizeof(GRN_COLUMN_NAME_VALUE) - 1) +#define GRN_COLUMN_NAME_SCORE "_score" +#define GRN_COLUMN_NAME_SCORE_LEN (sizeof(GRN_COLUMN_NAME_SCORE) - 1) +#define GRN_COLUMN_NAME_NSUBRECS "_nsubrecs" +#define GRN_COLUMN_NAME_NSUBRECS_LEN (sizeof(GRN_COLUMN_NAME_NSUBRECS) - 1) +#define GRN_COLUMN_NAME_MAX "_max" +#define GRN_COLUMN_NAME_MAX_LEN (sizeof(GRN_COLUMN_NAME_MAX) - 1) +#define GRN_COLUMN_NAME_MIN "_min" +#define GRN_COLUMN_NAME_MIN_LEN (sizeof(GRN_COLUMN_NAME_MIN) - 1) +#define GRN_COLUMN_NAME_SUM "_sum" +#define GRN_COLUMN_NAME_SUM_LEN (sizeof(GRN_COLUMN_NAME_SUM) - 1) +#define GRN_COLUMN_NAME_AVG "_avg" +#define GRN_COLUMN_NAME_AVG_LEN (sizeof(GRN_COLUMN_NAME_AVG) - 1) + +GRN_API grn_obj *grn_column_create(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size, + const char *path, grn_obj_flags flags, grn_obj *type); + +#define GRN_COLUMN_OPEN_OR_CREATE(ctx,table,name,name_size,path,flags,type,column) \ + (((column) = grn_obj_column((ctx), (table), (name), (name_size))) ||\ + ((column) = grn_column_create((ctx), (table), (name), (name_size), (path), (flags), (type)))) + +GRN_API grn_rc grn_column_index_update(grn_ctx *ctx, grn_obj *column, + grn_id id, unsigned int section, + grn_obj *oldvalue, grn_obj *newvalue); +GRN_API grn_obj *grn_column_table(grn_ctx *ctx, grn_obj *column); +GRN_API grn_rc grn_column_truncate(grn_ctx *ctx, grn_obj *column); + +/*------------------------------------------------------------- + * API for db, table and/or column + */ + +typedef enum { + GRN_INFO_ENCODING = 0, + GRN_INFO_SOURCE, + GRN_INFO_DEFAULT_TOKENIZER, + GRN_INFO_ELEMENT_SIZE, + GRN_INFO_CURR_MAX, + GRN_INFO_MAX_ELEMENT_SIZE, + GRN_INFO_SEG_SIZE, + GRN_INFO_CHUNK_SIZE, + GRN_INFO_MAX_SECTION, + GRN_INFO_HOOK_LOCAL_DATA, + GRN_INFO_ELEMENT_A, + GRN_INFO_ELEMENT_CHUNK, + GRN_INFO_ELEMENT_CHUNK_SIZE, + GRN_INFO_ELEMENT_BUFFER_FREE, + GRN_INFO_ELEMENT_NTERMS, + GRN_INFO_ELEMENT_NTERMS_VOID, + GRN_INFO_ELEMENT_SIZE_IN_CHUNK, + GRN_INFO_ELEMENT_POS_IN_CHUNK, + GRN_INFO_ELEMENT_SIZE_IN_BUFFER, + GRN_INFO_ELEMENT_POS_IN_BUFFER, + GRN_INFO_ELEMENT_ESTIMATE_SIZE, + GRN_INFO_NGRAM_UNIT_SIZE, + /* + GRN_INFO_VERSION, + GRN_INFO_CONFIGURE_OPTIONS, + GRN_INFO_CONFIG_PATH, + */ + GRN_INFO_PARTIAL_MATCH_THRESHOLD, + GRN_INFO_II_SPLIT_THRESHOLD, + GRN_INFO_SUPPORT_ZLIB, + GRN_INFO_SUPPORT_LZ4, +/* Just for backward compatibility. We'll remove it at 5.0.0. */ +#define GRN_INFO_SUPPORT_LZO GRN_INFO_SUPPORT_LZ4 + GRN_INFO_NORMALIZER, + GRN_INFO_TOKEN_FILTERS +} grn_info_type; + +GRN_API grn_obj *grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valuebuf); +GRN_API grn_rc grn_obj_set_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *value); +GRN_API grn_obj *grn_obj_get_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_info_type type, grn_obj *value); +GRN_API grn_rc grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_info_type type, grn_obj *value); + +GRN_API grn_obj *grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value); +GRN_API int grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values); + +#define GRN_COLUMN_EACH(ctx,column,id,value,block) do {\ + int _n;\ + grn_id id = 1;\ + while ((_n = grn_obj_get_values(ctx, column, id, (void **)&value)) > 0) {\ + for (; _n; _n--, id++, value++) {\ + block\ + }\ + }\ +} while (0) + +#define GRN_OBJ_SET_MASK (0x07) +#define GRN_OBJ_SET (0x01) +#define GRN_OBJ_INCR (0x02) +#define GRN_OBJ_DECR (0x03) +#define GRN_OBJ_APPEND (0x04) +#define GRN_OBJ_PREPEND (0x05) +#define GRN_OBJ_GET (0x01<<4) +#define GRN_OBJ_COMPARE (0x01<<5) +#define GRN_OBJ_LOCK (0x01<<6) +#define GRN_OBJ_UNLOCK (0x01<<7) + +GRN_API grn_rc grn_obj_set_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags); +GRN_API grn_rc grn_obj_remove(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_rc grn_obj_rename(grn_ctx *ctx, grn_obj *obj, + const char *name, unsigned int name_size); +GRN_API grn_rc grn_table_rename(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size); + +GRN_API grn_rc grn_column_rename(grn_ctx *ctx, grn_obj *column, + const char *name, unsigned int name_size); + +GRN_API grn_rc grn_obj_close(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_rc grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags); +GRN_API void grn_obj_unlink(grn_ctx *ctx, grn_obj *obj); + +GRN_API grn_user_data *grn_obj_user_data(grn_ctx *ctx, grn_obj *obj); + +GRN_API grn_rc grn_obj_set_finalizer(grn_ctx *ctx, grn_obj *obj, grn_proc_func *func); + +GRN_API const char *grn_obj_path(grn_ctx *ctx, grn_obj *obj); +GRN_API int grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size); + +GRN_API int grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size); + +GRN_API grn_id grn_obj_get_range(grn_ctx *ctx, grn_obj *obj); + +#define GRN_OBJ_GET_DOMAIN(obj) \ + ((obj)->header.type == GRN_TABLE_NO_KEY ? GRN_ID_NIL : (obj)->header.domain) + +GRN_API int grn_obj_expire(grn_ctx *ctx, grn_obj *obj, int threshold); +GRN_API int grn_obj_check(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_rc grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout); +GRN_API grn_rc grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id); +GRN_API grn_rc grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj); +GRN_API unsigned int grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj); +GRN_API int grn_obj_defrag(grn_ctx *ctx, grn_obj *obj, int threshold); + +GRN_API grn_obj *grn_obj_db(grn_ctx *ctx, grn_obj *obj); + +GRN_API grn_id grn_obj_id(grn_ctx *ctx, grn_obj *obj); + +typedef struct _grn_search_optarg grn_search_optarg; + +struct _grn_search_optarg { + grn_operator mode; + int similarity_threshold; + int max_interval; + int *weight_vector; + int vector_size; + grn_obj *proc; + int max_size; + grn_obj *scorer; +}; + +GRN_API grn_rc grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query, + grn_obj *res, grn_operator op, grn_search_optarg *optarg); + +typedef grn_rc grn_selector_func(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op); + +GRN_API grn_rc grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, + grn_selector_func selector); + +/*------------------------------------------------------------- + * grn_vector +*/ + +GRN_API unsigned int grn_vector_size(grn_ctx *ctx, grn_obj *vector); + +GRN_API grn_rc grn_vector_add_element(grn_ctx *ctx, grn_obj *vector, + const char *str, unsigned int str_len, + unsigned int weight, grn_id domain); + +GRN_API unsigned int grn_vector_get_element(grn_ctx *ctx, grn_obj *vector, + unsigned int offset, const char **str, + unsigned int *weight, grn_id *domain); + +/*------------------------------------------------------------- + * grn_uvector +*/ + +GRN_API unsigned int grn_uvector_size(grn_ctx *ctx, grn_obj *uvector); +GRN_API unsigned int grn_uvector_element_size(grn_ctx *ctx, grn_obj *uvector); + +GRN_API grn_rc grn_uvector_add_element(grn_ctx *ctx, grn_obj *vector, + grn_id id, unsigned int weight); + +GRN_API grn_id grn_uvector_get_element(grn_ctx *ctx, grn_obj *uvector, + unsigned int offset, + unsigned int *weight); + +/*------------------------------------------------------------- + * API for hook + */ + +GRN_API int grn_proc_call_next(grn_ctx *ctx, grn_obj *exec_info, grn_obj *in, grn_obj *out); +GRN_API void *grn_proc_get_ctx_local_data(grn_ctx *ctx, grn_obj *exec_info); +GRN_API void *grn_proc_get_hook_local_data(grn_ctx *ctx, grn_obj *exec_info); + +typedef enum { + GRN_HOOK_SET = 0, + GRN_HOOK_GET, + GRN_HOOK_INSERT, + GRN_HOOK_DELETE, + GRN_HOOK_SELECT +} grn_hook_entry; + +GRN_API grn_rc grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, + int offset, grn_obj *proc, grn_obj *data); +GRN_API int grn_obj_get_nhooks(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry); +GRN_API grn_obj *grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, + int offset, grn_obj *data); +GRN_API grn_rc grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset); + +GRN_API grn_obj *grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain); + +GRN_API int grn_column_index(grn_ctx *ctx, grn_obj *column, grn_operator op, + grn_obj **indexbuf, int buf_size, int *section); + +GRN_API grn_rc grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep); +GRN_API grn_rc grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer); + +/* geo */ + +typedef struct { + int latitude; + int longitude; +} grn_geo_point; + +GRN_API grn_rc grn_geo_select_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point, + grn_obj *res, + grn_operator op); +GRN_API unsigned int grn_geo_estimate_size_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point); +/* Deprecated since 4.0.8. Use grn_geo_estimate_size_in_rectangle() instead. */ +GRN_API int grn_geo_estimate_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point); +GRN_API grn_obj *grn_geo_cursor_open_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point, + int offset, + int limit); +GRN_API grn_posting *grn_geo_cursor_next(grn_ctx *ctx, grn_obj *cursor); + + +/* query & snippet */ + +#ifndef GRN_QUERY_AND +#define GRN_QUERY_AND '+' +#endif /* GRN_QUERY_AND */ +#ifndef GRN_QUERY_AND_NOT +# ifdef GRN_QUERY_BUT + /* Deprecated. Just for backward compatibility. */ +# define GRN_QUERY_AND_NOT GRN_QUERY_BUT +# else +# define GRN_QUERY_AND_NOT '-' +# endif /* GRN_QUERY_BUT */ +#endif /* GRN_QUERY_AND_NOT */ +#ifndef GRN_QUERY_ADJ_INC +#define GRN_QUERY_ADJ_INC '>' +#endif /* GRN_QUERY_ADJ_POS2 */ +#ifndef GRN_QUERY_ADJ_DEC +#define GRN_QUERY_ADJ_DEC '<' +#endif /* GRN_QUERY_ADJ_POS1 */ +#ifndef GRN_QUERY_ADJ_NEG +#define GRN_QUERY_ADJ_NEG '~' +#endif /* GRN_QUERY_ADJ_NEG */ +#ifndef GRN_QUERY_PREFIX +#define GRN_QUERY_PREFIX '*' +#endif /* GRN_QUERY_PREFIX */ +#ifndef GRN_QUERY_PARENL +#define GRN_QUERY_PARENL '(' +#endif /* GRN_QUERY_PARENL */ +#ifndef GRN_QUERY_PARENR +#define GRN_QUERY_PARENR ')' +#endif /* GRN_QUERY_PARENR */ +#ifndef GRN_QUERY_QUOTEL +#define GRN_QUERY_QUOTEL '"' +#endif /* GRN_QUERY_QUOTEL */ +#ifndef GRN_QUERY_QUOTER +#define GRN_QUERY_QUOTER '"' +#endif /* GRN_QUERY_QUOTER */ +#ifndef GRN_QUERY_ESCAPE +#define GRN_QUERY_ESCAPE '\\' +#endif /* GRN_QUERY_ESCAPE */ +#ifndef GRN_QUERY_COLUMN +#define GRN_QUERY_COLUMN ':' +#endif /* GRN_QUERY_COLUMN */ + +typedef struct _grn_snip_mapping grn_snip_mapping; + +struct _grn_snip_mapping { + void *dummy; +}; + +#define GRN_SNIP_NORMALIZE (0x01<<0) +#define GRN_SNIP_COPY_TAG (0x01<<1) +#define GRN_SNIP_SKIP_LEADING_SPACES (0x01<<2) + +#define GRN_SNIP_MAPPING_HTML_ESCAPE ((grn_snip_mapping *)-1) + +GRN_API grn_obj *grn_snip_open(grn_ctx *ctx, int flags, unsigned int width, + unsigned int max_results, + const char *defaultopentag, unsigned int defaultopentag_len, + const char *defaultclosetag, unsigned int defaultclosetag_len, + grn_snip_mapping *mapping); +GRN_API grn_rc grn_snip_add_cond(grn_ctx *ctx, grn_obj *snip, + const char *keyword, unsigned int keyword_len, + const char *opentag, unsigned int opentag_len, + const char *closetag, unsigned int closetag_len); +GRN_API grn_rc grn_snip_set_normalizer(grn_ctx *ctx, grn_obj *snip, + grn_obj *normalizer); +GRN_API grn_obj *grn_snip_get_normalizer(grn_ctx *ctx, grn_obj *snip); +GRN_API grn_rc grn_snip_exec(grn_ctx *ctx, grn_obj *snip, + const char *string, unsigned int string_len, + unsigned int *nresults, unsigned int *max_tagged_len); +GRN_API grn_rc grn_snip_get_result(grn_ctx *ctx, grn_obj *snip, const unsigned int index, + char *result, unsigned int *result_len); + +/* log */ + +#define GRN_LOG_TIME (0x01<<0) +#define GRN_LOG_TITLE (0x01<<1) +#define GRN_LOG_MESSAGE (0x01<<2) +#define GRN_LOG_LOCATION (0x01<<3) + +/* Deprecated since 2.1.2. Use grn_logger instead. */ +typedef struct _grn_logger_info grn_logger_info; + +/* Deprecated since 2.1.2. Use grn_logger instead. */ +struct _grn_logger_info { + grn_log_level max_level; + int flags; + void (*func)(int, const char *, const char *, const char *, const char *, void *); + void *func_arg; +}; + +/* Deprecated since 2.1.2. Use grn_logger_set() instead. */ +GRN_API grn_rc grn_logger_info_set(grn_ctx *ctx, const grn_logger_info *info); + +typedef struct _grn_logger grn_logger; + +struct _grn_logger { + grn_log_level max_level; + int flags; + void *user_data; + void (*log)(grn_ctx *ctx, grn_log_level level, + const char *timestamp, const char *title, const char *message, + const char *location, void *user_data); + void (*reopen)(grn_ctx *ctx, void *user_data); + void (*fin)(grn_ctx *ctx, void *user_data); +}; + +GRN_API grn_rc grn_logger_set(grn_ctx *ctx, const grn_logger *logger); + +GRN_API void grn_logger_set_max_level(grn_ctx *ctx, grn_log_level max_level); +GRN_API grn_log_level grn_logger_get_max_level(grn_ctx *ctx); + +#ifdef __GNUC__ +#define GRN_ATTRIBUTE_PRINTF(fmt_pos) \ + __attribute__ ((format(printf, fmt_pos, fmt_pos + 1))) +#else +#define GRN_ATTRIBUTE_PRINTF(fmt_pos) +#endif /* __GNUC__ */ + +GRN_API void grn_logger_put(grn_ctx *ctx, grn_log_level level, + const char *file, int line, const char *func, const char *fmt, ...) GRN_ATTRIBUTE_PRINTF(6); +GRN_API void grn_logger_reopen(grn_ctx *ctx); + +GRN_API grn_bool grn_logger_pass(grn_ctx *ctx, grn_log_level level); + +#ifndef GRN_LOG_DEFAULT_LEVEL +#define GRN_LOG_DEFAULT_LEVEL GRN_LOG_NOTICE +#endif /* GRN_LOG_DEFAULT_LEVEL */ + +GRN_API void grn_default_logger_set_max_level(grn_log_level level); +GRN_API grn_log_level grn_default_logger_get_max_level(void); +GRN_API void grn_default_logger_set_path(const char *path); +GRN_API const char *grn_default_logger_get_path(void); + +#define GRN_LOG(ctx,level,...) do {\ + if (grn_logger_pass(ctx, level)) {\ + grn_logger_put(ctx, (level), __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \ + }\ +} while (0) + +typedef struct _grn_query_logger grn_query_logger; + +struct _grn_query_logger { + unsigned int flags; + void *user_data; + void (*log)(grn_ctx *ctx, unsigned int flag, + const char *timestamp, const char *info, const char *message, + void *user_data); + void (*reopen)(grn_ctx *ctx, void *user_data); + void (*fin)(grn_ctx *ctx, void *user_data); +}; + +GRN_API grn_rc grn_query_logger_set(grn_ctx *ctx, const grn_query_logger *logger); + +GRN_API void grn_query_logger_put(grn_ctx *ctx, unsigned int flag, + const char *mark, + const char *format, ...) GRN_ATTRIBUTE_PRINTF(4); +GRN_API void grn_query_logger_reopen(grn_ctx *ctx); + +GRN_API grn_bool grn_query_logger_pass(grn_ctx *ctx, unsigned int flag); + +GRN_API void grn_default_query_logger_set_flags(unsigned int flags); +GRN_API unsigned int grn_default_query_logger_get_flags(void); +GRN_API void grn_default_query_logger_set_path(const char *path); +GRN_API const char *grn_default_query_logger_get_path(void); + +#define GRN_QUERY_LOG(ctx, flag, mark, format, ...) do {\ + if (grn_query_logger_pass(ctx, flag)) {\ + grn_query_logger_put(ctx, (flag), (mark), format, __VA_ARGS__);\ + }\ +} while (0) + +/* grn_bulk */ + +#define GRN_BULK_BUFSIZE (sizeof(grn_obj) - sizeof(grn_obj_header)) +/* This assumes that GRN_BULK_BUFSIZE is less than 32 (= 0x20). */ +#define GRN_BULK_BUFSIZE_MAX 0x1f +#define GRN_BULK_SIZE_IN_FLAGS(flags) ((flags) & GRN_BULK_BUFSIZE_MAX) +#define GRN_BULK_OUTP(bulk) ((bulk)->header.impl_flags & GRN_OBJ_OUTPLACE) +#define GRN_BULK_REWIND(bulk) do {\ + if ((bulk)->header.type == GRN_VECTOR) {\ + grn_obj *_body = (bulk)->u.v.body;\ + if (_body) {\ + if (GRN_BULK_OUTP(_body)) {\ + (_body)->u.b.curr = (_body)->u.b.head;\ + } else {\ + (_body)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\ + }\ + }\ + (bulk)->u.v.n_sections = 0;\ + } else {\ + if (GRN_BULK_OUTP(bulk)) {\ + (bulk)->u.b.curr = (bulk)->u.b.head;\ + } else {\ + (bulk)->header.flags &= ~GRN_BULK_BUFSIZE_MAX;\ + }\ + }\ +} while (0) +#define GRN_BULK_WSIZE(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.tail - (bulk)->u.b.head)\ + : GRN_BULK_BUFSIZE) +#define GRN_BULK_REST(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.tail - (bulk)->u.b.curr)\ + : GRN_BULK_BUFSIZE - GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)) +#define GRN_BULK_VSIZE(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.curr - (bulk)->u.b.head)\ + : GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)) +#define GRN_BULK_EMPTYP(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.curr == (bulk)->u.b.head)\ + : !(GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags))) +#define GRN_BULK_HEAD(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.head)\ + : (char *)&((bulk)->u.b.head)) +#define GRN_BULK_CURR(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.curr)\ + : (char *)&((bulk)->u.b.head) + GRN_BULK_SIZE_IN_FLAGS((bulk)->header.flags)) +#define GRN_BULK_TAIL(bulk) \ + (GRN_BULK_OUTP(bulk)\ + ? ((bulk)->u.b.tail)\ + : (char *)&((bulk)[1])) + +GRN_API grn_rc grn_bulk_reinit(grn_ctx *ctx, grn_obj *bulk, unsigned int size); +GRN_API grn_rc grn_bulk_resize(grn_ctx *ctx, grn_obj *bulk, unsigned int newsize); +GRN_API grn_rc grn_bulk_write(grn_ctx *ctx, grn_obj *bulk, + const char *str, unsigned int len); +GRN_API grn_rc grn_bulk_write_from(grn_ctx *ctx, grn_obj *bulk, + const char *str, unsigned int from, unsigned int len); +GRN_API grn_rc grn_bulk_reserve(grn_ctx *ctx, grn_obj *bulk, unsigned int len); +GRN_API grn_rc grn_bulk_space(grn_ctx *ctx, grn_obj *bulk, unsigned int len); +GRN_API grn_rc grn_bulk_truncate(grn_ctx *ctx, grn_obj *bulk, unsigned int len); +GRN_API grn_rc grn_bulk_fin(grn_ctx *ctx, grn_obj *bulk); + +/* grn_text */ + +GRN_API grn_rc grn_text_itoa(grn_ctx *ctx, grn_obj *bulk, int i); +GRN_API grn_rc grn_text_itoa_padded(grn_ctx *ctx, grn_obj *bulk, int i, char ch, unsigned int len); +GRN_API grn_rc grn_text_lltoa(grn_ctx *ctx, grn_obj *bulk, long long int i); +GRN_API grn_rc grn_text_ftoa(grn_ctx *ctx, grn_obj *bulk, double d); +GRN_API grn_rc grn_text_itoh(grn_ctx *ctx, grn_obj *bulk, int i, unsigned int len); +GRN_API grn_rc grn_text_itob(grn_ctx *ctx, grn_obj *bulk, grn_id id); +GRN_API grn_rc grn_text_lltob32h(grn_ctx *ctx, grn_obj *bulk, long long int i); +GRN_API grn_rc grn_text_benc(grn_ctx *ctx, grn_obj *bulk, unsigned int v); +GRN_API grn_rc grn_text_esc(grn_ctx *ctx, grn_obj *bulk, const char *s, unsigned int len); +GRN_API grn_rc grn_text_urlenc(grn_ctx *ctx, grn_obj *buf, + const char *str, unsigned int len); +GRN_API const char *grn_text_urldec(grn_ctx *ctx, grn_obj *buf, + const char *s, const char *e, char d); +GRN_API grn_rc grn_text_escape_xml(grn_ctx *ctx, grn_obj *buf, + const char *s, unsigned int len); +GRN_API grn_rc grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec); +GRN_API grn_rc grn_text_printf(grn_ctx *ctx, grn_obj *bulk, + const char *format, ...) GRN_ATTRIBUTE_PRINTF(3); +GRN_API grn_rc grn_text_vprintf(grn_ctx *ctx, grn_obj *bulk, + const char *format, va_list args); + +GRN_API void grn_ctx_recv_handler_set(grn_ctx *, + void (*func)(grn_ctx *, int, void *), + void *func_arg); + +/* various values exchanged via grn_obj */ + +#define GRN_OBJ_DO_SHALLOW_COPY (GRN_OBJ_REFER|GRN_OBJ_OUTPLACE) +#define GRN_OBJ_VECTOR (0x01<<7) + +#define GRN_OBJ_MUTABLE(obj) ((obj) && (obj)->header.type <= GRN_VECTOR) + +#define GRN_VALUE_FIX_SIZE_INIT(obj,flags,domain)\ + GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK,\ + ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain)) +#define GRN_VALUE_VAR_SIZE_INIT(obj,flags,domain)\ + GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_VECTOR : GRN_BULK,\ + ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain)) + +#define GRN_VOID_INIT(obj) GRN_OBJ_INIT((obj), GRN_VOID, 0, GRN_DB_VOID) +#define GRN_TEXT_INIT(obj,flags) \ + GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_TEXT) +#define GRN_SHORT_TEXT_INIT(obj,flags) \ + GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_SHORT_TEXT) +#define GRN_LONG_TEXT_INIT(obj,flags) \ + GRN_VALUE_VAR_SIZE_INIT(obj, flags, GRN_DB_LONG_TEXT) +#define GRN_TEXT_SET_REF(obj,str,len) do {\ + (obj)->u.b.head = (char *)(str);\ + (obj)->u.b.curr = (char *)(str) + (len);\ +} while (0) +#define GRN_TEXT_SET(ctx,obj,str,len) do {\ + if ((obj)->header.impl_flags & GRN_OBJ_REFER) {\ + GRN_TEXT_SET_REF((obj), (str), (len));\ + } else {\ + grn_bulk_write_from((ctx), (obj), (const char *)(str), 0, (unsigned int)(len));\ + }\ +} while (0) +#define GRN_TEXT_PUT(ctx,obj,str,len) \ + grn_bulk_write((ctx), (obj), (const char *)(str), (unsigned int)(len)) +#define GRN_TEXT_PUTC(ctx,obj,c) do {\ + char _c = (c); grn_bulk_write((ctx), (obj), &_c, 1);\ +} while (0) + +#define GRN_TEXT_PUTS(ctx,obj,str) GRN_TEXT_PUT((ctx), (obj), (str), strlen(str)) +#define GRN_TEXT_SETS(ctx,obj,str) GRN_TEXT_SET((ctx), (obj), (str), strlen(str)) +#define GRN_TEXT_VALUE(obj) GRN_BULK_HEAD(obj) +#define GRN_TEXT_LEN(obj) GRN_BULK_VSIZE(obj) + +#define GRN_BOOL_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_BOOL) +#define GRN_INT8_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT8) +#define GRN_UINT8_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT8) +#define GRN_INT16_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT16) +#define GRN_UINT16_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT16) +#define GRN_INT32_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT32) +#define GRN_UINT32_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT32) +#define GRN_INT64_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_INT64) +#define GRN_UINT64_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_UINT64) +#define GRN_FLOAT_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_FLOAT) +#define GRN_TIME_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TIME) +#define GRN_RECORD_INIT GRN_VALUE_FIX_SIZE_INIT +#define GRN_PTR_INIT(obj,flags,domain)\ + GRN_OBJ_INIT((obj), ((flags) & GRN_OBJ_VECTOR) ? GRN_PVECTOR : GRN_PTR,\ + ((flags) & GRN_OBJ_DO_SHALLOW_COPY), (domain)) +#define GRN_TOKYO_GEO_POINT_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_TOKYO_GEO_POINT) +#define GRN_WGS84_GEO_POINT_INIT(obj,flags) \ + GRN_VALUE_FIX_SIZE_INIT(obj, flags, GRN_DB_WGS84_GEO_POINT) + +#define GRN_BOOL_SET(ctx,obj,val) do {\ + unsigned char _val = (unsigned char)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\ +} while (0) +#define GRN_INT8_SET(ctx,obj,val) do {\ + signed char _val = (signed char)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed char));\ +} while (0) +#define GRN_UINT8_SET(ctx,obj,val) do {\ + unsigned char _val = (unsigned char)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned char));\ +} while (0) +#define GRN_INT16_SET(ctx,obj,val) do {\ + signed short _val = (signed short)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(signed short));\ +} while (0) +#define GRN_UINT16_SET(ctx,obj,val) do {\ + unsigned short _val = (unsigned short)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned short));\ +} while (0) +#define GRN_INT32_SET(ctx,obj,val) do {\ + int _val = (int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(int));\ +} while (0) +#define GRN_UINT32_SET(ctx,obj,val) do {\ + unsigned int _val = (unsigned int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(unsigned int));\ +} while (0) +#define GRN_INT64_SET(ctx,obj,val) do {\ + long long int _val = (long long int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long int));\ +} while (0) +#define GRN_UINT64_SET(ctx,obj,val) do {\ + long long unsigned int _val = (long long unsigned int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(long long unsigned int));\ +} while (0) +#define GRN_FLOAT_SET(ctx,obj,val) do {\ + double _val = (double)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(double));\ +} while (0) +#define GRN_TIME_SET GRN_INT64_SET +#define GRN_RECORD_SET(ctx,obj,val) do {\ + grn_id _val = (grn_id)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_id));\ +} while (0) +#define GRN_PTR_SET(ctx,obj,val) do {\ + grn_obj *_val = (grn_obj *)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_obj *));\ +} while (0) + +#define GRN_GEO_DEGREE2MSEC(degree)\ + ((int)((degree) * 3600 * 1000 + ((degree) > 0 ? 0.5 : -0.5))) +#define GRN_GEO_MSEC2DEGREE(msec)\ + ((((int)(msec)) / 3600.0) * 0.001) + +#define GRN_GEO_POINT_SET(ctx,obj,_latitude,_longitude) do {\ + grn_geo_point _val;\ + _val.latitude = (int)(_latitude);\ + _val.longitude = (int)(_longitude);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val, 0, sizeof(grn_geo_point));\ +} while (0) + +#define GRN_BOOL_SET_AT(ctx,obj,offset,val) do {\ + unsigned char _val = (unsigned char)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset), sizeof(unsigned char));\ +} while (0) +#define GRN_INT8_SET_AT(ctx,obj,offset,val) do {\ + signed char _val = (signed char)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(signed char), sizeof(signed char));\ +} while (0) +#define GRN_UINT8_SET_AT(ctx,obj,offset,val) do { \ + unsigned char _val = (unsigned char)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(unsigned char), sizeof(unsigned char));\ +} while (0) +#define GRN_INT16_SET_AT(ctx,obj,offset,val) do {\ + signed short _val = (signed short)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(signed short), sizeof(signed short));\ +} while (0) +#define GRN_UINT16_SET_AT(ctx,obj,offset,val) do { \ + unsigned short _val = (unsigned short)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(unsigned short), sizeof(unsigned short));\ +} while (0) +#define GRN_INT32_SET_AT(ctx,obj,offset,val) do {\ + int _val = (int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(int), sizeof(int));\ +} while (0) +#define GRN_UINT32_SET_AT(ctx,obj,offset,val) do { \ + unsigned int _val = (unsigned int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(unsigned int), sizeof(unsigned int));\ +} while (0) +#define GRN_INT64_SET_AT(ctx,obj,offset,val) do {\ + long long int _val = (long long int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(long long int), sizeof(long long int));\ +} while (0) +#define GRN_UINT64_SET_AT(ctx,obj,offset,val) do {\ + long long unsigned int _val = (long long unsigned int)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(long long unsigned int),\ + sizeof(long long unsigned int));\ +} while (0) +#define GRN_FLOAT_SET_AT(ctx,obj,offset,val) do {\ + double _val = (double)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(double), sizeof(double));\ +} while (0) +#define GRN_TIME_SET_AT GRN_INT64_SET_AT +#define GRN_RECORD_SET_AT(ctx,obj,offset,val) do {\ + grn_id _val = (grn_id)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(grn_id), sizeof(grn_id));\ +} while (0) +#define GRN_PTR_SET_AT(ctx,obj,offset,val) do {\ + grn_obj *_val = (grn_obj *)(val);\ + grn_bulk_write_from((ctx), (obj), (char *)&_val,\ + (offset) * sizeof(grn_obj *), sizeof(grn_obj *));\ +} while (0) + +#define GRN_TIME_USEC_PER_SEC 1000000 +#define GRN_TIME_PACK(sec, usec) ((long long int)(sec) * GRN_TIME_USEC_PER_SEC + (usec)) +#define GRN_TIME_UNPACK(time_value, sec, usec) do {\ + sec = (time_value) / GRN_TIME_USEC_PER_SEC;\ + usec = (time_value) % GRN_TIME_USEC_PER_SEC;\ +} while (0) + +GRN_API void grn_time_now(grn_ctx *ctx, grn_obj *obj); + +#define GRN_TIME_NOW(ctx,obj) (grn_time_now((ctx), (obj))) + +#define GRN_BOOL_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj))) +#define GRN_INT8_VALUE(obj) (*((signed char *)GRN_BULK_HEAD(obj))) +#define GRN_UINT8_VALUE(obj) (*((unsigned char *)GRN_BULK_HEAD(obj))) +#define GRN_INT16_VALUE(obj) (*((signed short *)GRN_BULK_HEAD(obj))) +#define GRN_UINT16_VALUE(obj) (*((unsigned short *)GRN_BULK_HEAD(obj))) +#define GRN_INT32_VALUE(obj) (*((int *)GRN_BULK_HEAD(obj))) +#define GRN_UINT32_VALUE(obj) (*((unsigned int *)GRN_BULK_HEAD(obj))) +#define GRN_INT64_VALUE(obj) (*((long long int *)GRN_BULK_HEAD(obj))) +#define GRN_UINT64_VALUE(obj) (*((long long unsigned int *)GRN_BULK_HEAD(obj))) +#define GRN_FLOAT_VALUE(obj) (*((double *)GRN_BULK_HEAD(obj))) +#define GRN_TIME_VALUE GRN_INT64_VALUE +#define GRN_RECORD_VALUE(obj) (*((grn_id *)GRN_BULK_HEAD(obj))) +#define GRN_PTR_VALUE(obj) (*((grn_obj **)GRN_BULK_HEAD(obj))) +#define GRN_GEO_POINT_VALUE(obj,_latitude,_longitude) do {\ + grn_geo_point *_val = (grn_geo_point *)GRN_BULK_HEAD(obj);\ + _latitude = _val->latitude;\ + _longitude = _val->longitude;\ +} while (0) + +#define GRN_BOOL_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_INT8_VALUE_AT(obj,offset) (((signed char *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_UINT8_VALUE_AT(obj,offset) (((unsigned char *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_INT16_VALUE_AT(obj,offset) (((signed short *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_UINT16_VALUE_AT(obj,offset) (((unsigned short *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_INT32_VALUE_AT(obj,offset) (((int *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_UINT32_VALUE_AT(obj,offset) (((unsigned int *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_INT64_VALUE_AT(obj,offset) (((long long int *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_UINT64_VALUE_AT(obj,offset) (((long long unsigned int *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_FLOAT_VALUE_AT(obj,offset) (((double *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_TIME_VALUE_AT GRN_INT64_VALUE_AT +#define GRN_RECORD_VALUE_AT(obj,offset) (((grn_id *)GRN_BULK_HEAD(obj))[offset]) +#define GRN_PTR_VALUE_AT(obj,offset) (((grn_obj **)GRN_BULK_HEAD(obj))[offset]) + +#define GRN_BOOL_PUT(ctx,obj,val) do {\ + unsigned char _val = (unsigned char)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\ +} while (0) +#define GRN_INT8_PUT(ctx,obj,val) do {\ + signed char _val = (signed char)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed char));\ +} while (0) +#define GRN_UINT8_PUT(ctx,obj,val) do {\ + unsigned char _val = (unsigned char)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned char));\ +} while (0) +#define GRN_INT16_PUT(ctx,obj,val) do {\ + signed short _val = (signed short)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(signed short));\ +} while (0) +#define GRN_UINT16_PUT(ctx,obj,val) do {\ + unsigned short _val = (unsigned short)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned short));\ +} while (0) +#define GRN_INT32_PUT(ctx,obj,val) do {\ + int _val = (int)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(int));\ +} while (0) +#define GRN_UINT32_PUT(ctx,obj,val) do {\ + unsigned int _val = (unsigned int)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(unsigned int));\ +} while (0) +#define GRN_INT64_PUT(ctx,obj,val) do {\ + long long int _val = (long long int)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long int));\ +} while (0) +#define GRN_UINT64_PUT(ctx,obj,val) do {\ + long long unsigned int _val = (long long unsigned int)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(long long unsigned int));\ +} while (0) +#define GRN_FLOAT_PUT(ctx,obj,val) do {\ + double _val = (double)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(double));\ +} while (0) +#define GRN_TIME_PUT GRN_INT64_PUT +#define GRN_RECORD_PUT(ctx,obj,val) do {\ + grn_id _val = (grn_id)(val); grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_id));\ +} while (0) +#define GRN_PTR_PUT(ctx,obj,val) do {\ + grn_obj *_val = (grn_obj *)(val);\ + grn_bulk_write((ctx), (obj), (char *)&_val, sizeof(grn_obj *));\ +} while (0) + +/* grn_str: deprecated. use grn_string instead. */ + +typedef struct { + const char *orig; + char *norm; + short *checks; + unsigned char *ctypes; + int flags; + unsigned int orig_blen; + unsigned int norm_blen; + unsigned int length; + grn_encoding encoding; +} grn_str; + +#define GRN_STR_REMOVEBLANK (0x01<<0) +#define GRN_STR_WITH_CTYPES (0x01<<1) +#define GRN_STR_WITH_CHECKS (0x01<<2) +#define GRN_STR_NORMALIZE GRN_OBJ_KEY_NORMALIZE + +GRN_API grn_str *grn_str_open(grn_ctx *ctx, const char *str, unsigned int str_len, + int flags); +GRN_API grn_rc grn_str_close(grn_ctx *ctx, grn_str *nstr); + +/* grn_string */ + +#define GRN_STRING_REMOVE_BLANK (0x01<<0) +#define GRN_STRING_WITH_TYPES (0x01<<1) +#define GRN_STRING_WITH_CHECKS (0x01<<2) +#define GRN_STRING_REMOVE_TOKENIZED_DELIMITER (0x01<<3) + +#define GRN_NORMALIZER_AUTO ((grn_obj *)1) + +#define GRN_CHAR_BLANK 0x80 +#define GRN_CHAR_IS_BLANK(c) ((c) & (GRN_CHAR_BLANK)) +#define GRN_CHAR_TYPE(c) ((c) & 0x7f) + +typedef enum { + GRN_CHAR_NULL = 0, + GRN_CHAR_ALPHA, + GRN_CHAR_DIGIT, + GRN_CHAR_SYMBOL, + GRN_CHAR_HIRAGANA, + GRN_CHAR_KATAKANA, + GRN_CHAR_KANJI, + GRN_CHAR_OTHERS +} grn_char_type; + +GRN_API grn_obj *grn_string_open(grn_ctx *ctx, + const char *string, + unsigned int length_in_bytes, + grn_obj *normalizer, int flags); +GRN_API grn_rc grn_string_get_original(grn_ctx *ctx, grn_obj *string, + const char **original, + unsigned int *length_in_bytes); +GRN_API int grn_string_get_flags(grn_ctx *ctx, grn_obj *string); +GRN_API grn_rc grn_string_get_normalized(grn_ctx *ctx, grn_obj *string, + const char **normalized, + unsigned int *length_in_bytes, + unsigned int *n_characters); +GRN_API grn_rc grn_string_set_normalized(grn_ctx *ctx, grn_obj *string, + char *normalized, + unsigned int length_in_bytes, + unsigned int n_characters); +GRN_API const short *grn_string_get_checks(grn_ctx *ctx, grn_obj *string); +GRN_API grn_rc grn_string_set_checks(grn_ctx *ctx, + grn_obj *string, + short *checks); +GRN_API const unsigned char *grn_string_get_types(grn_ctx *ctx, grn_obj *string); +GRN_API grn_rc grn_string_set_types(grn_ctx *ctx, + grn_obj *string, + unsigned char *types); +GRN_API grn_encoding grn_string_get_encoding(grn_ctx *ctx, grn_obj *string); + + +GRN_API int grn_charlen(grn_ctx *ctx, const char *str, const char *end); + +GRN_API grn_rc grn_ctx_push(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_obj *grn_ctx_pop(grn_ctx *ctx); + +GRN_API grn_obj *grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, + grn_obj *res, grn_operator op); + +GRN_API int grn_obj_columns(grn_ctx *ctx, grn_obj *table, + const char *str, unsigned int str_size, grn_obj *res); + +GRN_API grn_table_sort_key *grn_table_sort_key_from_str(grn_ctx *ctx, + const char *str, unsigned int str_size, + grn_obj *table, unsigned int *nkeys); +GRN_API grn_rc grn_table_sort_key_close(grn_ctx *ctx, + grn_table_sort_key *keys, unsigned int nkeys); + +GRN_API grn_bool grn_table_is_grouped(grn_ctx *ctx, grn_obj *table); + +GRN_API unsigned int grn_table_max_n_subrecs(grn_ctx *ctx, grn_obj *table); + +GRN_API grn_obj *grn_table_create_for_group(grn_ctx *ctx, + const char *name, + unsigned int name_size, + const char *path, + grn_obj *group_key, + grn_obj *value_type, + unsigned int max_n_subrecs); + +GRN_API unsigned int grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, + grn_id id, grn_id *subrecbuf, + int *scorebuf, int buf_size); + +GRN_API grn_obj *grn_table_tokenize(grn_ctx *ctx, grn_obj *table, + const char *str, unsigned int str_len, + grn_obj *buf, grn_bool addp); + +GRN_API grn_rc grn_load(grn_ctx *ctx, grn_content_type input_type, + const char *table, unsigned int table_len, + const char *columns, unsigned int columns_len, + const char *values, unsigned int values_len, + const char *ifexists, unsigned int ifexists_len, + const char *each, unsigned int each_len); + +#define GRN_CTX_MORE (0x01<<0) +#define GRN_CTX_TAIL (0x01<<1) +#define GRN_CTX_HEAD (0x01<<2) +#define GRN_CTX_QUIET (0x01<<3) +#define GRN_CTX_QUIT (0x01<<4) + +GRN_API grn_rc grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags); +GRN_API unsigned int grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags); +GRN_API unsigned int grn_ctx_recv(grn_ctx *ctx, char **str, unsigned int *str_len, int *flags); + +typedef struct _grn_ctx_info grn_ctx_info; + +struct _grn_ctx_info { + int fd; + unsigned int com_status; + grn_obj *outbuf; + unsigned char stat; +}; + +GRN_API grn_rc grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info); + +GRN_API grn_rc grn_set_segv_handler(void); +GRN_API grn_rc grn_set_int_handler(void); +GRN_API grn_rc grn_set_term_handler(void); + +/* hash */ + +typedef struct _grn_hash grn_hash; +typedef struct _grn_hash_cursor grn_hash_cursor; + +GRN_API grn_hash *grn_hash_create(grn_ctx *ctx, const char *path, unsigned int key_size, + unsigned int value_size, unsigned int flags); + +GRN_API grn_hash *grn_hash_open(grn_ctx *ctx, const char *path); + +GRN_API grn_rc grn_hash_close(grn_ctx *ctx, grn_hash *hash); + +GRN_API grn_id grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, + unsigned int key_size, void **value, int *added); +GRN_API grn_id grn_hash_get(grn_ctx *ctx, grn_hash *hash, const void *key, + unsigned int key_size, void **value); + +GRN_API int grn_hash_get_key(grn_ctx *ctx, grn_hash *hash, grn_id id, void *keybuf, int bufsize); +GRN_API int grn_hash_get_key2(grn_ctx *ctx, grn_hash *hash, grn_id id, grn_obj *bulk); +GRN_API int grn_hash_get_value(grn_ctx *ctx, grn_hash *hash, grn_id id, void *valuebuf); +GRN_API grn_rc grn_hash_set_value(grn_ctx *ctx, grn_hash *hash, grn_id id, + const void *value, int flags); + +typedef struct _grn_table_delete_optarg grn_table_delete_optarg; + +struct _grn_table_delete_optarg { + int flags; + int (*func)(grn_ctx *ctx, grn_obj *, grn_id, void *); + void *func_arg; +}; + +GRN_API grn_rc grn_hash_delete_by_id(grn_ctx *ctx, grn_hash *hash, grn_id id, + grn_table_delete_optarg *optarg); +GRN_API grn_rc grn_hash_delete(grn_ctx *ctx, grn_hash *hash, + const void *key, unsigned int key_size, + grn_table_delete_optarg *optarg); + +GRN_API grn_hash_cursor *grn_hash_cursor_open(grn_ctx *ctx, grn_hash *hash, + const void *min, unsigned int min_size, + const void *max, unsigned int max_size, + int offset, int limit, int flags); +GRN_API grn_id grn_hash_cursor_next(grn_ctx *ctx, grn_hash_cursor *c); +GRN_API void grn_hash_cursor_close(grn_ctx *ctx, grn_hash_cursor *c); + +GRN_API int grn_hash_cursor_get_key(grn_ctx *ctx, grn_hash_cursor *c, void **key); +GRN_API int grn_hash_cursor_get_value(grn_ctx *ctx, grn_hash_cursor *c, void **value); +GRN_API grn_rc grn_hash_cursor_set_value(grn_ctx *ctx, grn_hash_cursor *c, + const void *value, int flags); + +GRN_API int grn_hash_cursor_get_key_value(grn_ctx *ctx, grn_hash_cursor *c, + void **key, unsigned int *key_size, void **value); + +GRN_API grn_rc grn_hash_cursor_delete(grn_ctx *ctx, grn_hash_cursor *c, + grn_table_delete_optarg *optarg); + +#define GRN_HASH_EACH(ctx,hash,id,key,key_size,value,block) do {\ + grn_hash_cursor *_sc = grn_hash_cursor_open(ctx, hash, NULL, 0, NULL, 0, 0, -1, 0); \ + if (_sc) {\ + grn_id id;\ + while ((id = grn_hash_cursor_next(ctx, _sc))) {\ + grn_hash_cursor_get_key_value(ctx, _sc, (void **)(key),\ + (key_size), (void **)(value));\ + block\ + }\ + grn_hash_cursor_close(ctx, _sc);\ + }\ +} while (0) + +/* array */ + +typedef struct _grn_array grn_array; +typedef struct _grn_array_cursor grn_array_cursor; + +GRN_API grn_array *grn_array_create(grn_ctx *ctx, const char *path, + unsigned int value_size, unsigned int flags); +GRN_API grn_array *grn_array_open(grn_ctx *ctx, const char *path); +GRN_API grn_rc grn_array_close(grn_ctx *ctx, grn_array *array); +GRN_API grn_id grn_array_add(grn_ctx *ctx, grn_array *array, void **value); +GRN_API grn_id grn_array_push(grn_ctx *ctx, grn_array *array, + void (*func)(grn_ctx *ctx, grn_array *array, + grn_id id, void *func_arg), + void *func_arg); +GRN_API grn_id grn_array_pull(grn_ctx *ctx, grn_array *array, grn_bool blockp, + void (*func)(grn_ctx *ctx, grn_array *array, + grn_id id, void *func_arg), + void *func_arg); +GRN_API void grn_array_unblock(grn_ctx *ctx, grn_array *array); +GRN_API int grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf); +GRN_API grn_rc grn_array_set_value(grn_ctx *ctx, grn_array *array, grn_id id, + const void *value, int flags); +GRN_API grn_array_cursor *grn_array_cursor_open(grn_ctx *ctx, grn_array *array, + grn_id min, grn_id max, + int offset, int limit, int flags); +GRN_API grn_id grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor); +GRN_API int grn_array_cursor_get_value(grn_ctx *ctx, grn_array_cursor *cursor, void **value); +GRN_API grn_rc grn_array_cursor_set_value(grn_ctx *ctx, grn_array_cursor *cursor, + const void *value, int flags); +GRN_API grn_rc grn_array_cursor_delete(grn_ctx *ctx, grn_array_cursor *cursor, + grn_table_delete_optarg *optarg); +GRN_API void grn_array_cursor_close(grn_ctx *ctx, grn_array_cursor *cursor); +GRN_API grn_rc grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id, + grn_table_delete_optarg *optarg); + +GRN_API grn_id grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id); + +GRN_API void *_grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id); + +#define GRN_ARRAY_EACH(ctx,array,head,tail,id,value,block) do {\ + grn_array_cursor *_sc = grn_array_cursor_open(ctx, array, head, tail, 0, -1, 0); \ + if (_sc) {\ + grn_id id;\ + while ((id = grn_array_cursor_next(ctx, _sc))) {\ + grn_array_cursor_get_value(ctx, _sc, (void **)(value));\ + block\ + }\ + grn_array_cursor_close(ctx, _sc); \ + }\ +} while (0) + +/* pat */ + +typedef struct _grn_pat grn_pat; +typedef struct _grn_pat_cursor grn_pat_cursor; + +GRN_API grn_pat *grn_pat_create(grn_ctx *ctx, const char *path, unsigned int key_size, + unsigned int value_size, unsigned int flags); + +GRN_API grn_pat *grn_pat_open(grn_ctx *ctx, const char *path); + +GRN_API grn_rc grn_pat_close(grn_ctx *ctx, grn_pat *pat); + +GRN_API grn_rc grn_pat_remove(grn_ctx *ctx, const char *path); + +GRN_API grn_id grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key, + unsigned int key_size, void **value); +GRN_API grn_id grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key, + unsigned int key_size, void **value, int *added); + +GRN_API int grn_pat_get_key(grn_ctx *ctx, grn_pat *pat, grn_id id, void *keybuf, int bufsize); +GRN_API int grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk); +GRN_API int grn_pat_get_value(grn_ctx *ctx, grn_pat *pat, grn_id id, void *valuebuf); +GRN_API grn_rc grn_pat_set_value(grn_ctx *ctx, grn_pat *pat, grn_id id, + const void *value, int flags); + +GRN_API grn_rc grn_pat_delete_by_id(grn_ctx *ctx, grn_pat *pat, grn_id id, + grn_table_delete_optarg *optarg); +GRN_API grn_rc grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, unsigned int key_size, + grn_table_delete_optarg *optarg); +GRN_API int grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id, + grn_table_delete_optarg *optarg); + +typedef struct _grn_table_scan_hit grn_pat_scan_hit; +typedef struct _grn_table_scan_hit grn_dat_scan_hit; + +struct _grn_table_scan_hit { + grn_id id; + unsigned int offset; + unsigned int length; +}; + +GRN_API int grn_pat_scan(grn_ctx *ctx, grn_pat *pat, const char *str, unsigned int str_len, + grn_pat_scan_hit *sh, unsigned int sh_size, const char **rest); + +GRN_API grn_rc grn_pat_prefix_search(grn_ctx *ctx, grn_pat *pat, + const void *key, unsigned int key_size, grn_hash *h); +GRN_API grn_rc grn_pat_suffix_search(grn_ctx *ctx, grn_pat *pat, + const void *key, unsigned int key_size, grn_hash *h); +GRN_API grn_id grn_pat_lcp_search(grn_ctx *ctx, grn_pat *pat, + const void *key, unsigned int key_size); + +GRN_API unsigned int grn_pat_size(grn_ctx *ctx, grn_pat *pat); + +GRN_API grn_pat_cursor *grn_pat_cursor_open(grn_ctx *ctx, grn_pat *pat, + const void *min, unsigned int min_size, + const void *max, unsigned int max_size, + int offset, int limit, int flags); +GRN_API grn_id grn_pat_cursor_next(grn_ctx *ctx, grn_pat_cursor *c); +GRN_API void grn_pat_cursor_close(grn_ctx *ctx, grn_pat_cursor *c); + +GRN_API int grn_pat_cursor_get_key(grn_ctx *ctx, grn_pat_cursor *c, void **key); +GRN_API int grn_pat_cursor_get_value(grn_ctx *ctx, grn_pat_cursor *c, void **value); + +GRN_API int grn_pat_cursor_get_key_value(grn_ctx *ctx, grn_pat_cursor *c, + void **key, unsigned int *key_size, void **value); +GRN_API grn_rc grn_pat_cursor_set_value(grn_ctx *ctx, grn_pat_cursor *c, + const void *value, int flags); +GRN_API grn_rc grn_pat_cursor_delete(grn_ctx *ctx, grn_pat_cursor *c, + grn_table_delete_optarg *optarg); + +#define GRN_PAT_EACH(ctx,pat,id,key,key_size,value,block) do { \ + grn_pat_cursor *_sc = grn_pat_cursor_open(ctx, pat, NULL, 0, NULL, 0, 0, -1, 0); \ + if (_sc) {\ + grn_id id;\ + while ((id = grn_pat_cursor_next(ctx, _sc))) {\ + grn_pat_cursor_get_key_value(ctx, _sc, (void **)(key),\ + (key_size), (void **)(value));\ + block\ + }\ + grn_pat_cursor_close(ctx, _sc);\ + }\ +} while (0) + +/* dat */ + +typedef struct _grn_dat grn_dat; +typedef struct _grn_dat_cursor grn_dat_cursor; + +GRN_API int grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str, + unsigned int str_size, grn_dat_scan_hit *scan_hits, + unsigned int max_num_scan_hits, const char **str_rest); + +GRN_API grn_id grn_dat_lcp_search(grn_ctx *ctx, grn_dat *dat, + const void *key, unsigned int key_size); + +GRN_API grn_dat *grn_dat_create(grn_ctx *ctx, const char *path, unsigned int key_size, + unsigned int value_size, unsigned int flags); + +GRN_API grn_dat *grn_dat_open(grn_ctx *ctx, const char *path); + +GRN_API grn_rc grn_dat_close(grn_ctx *ctx, grn_dat *dat); + +GRN_API grn_rc grn_dat_remove(grn_ctx *ctx, const char *path); + +GRN_API grn_id grn_dat_get(grn_ctx *ctx, grn_dat *dat, const void *key, + unsigned int key_size, void **value); +GRN_API grn_id grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key, + unsigned int key_size, void **value, int *added); + +GRN_API int grn_dat_get_key(grn_ctx *ctx, grn_dat *dat, grn_id id, void *keybuf, int bufsize); +GRN_API int grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk); + +GRN_API grn_rc grn_dat_delete_by_id(grn_ctx *ctx, grn_dat *dat, grn_id id, + grn_table_delete_optarg *optarg); +GRN_API grn_rc grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_size, + grn_table_delete_optarg *optarg); + +GRN_API grn_rc grn_dat_update_by_id(grn_ctx *ctx, grn_dat *dat, grn_id src_key_id, + const void *dest_key, unsigned int dest_key_size); +GRN_API grn_rc grn_dat_update(grn_ctx *ctx, grn_dat *dat, + const void *src_key, unsigned int src_key_size, + const void *dest_key, unsigned int dest_key_size); + +GRN_API unsigned int grn_dat_size(grn_ctx *ctx, grn_dat *dat); + +GRN_API grn_dat_cursor *grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat, + const void *min, unsigned int min_size, + const void *max, unsigned int max_size, + int offset, int limit, int flags); +GRN_API grn_id grn_dat_cursor_next(grn_ctx *ctx, grn_dat_cursor *c); +GRN_API void grn_dat_cursor_close(grn_ctx *ctx, grn_dat_cursor *c); + +GRN_API int grn_dat_cursor_get_key(grn_ctx *ctx, grn_dat_cursor *c, const void **key); +GRN_API grn_rc grn_dat_cursor_delete(grn_ctx *ctx, grn_dat_cursor *c, + grn_table_delete_optarg *optarg); + +#define GRN_DAT_EACH(ctx,dat,id,key,key_size,block) do {\ + grn_dat_cursor *_sc = grn_dat_cursor_open(ctx, dat, NULL, 0, NULL, 0, 0, -1, 0);\ + if (_sc) {\ + grn_id id;\ + unsigned int *_ks = (key_size);\ + if (_ks) {\ + while ((id = grn_dat_cursor_next(ctx, _sc))) {\ + int _ks_raw = grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\ + *(_ks) = (unsigned int)_ks_raw;\ + block\ + }\ + } else {\ + while ((id = grn_dat_cursor_next(ctx, _sc))) {\ + grn_dat_cursor_get_key(ctx, _sc, (const void **)(key));\ + block\ + }\ + }\ + grn_dat_cursor_close(ctx, _sc);\ + }\ +} while (0) + +#ifdef __cplusplus +} +#endif + +#endif /* GROONGA_GROONGA_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/ii.h b/storage/mroonga/vendor/groonga/include/groonga/ii.h new file mode 100644 index 00000000000..1bd8ce25309 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/ii.h @@ -0,0 +1,46 @@ +/* + Copyright(C) 2009-2014 Brazil + + This library 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 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_II_H +#define GROONGA_II_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* buffered index builder */ + +typedef struct _grn_ii grn_ii; +typedef struct _grn_ii_buffer grn_ii_buffer; + +GRN_API unsigned int grn_ii_estimate_size(grn_ctx *ctx, grn_ii *ii, grn_id tid); + +GRN_API grn_ii_buffer *grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii, + long long unsigned int update_buffer_size); +GRN_API grn_rc grn_ii_buffer_append(grn_ctx *ctx, + grn_ii_buffer *ii_buffer, + grn_id rid, + unsigned int section, + grn_obj *value); +GRN_API grn_rc grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer); +GRN_API grn_rc grn_ii_buffer_close(grn_ctx *ctx, grn_ii_buffer *ii_buffer); + +#ifdef __cplusplus +} +#endif + +#endif /* GROONGA_II_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/nfkc.h b/storage/mroonga/vendor/groonga/include/groonga/nfkc.h index 3b7e294fb97..f4e628de53c 100644 --- a/storage/mroonga/vendor/groonga/include/groonga/nfkc.h +++ b/storage/mroonga/vendor/groonga/include/groonga/nfkc.h @@ -14,8 +14,8 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_NFKC_H -#define GRN_NFKC_H +#ifndef GROONGA_NFKC_H +#define GROONGA_NFKC_H #include <groonga.h> @@ -29,4 +29,4 @@ GRN_API grn_char_type grn_nfkc_char_type(const unsigned char *str); } #endif -#endif /* GRN_NFKC_H */ +#endif /* GROONGA_NFKC_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/obj.h b/storage/mroonga/vendor/groonga/include/groonga/obj.h new file mode 100644 index 00000000000..7544a6cb382 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/obj.h @@ -0,0 +1,37 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library 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 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_OBJ_H +#define GROONGA_OBJ_H + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API grn_bool grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_bool grn_obj_is_table(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_bool grn_obj_is_proc(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_bool grn_obj_is_function_proc(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_bool grn_obj_is_selector_proc(grn_ctx *ctx, grn_obj *obj); +GRN_API grn_bool grn_obj_is_scorer_proc(grn_ctx *ctx, grn_obj *obj); + +#ifdef __cplusplus +} +#endif + +#endif /* GROONGA_OBJ_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/output.h b/storage/mroonga/vendor/groonga/include/groonga/output.h new file mode 100644 index 00000000000..fc23bb2db01 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/output.h @@ -0,0 +1,108 @@ +/* + Copyright(C) 2009-2015 Brazil + + This library 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 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_OUTPUT_H +#define GROONGA_OUTPUT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _grn_obj_format grn_obj_format; + +#define GRN_OBJ_FORMAT_WITH_COLUMN_NAMES (0x01<<0) +#define GRN_OBJ_FORMAT_AS_ARRAY (0x01<<3) +/* Deprecated since 4.0.1. It will be removed at 5.0.0. + Use GRN_OBJ_FORMAT_AS_ARRAY instead.*/ +#define GRN_OBJ_FORMAT_ASARRAY GRN_OBJ_FORMAT_AS_ARRAY +#define GRN_OBJ_FORMAT_WITH_WEIGHT (0x01<<4) + +struct _grn_obj_format { + grn_obj columns; + const void *min; + const void *max; + unsigned int min_size; + unsigned int max_size; + int nhits; + int offset; + int limit; + int hits_offset; + int flags; + grn_obj *expression; +}; + +#define GRN_OBJ_FORMAT_INIT(format,format_nhits,format_offset,format_limit,format_hits_offset) do { \ + GRN_PTR_INIT(&(format)->columns, GRN_OBJ_VECTOR, GRN_ID_NIL);\ + (format)->nhits = (format_nhits);\ + (format)->offset = (format_offset);\ + (format)->limit = (format_limit);\ + (format)->hits_offset = (format_hits_offset);\ + (format)->flags = 0;\ + (format)->expression = NULL;\ +} while (0) + +#define GRN_OBJ_FORMAT_FIN(ctx,format) do {\ + int ncolumns = GRN_BULK_VSIZE(&(format)->columns) / sizeof(grn_obj *);\ + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&(format)->columns);\ + while (ncolumns--) { grn_obj_unlink((ctx), *columns++); }\ + GRN_OBJ_FIN((ctx), &(format)->columns);\ + if ((format)->expression) { GRN_OBJ_FIN((ctx), (format)->expression); } \ +} while (0) + +GRN_API void grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *obj, grn_obj_format *format); +GRN_API void grn_output_envelope(grn_ctx *ctx, grn_rc rc, + grn_obj *head, grn_obj *body, grn_obj *foot, + const char *file, int line); + +GRN_API void grn_ctx_output_flush(grn_ctx *ctx, int flags); +GRN_API void grn_ctx_output_array_open(grn_ctx *ctx, + const char *name, int nelements); +GRN_API void grn_ctx_output_array_close(grn_ctx *ctx); +GRN_API void grn_ctx_output_map_open(grn_ctx *ctx, + const char *name, int nelements); +GRN_API void grn_ctx_output_map_close(grn_ctx *ctx); +GRN_API void grn_ctx_output_int32(grn_ctx *ctx, int value); +GRN_API void grn_ctx_output_int64(grn_ctx *ctx, long long int value); +GRN_API void grn_ctx_output_float(grn_ctx *ctx, double value); +GRN_API void grn_ctx_output_cstr(grn_ctx *ctx, const char *value); +GRN_API void grn_ctx_output_str(grn_ctx *ctx, + const char *value, unsigned int value_len); +GRN_API void grn_ctx_output_bool(grn_ctx *ctx, grn_bool value); +GRN_API void grn_ctx_output_obj(grn_ctx *ctx, + grn_obj *value, grn_obj_format *format); +GRN_API void grn_ctx_output_table_columns(grn_ctx *ctx, + grn_obj *table, + grn_obj_format *format); +GRN_API void grn_ctx_output_table_records(grn_ctx *ctx, + grn_obj *table, + grn_obj_format *format); + + +GRN_API grn_content_type grn_ctx_get_output_type(grn_ctx *ctx); +GRN_API grn_rc grn_ctx_set_output_type(grn_ctx *ctx, grn_content_type type); +GRN_API const char *grn_ctx_get_mime_type(grn_ctx *ctx); + +/* obsolete */ +GRN_API grn_rc grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, + grn_obj_format *format); + +#ifdef __cplusplus +} +#endif + +#endif /* GROONGA_OUTPUT_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/plugin.h b/storage/mroonga/vendor/groonga/include/groonga/plugin.h index 98676acf6be..bbd8923e5d6 100644 --- a/storage/mroonga/vendor/groonga/include/groonga/plugin.h +++ b/storage/mroonga/vendor/groonga/include/groonga/plugin.h @@ -15,8 +15,8 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_PLUGIN_H -#define GRN_PLUGIN_H +#ifndef GROONGA_PLUGIN_H +#define GROONGA_PLUGIN_H #include <stddef.h> @@ -26,9 +26,24 @@ extern "C" { #endif -#define GRN_PLUGIN_INIT grn_plugin_impl_init -#define GRN_PLUGIN_REGISTER grn_plugin_impl_register -#define GRN_PLUGIN_FIN grn_plugin_impl_fin +# define GRN_PLUGIN_IMPL_NAME_RAW(type) \ + grn_plugin_impl_ ## type +# define GRN_PLUGIN_IMPL_NAME_TAGGED(type, tag) \ + GRN_PLUGIN_IMPL_NAME_RAW(type ## _ ## tag) +# define GRN_PLUGIN_IMPL_NAME_TAGGED_EXPANDABLE(type, tag) \ + GRN_PLUGIN_IMPL_NAME_TAGGED(type, tag) + +#ifdef GRN_PLUGIN_FUNCTION_TAG +# define GRN_PLUGIN_IMPL_NAME(type) \ + GRN_PLUGIN_IMPL_NAME_TAGGED_EXPANDABLE(type, GRN_PLUGIN_FUNCTION_TAG) +#else /* GRN_PLUGIN_FUNCTION_TAG */ +# define GRN_PLUGIN_IMPL_NAME(type) \ + GRN_PLUGIN_IMPL_NAME_RAW(type) +#endif /* GRN_PLUGIN_FUNCTION_TAG */ + +#define GRN_PLUGIN_INIT GRN_PLUGIN_IMPL_NAME(init) +#define GRN_PLUGIN_REGISTER GRN_PLUGIN_IMPL_NAME(register) +#define GRN_PLUGIN_FIN GRN_PLUGIN_IMPL_NAME(fin) #if defined(_WIN32) || defined(_WIN64) # define GRN_PLUGIN_EXPORT __declspec(dllexport) @@ -117,6 +132,8 @@ GRN_API void grn_plugin_mutex_unlock(grn_ctx *ctx, grn_plugin_mutex *mutex); GRN_API grn_obj *grn_plugin_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, grn_id domain, grn_obj_flags flags); +GRN_API grn_obj *grn_plugin_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data); + GRN_API grn_obj *grn_plugin_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, int name_size); @@ -149,4 +166,4 @@ GRN_API grn_obj * grn_plugin_command_create(grn_ctx *ctx, } #endif -#endif /* GRN_PLUGIN_H */ +#endif /* GROONGA_PLUGIN_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/request_canceler.h b/storage/mroonga/vendor/groonga/include/groonga/request_canceler.h new file mode 100644 index 00000000000..0032a778c25 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/request_canceler.h @@ -0,0 +1,39 @@ +/* + Copyright(C) 2014 Brazil + + This library 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 2.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GROONGA_REQUEST_CANCELER_H +#define GROONGA_REQUEST_CANCELER_H + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API void grn_request_canceler_register(grn_ctx *ctx, + const char *request_id, + unsigned int size); +GRN_API void grn_request_canceler_unregister(grn_ctx *ctx, + const char *request_id, + unsigned int size); +GRN_API grn_bool grn_request_canceler_cancel(const char *request_id, + unsigned int size); + +#ifdef __cplusplus +} +#endif + +#endif /* GROONGA_REQUEST_CANCELER_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/scorer.h b/storage/mroonga/vendor/groonga/include/groonga/scorer.h new file mode 100644 index 00000000000..a50d0d8cd71 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/scorer.h @@ -0,0 +1,88 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_SCORER_H +#define GROONGA_SCORER_H + +#include <groonga/plugin.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct _grn_scorer_matched_record grn_scorer_matched_record; + +GRN_API grn_obj * + grn_scorer_matched_record_get_table(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API grn_obj * + grn_scorer_matched_record_get_lexicon(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API grn_id + grn_scorer_matched_record_get_id(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API grn_obj * + grn_scorer_matched_record_get_terms(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API grn_obj * + grn_scorer_matched_record_get_term_weights(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API unsigned int + grn_scorer_matched_record_get_total_term_weights(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API long long unsigned int + grn_scorer_matched_record_get_n_documents(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API unsigned int + grn_scorer_matched_record_get_n_occurrences(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API long long unsigned int + grn_scorer_matched_record_get_n_candidates(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API unsigned int + grn_scorer_matched_record_get_n_tokens(grn_ctx *ctx, + grn_scorer_matched_record *record); +GRN_API int + grn_scorer_matched_record_get_weight(grn_ctx *ctx, + grn_scorer_matched_record *record); + + + +typedef double grn_scorer_score_func(grn_ctx *ctx, + grn_scorer_matched_record *record); + +/* + grn_scorer_register() registers a plugin to the database which is + associated with `ctx'. `plugin_name_ptr' and `plugin_name_length' specify the + plugin name. Alphabetic letters ('A'-'Z' and 'a'-'z'), digits ('0'-'9') and + an underscore ('_') are capable characters. + + `score' is called for scoring matched records one by one. + + grn_scorer_register() returns GRN_SUCCESS on success, an error + code on failure. + */ +GRN_PLUGIN_EXPORT grn_rc grn_scorer_register(grn_ctx *ctx, + const char *plugin_name_ptr, + int plugin_name_length, + grn_scorer_score_func *score); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* GROONGA_SCORER_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/token.h b/storage/mroonga/vendor/groonga/include/groonga/token.h new file mode 100644 index 00000000000..5aeaf0b4361 --- /dev/null +++ b/storage/mroonga/vendor/groonga/include/groonga/token.h @@ -0,0 +1,136 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GROONGA_TOKEN_H +#define GROONGA_TOKEN_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * grn_tokenize_mode describes propose for tokenization. + * + * `GRN_TOKENIZE_GET`: Tokenize for search. + * + * `GRN_TOKENIZE_ADD`: Tokenize for adding token to index. + * + * `GRN_TOKENIZE_DELETE`: Tokenize for deleting token from index. + * + * @since 4.0.8 + */ +typedef enum { + GRN_TOKENIZE_GET = 0, + GRN_TOKENIZE_ADD, + GRN_TOKENIZE_DELETE +} grn_tokenize_mode; + +/* + grn_token_mode describes propose for tokenization. + + `GRN_TOKEN_GET`: Tokenization for search. + + `GRN_TOKEN_ADD`: Tokenization for adding token to index. + + `GRN_TOKEN_DEL`: Tokenization for deleting token from index. + + @since 4.0.7 + @deprecated since 4.0.8. Use grn_tokenize_mode instead. + */ +typedef grn_tokenize_mode grn_token_mode; + +#define GRN_TOKEN_GET GRN_TOKENIZE_GET +#define GRN_TOKEN_ADD GRN_TOKENIZE_ADD +#define GRN_TOKEN_DEL GRN_TOKENIZE_DELETE + +/* + * grn_token_status is a flag set for tokenizer status codes. + * If a document or query contains no tokens, push an empty string with + * GRN_TOKEN_LAST as a token. + * + * @since 4.0.8 + */ +typedef unsigned int grn_token_status; + +/* + * GRN_TOKEN_CONTINUE means that the next token is not the last one. + * + * @since 4.0.8 + */ +#define GRN_TOKEN_CONTINUE (0) +/* + * GRN_TOKEN_LAST means that the next token is the last one. + * + * @since 4.0.8 + */ +#define GRN_TOKEN_LAST (0x01L<<0) +/* + * GRN_TOKEN_OVERLAP means that ... + * + * @since 4.0.8 + */ +#define GRN_TOKEN_OVERLAP (0x01L<<1) +/* + * GRN_TOKEN_UNMATURED means that ... + * + * @since 4.0.8 + */ +#define GRN_TOKEN_UNMATURED (0x01L<<2) +/* + * GRN_TOKEN_REACH_END means that ... + * + * @since 4.0.8 + */ +#define GRN_TOKEN_REACH_END (0x01L<<3) +/* + * GRN_TOKEN_SKIP means that the token is skipped + * + * @since 4.0.8 + */ +#define GRN_TOKEN_SKIP (0x01L<<4) +/* + * GRN_TOKEN_SKIP_WITH_POSITION means that the token and postion is skipped + * + * @since 4.0.8 + */ +#define GRN_TOKEN_SKIP_WITH_POSITION (0x01L<<5) +/* + * GRN_TOKEN_FORCE_PREIX that the token is used common prefix search + * + * @since 4.0.8 + */ +#define GRN_TOKEN_FORCE_PREFIX (0x01L<<6) + +typedef struct _grn_token grn_token; + +GRN_PLUGIN_EXPORT grn_obj *grn_token_get_data(grn_ctx *ctx, + grn_token *token); +GRN_PLUGIN_EXPORT grn_rc grn_token_set_data(grn_ctx *ctx, + grn_token *token, + const char *str_ptr, + int str_length); +GRN_PLUGIN_EXPORT grn_token_status grn_token_get_status(grn_ctx *ctx, + grn_token *token); +GRN_PLUGIN_EXPORT grn_rc grn_token_set_status(grn_ctx *ctx, + grn_token *token, + grn_token_status status); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* GROONGA_TOKEN_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/token_filter.h b/storage/mroonga/vendor/groonga/include/groonga/token_filter.h index 2ae553b8630..9c5a3567b3b 100644 --- a/storage/mroonga/vendor/groonga/include/groonga/token_filter.h +++ b/storage/mroonga/vendor/groonga/include/groonga/token_filter.h @@ -15,10 +15,8 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_PLUGIN_TOKEN_FILTER_H -#define GRN_PLUGIN_TOKEN_FILTER_H - -#include <stddef.h> +#ifndef GROONGA_TOKEN_FILTER_H +#define GROONGA_TOKEN_FILTER_H #include <groonga/tokenizer.h> @@ -28,7 +26,7 @@ extern "C" { typedef void *grn_token_filter_init_func(grn_ctx *ctx, grn_obj *table, - grn_token_mode mode); + grn_tokenize_mode mode); typedef void grn_token_filter_filter_func(grn_ctx *ctx, grn_token *current_token, @@ -68,4 +66,4 @@ GRN_PLUGIN_EXPORT grn_rc grn_token_filter_register(grn_ctx *ctx, } /* extern "C" */ #endif /* __cplusplus */ -#endif /* GRN_PLUGIN_TOKEN_FILTER_H */ +#endif /* GROONGA_TOKEN_FILTER_H */ diff --git a/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h b/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h index 9792e018b31..8ad7f6757f4 100644 --- a/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h +++ b/storage/mroonga/vendor/groonga/include/groonga/tokenizer.h @@ -15,12 +15,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_PLUGIN_TOKENIZER_H -#define GRN_PLUGIN_TOKENIZER_H - -#include <stddef.h> +#ifndef GROONGA_TOKENIZER_H +#define GROONGA_TOKENIZER_H #include <groonga/plugin.h> +#include <groonga/token.h> #ifdef __cplusplus extern "C" { @@ -30,23 +29,6 @@ extern "C" { #define GRN_TOKENIZER_TOKENIZED_DELIMITER_UTF8_LEN 3 /* - grn_token_mode describes propose for tokenization. - - `GRN_TOKEN_GET`: Tokenization for search. - - `GRN_TOKEN_ADD`: Tokenization for adding token to index. - - `GRN_TOKEN_DEL`: Tokenization for deleting token from index. - - @since 4.0.7 - */ -typedef enum { - GRN_TOKEN_GET = 0, - GRN_TOKEN_ADD, - GRN_TOKEN_DEL -} grn_token_mode; - -/* grn_tokenizer_charlen() returns the length (#bytes) of the first character in the string specified by `str_ptr' and `str_length'. If the starting bytes are invalid as a character, grn_tokenizer_charlen() returns 0. See @@ -101,7 +83,9 @@ struct _grn_tokenizer_query { grn_encoding encoding; unsigned int flags; grn_bool have_tokenized_delimiter; + /* Deprecated since 4.0.8. Use tokenize_mode instead. */ grn_token_mode token_mode; + grn_tokenize_mode tokenize_mode; }; /* @@ -166,23 +150,59 @@ GRN_PLUGIN_EXPORT void grn_tokenizer_token_fin(grn_ctx *ctx, grn_tokenizer_token * grn_tokenizer_status is a flag set for tokenizer status codes. * If a document or query contains no tokens, push an empty string with * GRN_TOKENIZER_TOKEN_LAST as a token. + * + * @deprecated since 4.0.8. Use grn_token_status instead. + */ +typedef grn_token_status grn_tokenizer_status; + +/* + * GRN_TOKENIZER_TOKEN_CONTINUE means that the next token is not the last one. + * + * @deprecated since 4.0.8. Use GRN_TOKEN_CONTINUE instead. + */ +#define GRN_TOKENIZER_TOKEN_CONTINUE GRN_TOKEN_CONTINUE +/* + * GRN_TOKENIZER_TOKEN_LAST means that the next token is the last one. + * + * @deprecated since 4.0.8. Use GRN_TOKEN_LAST instead. + */ +#define GRN_TOKENIZER_TOKEN_LAST GRN_TOKEN_LAST +/* + * GRN_TOKENIZER_TOKEN_OVERLAP means that ... + * + * @deprecated since 4.0.8. Use GRN_TOKEN_OVERLAP instead. + */ +#define GRN_TOKENIZER_TOKEN_OVERLAP GRN_TOKEN_OVERLAP +/* + * GRN_TOKENIZER_TOKEN_UNMATURED means that ... + * + * @deprecated since 4.0.8. Use GRN_TOKEN_UNMATURED instead. + */ +#define GRN_TOKENIZER_TOKEN_UNMATURED GRN_TOKEN_UNMATURED +/* + * GRN_TOKENIZER_TOKEN_REACH_END means that ... + * + * @deprecated since 4.0.8. Use GRN_TOKEN_REACH_END instead. + */ +#define GRN_TOKENIZER_TOKEN_REACH_END GRN_TOKEN_REACH_END +/* + * GRN_TOKENIZER_TOKEN_SKIP means that the token is skipped + * + * @deprecated since 4.0.8. Use GRN_TOKEN_SKIP instead. */ -typedef unsigned int grn_tokenizer_status; - -/* GRN_TOKENIZER_TOKEN_CONTINUE means that the next token is not the last one. */ -#define GRN_TOKENIZER_TOKEN_CONTINUE (0) -/* GRN_TOKENIZER_TOKEN_LAST means that the next token is the last one. */ -#define GRN_TOKENIZER_TOKEN_LAST (0x01L<<0) -/* GRN_TOKENIZER_TOKEN_OVERLAP means that ... */ -#define GRN_TOKENIZER_TOKEN_OVERLAP (0x01L<<1) -/* GRN_TOKENIZER_TOKEN_UNMATURED means that ... */ -#define GRN_TOKENIZER_TOKEN_UNMATURED (0x01L<<2) -/* GRN_TOKENIZER_TOKEN_REACH_END means that ... */ -#define GRN_TOKENIZER_TOKEN_REACH_END (0x01L<<3) -/* GRN_TOKENIZER_TOKEN_SKIP means that the token is skipped */ -#define GRN_TOKENIZER_TOKEN_SKIP (0x01L<<4) -/* GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION means that the token and postion is skipped */ -#define GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION (0x01L<<5) +#define GRN_TOKENIZER_TOKEN_SKIP GRN_TOKEN_SKIP +/* + * GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION means that the token and postion is skipped + * + * @deprecated since 4.0.8. Use GRN_TOKEN_SKIP_WITH_POSITION instead. + */ +#define GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION GRN_TOKEN_SKIP_WITH_POSITION +/* + * GRN_TOKENIZER_TOKEN_FORCE_PREIX that the token is used common prefix search + * + * @deprecated since 4.0.8. Use GRN_TOKEN_FORCE_PREIX instead. + */ +#define GRN_TOKENIZER_TOKEN_FORCE_PREFIX GRN_TOKEN_FORCE_PREFIX /* * GRN_TOKENIZER_CONTINUE and GRN_TOKENIZER_LAST are deprecated. They @@ -193,32 +213,17 @@ typedef unsigned int grn_tokenizer_status; #define GRN_TOKENIZER_CONTINUE GRN_TOKENIZER_TOKEN_CONTINUE #define GRN_TOKENIZER_LAST GRN_TOKENIZER_TOKEN_LAST -typedef struct _grn_token grn_token; - -GRN_PLUGIN_EXPORT grn_obj *grn_token_get_data(grn_ctx *ctx, - grn_token *token); -GRN_PLUGIN_EXPORT grn_rc grn_token_set_data(grn_ctx *ctx, - grn_token *token, - const char *str_ptr, - int str_length); -GRN_PLUGIN_EXPORT grn_tokenizer_status grn_token_get_status(grn_ctx *ctx, - grn_token *token); -GRN_PLUGIN_EXPORT grn_rc grn_token_set_status(grn_ctx *ctx, - grn_token *token, - grn_tokenizer_status status); - - /* grn_tokenizer_token_push() pushes the next token into `token'. Note that grn_tokenizer_token_push() does not make a copy of the given string. This means that you have to maintain a memory space allocated to the string. Also note that the grn_tokenizer_token object must be maintained until the - request for the next token or finalization comes. See grn_tokenizer_status in + request for the next token or finalization comes. See grn_token_status in this header for more details of `status'. */ GRN_PLUGIN_EXPORT void grn_tokenizer_token_push(grn_ctx *ctx, grn_tokenizer_token *token, const char *str_ptr, unsigned int str_length, - grn_tokenizer_status status); + grn_token_status status); /* grn_tokenizer_tokenized_delimiter_next() extracts the next token @@ -254,4 +259,4 @@ GRN_PLUGIN_EXPORT grn_rc grn_tokenizer_register(grn_ctx *ctx, const char *plugin } /* extern "C" */ #endif /* __cplusplus */ -#endif /* GRN_PLUGIN_TOKENIZER_H */ +#endif /* GROONGA_TOKENIZER_H */ diff --git a/storage/mroonga/vendor/groonga/lib/util.h b/storage/mroonga/vendor/groonga/include/groonga/util.h index b4dbb000aed..446cb88f8c3 100644 --- a/storage/mroonga/vendor/groonga/lib/util.h +++ b/storage/mroonga/vendor/groonga/include/groonga/util.h @@ -1,9 +1,10 @@ -/* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2010-2011 Brazil +/* + Copyright(C) 2010-2014 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License version 2.1 as published by the Free Software Foundation. + License as published by the Free Software Foundation; either + version 2.1 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 @@ -14,35 +15,26 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_UTIL_H -#define GRN_UTIL_H +#ifndef GROONGA_UTIL_H +#define GROONGA_UTIL_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif -GRN_API grn_rc grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *offset, int *limit); - GRN_API grn_obj *grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj); +GRN_API grn_obj *grn_inspect_indented(grn_ctx *ctx, grn_obj *buffer, + grn_obj *obj, const char *indent); GRN_API grn_obj *grn_inspect_name(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj); GRN_API grn_obj *grn_inspect_encoding(grn_ctx *ctx, grn_obj *buffer, grn_encoding encoding); GRN_API grn_obj *grn_inspect_type(grn_ctx *ctx, grn_obj *buffer, unsigned char type); -void grn_p(grn_ctx *ctx, grn_obj *obj); -void grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point); -GRN_API const char *grn_win32_base_dir(void); -GRN_API char *grn_path_separator_to_system(char *dest, char *groonga_path); +GRN_API void grn_p(grn_ctx *ctx, grn_obj *obj); +GRN_API void grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point); +GRN_API void grn_p_ii_values(grn_ctx *ctx, grn_obj *obj); #ifdef __cplusplus } #endif -#endif /* GRN_UTIL_H */ +#endif /* GROONGA_UTIL_H */ diff --git a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt index d19c88e4311..2103436545f 100644 --- a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt @@ -19,7 +19,10 @@ add_definitions( include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/dat - ${MRUBY_INCLUDE_DIRS}) + ${MRUBY_INCLUDE_DIRS} + ${LIBLZ4_INCLUDE_DIRS}) +link_directories( + ${LIBLZ4_LIBRARY_DIRS}) read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am LIBGROONGA_SOURCES) read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/dat/sources.am LIBGRNDAT_SOURCES) @@ -36,54 +39,46 @@ set_source_files_properties(dat.cpp ${LIBGRNDAT_SOURCES} PROPERTIES COMPILE_FLAGS "${GRN_CXX_COMPILE_FLAGS}") -if(MRN_GROONGA_BUNDLED) - add_library(libgroonga STATIC - ${LIBGROONGA_SOURCES} - ${LIBGRNDAT_SOURCES} - ${LIBGRNMRB_SOURCES} - ${MRUBY_LIBS}) +set(GRN_ALL_SOURCES + ${LIBGROONGA_SOURCES} + ${LIBGRNDAT_SOURCES} + ${LIBGRNMRB_SOURCES} + ${MRUBY_LIBS}) +if(GRN_EMBED) + add_library(libgroonga STATIC ${GRN_ALL_SOURCES}) else() - add_library(libgroonga SHARED - ${LIBGROONGA_SOURCES} - ${LIBGRNDAT_SOURCES} - ${LIBGRNMRB_SOURCES} - ${MRUBY_LIBS}) + add_library(libgroonga SHARED ${GRN_ALL_SOURCES}) endif() set_target_properties(libgroonga PROPERTIES OUTPUT_NAME "groonga") -if(NOT MRN_GROONGA_BUNDLED) - target_link_libraries(libgroonga + +set(GRN_ALL_LIBRARIES ${EXECINFO_LIBS} ${RT_LIBS} ${PTHREAD_LIBS} ${Z_LIBS} - ${LZO2_LIBS} + ${LIBLZ4_LIBRARIES} ${DL_LIBS} + ${M_LIBS} ${WS2_32_LIBS}) +if(GRN_EMBED) + target_link_libraries(libgroonga + ${GRN_ALL_LIBRARIES} + ${STDCPP_LIBS}) +else() + target_link_libraries(libgroonga + ${GRN_ALL_LIBRARIES}) install(TARGETS libgroonga ARCHIVE DESTINATION "${LIB_DIR}" LIBRARY DESTINATION "${LIB_DIR}" RUNTIME DESTINATION "${BIN_DIR}") -else() - target_link_libraries(libgroonga - ${EXECINFO_LIBS} - ${RT_LIBS} - ${PTHREAD_LIBS} - ${Z_LIBS} - ${LZO2_LIBS} - ${DL_LIBS} - ${M_LIBS} - ${STDCPP_LIBS} - ${WS2_32_LIBS}) endif() -if(GRN_WITH_MRUBY) +if(GRN_WITH_MRUBY AND NOT GRN_EMBED) read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/sources.am RUBY_SCRIPTS) string(REGEX REPLACE "([^;]+)" "mrb/scripts/\\1" RUBY_SCRIPTS "${RUBY_SCRIPTS}") - if(NOT MRN_GROONGA_BUNDLED) - install( - FILES ${RUBY_SCRIPTS} - DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}") - endif() + install( + FILES ${RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}") endif() diff --git a/storage/mroonga/vendor/groonga/lib/Makefile.am b/storage/mroonga/vendor/groonga/lib/Makefile.am index 047c41a25da..8f4e76ea212 100644 --- a/storage/mroonga/vendor/groonga/lib/Makefile.am +++ b/storage/mroonga/vendor/groonga/lib/Makefile.am @@ -10,8 +10,17 @@ AM_CFLAGS = \ $(COVERAGE_CFLAGS) \ $(GRN_CFLAGS) \ $(MESSAGE_PACK_CFLAGS) \ - $(MRUBY_CFLAGS) -DEFAULT_INCLUDES = -I$(top_builddir) -I$(top_srcdir)/include + $(LIBLZ4_CFLAGS) + +BUNDLED_LIBRARIES_CFLAGS = \ + $(MRUBY_CFLAGS) \ + $(ONIGMO_CFLAGS) + +DEFAULT_INCLUDES = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + $(BUNDLED_LIBRARIES_CFLAGS) + DEFS += -D_REENTRANT $(GRN_DEFS) -DGRN_DAT_EXPORT include sources.am @@ -24,12 +33,20 @@ libgroonga_la_LDFLAGS = \ libgroonga_la_LIBADD = \ dat/libgrndat.la \ mrb/libgrnmrb.la \ - $(MESSAGE_PACK_LIBS) \ - $(MRUBY_LIBS) + $(MESSAGE_PACK_LIBS) + +if WITH_MRUBY +libgroonga_la_LIBADD += \ + ../vendor/mruby/libmruby.la +endif + +libgroonga_la_LIBADD += \ + $(ONIGMO_LIBS) \ + $(LIBLZ4_LIBS) if WITH_LEMON BUILT_SOURCES = \ - ecmascript.c + grn_ecmascript.c SUFFIXES = .lemon .c @@ -38,9 +55,9 @@ SUFFIXES = .lemon .c endif EXTRA_DIST = \ - ecmascript.c \ - ecmascript.h \ - ecmascript.lemon \ + grn_ecmascript.c \ + grn_ecmascript.h \ + grn_ecmascript.lemon \ CMakeLists.txt CLEANFILES = *.gcno *.gcda diff --git a/storage/mroonga/vendor/groonga/lib/com.c b/storage/mroonga/vendor/groonga/lib/com.c index 172ad91ed1e..a17d3a931de 100644 --- a/storage/mroonga/vendor/groonga/lib/com.c +++ b/storage/mroonga/vendor/groonga/lib/com.c @@ -15,11 +15,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <stdio.h> #include <string.h> -#include "ctx_impl.h" +#include "grn_ctx_impl.h" #ifdef WIN32 # include <ws2tcpip.h> @@ -38,8 +38,8 @@ # endif /* HAVE_SIGNAL_H */ #endif /* WIN32 */ -#include "ctx.h" -#include "com.h" +#include "grn_ctx.h" +#include "grn_com.h" #ifndef PF_INET #define PF_INET AF_INET @@ -193,7 +193,7 @@ grn_msg_send(grn_ctx *ctx, grn_obj *msg, int flags) { ssize_t ret; ret = send(peer->fd, GRN_BULK_HEAD(msg), GRN_BULK_VSIZE(msg), MSG_NOSIGNAL); - if (ret == -1) { SERR("send"); } + if (ret == -1) { SOERR("send"); } if (ctx->rc != GRN_OPERATION_WOULD_BLOCK) { grn_com_queue_enque(ctx, m->old, (grn_com_queue_entry *)msg); return ctx->rc; @@ -251,7 +251,7 @@ grn_com_init(void) WSADATA wd; if (WSAStartup(MAKEWORD(2, 0), &wd) != 0) { grn_ctx *ctx = &grn_gctx; - SERR("WSAStartup"); + SOERR("WSAStartup"); } #else /* WIN32 */ #ifndef USE_MSG_NOSIGNAL @@ -281,7 +281,7 @@ grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_si COND_INIT(ev->cond); GRN_COM_QUEUE_INIT(&ev->recv_old); #ifndef USE_SELECT -#ifdef USE_EPOLL +# ifdef USE_EPOLL if ((ev->events = GRN_MALLOC(sizeof(struct epoll_event) * max_nevents))) { if ((ev->epfd = epoll_create(max_nevents)) != -1) { goto exit; @@ -290,8 +290,8 @@ grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_si } GRN_FREE(ev->events); } -#else /* USE_EPOLL */ -#ifdef USE_KQUEUE +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE if ((ev->events = GRN_MALLOC(sizeof(struct kevent) * max_nevents))) { if ((ev->kqfd = kqueue()) != -1) { goto exit; @@ -300,17 +300,17 @@ grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_si } GRN_FREE(ev->events); } -#else /* USE_KQUEUE */ +# else /* USE_KQUEUE */ if ((ev->events = GRN_MALLOC(sizeof(struct pollfd) * max_nevents))) { goto exit; } -#endif /* USE_KQUEUE*/ -#endif /* USE_EPOLL */ +# endif /* USE_KQUEUE*/ +# endif /* USE_EPOLL */ grn_hash_close(ctx, ev->hash); ev->hash = NULL; ev->events = NULL; #else /* USE_SELECT */ - + goto exit; #endif /* USE_SELECT */ } exit : @@ -327,12 +327,12 @@ grn_com_event_fin(grn_ctx *ctx, grn_com_event *ev) if (ev->hash) { grn_hash_close(ctx, ev->hash); } #ifndef USE_SELECT if (ev->events) { GRN_FREE(ev->events); } -#ifdef USE_EPOLL +# ifdef USE_EPOLL GRN_CLOSE(ev->epfd); -#endif /* USE_EPOLL */ -#ifdef USE_KQUEUE +# endif /* USE_EPOLL */ +# ifdef USE_KQUEUE GRN_CLOSE(ev->kqfd); -#endif /* USE_KQUEUE*/ +# endif /* USE_KQUEUE*/ #endif /* USE_SELECT */ return GRN_SUCCESS; } @@ -387,7 +387,10 @@ grn_com_event_mod(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_ if (!ev) { return GRN_INVALID_ARGUMENT; } if (grn_hash_get(ctx, ev->hash, &fd, sizeof(grn_sock), (void **)&c)) { if (c->fd != fd) { - GRN_LOG(ctx, GRN_LOG_ERROR, "grn_com_event_mod fd unmatch %d != %d", c->fd, fd); + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_com_event_mod fd unmatch " + "%" GRN_FMT_SOCKET " != %" GRN_FMT_SOCKET, + c->fd, fd); return GRN_OBJECT_CORRUPT; } if (com) { *com = c; } @@ -449,7 +452,9 @@ grn_com_event_del(grn_ctx *ctx, grn_com_event *ev, grn_sock fd) #endif /* USE_KQUEUE */ return grn_hash_delete_by_id(ctx, ev->hash, id, NULL); } else { - GRN_LOG(ctx, GRN_LOG_ERROR, "%04x| fd(%d) not found in ev(%p)", getpid(), fd, ev); + GRN_LOG(ctx, GRN_LOG_ERROR, + "%04x| fd(%" GRN_FMT_SOCKET ") not found in ev(%p)", + getpid(), fd, ev); return GRN_INVALID_ARGUMENT; } } @@ -469,7 +474,7 @@ grn_com_event_start_accept(grn_ctx *ctx, grn_com_event *ev) if (listen(com->fd, LISTEN_BACKLOG) == 0) { com->accepting = GRN_TRUE; } else { - SERR("listen - start accept"); + SOERR("listen - start accept"); } } GRN_API_RETURN(ctx->rc); @@ -487,7 +492,7 @@ grn_com_event_stop_accept(grn_ctx *ctx, grn_com_event *ev) if (listen(com->fd, 0) == 0) { com->accepting = GRN_FALSE; } else { - SERR("listen - disable accept"); + SOERR("listen - disable accept"); } } GRN_API_RETURN(ctx->rc); @@ -505,7 +510,7 @@ grn_com_receiver(grn_ctx *ctx, grn_com *com) if (errno == EMFILE) { grn_com_event_stop_accept(ctx, ev); } else { - SERR("accept"); + SOERR("accept"); } return; } @@ -562,7 +567,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) }); nevents = select(nfds + 1, &rfds, &wfds, NULL, (timeout >= 0) ? &tv : NULL); if (nevents < 0) { - SERR("select"); + SOERR("select"); if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); } return ctx->rc; } @@ -571,7 +576,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) if (FD_ISSET(*pfd, &rfds)) { grn_com_receiver(ctx, com); } }); #else /* USE_SELECT */ -#ifdef USE_EPOLL +# ifdef USE_EPOLL struct epoll_event *ep; ctx->errlvl = GRN_OK; ctx->rc = GRN_SUCCESS; @@ -579,8 +584,8 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) if (nevents < 0) { SERR("epoll_wait"); } -#else /* USE_EPOLL */ -#ifdef USE_KQUEUE +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE struct kevent *ep; struct timespec tv; if (timeout >= 0) { @@ -591,7 +596,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) if (nevents < 0) { SERR("kevent"); } -#else /* USE_KQUEUE */ +# else /* USE_KQUEUE */ uint32_t dummy; int nfd = 0, *pfd; struct pollfd *ep = ev->events; @@ -609,8 +614,8 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) if (nevents < 0) { SERR("poll"); } -#endif /* USE_KQUEUE */ -#endif /* USE_EPOLL */ +# endif /* USE_KQUEUE */ +# endif /* USE_EPOLL */ if (ctx->rc != GRN_SUCCESS) { if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); @@ -620,7 +625,7 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) if (timeout < 0 && !nevents) { GRN_LOG(ctx, GRN_LOG_NOTICE, "poll returns 0 events"); } for (ep = ev->events; nevents; ep++) { int efd; -#ifdef USE_EPOLL +# ifdef USE_EPOLL efd = ep->data.fd; nevents--; // todo : com = ep->data.ptr; @@ -631,12 +636,12 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) e.data.fd = efd; e.events = ep->events; if (epoll_ctl(ev->epfd, EPOLL_CTL_DEL, efd, &e) == -1) { SERR("epoll_ctl"); } - if (grn_sock_close(efd) == -1) { SERR("close"); } + if (grn_sock_close(efd) == -1) { SOERR("close"); } continue; } if ((ep->events & GRN_COM_POLLIN)) { grn_com_receiver(ctx, com); } -#else /* USE_EPOLL */ -#ifdef USE_KQUEUE +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE efd = ep->ident; nevents--; // todo : com = ep->udata; @@ -645,22 +650,22 @@ grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->set", efd); EV_SET(&e, efd, ep->filter, EV_DELETE, 0, 0, NULL); if (kevent(ev->kqfd, &e, 1, NULL, 0, NULL) == -1) { SERR("kevent"); } - if (grn_sock_close(efd) == -1) { SERR("close"); } + if (grn_sock_close(efd) == -1) { SOERR("close"); } continue; } if ((ep->filter == GRN_COM_POLLIN)) { grn_com_receiver(ctx, com); } -#else +# else efd = ep->fd; if (!(ep->events & ep->revents)) { continue; } nevents--; if (!grn_hash_get(ctx, ev->hash, &efd, sizeof(grn_sock), (void *)&com)) { GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->hash", efd); - if (grn_sock_close(efd) == -1) { SERR("close"); } + if (grn_sock_close(efd) == -1) { SOERR("close"); } continue; } if ((ep->revents & GRN_COM_POLLIN)) { grn_com_receiver(ctx, com); } -#endif /* USE_KQUEUE */ -#endif /* USE_EPOLL */ +# endif /* USE_KQUEUE */ +# endif /* USE_EPOLL */ } #endif /* USE_SELECT */ /* todo : @@ -682,7 +687,7 @@ grn_com_send_http(grn_ctx *ctx, grn_com *cs, const char *path, uint32_t path_len GRN_TEXT_PUTS(ctx, &buf, " HTTP/1.0\r\n\r\n"); // todo : refine if ((ret = send(cs->fd, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf), MSG_NOSIGNAL|flags)) == -1) { - SERR("send"); + SOERR("send"); } if (ret != GRN_BULK_VSIZE(&buf)) { GRN_LOG(ctx, GRN_LOG_NOTICE, "send %d != %d", (int)ret, (int)GRN_BULK_VSIZE(&buf)); @@ -710,7 +715,7 @@ grn_com_send(grn_ctx *ctx, grn_com *cs, wsabufs[1].buf = (char *)body; wsabufs[1].len = size; if (WSASend(cs->fd, wsabufs, 2, &n_sent, 0, NULL, NULL) == SOCKET_ERROR) { - SERR("WSASend"); + SOERR("WSASend"); } ret = n_sent; #else /* WIN32 */ @@ -728,18 +733,19 @@ grn_com_send(grn_ctx *ctx, grn_com *cs, msg_iov[1].iov_base = (char *)body; msg_iov[1].iov_len = size; if ((ret = sendmsg(cs->fd, &msg, MSG_NOSIGNAL|flags)) == -1) { - SERR("sendmsg"); + SOERR("sendmsg"); rc = ctx->rc; } #endif /* WIN32 */ } else { if ((ret = send(cs->fd, (const void *)header, whole_size, MSG_NOSIGNAL|flags)) == -1) { - SERR("send"); + SOERR("send"); rc = ctx->rc; } } if (ret != whole_size) { - GRN_LOG(ctx, GRN_LOG_ERROR, "sendmsg(%d): %" GRN_FMT_LLD " < %" GRN_FMT_LLU, + GRN_LOG(ctx, GRN_LOG_ERROR, + "sendmsg(%" GRN_FMT_SOCKET "): %" GRN_FMT_LLD " < %" GRN_FMT_LLU, cs->fd, (long long int)ret, (unsigned long long int)whole_size); rc = ctx->rc; } @@ -781,7 +787,7 @@ grn_com_recv_text(grn_ctx *ctx, grn_com *com, for (;;) { if (grn_bulk_reserve(ctx, buf, BUFSIZE)) { return ctx->rc; } if ((ret = recv(com->fd, GRN_BULK_CURR(buf), BUFSIZE, 0)) < 0) { - SERR("recv text"); + SOERR("recv text"); if (ctx->rc == GRN_OPERATION_WOULD_BLOCK || ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); @@ -813,7 +819,7 @@ exit : GRN_BULK_REWIND(buf); grn_bulk_reserve(ctx, buf, BUFSIZE); if ((ret = recv(com->fd, GRN_BULK_CURR(buf), BUFSIZE, 0)) < 0) { - SERR("recv text body"); + SOERR("recv text body"); } else { GRN_BULK_CURR(buf) += ret; } @@ -831,8 +837,8 @@ grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf) size_t rest = sizeof(grn_com_header); do { if ((ret = recv(com->fd, p, rest, 0)) < 0) { - SERR("recv size"); - GRN_LOG(ctx, GRN_LOG_ERROR, "recv error (%d)", com->fd); + SOERR("recv size"); + GRN_LOG(ctx, GRN_LOG_ERROR, "recv error (%" GRN_FMT_SOCKET ")", com->fd); if (ctx->rc == GRN_OPERATION_WOULD_BLOCK || ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); @@ -852,7 +858,14 @@ grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf) } } } while (rest); - GRN_LOG(ctx, GRN_LOG_INFO, "recv (%d,%x,%d,%02x,%02x,%04x)", ntohl(header->size), header->flags, header->proto, header->qtype, header->level, header->status); + GRN_LOG(ctx, GRN_LOG_INFO, + "recv (%u,%x,%d,%02x,%02x,%04x)", + (uint32_t)ntohl(header->size), + header->flags, + header->proto, + header->qtype, + header->level, + header->status); { uint8_t proto = header->proto; size_t value_size = ntohl(header->size); @@ -868,7 +881,7 @@ grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf) retry = 0; for (rest = value_size; rest;) { if ((ret = recv(com->fd, GRN_BULK_CURR(buf), rest, MSG_WAITALL)) < 0) { - SERR("recv body"); + SOERR("recv body"); if (ctx->rc == GRN_OPERATION_WOULD_BLOCK || ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); @@ -926,7 +939,7 @@ grn_com_copen(grn_ctx *ctx, grn_com_event *ev, const char *dest, int port) #endif #ifdef EAI_SYSTEM case EAI_SYSTEM: - SERR("getaddrinfo"); + SOERR("getaddrinfo"); break; #endif default: @@ -943,12 +956,13 @@ grn_com_copen(grn_ctx *ctx, grn_com_event *ev, const char *dest, int port) fd = socket(addrinfo_ptr->ai_family, addrinfo_ptr->ai_socktype, addrinfo_ptr->ai_protocol); if (fd == -1) { - SERR("socket"); - } else if (setsockopt(fd, 6, TCP_NODELAY, &value, sizeof(value))) { - SERR("setsockopt"); + SOERR("socket"); + } else if (setsockopt(fd, 6, TCP_NODELAY, + (const char *)&value, sizeof(value))) { + SOERR("setsockopt"); grn_sock_close(fd); } else if (connect(fd, addrinfo_ptr->ai_addr, addrinfo_ptr->ai_addrlen)) { - SERR("connect"); + SOERR("connect"); grn_sock_close(fd); } else { break; @@ -981,9 +995,9 @@ void grn_com_close_(grn_ctx *ctx, grn_com *com) { grn_sock fd = com->fd; - if (shutdown(fd, SHUT_RDWR) == -1) { /* SERR("shutdown"); */ } + if (shutdown(fd, SHUT_RDWR) == -1) { /* SOERR("shutdown"); */ } if (grn_sock_close(fd) == -1) { - SERR("close"); + SOERR("close"); } else { com->closed = 1; } @@ -1040,7 +1054,7 @@ grn_com_sopen(grn_ctx *ctx, grn_com_event *ev, #endif #ifdef EAI_SYSTEM case EAI_SYSTEM: - SERR("getaddrinfo"); + SOERR("getaddrinfo"); break; #endif default: @@ -1052,7 +1066,7 @@ grn_com_sopen(grn_ctx *ctx, grn_com_event *ev, goto exit; } if ((lfd = socket(bind_address_info->ai_family, SOCK_STREAM, 0)) == -1) { - SERR("socket"); + SOERR("socket"); goto exit; } memcpy(&ev->curr_edge_id.addr, he->h_addr, he->h_length); @@ -1061,20 +1075,20 @@ grn_com_sopen(grn_ctx *ctx, grn_com_event *ev, { int v = 1; if (setsockopt(lfd, SOL_TCP, TCP_NODELAY, (void *) &v, sizeof(int)) == -1) { - SERR("setsockopt"); + SOERR("setsockopt"); goto exit; } if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (void *) &v, sizeof(int)) == -1) { - SERR("setsockopt"); + SOERR("setsockopt"); goto exit; } } if (bind(lfd, bind_address_info->ai_addr, bind_address_info->ai_addrlen) < 0) { - SERR("bind"); + SOERR("bind"); goto exit; } if (listen(lfd, LISTEN_BACKLOG) < 0) { - SERR("listen"); + SOERR("listen"); goto exit; } if (ev) { diff --git a/storage/mroonga/vendor/groonga/lib/command.c b/storage/mroonga/vendor/groonga/lib/command.c new file mode 100644 index 00000000000..b0f75229744 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/command.c @@ -0,0 +1,194 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <string.h> + +#include "grn.h" +#include "grn_db.h" +#include "grn_ctx_impl.h" + +struct _grn_command_input { + grn_obj *command; + grn_hash *arguments; +}; + +grn_command_input * +grn_command_input_open(grn_ctx *ctx, grn_obj *command) +{ + grn_command_input *input = NULL; + + GRN_API_ENTER; + input = GRN_MALLOC(sizeof(grn_command_input)); + if (!input) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[command-input] failed to allocate grn_command_input"); + goto exit; + } + + input->command = command; + /* TODO: Allocate by self. */ + { + uint32_t n; + input->arguments = grn_expr_get_vars(ctx, input->command, &n); + } + +exit : + GRN_API_RETURN(input); +} + +grn_rc +grn_command_input_close(grn_ctx *ctx, grn_command_input *input) +{ + GRN_API_ENTER; + + /* TODO: Free input->arguments by self. */ + grn_expr_clear_vars(ctx, input->command); + GRN_FREE(input); + + GRN_API_RETURN(ctx->rc); +} + +grn_obj * +grn_command_input_add(grn_ctx *ctx, + grn_command_input *input, + const char *name, + int name_size, + grn_bool *added) +{ + grn_obj *argument = NULL; + /* TODO: Use grn_bool */ + int internal_added = GRN_FALSE; + + GRN_API_ENTER; + + if (name_size == -1) { + name_size = strlen(name); + } + if (input->arguments) { + grn_hash_add(ctx, input->arguments, name, name_size, (void **)&argument, + &internal_added); + if (internal_added) { + GRN_TEXT_INIT(argument, 0); + } + } + if (added) { + *added = internal_added; + } + + GRN_API_RETURN(argument); +} + +grn_obj * +grn_command_input_get(grn_ctx *ctx, + grn_command_input *input, + const char *name, + int name_size) +{ + grn_obj *argument = NULL; + + GRN_API_ENTER; + + if (name_size == -1) { + name_size = strlen(name); + } + if (input->arguments) { + grn_hash_get(ctx, input->arguments, name, name_size, (void **)&argument); + } + + GRN_API_RETURN(argument); +} + +grn_obj * +grn_command_input_at(grn_ctx *ctx, + grn_command_input *input, + unsigned int offset) +{ + grn_obj *argument = NULL; + + GRN_API_ENTER; + if (input->arguments) { + uint32_t size; + argument = (grn_obj *)grn_hash_get_value_(ctx, input->arguments, + offset + 1, &size); + } + GRN_API_RETURN(argument); +} + +grn_rc +grn_command_register(grn_ctx *ctx, + const char *command_name, + int command_name_size, + grn_command_run_func *run, + grn_expr_var *vars, + unsigned int n_vars, + void *user_data) +{ + GRN_API_ENTER; + + if (command_name_size == -1) { + command_name_size = strlen(command_name); + } + + { + grn_obj *command_object; + command_object = grn_proc_create(ctx, + command_name, + command_name_size, + GRN_PROC_COMMAND, + NULL, NULL, NULL, n_vars, vars); + if (!command_object) { + GRN_PLUGIN_ERROR(ctx, GRN_COMMAND_ERROR, + "[command][%.*s] failed to grn_proc_create()", + command_name_size, command_name); + GRN_API_RETURN(ctx->rc); + } + + { + grn_proc *command = (grn_proc *)command_object; + command->callbacks.command.run = run; + command->user_data = user_data; + } + } + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_rc +grn_command_run(grn_ctx *ctx, + grn_obj *command, + grn_command_input *input) +{ + grn_proc *proc; + + GRN_API_ENTER; + + proc = (grn_proc *)command; + if (proc->callbacks.command.run) { + proc->callbacks.command.run(ctx, command, input, proc->user_data); + } else { + /* TODO: REMOVE ME. For backward compatibility. */ + uint32_t stack_curr = ctx->impl->stack_curr; + grn_proc_call(ctx, command, 0, command); + if (ctx->impl->stack_curr > stack_curr) { + grn_ctx_pop(ctx); + } + } + + GRN_API_RETURN(ctx->rc); +} + diff --git a/storage/mroonga/vendor/groonga/lib/ctx.c b/storage/mroonga/vendor/groonga/lib/ctx.c index a419081635f..5408832dfcc 100644 --- a/storage/mroonga/vendor/groonga/lib/ctx.c +++ b/storage/mroonga/vendor/groonga/lib/ctx.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,16 +16,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <string.h> -#include "token.h" -#include "ctx_impl.h" -#include "pat.h" -#include "plugin_in.h" -#include "snip.h" -#include "output.h" -#include "normalizer_in.h" -#include "ctx_impl_mrb.h" +#include "grn_request_canceler.h" +#include "grn_tokenizers.h" +#include "grn_ctx_impl.h" +#include "grn_pat.h" +#include "grn_plugin.h" +#include "grn_snip.h" +#include "grn_output.h" +#include "grn_normalizer.h" +#include "grn_ctx_impl_mrb.h" #include <stdio.h> #include <stdarg.h> #include <time.h> @@ -132,15 +133,25 @@ grn_rc grn_timeval2str(grn_ctx *ctx, grn_timeval *tv, char *buf) { struct tm *ltm; -#ifdef HAVE_LOCALTIME_R + const char *function_name; +#ifdef HAVE__LOCALTIME64_S struct tm tm; time_t t = tv->tv_sec; + function_name = "localtime_s"; + ltm = (localtime_s(&tm, &t) == 0) ? &tm : NULL; +#else /* HAVE__LOCALTIME64_S */ +# ifdef HAVE_LOCALTIME_R + struct tm tm; + time_t t = tv->tv_sec; + function_name = "localtime_r"; ltm = localtime_r(&t, &tm); -#else /* HAVE_LOCALTIME_R */ +# else /* HAVE_LOCALTIME_R */ time_t tvsec = (time_t) tv->tv_sec; + function_name = "localtime"; ltm = localtime(&tvsec); -#endif /* HAVE_LOCALTIME_R */ - if (!ltm) { SERR("localtime"); } +# endif /* HAVE_LOCALTIME_R */ +#endif /* HAVE__LOCALTIME64_S */ + if (!ltm) { SERR(function_name); } snprintf(buf, GRN_TIMEVAL_STR_SIZE - 1, GRN_TIMEVAL_STR_FORMAT, ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, ltm->tm_hour, ltm->tm_min, ltm->tm_sec, @@ -241,7 +252,7 @@ grn_alloc_info_set_backtrace(char *buffer, size_t size) } inline static void -grn_alloc_info_add(void *address) +grn_alloc_info_add(void *address, const char *file, int line, const char *func) { grn_ctx *ctx; grn_alloc_info *new_alloc_info; @@ -254,6 +265,17 @@ grn_alloc_info_add(void *address) new_alloc_info->freed = GRN_FALSE; grn_alloc_info_set_backtrace(new_alloc_info->alloc_backtrace, sizeof(new_alloc_info->alloc_backtrace)); + if (file) { + new_alloc_info->file = strdup(file); + } else { + new_alloc_info->file = NULL; + } + new_alloc_info->line = line; + if (func) { + new_alloc_info->func = strdup(func); + } else { + new_alloc_info->func = NULL; + } new_alloc_info->next = ctx->impl->alloc_info; ctx->impl->alloc_info = new_alloc_info; } @@ -291,8 +313,13 @@ grn_alloc_info_dump(grn_ctx *ctx) if (alloc_info->freed) { printf("address[%d][freed]: %p\n", i, alloc_info->address); } else { - printf("address[%d][not-freed]: %p:\n%s", - i, alloc_info->address, alloc_info->alloc_backtrace); + printf("address[%d][not-freed]: %p: %s:%d: %s()\n%s", + i, + alloc_info->address, + alloc_info->file ? alloc_info->file : "(unknown)", + alloc_info->line, + alloc_info->func ? alloc_info->func : "(unknown)", + alloc_info->alloc_backtrace); } i++; } @@ -340,13 +367,15 @@ grn_alloc_info_free(grn_ctx *ctx) grn_alloc_info *current_alloc_info = alloc_info; alloc_info = alloc_info->next; current_alloc_info->next = NULL; + free(current_alloc_info->file); + free(current_alloc_info->func); free(current_alloc_info); } ctx->impl->alloc_info = NULL; } #else /* USE_MEMORY_DEBUG */ -# define grn_alloc_info_add(address) +# define grn_alloc_info_add(address, file, line, func) # define grn_alloc_info_change(old_address, new_address) # define grn_alloc_info_check(address) # define grn_alloc_info_dump(ctx) @@ -372,17 +401,17 @@ int grn_fmalloc_line = 0; static void grn_ctx_impl_init_malloc(grn_ctx *ctx) { -# ifdef USE_FAIL_MALLOC +# ifdef USE_FAIL_MALLOC ctx->impl->malloc_func = grn_malloc_fail; ctx->impl->calloc_func = grn_calloc_fail; ctx->impl->realloc_func = grn_realloc_fail; ctx->impl->strdup_func = grn_strdup_fail; -# else +# else ctx->impl->malloc_func = grn_malloc_default; ctx->impl->calloc_func = grn_calloc_default; ctx->impl->realloc_func = grn_realloc_default; ctx->impl->strdup_func = grn_strdup_default; -# endif +# endif } #endif @@ -423,7 +452,7 @@ grn_ctx_loader_clear(grn_ctx *ctx) #define IMPL_SIZE ((sizeof(struct _grn_ctx_impl) + (grn_pagesize - 1)) & ~(grn_pagesize - 1)) #ifdef GRN_WITH_MESSAGE_PACK -static inline int +static int grn_msgpack_buffer_write(void *data, const char *buf, unsigned int len) { grn_ctx *ctx = (grn_ctx *)data; @@ -434,7 +463,6 @@ grn_msgpack_buffer_write(void *data, const char *buf, unsigned int len) static void grn_ctx_impl_init(grn_ctx *ctx) { - grn_io_mapinfo mi; if (!(ctx->impl = grn_io_anon_map(ctx, &mi, IMPL_SIZE))) { ctx->impl = NULL; @@ -559,8 +587,8 @@ grn_ctx_impl_set_current_error_message(grn_ctx *ctx) strcpy(ctx->impl->previous_errbuf, ctx->errbuf); } -grn_rc -grn_ctx_init(grn_ctx *ctx, int flags) +static grn_rc +grn_ctx_init_internal(grn_ctx *ctx, int flags) { if (!ctx) { return GRN_INVALID_ARGUMENT; } // if (ctx->stat != GRN_CTX_FIN) { return GRN_INVALID_ARGUMENT; } @@ -591,6 +619,20 @@ grn_ctx_init(grn_ctx *ctx, int flags) return ctx->rc; } +grn_rc +grn_ctx_init(grn_ctx *ctx, int flags) +{ + grn_rc rc; + + rc = grn_ctx_init_internal(ctx, flags); + if (rc == GRN_SUCCESS) { + grn_ctx_impl_init(ctx); + rc = ctx->rc; + } + + return rc; +} + grn_ctx * grn_ctx_open(int flags) { @@ -706,7 +748,6 @@ grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *finalizer) { if (!ctx) { return GRN_INVALID_ARGUMENT; } if (!ctx->impl) { - grn_ctx_impl_init(ctx); if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; } } ctx->impl->finalizer = finalizer; @@ -1227,7 +1268,7 @@ grn_init(void) grn_gtick = 0; ctx->next = ctx; ctx->prev = ctx; - grn_ctx_init(ctx, 0); + grn_ctx_init_internal(ctx, 0); ctx->encoding = grn_encoding_parse(GRN_DEFAULT_ENCODING); grn_timeval_now(ctx, &grn_starttime); #ifdef WIN32 @@ -1282,8 +1323,8 @@ grn_init(void) GRN_LOG(ctx, GRN_LOG_ALERT, "grn_normalizer_init failed (%d)", rc); return rc; } - if ((rc = grn_token_init())) { - GRN_LOG(ctx, GRN_LOG_ALERT, "grn_token_init failed (%d)", rc); + if ((rc = grn_tokenizers_init())) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_tokenizers_init failed (%d)", rc); return rc; } /* @@ -1293,6 +1334,13 @@ grn_init(void) } */ grn_cache_init(); + if (!grn_request_canceler_init()) { + rc = ctx->rc; + grn_cache_fin(); + GRN_LOG(ctx, GRN_LOG_ALERT, + "failed to initialize request canceler (%d)", rc); + return rc; + } GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_init"); check_overcommit_memory(ctx); check_grn_ja_skip_same_value_put(ctx); @@ -1379,8 +1427,9 @@ grn_fin(void) } } query_logger_fin(ctx); + grn_request_canceler_fin(); grn_cache_fin(); - grn_token_fin(); + grn_tokenizers_fin(); grn_normalizer_fin(); grn_plugins_fin(); grn_io_fin(); @@ -1396,7 +1445,6 @@ grn_rc grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags) { GRN_API_ENTER; - if (!ctx->impl) { grn_ctx_impl_init(ctx); } if (!ctx->impl) { goto exit; } { grn_com *com = grn_com_copen(ctx, NULL, host, port); @@ -1428,16 +1476,6 @@ grn_ctx_get_command_version(grn_ctx *ctx) } } -const char * -grn_ctx_get_mime_type(grn_ctx *ctx) -{ - if (ctx->impl) { - return ctx->impl->mime_type; - } else { - return NULL; - } -} - grn_rc grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version) { @@ -1456,6 +1494,40 @@ grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version) } } +grn_content_type +grn_ctx_get_output_type(grn_ctx *ctx) +{ + if (ctx->impl) { + return ctx->impl->output_type; + } else { + return GRN_CONTENT_NONE; + } +} + +grn_rc +grn_ctx_set_output_type(grn_ctx *ctx, grn_content_type type) +{ + grn_rc rc = GRN_SUCCESS; + + if (ctx->impl) { + ctx->impl->output_type = type; + } else { + rc = GRN_INVALID_ARGUMENT; + } + + return rc; +} + +const char * +grn_ctx_get_mime_type(grn_ctx *ctx) +{ + if (ctx->impl) { + return ctx->impl->mime_type; + } else { + return NULL; + } +} + long long int grn_ctx_get_match_escalation_threshold(grn_ctx *ctx) { @@ -1613,9 +1685,11 @@ get_command_version(grn_ctx *ctx, const char *p, const char *pe) #define INDEX_HTML "index.html" #define OUTPUT_TYPE "output_type" #define COMMAND_VERSION "command_version" +#define REQUEST_ID "request_id" #define EXPR_MISSING "expr_missing" #define OUTPUT_TYPE_LEN (sizeof(OUTPUT_TYPE) - 1) #define COMMAND_VERSION_LEN (sizeof(COMMAND_VERSION) - 1) +#define REQUEST_ID_LEN (sizeof(REQUEST_ID) - 1) #define HTTP_QUERY_PAIR_DELIMITER "=" #define HTTP_QUERY_PAIRS_DELIMITERS "&;" @@ -1631,8 +1705,10 @@ grn_obj * grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len) { grn_obj buf, *expr, *val; + grn_obj request_id; const char *p = path, *e = path + path_len, *v, *key_end, *filename_end; GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_INIT(&request_id, 0); p = grn_text_urldec(ctx, &buf, p, e, '?'); if (!GRN_TEXT_LEN(&buf)) { GRN_TEXT_SETS(ctx, &buf, INDEX_HTML); } v = GRN_TEXT_VALUE(&buf); @@ -1659,6 +1735,12 @@ grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len) p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS); get_command_version(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf)); if (ctx->rc) { goto exit; } + } else if (l == REQUEST_ID_LEN && + !memcmp(v, REQUEST_ID, REQUEST_ID_LEN)) { + GRN_BULK_REWIND(&request_id); + p = grn_text_cgidec(ctx, &request_id, p, e, + HTTP_QUERY_PAIRS_DELIMITERS); + if (ctx->rc) { goto exit; } } else { if (!(val = grn_expr_get_or_add_var(ctx, expr, v, l))) { val = &buf; @@ -1667,8 +1749,18 @@ grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len) p = grn_text_cgidec(ctx, val, p, e, HTTP_QUERY_PAIRS_DELIMITERS); } } + if (GRN_TEXT_LEN(&request_id) > 0) { + grn_request_canceler_register(ctx, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + } ctx->impl->curr_expr = expr; grn_expr_exec(ctx, expr, 0); + if (GRN_TEXT_LEN(&request_id) > 0) { + grn_request_canceler_unregister(ctx, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + } } else { ERR(GRN_INVALID_ARGUMENT, "invalid command name: %.*s", command_name_size, command_name); @@ -1693,8 +1785,10 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len) char tok_type; int offset = 0; grn_obj buf, *expr = NULL, *val = NULL; + grn_obj request_id; const char *p = str, *e = str + str_len, *v; GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_INIT(&request_id, 0); p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); while (p < e) { @@ -1720,6 +1814,11 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len) p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); get_command_version(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf)); if (ctx->rc) { goto exit; } + } else if (l == REQUEST_ID_LEN && + !memcmp(v, REQUEST_ID, REQUEST_ID_LEN)) { + GRN_BULK_REWIND(&request_id); + p = grn_text_unesc_tok(ctx, &request_id, p, e, &tok_type); + if (ctx->rc) { goto exit; } } else if (expr && (val = grn_expr_get_or_add_var(ctx, expr, v, l))) { grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); p = grn_text_unesc_tok(ctx, val, p, e, &tok_type); @@ -1740,6 +1839,11 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len) break; } } + if (GRN_TEXT_LEN(&request_id) > 0) { + grn_request_canceler_register(ctx, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + } ctx->impl->curr_expr = expr; if (expr && command_proc_p(expr)) { grn_expr_exec(ctx, expr, 0); @@ -1751,7 +1855,13 @@ grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len) (int)GRN_TEXT_LEN(&buf), GRN_TEXT_VALUE(&buf)); } } + if (GRN_TEXT_LEN(&request_id) > 0) { + grn_request_canceler_unregister(ctx, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + } exit : + GRN_OBJ_FIN(ctx, &request_id); GRN_OBJ_FIN(ctx, &buf); return expr; } @@ -1991,7 +2101,7 @@ grn_cache_open(grn_ctx *ctx) goto exit; } - cache->next = (grn_cache_entry*)cache; + cache->next = (grn_cache_entry *)cache; cache->prev = (grn_cache_entry *)cache; cache->hash = grn_hash_create(&grn_gctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_cache_entry), GRN_OBJ_KEY_VAR_SIZE); @@ -2208,7 +2318,6 @@ grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags, void *res = NULL; if (!ctx) { return res; } if (!ctx->impl) { - grn_ctx_impl_init(ctx); if (ERRP(ctx, GRN_ERROR)) { return res; } } CRITICAL_SECTION_ENTER(ctx->impl->lock); @@ -2220,7 +2329,7 @@ grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags, if (size > GRN_CTX_SEGMENT_SIZE) { uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; if (npages >= (1LL<<32)) { - MERR("too long request size=%zu", size); + MERR("too long request size=%" GRN_FMT_SIZE, size); goto exit; } for (i = 0, mi = ctx->impl->segs;; i++, mi++) { @@ -2395,7 +2504,6 @@ grn_ctx_use(grn_ctx *ctx, grn_obj *db) if (db && !DB_P(db)) { ctx->rc = GRN_INVALID_ARGUMENT; } else { - if (!ctx->impl) { grn_ctx_impl_init(ctx); } if (!ctx->rc) { ctx->impl->db = db; if (db) { @@ -2416,7 +2524,6 @@ grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, { if (!ctx) { return NULL; } if (!ctx->impl) { - grn_ctx_impl_init(ctx); if (ERRP(ctx, GRN_ERROR)) { return NULL; } } { @@ -2425,7 +2532,7 @@ grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, if (size > GRN_CTX_SEGMENT_SIZE) { uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; if (npages >= (1LL<<32)) { - MERR("too long request size=%zu", size); + MERR("too long request size=%" GRN_FMT_SIZE, size); return NULL; } for (;;) { @@ -2611,14 +2718,14 @@ grn_malloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const void *res = malloc(size); if (res) { GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res); + grn_alloc_info_add(res, file, line, func); } else { if (!(res = malloc(size))) { - MERR("malloc fail (%zu)=%p (%s:%d) <%d>", + MERR("malloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", size, res, file, line, alloc_count); } else { GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res); + grn_alloc_info_add(res, file, line, func); } } return res; @@ -2633,7 +2740,7 @@ grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const void *res = calloc(size, 1); if (res) { GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res); + grn_alloc_info_add(res, file, line, func); } else { if (!(res = calloc(size, 1))) { MERR("calloc fail (%" GRN_FMT_LLU ")=%p (%s:%d) <%" GRN_FMT_LLU ">", @@ -2641,7 +2748,7 @@ grn_calloc_default(grn_ctx *ctx, size_t size, const char* file, int line, const (unsigned long long int)alloc_count); } else { GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res); + grn_alloc_info_add(res, file, line, func); } } return res; @@ -2671,7 +2778,8 @@ grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int if (size) { if (!(res = realloc(ptr, size))) { if (!(res = realloc(ptr, size))) { - MERR("realloc fail (%p,%zu)=%p (%s:%d) <%d>", ptr, size, res, file, line, alloc_count); + MERR("realloc fail (%p,%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + ptr, size, res, file, line, alloc_count); return NULL; } } @@ -2679,7 +2787,7 @@ grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, const char* file, int grn_alloc_info_change(ptr, res); } else { GRN_ADD_ALLOC_COUNT(1); - grn_alloc_info_add(res); + grn_alloc_info_add(res, file, line, func); } } else { if (!ptr) { return NULL; } @@ -2705,9 +2813,13 @@ grn_strdup_default(grn_ctx *ctx, const char *s, const char* file, int line, cons char *res = strdup(s); if (res) { GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, file, line, func); } else { if (!(res = strdup(s))) { MERR("strdup(%p)=%p (%s:%d) <%d>", s, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, file, line, func); } } return res; @@ -2758,7 +2870,8 @@ grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, const char* file, int lin if (grn_fail_malloc_check(size, file, line, func)) { return grn_realloc_default(ctx, ptr, size, file, line, func); } else { - MERR("fail_realloc (%p,%zu) (%s:%d@%s) <%d>", ptr, size, file, line, func, alloc_count); + MERR("fail_realloc (%p,%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + ptr, size, file, line, func, alloc_count); return NULL; } } @@ -2922,6 +3035,18 @@ grn_set_term_handler(void) } void +grn_ctx_output_flush(grn_ctx *ctx, int flags) +{ + if (flags & GRN_CTX_QUIET) { + return; + } + if (!ctx->impl->output) { + return; + } + ctx->impl->output(ctx, 0, ctx->impl->data.ptr); +} + +void grn_ctx_output_array_open(grn_ctx *ctx, const char *name, int nelements) { grn_output_array_open(ctx, ctx->impl->outbuf, ctx->impl->output_type, @@ -2990,3 +3115,25 @@ grn_ctx_output_obj(grn_ctx *ctx, grn_obj *value, grn_obj_format *format) grn_output_obj(ctx, ctx->impl->outbuf, ctx->impl->output_type, value, format); } + +void +grn_ctx_output_table_columns(grn_ctx *ctx, grn_obj *table, + grn_obj_format *format) +{ + grn_output_table_columns(ctx, + ctx->impl->outbuf, + ctx->impl->output_type, + table, + format); +} + +void +grn_ctx_output_table_records(grn_ctx *ctx, grn_obj *table, + grn_obj_format *format) +{ + grn_output_table_records(ctx, + ctx->impl->outbuf, + ctx->impl->output_type, + table, + format); +} diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c b/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c index 21531e4a837..05692eee13e 100644 --- a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c +++ b/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013-2014 Brazil + Copyright(C) 2013-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,27 +16,67 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "ctx_impl_mrb.h" -#include "ctx_impl.h" - -#include "mrb.h" -#include "mrb/mrb_error.h" -#include "mrb/mrb_id.h" -#include "mrb/mrb_operator.h" -#include "mrb/mrb_ctx.h" -#include "mrb/mrb_logger.h" -#include "mrb/mrb_void.h" -#include "mrb/mrb_bulk.h" -#include "mrb/mrb_obj.h" -#include "mrb/mrb_column.h" -#include "mrb/mrb_fixed_size_column.h" -#include "mrb/mrb_variable_size_column.h" -#include "mrb/mrb_index_column.h" -#include "mrb/mrb_expr.h" -#include "mrb/mrb_accessor.h" -#include "mrb/mrb_procedure.h" +#include "grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY +# include <string.h> + +# include "grn_ctx_impl_mrb.h" + +# include "grn_mrb.h" +# include "mrb/mrb_converter.h" +# include "mrb/mrb_error.h" +# include "mrb/mrb_id.h" +# include "mrb/mrb_operator.h" +# include "mrb/mrb_ctx.h" +# include "mrb/mrb_logger.h" +# include "mrb/mrb_void.h" +# include "mrb/mrb_bulk.h" +# include "mrb/mrb_object.h" +# include "mrb/mrb_database.h" +# include "mrb/mrb_table.h" +# include "mrb/mrb_array.h" +# include "mrb/mrb_hash_table.h" +# include "mrb/mrb_patricia_trie.h" +# include "mrb/mrb_double_array_trie.h" +# include "mrb/mrb_column.h" +# include "mrb/mrb_fixed_size_column.h" +# include "mrb/mrb_variable_size_column.h" +# include "mrb/mrb_index_column.h" +# include "mrb/mrb_index_cursor.h" +# include "mrb/mrb_type.h" +# include "mrb/mrb_expr.h" +# include "mrb/mrb_accessor.h" +# include "mrb/mrb_procedure.h" +# include "mrb/mrb_command.h" +# include "mrb/mrb_command_input.h" +# include "mrb/mrb_table_cursor.h" +# include "mrb/mrb_table_cursor_flags.h" +# include "mrb/mrb_writer.h" + +# include <mruby/array.h> +# include <mruby/variable.h> +#endif /* GRN_WITH_MRUBY */ + +#ifdef GRN_WITH_MRUBY +static mrb_value +mrb_kernel_load(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *path; + + mrb_get_args(mrb, "z", &path); + + grn_mrb_load(ctx, path); + if (mrb->exc) { + mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); + } + + grn_mrb_ctx_check(mrb); + + return mrb_true_value(); +} + static void grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx) { @@ -45,8 +85,29 @@ grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx) mrb->ud = ctx; ctx->impl->mrb.module = mrb_define_module(mrb, "Groonga"); - grn_mrb_load(ctx, "backtrace_entry.rb"); + mrb_define_class(mrb, "LoadError", mrb_class_get(mrb, "ScriptError")); + mrb_define_method(mrb, mrb->kernel_module, + "load", mrb_kernel_load, MRB_ARGS_REQ(1)); + + { + mrb_value load_path; + const char *plugins_dir; + const char *system_ruby_scripts_dir; + + load_path = mrb_ary_new(mrb); + plugins_dir = grn_plugin_get_system_plugins_dir(); + mrb_ary_push(mrb, load_path, + mrb_str_new_cstr(mrb, plugins_dir)); + system_ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(ctx); + mrb_ary_push(mrb, load_path, + mrb_str_new_cstr(mrb, system_ruby_scripts_dir)); + mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$LOAD_PATH"), load_path); + } + + grn_mrb_load(ctx, "require.rb"); + grn_mrb_load(ctx, "initialize/pre.rb"); + grn_mrb_converter_init(ctx); grn_mrb_error_init(ctx); grn_mrb_id_init(ctx); grn_mrb_operator_init(ctx); @@ -54,20 +115,29 @@ grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx) grn_mrb_logger_init(ctx); grn_mrb_void_init(ctx); grn_mrb_bulk_init(ctx); - grn_mrb_obj_init(ctx); + grn_mrb_object_init(ctx); + grn_mrb_database_init(ctx); + grn_mrb_table_init(ctx); + grn_mrb_array_init(ctx); + grn_mrb_hash_table_init(ctx); + grn_mrb_patricia_trie_init(ctx); + grn_mrb_double_array_trie_init(ctx); grn_mrb_column_init(ctx); grn_mrb_fixed_size_column_init(ctx); grn_mrb_variable_size_column_init(ctx); grn_mrb_index_column_init(ctx); + grn_mrb_index_cursor_init(ctx); + grn_mrb_type_init(ctx); grn_mrb_expr_init(ctx); grn_mrb_accessor_init(ctx); grn_mrb_procedure_init(ctx); -} + grn_mrb_command_init(ctx); + grn_mrb_command_input_init(ctx); + grn_mrb_table_cursor_init(ctx); + grn_mrb_table_cursor_flags_init(ctx); + grn_mrb_writer_init(ctx); -static void -grn_ctx_impl_mrb_init_eval(grn_ctx *ctx) -{ - grn_mrb_load(ctx, "eval_context.rb"); + grn_mrb_load(ctx, "initialize/post.rb"); } void @@ -77,11 +147,30 @@ grn_ctx_impl_mrb_init(grn_ctx *ctx) grn_mruby_enabled = getenv("GRN_MRUBY_ENABLED"); if (grn_mruby_enabled && strcmp(grn_mruby_enabled, "no") == 0) { ctx->impl->mrb.state = NULL; + ctx->impl->mrb.base_directory[0] = '\0'; ctx->impl->mrb.module = NULL; + ctx->impl->mrb.object_class = NULL; + ctx->impl->mrb.checked_procs = NULL; + ctx->impl->mrb.registered_plugins = NULL; + ctx->impl->mrb.builtin.time_class = NULL; } else { - ctx->impl->mrb.state = mrb_open(); + mrb_state *mrb; + + mrb = mrb_open(); + ctx->impl->mrb.state = mrb; + ctx->impl->mrb.base_directory[0] = '\0'; grn_ctx_impl_mrb_init_bindings(ctx); - grn_ctx_impl_mrb_init_eval(ctx); + /* TODO: Implement better error handling on init. */ + if (ctx->impl->mrb.state->exc) { + mrb_print_error(mrb); + } + ctx->impl->mrb.checked_procs = + grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY); + ctx->impl->mrb.registered_plugins = + grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY); + GRN_VOID_INIT(&(ctx->impl->mrb.buffer.from)); + GRN_VOID_INIT(&(ctx->impl->mrb.buffer.to)); + ctx->impl->mrb.builtin.time_class = mrb_class_get(mrb, "Time"); } } @@ -91,9 +180,13 @@ grn_ctx_impl_mrb_fin(grn_ctx *ctx) if (ctx->impl->mrb.state) { mrb_close(ctx->impl->mrb.state); ctx->impl->mrb.state = NULL; + grn_hash_close(ctx, ctx->impl->mrb.checked_procs); + grn_hash_close(ctx, ctx->impl->mrb.registered_plugins); + GRN_OBJ_FIN(ctx, &(ctx->impl->mrb.buffer.from)); + GRN_OBJ_FIN(ctx, &(ctx->impl->mrb.buffer.to)); } } -#else +#else /* GRN_WITH_MRUBY */ void grn_ctx_impl_mrb_init(grn_ctx *ctx) { @@ -103,4 +196,4 @@ void grn_ctx_impl_mrb_fin(grn_ctx *ctx) { } -#endif +#endif /* GRN_WITH_MRUBY */ diff --git a/storage/mroonga/vendor/groonga/lib/dat.cpp b/storage/mroonga/vendor/groonga/lib/dat.cpp index 8588857cd5d..4a3db12d67d 100644 --- a/storage/mroonga/vendor/groonga/lib/dat.cpp +++ b/storage/mroonga/vendor/groonga/lib/dat.cpp @@ -14,16 +14,16 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <sys/types.h> #include <sys/stat.h> #include <cstring> #include <new> -#include "str.h" -#include "io.h" -#include "dat.h" -#include "util.h" -#include "normalizer_in.h" +#include "grn_str.h" +#include "grn_io.h" +#include "grn_dat.h" +#include "grn_util.h" +#include "grn_normalizer.h" #include "dat/trie.hpp" #include "dat/cursor-factory.hpp" @@ -678,12 +678,18 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str, { if (!grn_dat_open_trie_if_needed(ctx, dat) || !str || !(dat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) || !scan_hits) { + if (str_rest) { + *str_rest = str; + } return -1; } grn::dat::Trie * const trie = static_cast<grn::dat::Trie *>(dat->trie); if (!trie) { - return -1; + if (str_rest) { + *str_rest = str + str_size; + } + return 0; } if (!max_num_scan_hits || !str_size) { @@ -701,7 +707,9 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str, dat->normalizer, flags); if (!normalized_string) { - *str_rest = str; + if (str_rest) { + *str_rest = str; + } return -1; } grn_string_get_normalized(ctx, normalized_string, &str, &str_size, NULL); @@ -778,6 +786,9 @@ grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str, } catch (const grn::dat::Exception &ex) { ERR(grn_dat_translate_error_code(ex.code()), "grn::dat::lcp_search failed"); + if (str_rest) { + *str_rest = str; + } return -1; } return static_cast<int>(num_scan_hits); diff --git a/storage/mroonga/vendor/groonga/lib/dat/Makefile.am b/storage/mroonga/vendor/groonga/lib/dat/Makefile.am index 6bad7730de4..0a58629cc77 100644 --- a/storage/mroonga/vendor/groonga/lib/dat/Makefile.am +++ b/storage/mroonga/vendor/groonga/lib/dat/Makefile.am @@ -2,8 +2,7 @@ DEFS += -D_REENTRANT $(GRN_DEFS) -DGRN_DAT_EXPORT DEFAULT_INCLUDES = \ -I$(top_builddir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/lib + -I$(top_srcdir)/include noinst_LTLIBRARIES = libgrndat.la diff --git a/storage/mroonga/vendor/groonga/lib/dat/dat.hpp b/storage/mroonga/vendor/groonga/lib/dat/dat.hpp index a2b225a9cf4..d2b2264752b 100644 --- a/storage/mroonga/vendor/groonga/lib/dat/dat.hpp +++ b/storage/mroonga/vendor/groonga/lib/dat/dat.hpp @@ -175,13 +175,6 @@ class Exception : public std::exception { what_(ex.what_) {} virtual ~Exception() throw() {} - virtual Exception &operator=(const Exception &ex) throw() { - file_ = ex.file_; - line_ = ex.line_; - what_ = ex.what_; - return *this; - } - virtual ErrorCode code() const throw() = 0; virtual const char *file() const throw() { return file_; @@ -210,11 +203,6 @@ class Error : public Exception { : Exception(ex) {} virtual ~Error() throw() {} - virtual Error &operator=(const Error &ex) throw() { - *static_cast<Exception *>(this) = ex; - return *this; - } - virtual ErrorCode code() const throw() { return T; } diff --git a/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp b/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp index 6382ae965a9..3643a806292 100644 --- a/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp +++ b/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp @@ -36,6 +36,12 @@ #include <algorithm> #include <limits> +#ifdef WIN32 +# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE) +#else /* WIN32 */ +# define GRN_IO_FILE_CREATE_MODE 0644 +#endif /* WIN32 */ + namespace grn { namespace dat { @@ -119,7 +125,7 @@ void FileImpl::swap(FileImpl *rhs) { void FileImpl::create_(const char *path, UInt64 size) { if ((path != NULL) && (path[0] != '\0')) { - file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE, + file_ = ::CreateFileA(path, GRN_IO_FILE_CREATE_MODE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); GRN_DAT_THROW_IF(IO_ERROR, file_ == INVALID_HANDLE_VALUE); @@ -162,7 +168,7 @@ void FileImpl::open_(const char *path) { GRN_DAT_THROW_IF(IO_ERROR, static_cast<UInt64>(st.st_size) > std::numeric_limits< ::size_t>::max()); - file_ = ::CreateFileA(path, GENERIC_READ | GENERIC_WRITE, + file_ = ::CreateFileA(path, GRN_IO_FILE_CREATE_MODE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); GRN_DAT_THROW_IF(IO_ERROR, file_ == NULL); @@ -192,7 +198,7 @@ void FileImpl::create_(const char *path, UInt64 size) { size > static_cast<UInt64>(std::numeric_limits< ::off_t>::max())); if ((path != NULL) && (path[0] != '\0')) { - fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, 0666); + fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, GRN_IO_FILE_CREATE_MODE); GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1); const ::off_t file_size = static_cast< ::off_t>(size); diff --git a/storage/mroonga/vendor/groonga/lib/db.c b/storage/mroonga/vendor/groonga/lib/db.c index f948dc7353a..b9cea065a6a 100644 --- a/storage/mroonga/vendor/groonga/lib/db.c +++ b/storage/mroonga/vendor/groonga/lib/db.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2014 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -14,21 +14,23 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" -#include "db.h" -#include "hash.h" -#include "pat.h" -#include "dat.h" -#include "ii.h" -#include "ctx_impl.h" -#include "token.h" -#include "proc.h" -#include "plugin_in.h" -#include "geo.h" -#include "snip.h" -#include "string_in.h" -#include "normalizer_in.h" -#include "util.h" +#include "grn.h" +#include "grn_db.h" +#include "grn_hash.h" +#include "grn_pat.h" +#include "grn_dat.h" +#include "grn_ii.h" +#include "grn_ctx_impl.h" +#include "grn_token_cursor.h" +#include "grn_tokenizers.h" +#include "grn_proc.h" +#include "grn_plugin.h" +#include "grn_geo.h" +#include "grn_scorers.h" +#include "grn_snip.h" +#include "grn_string.h" +#include "grn_normalizer.h" +#include "grn_util.h" #include <string.h> #include <float.h> @@ -46,6 +48,9 @@ typedef struct { ((table)->header.impl_flags & GRN_TABLE_GROUPED) #define GRN_TABLE_GROUPED_ON(table)\ ((table)->header.impl_flags |= GRN_TABLE_GROUPED) +#define GRN_TABLE_IS_MULTI_KEYS_GROUPED(table)\ + (GRN_TABLE_IS_GROUPED(table) &&\ + table->header.domain == GRN_ID_NIL) #define WITH_NORMALIZE(table,key,key_size,block) do {\ if ((table)->normalizer && key && key_size > 0) {\ @@ -67,7 +72,7 @@ inline static grn_id grn_table_add_v_inline(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, void **value, int *added); inline static void -grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score, +grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score, grn_rset_posinfo *pi, int dir); inline static grn_id grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc); @@ -78,6 +83,10 @@ static void grn_obj_ensure_bulk(grn_ctx *ctx, grn_obj *obj); static void grn_obj_ensure_vector(grn_ctx *ctx, grn_obj *obj); inline static void +grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, + grn_id *range_id, grn_obj_flags *range_flags); + +inline static void gen_pathname(const char *path, char *buffer, int fno) { size_t len = strlen(path); @@ -252,6 +261,7 @@ grn_db_open(grn_ctx *ctx, const char *path) #endif grn_db_init_builtin_tokenizers(ctx); grn_db_init_builtin_normalizers(ctx); + grn_db_init_builtin_scorers(ctx); grn_db_init_builtin_query(ctx); GRN_API_RETURN((grn_obj *)s); } @@ -582,12 +592,17 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ if (!added) { db_value *vp; if ((vp = grn_tiny_array_at(&s->values, id)) && (res = (grn_proc *)vp->ptr)) { + /* TODO: Do more robust check. */ if (res->funcs[PROC_INIT] || res->funcs[PROC_NEXT] || res->funcs[PROC_FIN]) { ERR(GRN_INVALID_ARGUMENT, "already used name"); GRN_API_RETURN(NULL); } + if (range != GRN_ID_NIL) { + grn_plugin_close(ctx, range); + } + GRN_API_RETURN((grn_obj *)res); } else { added = 1; } @@ -609,6 +624,7 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ res->funcs[PROC_NEXT] = next; res->funcs[PROC_FIN] = fin; res->selector = NULL; + memset(&(res->callbacks), 0, sizeof(res->callbacks)); GRN_TEXT_INIT(&res->name_buf, 0); res->vars = NULL; res->nvars = 0; @@ -633,6 +649,7 @@ grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type typ static void calc_rec_size(grn_obj_flags flags, uint32_t max_n_subrecs, uint32_t range_size, + uint32_t additional_value_size, uint8_t *subrec_size, uint8_t *subrec_offset, uint32_t *key_size, uint32_t *value_size) { @@ -676,6 +693,7 @@ calc_rec_size(grn_obj_flags flags, uint32_t max_n_subrecs, uint32_t range_size, } else { *value_size = range_size; } + *value_size += additional_value_size; } static void _grn_obj_remove(grn_ctx *ctx, grn_obj *obj); @@ -728,7 +746,9 @@ static grn_obj * grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name, unsigned int name_size, const char *path, grn_obj_flags flags, grn_obj *key_type, - grn_obj *value_type, uint32_t max_n_subrecs) + grn_obj *value_type, + uint32_t max_n_subrecs, + uint32_t additional_value_size) { grn_id id; grn_id domain = GRN_ID_NIL, range = GRN_ID_NIL; @@ -862,8 +882,8 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name, return NULL; } } - calc_rec_size(flags, max_n_subrecs, range_size, &subrec_size, - &subrec_offset, &key_size, &value_size); + calc_rec_size(flags, max_n_subrecs, range_size, additional_value_size, + &subrec_size, &subrec_offset, &key_size, &value_size); switch (flags & GRN_OBJ_TABLE_TYPE_MASK) { case GRN_OBJ_TABLE_HASH_KEY : res = (grn_obj *)grn_hash_create(ctx, path, key_size, value_size, flags); @@ -886,6 +906,7 @@ grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name, DB_OBJ(res)->max_n_subrecs = max_n_subrecs; DB_OBJ(res)->subrec_size = subrec_size; DB_OBJ(res)->subrec_offset = subrec_offset; + DB_OBJ(res)->flags.group = 0; if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { _grn_obj_remove(ctx, res); res = NULL; @@ -904,7 +925,8 @@ grn_table_create(grn_ctx *ctx, const char *name, unsigned int name_size, grn_obj *res; GRN_API_ENTER; res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, - flags, key_type, value_type, 0); + flags, key_type, value_type, + 0, 0); GRN_API_RETURN(res); } @@ -915,15 +937,27 @@ grn_table_create_for_group(grn_ctx *ctx, const char *name, unsigned int max_n_subrecs) { grn_obj *res = NULL; - grn_obj *key_type; GRN_API_ENTER; - key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, group_key)); - if (key_type) { + if (group_key) { + grn_obj *key_type; + key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, group_key)); + if (key_type) { + res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, + GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC| + GRN_OBJ_UNIT_USERDEF_DOCUMENT, + key_type, value_type, + max_n_subrecs, 0); + grn_obj_unlink(ctx, key_type); + } + } else { res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, GRN_TABLE_HASH_KEY| + GRN_OBJ_KEY_VAR_SIZE| GRN_OBJ_WITH_SUBREC| GRN_OBJ_UNIT_USERDEF_DOCUMENT, - key_type, value_type, max_n_subrecs); + NULL, value_type, + max_n_subrecs, 0); } GRN_API_RETURN(res); } @@ -957,7 +991,7 @@ grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, grn_id id, } for (; count < limit; count++) { if (scorebuf) { - scorebuf[count] = *((int *)psubrec); + scorebuf[count] = *((double *)psubrec); } psubrec += GRN_RSET_SCORE_SIZE; if (subrecbuf) { @@ -1681,6 +1715,22 @@ delete_reference_records(grn_ctx *ctx, grn_obj *table, grn_id id) return ctx->rc; } +static grn_rc +grn_table_delete_prepare(grn_ctx *ctx, grn_obj *table, + grn_id id, const void *key, unsigned int key_size) +{ + grn_rc rc; + + rc = delete_reference_records(ctx, table, id); + if (rc != GRN_SUCCESS) { + return rc; + } + call_delete_hook(ctx, table, id, key, key_size); + clear_column_values(ctx, table, id); + + return rc; +} + grn_rc grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) { @@ -1690,12 +1740,10 @@ grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key if (table) { if (key && key_size) { rid = grn_table_get(ctx, table, key, key_size); } if (rid) { - rc = delete_reference_records(ctx, table, rid); + rc = grn_table_delete_prepare(ctx, table, rid, key, key_size); if (rc != GRN_SUCCESS) { goto exit; } - call_delete_hook(ctx, table, rid, key, key_size); - clear_column_values(ctx, table, rid); switch (table->header.type) { case GRN_DB : /* todo : delete tables and columns from db */ @@ -1740,10 +1788,12 @@ grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key }); break; } - grn_obj_touch(ctx, table, NULL); + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, table, NULL); + } } } -exit: +exit : GRN_API_RETURN(rc); } @@ -1753,16 +1803,17 @@ _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, { grn_rc rc = GRN_INVALID_ARGUMENT; if (table) { - const void *key; - unsigned int key_size; if (id) { - rc = delete_reference_records(ctx, table, id); + const void *key = NULL; + unsigned int key_size = 0; + + if (table->header.type != GRN_TABLE_NO_KEY) { + key = _grn_table_key(ctx, table, id, &key_size); + } + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); if (rc != GRN_SUCCESS) { goto exit; } - if ((key = _grn_table_key(ctx, table, id, &key_size))) { - call_delete_hook(ctx, table, id, key, key_size); - } // todo : support optarg switch (table->header.type) { case GRN_TABLE_PAT_KEY : @@ -1778,12 +1829,9 @@ _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, rc = grn_array_delete_by_id(ctx, (grn_array *)table, id, optarg); break; } - if (rc == GRN_SUCCESS) { - clear_column_values(ctx, table, id); - } } } -exit: +exit : return rc; } @@ -1801,7 +1849,9 @@ grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id) } else { rc = _grn_table_delete_by_id(ctx, table, id, NULL); } - grn_obj_touch(ctx, table, NULL); + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, table, NULL); + } GRN_API_RETURN(rc); } @@ -1839,6 +1889,9 @@ grn_column_truncate(grn_ctx *ctx, grn_obj *column) rc = grn_ra_truncate(ctx, (grn_ra *)column); break; } + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, column, NULL); + } } exit : GRN_API_RETURN(rc); @@ -1905,7 +1958,9 @@ grn_table_truncate(grn_ctx *ctx, grn_obj *table) grn_obj_set_info(ctx, table, GRN_INFO_NORMALIZER, normalizer); grn_obj_set_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); GRN_OBJ_FIN(ctx, &token_filters); - grn_obj_touch(ctx, table, NULL); + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, table, NULL); + } } exit : GRN_API_RETURN(rc); @@ -1948,7 +2003,7 @@ grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_obj_flags *flags, case GRN_TABLE_NO_KEY : if (flags) { *flags = 0; } if (encoding) { *encoding = GRN_ENC_NONE; } - if (tokenizer) { *tokenizer = grn_token_uvector; } + if (tokenizer) { *tokenizer = grn_tokenizer_uvector; } if (normalizer) { *normalizer = NULL; } if (token_filters) { *token_filters = NULL; } rc = GRN_SUCCESS; @@ -1991,10 +2046,10 @@ grn_table_size(grn_ctx *ctx, grn_obj *table) } inline static void -subrecs_push(byte *subrecs, int size, int n_subrecs, int score, void *body, int dir) +subrecs_push(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir) { byte *v; - int *c2; + double *c2; int n = n_subrecs - 1, n2; while (n) { n2 = (n - 1) >> 1; @@ -2004,15 +2059,16 @@ subrecs_push(byte *subrecs, int size, int n_subrecs, int score, void *body, int n = n2; } v = subrecs + n * (GRN_RSET_SCORE_SIZE + size); - *((int *)v) = score; + *((double *)v) = score; memcpy(v + GRN_RSET_SCORE_SIZE, body, size); } inline static void -subrecs_replace_min(byte *subrecs, int size, int n_subrecs, int score, void *body, int dir) +subrecs_replace_min(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir) { byte *v; - int n = 0, n1, n2, *c1, *c2; + int n = 0, n1, n2; + double *c1, *c2; for (;;) { n1 = n * 2 + 1; n2 = n1 + 1; @@ -2043,7 +2099,7 @@ subrecs_replace_min(byte *subrecs, int size, int n_subrecs, int score, void *bod } inline static void -grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score, +grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score, grn_rset_posinfo *pi, int dir) { if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { @@ -2056,7 +2112,7 @@ grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score, if (pi) { byte *body = (byte *)pi + DB_OBJ(table)->subrec_offset; if (limit < n_subrecs) { - if (GRN_RSET_SUBRECS_CMP(score, *ri->subrecs, dir) > 0) { + if (GRN_RSET_SUBRECS_CMP(score, *((double *)(ri->subrecs)), dir) > 0) { subrecs_replace_min((byte *)ri->subrecs, subrec_size, limit, score, body, dir); } } else { @@ -2068,7 +2124,7 @@ grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, int score, } void -grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, int score, +grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score, grn_rset_posinfo *pi, int dir) { grn_table_add_subrec_inline(table, ri, score, pi, dir); @@ -2389,24 +2445,58 @@ grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc) if (!tc) { ERR(GRN_INVALID_ARGUMENT, "tc is null"); } else { + grn_id id; + grn_obj *table; + const void *key = NULL; + unsigned int key_size = 0; switch (tc->header.type) { case GRN_CURSOR_TABLE_PAT_KEY : - rc = grn_pat_cursor_delete(ctx, (grn_pat_cursor *)tc, NULL); + { + grn_pat_cursor *pc = (grn_pat_cursor *)tc; + id = pc->curr_rec; + table = (grn_obj *)(pc->pat); + key = _grn_pat_key(ctx, pc->pat, id, &key_size); + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = grn_pat_cursor_delete(ctx, pc, NULL); + } break; case GRN_CURSOR_TABLE_DAT_KEY : rc = GRN_OPERATION_NOT_SUPPORTED; break; case GRN_CURSOR_TABLE_HASH_KEY : - rc = grn_hash_cursor_delete(ctx, (grn_hash_cursor *)tc, NULL); + { + grn_hash_cursor *hc = (grn_hash_cursor *)tc; + id = hc->curr_rec; + table = (grn_obj *)(hc->hash); + key = _grn_hash_key(ctx, hc->hash, id, &key_size); + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = grn_hash_cursor_delete(ctx, hc, NULL); + } break; case GRN_CURSOR_TABLE_NO_KEY : - rc = grn_array_cursor_delete(ctx, (grn_array_cursor *)tc, NULL); + { + grn_array_cursor *ac = (grn_array_cursor *)tc; + id = ac->curr_rec; + table = (grn_obj *)(ac->array); + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = grn_array_cursor_delete(ctx, ac, NULL); + } break; default : ERR(GRN_INVALID_ARGUMENT, "invalid type %d", tc->header.type); break; } } +exit : GRN_API_RETURN(rc); } @@ -2975,9 +3065,42 @@ grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query, #define GRN_TABLE_GROUP_FILTER_PREFIX 0 #define GRN_TABLE_GROUP_FILTER_SUFFIX (1L<<2) -static int -accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res) +inline static void +grn_table_group_add_subrec(grn_ctx *ctx, + grn_obj *table, + grn_rset_recinfo *ri, double score, + grn_rset_posinfo *pi, int dir, + grn_obj *calc_target, + grn_obj *value_buffer) { + grn_table_group_flags flags; + + if (!(DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC)) { + return; + } + + grn_table_add_subrec_inline(table, ri, score, pi, dir); + + flags = DB_OBJ(table)->flags.group; + + if (!(flags & (GRN_TABLE_GROUP_CALC_MAX | + GRN_TABLE_GROUP_CALC_MIN | + GRN_TABLE_GROUP_CALC_SUM | + GRN_TABLE_GROUP_CALC_AVG))) { + return; + } + + GRN_BULK_REWIND(value_buffer); + grn_obj_get_value(ctx, calc_target, pi->rid, value_buffer); + grn_rset_recinfo_update_calc_values(ctx, ri, table, value_buffer); +} + +static grn_bool +accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, + grn_table_group_result *result) +{ + grn_obj *res = result->table; + grn_obj *calc_target = result->calc_target; if (key->header.type == GRN_ACCESSOR) { grn_accessor *a = (grn_accessor *)key; if (a->action == GRN_ACCESSOR_GET_KEY && @@ -2987,6 +3110,9 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res int idp = GRN_OBJ_TABLEP(range); grn_table_cursor *tc; if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_bool processed = GRN_TRUE; + grn_obj value_buffer; + GRN_VOID_INIT(&value_buffer); switch (a->next->obj->header.type) { case GRN_COLUMN_FIX_SIZE : { @@ -3011,8 +3137,11 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res } if ((!idp || *((grn_id *)v)) && grn_table_add_v_inline(ctx, res, v, element_size, &value, NULL)) { - grn_table_add_subrec_inline(res, value, ri ? ri->score : 0, - (grn_rset_posinfo *)&id, 0); + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); } } GRN_RA_CACHE_FIN(ra, &cache); @@ -3037,8 +3166,11 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res while (len) { if ((*v != GRN_ID_NIL) && grn_table_add_v_inline(ctx, res, v, sizeof(grn_id), &value, NULL)) { - grn_table_add_subrec_inline(res, value, ri ? ri->score : 0, - (grn_rset_posinfo *)&id, 0); + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); } v++; len -= sizeof(grn_id); @@ -3047,18 +3179,109 @@ accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, grn_obj *res } } } else { - return 0; + processed = GRN_FALSE; } break; default : - return 0; + processed = GRN_FALSE; + break; } + GRN_OBJ_FIN(ctx, &value_buffer); grn_table_cursor_close(ctx, tc); - return 1; + return processed; } } } - return 0; + return GRN_FALSE; +} + +static void +grn_table_group_single_key_records(grn_ctx *ctx, grn_obj *table, + grn_obj *key, grn_table_group_result *result) +{ + grn_obj bulk; + grn_obj value_buffer; + grn_table_cursor *tc; + grn_obj *res = result->table; + grn_obj *calc_target = result->calc_target; + + GRN_TEXT_INIT(&bulk, 0); + GRN_VOID_INIT(&value_buffer); + if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); + int idp = GRN_OBJ_TABLEP(range); + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + void *value; + grn_rset_recinfo *ri = NULL; + GRN_BULK_REWIND(&bulk); + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + grn_obj_get_value(ctx, key, id, &bulk); + switch (bulk.header.type) { + case GRN_UVECTOR : + { + // todo : support objects except grn_id + grn_id *v = (grn_id *)GRN_BULK_HEAD(&bulk); + grn_id *ve = (grn_id *)GRN_BULK_CURR(&bulk); + while (v < ve) { + if ((*v != GRN_ID_NIL) && + grn_table_add_v_inline(ctx, res, + v, sizeof(grn_id), &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + v++; + } + } + break; + case GRN_VECTOR : + { + unsigned int i, n_elements; + n_elements = grn_vector_size(ctx, &bulk); + for (i = 0; i < n_elements; i++) { + const char *content; + unsigned int content_length; + content_length = grn_vector_get_element(ctx, &bulk, i, + &content, NULL, NULL); + if (grn_table_add_v_inline(ctx, res, + content, content_length, + &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + } + break; + case GRN_BULK : + { + if ((!idp || *((grn_id *)GRN_BULK_HEAD(&bulk))) && + grn_table_add_v_inline(ctx, res, + GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), + &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, "invalid column"); + break; + } + } + grn_table_cursor_close(ctx, tc); + } + grn_obj_close(ctx, &bulk); } grn_rc @@ -3164,6 +3387,263 @@ grn_table_group_with_range_gap(grn_ctx *ctx, grn_obj *table, return 0; } +static inline void +grn_table_group_multi_keys_add_record(grn_ctx *ctx, + grn_table_sort_key *keys, + int n_keys, + grn_table_group_result *results, + int n_results, + grn_id id, + grn_rset_recinfo *ri, + grn_obj *vector, + grn_obj *bulk) +{ + int r; + grn_table_group_result *rp; + + for (r = 0, rp = results; r < n_results; r++, rp++) { + void *value; + int i; + int end; + + if (rp->key_end > n_keys) { + end = n_keys; + } else { + end = rp->key_end + 1; + } + GRN_BULK_REWIND(bulk); + grn_text_benc(ctx, bulk, end - rp->key_begin); + for (i = rp->key_begin; i < end; i++) { + grn_section section = vector->u.v.sections[i]; + grn_text_benc(ctx, bulk, section.length); + } + { + grn_obj *body = vector->u.v.body; + if (body) { + GRN_TEXT_PUT(ctx, bulk, GRN_BULK_HEAD(body), GRN_BULK_VSIZE(body)); + } + } + for (i = rp->key_begin; i < end; i++) { + grn_section section = vector->u.v.sections[i]; + grn_text_benc(ctx, bulk, section.weight); + grn_text_benc(ctx, bulk, section.domain); + } + + // todo : cut off GRN_ID_NIL + if (grn_table_add_v_inline(ctx, rp->table, + GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk), + &value, NULL)) { + grn_table_group_add_subrec(ctx, rp->table, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + rp->calc_target, + bulk); + } + } +} + +static void +grn_table_group_multi_keys_scalar_records(grn_ctx *ctx, + grn_obj *table, + grn_table_sort_key *keys, + int n_keys, + grn_table_group_result *results, + int n_results) +{ + grn_id id; + grn_table_cursor *tc; + grn_obj bulk; + grn_obj vector; + + tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { + return; + } + + GRN_TEXT_INIT(&bulk, 0); + GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID); + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + int k; + grn_table_sort_key *kp; + grn_rset_recinfo *ri = NULL; + + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + + GRN_BULK_REWIND(&vector); + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + GRN_BULK_REWIND(&bulk); + grn_obj_get_value(ctx, kp->key, id, &bulk); + grn_vector_add_element(ctx, &vector, + GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), + 0, + bulk.header.domain); + } + + grn_table_group_multi_keys_add_record(ctx, keys, n_keys, results, n_results, + id, ri, &vector, &bulk); + } + GRN_OBJ_FIN(ctx, &vector); + GRN_OBJ_FIN(ctx, &bulk); + grn_table_cursor_close(ctx, tc); +} + +static inline void +grn_table_group_multi_keys_vector_record(grn_ctx *ctx, + grn_table_sort_key *keys, + grn_obj *key_buffers, + int nth_key, + int n_keys, + grn_table_group_result *results, + int n_results, + grn_id id, + grn_rset_recinfo *ri, + grn_obj *vector, + grn_obj *bulk) +{ + int k; + grn_table_sort_key *kp; + + for (k = nth_key, kp = &(keys[nth_key]); k < n_keys; k++, kp++) { + grn_obj *key_buffer = &(key_buffers[k]); + switch (key_buffer->header.type) { + case GRN_UVECTOR : + { + unsigned int n_vector_elements; + grn_id domain; + grn_id *ids; + unsigned int i, n_ids; + + n_vector_elements = grn_vector_size(ctx, vector); + domain = key_buffer->header.domain; + ids = (grn_id *)GRN_BULK_HEAD(key_buffer); + n_ids = GRN_BULK_VSIZE(key_buffer) / sizeof(grn_id); + for (i = 0; i < n_ids; i++) { + grn_id element_id = ids[i]; + grn_vector_add_element(ctx, vector, + (const char *)(&element_id), sizeof(grn_id), + 0, + domain); + grn_table_group_multi_keys_vector_record(ctx, + keys, key_buffers, + k + 1, n_keys, + results, n_results, + id, ri, vector, bulk); + while (grn_vector_size(ctx, vector) != n_vector_elements) { + const char *content; + grn_vector_pop_element(ctx, vector, &content, NULL, NULL); + } + } + return; + } + break; + case GRN_VECTOR : + { + unsigned int n_vector_elements; + unsigned int i, n_key_elements; + + n_vector_elements = grn_vector_size(ctx, vector); + n_key_elements = grn_vector_size(ctx, key_buffer); + for (i = 0; i < n_key_elements; i++) { + const char *content; + unsigned int content_length; + grn_id domain; + content_length = grn_vector_get_element(ctx, key_buffer, i, + &content, NULL, &domain); + grn_vector_add_element(ctx, vector, + content, content_length, + 0, + domain); + grn_table_group_multi_keys_vector_record(ctx, + keys, key_buffers, + k + 1, n_keys, + results, n_results, + id, ri, vector, bulk); + while (grn_vector_size(ctx, vector) != n_vector_elements) { + grn_vector_pop_element(ctx, vector, &content, NULL, NULL); + } + } + return; + } + break; + default : + grn_vector_add_element(ctx, vector, + GRN_BULK_HEAD(key_buffer), + GRN_BULK_VSIZE(key_buffer), + 0, + key_buffer->header.domain); + } + } + + if (k == n_keys) { + grn_table_group_multi_keys_add_record(ctx, + keys, n_keys, + results, n_results, + id, ri, vector, bulk); + } +} + +static void +grn_table_group_multi_keys_vector_records(grn_ctx *ctx, + grn_obj *table, + grn_table_sort_key *keys, + int n_keys, + grn_table_group_result *results, + int n_results) +{ + grn_id id; + grn_table_cursor *tc; + grn_obj bulk; + grn_obj vector; + grn_obj *key_buffers; + int k; + + tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { + return; + } + + key_buffers = GRN_MALLOCN(grn_obj, n_keys); + if (!key_buffers) { + grn_table_cursor_close(ctx, tc); + return; + } + + GRN_TEXT_INIT(&bulk, 0); + GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID); + for (k = 0; k < n_keys; k++) { + GRN_VOID_INIT(&(key_buffers[k])); + } + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + grn_table_sort_key *kp; + grn_rset_recinfo *ri = NULL; + + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + grn_obj *key_buffer = &(key_buffers[k]); + GRN_BULK_REWIND(key_buffer); + grn_obj_get_value(ctx, kp->key, id, key_buffer); + } + + GRN_BULK_REWIND(&vector); + grn_table_group_multi_keys_vector_record(ctx, + keys, key_buffers, 0, n_keys, + results, n_results, + id, ri, &vector, &bulk); + } + for (k = 0; k < n_keys; k++) { + GRN_OBJ_FIN(ctx, &(key_buffers[k])); + } + GRN_FREE(key_buffers); + GRN_OBJ_FIN(ctx, &vector); + GRN_OBJ_FIN(ctx, &bulk); + grn_table_cursor_close(ctx, tc); +} + grn_rc grn_table_group(grn_ctx *ctx, grn_obj *table, grn_table_sort_key *keys, int n_keys, @@ -3177,9 +3657,6 @@ grn_table_group(grn_ctx *ctx, grn_obj *table, GRN_API_ENTER; { int k, r; - void *key; - grn_obj bulk; - grn_table_cursor *tc; grn_table_sort_key *kp; grn_table_group_result *rp; for (k = 0, kp = keys; k < n_keys; k++, kp++) { @@ -3190,94 +3667,59 @@ grn_table_group(grn_ctx *ctx, grn_obj *table, } for (r = 0, rp = results; r < n_results; r++, rp++) { if (!rp->table) { - ERR(GRN_INVALID_ARGUMENT, "table missing in (%d)", r); - goto exit; + grn_obj_flags flags; + grn_obj *key_type = NULL; + uint32_t additional_value_size; + + flags = GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC| + GRN_OBJ_UNIT_USERDEF_DOCUMENT; + if (n_keys == 1) { + key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys[0].key)); + } else { + flags |= GRN_OBJ_KEY_VAR_SIZE; + } + additional_value_size = grn_rset_recinfo_calc_values_size(ctx, + rp->flags); + rp->table = grn_table_create_with_max_n_subrecs(ctx, NULL, 0, NULL, + flags, + key_type, table, + rp->max_n_subrecs, + additional_value_size); + if (key_type) { + grn_obj_unlink(ctx, key_type); + } + if (!rp->table) { + goto exit; + } + DB_OBJ(rp->table)->flags.group = rp->flags; } } - GRN_TEXT_INIT(&bulk, 0); if (n_keys == 1 && n_results == 1) { - if (!accelerated_table_group(ctx, table, keys->key, results->table)) { - if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { - grn_id id; - grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys->key)); - int idp = GRN_OBJ_TABLEP(range); - while ((id = grn_table_cursor_next_inline(ctx, tc))) { - void *value; - grn_rset_recinfo *ri = NULL; - GRN_BULK_REWIND(&bulk); - if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { - grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); - } - grn_obj_get_value(ctx, keys->key, id, &bulk); - switch (bulk.header.type) { - case GRN_UVECTOR : - { - // todo : support objects except grn_id - grn_id *v = (grn_id *)GRN_BULK_HEAD(&bulk); - grn_id *ve = (grn_id *)GRN_BULK_CURR(&bulk); - while (v < ve) { - if ((*v != GRN_ID_NIL) && - grn_table_add_v_inline(ctx, results->table, v, sizeof(grn_id), &value, NULL)) { - grn_table_add_subrec_inline(results->table, value, ri ? ri->score : 0, - (grn_rset_posinfo *)&id, 0); - } - v++; - } - } - break; - case GRN_VECTOR : - ERR(GRN_OPERATION_NOT_SUPPORTED, "sorry.. not implemented yet"); - /* todo */ - break; - case GRN_BULK : - { - if ((!idp || *((grn_id *)GRN_BULK_HEAD(&bulk))) && - grn_table_add_v_inline(ctx, results->table, - GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), &value, NULL)) { - grn_table_add_subrec_inline(results->table, value, ri ? ri->score : 0, - (grn_rset_posinfo *)&id, 0); - } - } - break; - default : - ERR(GRN_INVALID_ARGUMENT, "invalid column"); - break; - } - } - grn_table_cursor_close(ctx, tc); - } + if (!accelerated_table_group(ctx, table, keys->key, results)) { + grn_table_group_single_key_records(ctx, table, keys->key, results); } } else { - if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { - grn_id id; - while ((id = grn_table_cursor_next_inline(ctx, tc))) { - grn_rset_recinfo *ri = NULL; - GRN_BULK_REWIND(&bulk); - if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { - grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); - } - for (k = 0, kp = keys; k < n_keys; k++, kp++) { - kp->offset = GRN_BULK_VSIZE(&bulk); - grn_obj_get_value(ctx, kp->key, id, &bulk); - } - for (r = 0, rp = results; r < n_results; r++, rp++) { - void *value; - int begin = keys[rp->key_begin].offset; - int end = rp->key_end >= n_keys - ? GRN_BULK_VSIZE(&bulk) - : keys[rp->key_end].offset; - key = GRN_BULK_HEAD(&bulk) + begin; - // todo : cut off GRN_ID_NIL - if (grn_table_add_v_inline(ctx, rp->table, key, end - begin, &value, NULL)) { - grn_table_add_subrec_inline(rp->table, value, ri ? ri->score : 0, - (grn_rset_posinfo *)&id, 0); - } - } + grn_bool have_vector = GRN_FALSE; + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + grn_id range_id; + grn_obj_flags range_flags = 0; + grn_obj_get_range_info(ctx, kp->key, &range_id, &range_flags); + if (range_flags == GRN_OBJ_VECTOR) { + have_vector = GRN_TRUE; + break; } - grn_table_cursor_close(ctx, tc); + } + if (have_vector) { + grn_table_group_multi_keys_vector_records(ctx, table, + keys, n_keys, + results, n_results); + } else { + grn_table_group_multi_keys_scalar_records(ctx, table, + keys, n_keys, + results, n_results); } } - grn_obj_close(ctx, &bulk); for (r = 0, rp = results; r < n_results; r++, rp++) { GRN_TABLE_GROUPED_ON(rp->table); } @@ -3674,8 +4116,9 @@ grn_column_create(grn_ctx *ctx, grn_obj *table, if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { _grn_obj_remove(ctx, res); res = NULL; + } else { + grn_obj_touch(ctx, res, NULL); } - grn_obj_touch(ctx, res, NULL); } exit : if (!res && id) { grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); } @@ -3816,17 +4259,67 @@ grn_vector_delimit(grn_ctx *ctx, grn_obj *vector) */ static unsigned int -grn_uvector_size_internal(grn_ctx *ctx, grn_obj *uvector) +grn_uvector_element_size_internal(grn_ctx *ctx, grn_obj *uvector) { - unsigned int size; + unsigned int element_size; if (IS_WEIGHT_UVECTOR(uvector)) { - size = GRN_BULK_VSIZE(uvector) / sizeof(weight_uvector_entry); + element_size = sizeof(weight_uvector_entry); } else { - size = GRN_BULK_VSIZE(uvector) / sizeof(grn_id); + switch (uvector->header.domain) { + case GRN_DB_BOOL : + element_size = sizeof(grn_bool); + break; + case GRN_DB_INT8 : + element_size = sizeof(int8_t); + break; + case GRN_DB_UINT8 : + element_size = sizeof(uint8_t); + break; + case GRN_DB_INT16 : + element_size = sizeof(int16_t); + break; + case GRN_DB_UINT16 : + element_size = sizeof(uint16_t); + break; + case GRN_DB_INT32 : + element_size = sizeof(int32_t); + break; + case GRN_DB_UINT32 : + element_size = sizeof(uint32_t); + break; + case GRN_DB_INT64 : + element_size = sizeof(int64_t); + break; + case GRN_DB_UINT64 : + element_size = sizeof(uint64_t); + break; + case GRN_DB_FLOAT : + element_size = sizeof(double); + break; + case GRN_DB_TIME : + element_size = sizeof(int64_t); + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + element_size = sizeof(grn_geo_point); + break; + default : + element_size = sizeof(grn_id); + break; + } } - return size; + return element_size; +} + +static unsigned int +grn_uvector_size_internal(grn_ctx *ctx, grn_obj *uvector) +{ + unsigned int element_size; + + element_size = grn_uvector_element_size_internal(ctx, uvector); + return GRN_BULK_VSIZE(uvector) / element_size; } unsigned int @@ -4098,6 +4591,30 @@ grn_uvector_size(grn_ctx *ctx, grn_obj *uvector) GRN_API_RETURN(size); } +unsigned int +grn_uvector_element_size(grn_ctx *ctx, grn_obj *uvector) +{ + unsigned int element_size; + + if (!uvector) { + ERR(GRN_INVALID_ARGUMENT, "uvector must not be NULL"); + return 0; + } + + if (uvector->header.type != GRN_UVECTOR) { + grn_obj type_name; + GRN_TEXT_INIT(&type_name, 0); + grn_inspect_type(ctx, &type_name, uvector->header.type); + ERR(GRN_INVALID_ARGUMENT, "must be GRN_UVECTOR: %.*s", + (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name)); + GRN_OBJ_FIN(ctx, &type_name); + return 0; + } + + GRN_API_ENTER; + element_size = grn_uvector_element_size_internal(ctx, uvector); + GRN_API_RETURN(element_size); +} grn_rc grn_uvector_add_element(grn_ctx *ctx, grn_obj *uvector, @@ -4184,6 +4701,68 @@ accessor_new(grn_ctx *ctx) return res; } +inline static grn_bool +grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj, + grn_accessor **res, uint8_t action) +{ + grn_bool succeeded = GRN_FALSE; + grn_accessor **rp; + + for (rp = res; GRN_TRUE; rp = &(*rp)->next) { + *rp = accessor_new(ctx); + (*rp)->obj = obj; + + switch (action) { + case GRN_ACCESSOR_GET_SCORE : + if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) { + (*rp)->action = action; + succeeded = GRN_TRUE; + goto exit; + } + break; + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + case GRN_ACCESSOR_GET_AVG : + case GRN_ACCESSOR_GET_NSUBRECS : + if (GRN_TABLE_IS_GROUPED(obj)) { + (*rp)->action = action; + succeeded = GRN_TRUE; + goto exit; + } + break; + } + + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + break; + case GRN_TABLE_NO_KEY : + if (!obj->header.domain) { + goto exit; + } + (*rp)->action = GRN_ACCESSOR_GET_VALUE; + break; + default : + /* lookup failed */ + goto exit; + } + if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { + goto exit; + } + } + +exit : + if (!succeeded) { + grn_obj_close(ctx, (grn_obj *)*res); + *res = NULL; + } + + return succeeded; +} + static grn_obj * grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int name_size) { @@ -4203,6 +4782,10 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int case GRN_ACCESSOR_GET_VALUE : case GRN_ACCESSOR_GET_SCORE : case GRN_ACCESSOR_GET_NSUBRECS : + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + case GRN_ACCESSOR_GET_AVG : obj = grn_ctx_at(ctx, DB_OBJ(res->obj)->range); break; case GRN_ACCESSOR_GET_COLUMN_VALUE : @@ -4240,6 +4823,11 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int for (rp = &res; !done; rp = &(*rp)->next) { *rp = accessor_new(ctx); (*rp)->obj = obj; + if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) { + (*rp)->action = GRN_ACCESSOR_GET_KEY; + done++; + break; + } if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { grn_obj_close(ctx, (grn_obj *)res); res = NULL; @@ -4366,42 +4954,23 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int } } break; - case 's' : /* score */ - if (len != GRN_COLUMN_NAME_SCORE_LEN || - memcmp(name, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN)) { - goto exit; - } - for (rp = &res; !done; rp = &(*rp)->next) { - *rp = accessor_new(ctx); - (*rp)->obj = obj; - if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) { - (*rp)->action = GRN_ACCESSOR_GET_SCORE; - done++; - } else { - switch (obj->header.type) { - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_DAT_KEY : - case GRN_TABLE_HASH_KEY : - (*rp)->action = GRN_ACCESSOR_GET_KEY; - break; - case GRN_TABLE_NO_KEY : - if (obj->header.domain) { - (*rp)->action = GRN_ACCESSOR_GET_VALUE; - break; - } - /* fallthru */ - default : - /* lookup failed */ - grn_obj_close(ctx, (grn_obj *)res); - res = NULL; - goto exit; - } - if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { - grn_obj_close(ctx, (grn_obj *)res); - res = NULL; - goto exit; - } + case 's' : /* score, sum */ + if (len == GRN_COLUMN_NAME_SCORE_LEN && + memcmp(name, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_SCORE)) { + goto exit; + } + } else if (len == GRN_COLUMN_NAME_SUM_LEN && + memcmp(name, + GRN_COLUMN_NAME_SUM, + GRN_COLUMN_NAME_SUM_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_SUM)) { + goto exit; } + } else { + goto exit; } break; case 'n' : /* nsubrecs */ @@ -4411,37 +4980,43 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int GRN_COLUMN_NAME_NSUBRECS_LEN)) { goto exit; } - for (rp = &res; !done; rp = &(*rp)->next) { - *rp = accessor_new(ctx); - (*rp)->obj = obj; - if (GRN_TABLE_IS_GROUPED(obj)) { - (*rp)->action = GRN_ACCESSOR_GET_NSUBRECS; - done++; - } else { - switch (obj->header.type) { - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_DAT_KEY : - case GRN_TABLE_HASH_KEY : - (*rp)->action = GRN_ACCESSOR_GET_KEY; - break; - case GRN_TABLE_NO_KEY : - if (obj->header.domain) { - (*rp)->action = GRN_ACCESSOR_GET_VALUE; - break; - } - /* fallthru */ - default : - /* lookup failed */ - grn_obj_close(ctx, (grn_obj *)res); - res = NULL; - goto exit; - } - if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { - grn_obj_close(ctx, (grn_obj *)res); - res = NULL; - goto exit; - } + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_NSUBRECS)) { + goto exit; + } + break; + case 'm' : /* max, min */ + if (len == GRN_COLUMN_NAME_MAX_LEN && + memcmp(name, + GRN_COLUMN_NAME_MAX, + GRN_COLUMN_NAME_MAX_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_MAX)) { + goto exit; + } + } else if (len == GRN_COLUMN_NAME_MIN_LEN && + memcmp(name, + GRN_COLUMN_NAME_MIN, + GRN_COLUMN_NAME_MIN_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_MIN)) { + goto exit; + } + } else { + goto exit; + } + break; + case 'a' : /* avg */ + if (len == GRN_COLUMN_NAME_AVG_LEN && + memcmp(name, + GRN_COLUMN_NAME_AVG, + GRN_COLUMN_NAME_AVG_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_AVG)) { + goto exit; } + } else { + goto exit; } break; default : @@ -4468,7 +5043,9 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int (*rp)->action = GRN_ACCESSOR_GET_COLUMN_VALUE; break; } else { - if (!obj->header.domain) { + grn_id next_obj_id; + next_obj_id = obj->header.domain; + if (!next_obj_id) { // ERR(GRN_INVALID_ARGUMENT, "no such column: <%s>", name); if (!is_chained) { grn_obj_close(ctx, (grn_obj *)res); @@ -4478,7 +5055,8 @@ grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int } *rp = accessor_new(ctx); (*rp)->obj = obj; - if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { + obj = grn_ctx_at(ctx, next_obj_id); + if (!obj) { grn_obj_close(ctx, (grn_obj *)res); res = NULL; goto exit; @@ -4527,6 +5105,33 @@ grn_column_is_vector(grn_ctx *ctx, grn_obj *column) return type == GRN_OBJ_COLUMN_VECTOR; } +inline static grn_bool +grn_column_is_index(grn_ctx *ctx, grn_obj *column) +{ + grn_obj_flags type; + + if (column->header.type == GRN_ACCESSOR) { + grn_accessor *a; + for (a = (grn_accessor *)column; a; a = a->next) { + if (a->next) { + continue; + } + if (a->action != GRN_ACCESSOR_GET_COLUMN_VALUE) { + return GRN_FALSE; + } + + column = a->obj; + } + } + + if (column->header.type != GRN_COLUMN_INDEX) { + return GRN_FALSE; + } + + type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; + return type == GRN_OBJ_COLUMN_INDEX; +} + inline static void grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, grn_id *range_id, grn_obj_flags *range_flags) @@ -4549,16 +5154,21 @@ grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, } break; case GRN_ACCESSOR_GET_SCORE : + *range_id = GRN_DB_FLOAT; + break; case GRN_ACCESSOR_GET_NSUBRECS : *range_id = GRN_DB_INT32; break; + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + *range_id = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_AVG : + *range_id = GRN_DB_FLOAT; + break; case GRN_ACCESSOR_GET_COLUMN_VALUE : - if (GRN_DB_OBJP(a->obj)) { - *range_id = DB_OBJ(a->obj)->range; - if (grn_column_is_vector(ctx, a->obj)) { - *range_flags = GRN_OBJ_VECTOR; - } - } + grn_obj_get_range_info(ctx, a->obj, range_id, range_flags); break; case GRN_ACCESSOR_GET_KEY : if (GRN_DB_OBJP(a->obj)) { *range_id = DB_OBJ(a->obj)->header.domain; } @@ -4594,6 +5204,10 @@ grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj) switch (a->action) { case GRN_ACCESSOR_GET_SCORE : case GRN_ACCESSOR_GET_NSUBRECS : + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + case GRN_ACCESSOR_GET_AVG : res = 0; break; case GRN_ACCESSOR_GET_ID : @@ -5071,7 +5685,7 @@ grn_accessor_get_value_(grn_ctx *ctx, grn_accessor *a, grn_id id, uint32_t *size case GRN_ACCESSOR_GET_SCORE : if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { value = (const char *)&((grn_rset_recinfo *)value)->score; - *size = sizeof(int); + *size = sizeof(double); } break; case GRN_ACCESSOR_GET_NSUBRECS : @@ -5080,6 +5694,42 @@ grn_accessor_get_value_(grn_ctx *ctx, grn_accessor *a, grn_id id, uint32_t *size *size = sizeof(int); } break; + case GRN_ACCESSOR_GET_MAX : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_max_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_MAX_SIZE; + } + break; + case GRN_ACCESSOR_GET_MIN : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_min_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_MIN_SIZE; + } + break; + case GRN_ACCESSOR_GET_SUM : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_sum_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_SUM_SIZE; + } + break; + case GRN_ACCESSOR_GET_AVG : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_avg_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_AVG_SIZE; + } + break; case GRN_ACCESSOR_GET_COLUMN_VALUE : /* todo : support vector */ value = grn_obj_get_value_(ctx, a->obj, id, size); @@ -5120,13 +5770,35 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) switch (a->action) { case GRN_ACCESSOR_GET_ID : GRN_UINT32_PUT(ctx, value, id); + value->header.domain = GRN_DB_UINT32; vp = GRN_BULK_HEAD(value) + size0; vs = GRN_BULK_VSIZE(value) - size0; break; case GRN_ACCESSOR_GET_KEY : - grn_table_get_key2(ctx, a->obj, id, value); - vp = GRN_BULK_HEAD(value) + size0; - vs = GRN_BULK_VSIZE(value) - size0; + if (!a->next && GRN_TABLE_IS_MULTI_KEYS_GROUPED(a->obj)) { + grn_obj_ensure_vector(ctx, value); + if (id) { + grn_obj raw_vector; + GRN_TEXT_INIT(&raw_vector, 0); + grn_table_get_key2(ctx, a->obj, id, &raw_vector); + grn_vector_decode(ctx, value, + GRN_BULK_HEAD(&raw_vector), + GRN_BULK_VSIZE(&raw_vector)); + GRN_OBJ_FIN(ctx, &raw_vector); + } + vp = NULL; + vs = 0; + } else { + if (id) { + grn_table_get_key2(ctx, a->obj, id, value); + vp = GRN_BULK_HEAD(value) + size0; + vs = GRN_BULK_VSIZE(value) - size0; + } else { + vp = NULL; + vs = 0; + } + value->header.domain = a->obj->header.domain; + } break; case GRN_ACCESSOR_GET_VALUE : grn_obj_get_value(ctx, a->obj, id, value); @@ -5134,17 +5806,66 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) vs = GRN_BULK_VSIZE(value) - size0; break; case GRN_ACCESSOR_GET_SCORE : - grn_obj_get_value(ctx, a->obj, id, value); - { + if (id) { grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); - GRN_INT32_PUT(ctx, value, ri->score); + GRN_FLOAT_PUT(ctx, value, ri->score); + } else { + GRN_FLOAT_PUT(ctx, value, 0.0); } + value->header.domain = GRN_DB_FLOAT; break; case GRN_ACCESSOR_GET_NSUBRECS : - { + if (id) { grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); GRN_INT32_PUT(ctx, value, ri->n_subrecs); + } else { + GRN_INT32_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT32; + break; + case GRN_ACCESSOR_GET_MAX : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t max; + max = grn_rset_recinfo_get_max(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, value, max); + } else { + GRN_INT64_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_MIN : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t min; + min = grn_rset_recinfo_get_min(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, value, min); + } else { + GRN_INT64_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_SUM : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t sum; + sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, value, sum); + } else { + GRN_INT64_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_AVG : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + double avg; + avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj); + GRN_FLOAT_PUT(ctx, value, avg); + } else { + GRN_FLOAT_PUT(ctx, value, 0.0); } + value->header.domain = GRN_DB_FLOAT; break; case GRN_ACCESSOR_GET_COLUMN_VALUE : /* todo : support vector */ @@ -5165,7 +5886,11 @@ grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) break; } if ((a = a->next)) { - id = *((grn_id *)vp); + if (vs > 0) { + id = *((grn_id *)vp); + } else { + id = GRN_ID_NIL; + } } else { break; } @@ -5208,15 +5933,14 @@ grn_accessor_set_value(grn_ctx *ctx, grn_accessor *a, grn_id id, } else { uint32_t size; if ((ri = (grn_rset_recinfo *) grn_obj_get_value_(ctx, a->obj, id, &size))) { - vp = &ri->score; // todo : flags support - if (value->header.domain == GRN_DB_INT32) { - memcpy(vp, GRN_BULK_HEAD(value), sizeof(int)); + if (value->header.domain == GRN_DB_FLOAT) { + ri->score = GRN_FLOAT_VALUE(value); } else { grn_obj buf; - GRN_INT32_INIT(&buf, 0); + GRN_FLOAT_INIT(&buf, 0); grn_obj_cast(ctx, value, &buf, GRN_FALSE); - memcpy(vp, GRN_BULK_HEAD(&buf), sizeof(int)); + ri->score = GRN_FLOAT_VALUE(&buf); GRN_OBJ_FIN(ctx, &buf); } } @@ -5230,6 +5954,74 @@ grn_accessor_set_value(grn_ctx *ctx, grn_accessor *a, grn_id id, vp = &ri->n_subrecs; } break; + case GRN_ACCESSOR_GET_MAX : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_INT64) { + grn_rset_recinfo_set_max(ctx, ri, a->obj, GRN_INT64_VALUE(value)); + } else { + grn_obj value_int64; + GRN_INT64_INIT(&value_int64, 0); + if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { + grn_rset_recinfo_set_max(ctx, ri, a->obj, + GRN_INT64_VALUE(&value_int64)); + } + GRN_OBJ_FIN(ctx, &value_int64); + } + } + break; + case GRN_ACCESSOR_GET_MIN : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_INT64) { + grn_rset_recinfo_set_min(ctx, ri, a->obj, GRN_INT64_VALUE(value)); + } else { + grn_obj value_int64; + GRN_INT64_INIT(&value_int64, 0); + if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { + grn_rset_recinfo_set_min(ctx, ri, a->obj, + GRN_INT64_VALUE(&value_int64)); + } + GRN_OBJ_FIN(ctx, &value_int64); + } + } + break; + case GRN_ACCESSOR_GET_SUM : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_INT64) { + grn_rset_recinfo_set_sum(ctx, ri, a->obj, GRN_INT64_VALUE(value)); + } else { + grn_obj value_int64; + GRN_INT64_INIT(&value_int64, 0); + if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { + grn_rset_recinfo_set_sum(ctx, ri, a->obj, + GRN_INT64_VALUE(&value_int64)); + } + GRN_OBJ_FIN(ctx, &value_int64); + } + } + break; + case GRN_ACCESSOR_GET_AVG : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_FLOAT) { + grn_rset_recinfo_set_avg(ctx, ri, a->obj, GRN_FLOAT_VALUE(value)); + } else { + grn_obj value_float; + GRN_FLOAT_INIT(&value_float, 0); + if (!grn_obj_cast(ctx, value, &value_float, GRN_FALSE)) { + grn_rset_recinfo_set_avg(ctx, ri, a->obj, + GRN_FLOAT_VALUE(&value_float)); + } + GRN_OBJ_FIN(ctx, &value_float); + } + } + break; case GRN_ACCESSOR_GET_COLUMN_VALUE : /* todo : support vector */ if (a->next) { @@ -5671,7 +6463,7 @@ grn_obj_set_value_column_var_size_vector(grn_ctx *ctx, grn_obj *obj, grn_id id, if (v && s && (token_cursor = grn_token_cursor_open(ctx, lexicon, v, s, GRN_TOKEN_ADD, token_flags))) { - while (token_cursor->status == GRN_TOKEN_DOING) { + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { grn_id tid = grn_token_cursor_next(ctx, token_cursor); grn_uvector_add_element(ctx, &uvector, tid, 0); } @@ -5952,12 +6744,45 @@ grn_obj_get_value_(grn_ctx *ctx, grn_obj *obj, grn_id id, uint32_t *size) } static void +grn_obj_get_value_expr(grn_ctx *ctx, grn_obj *expr, grn_id id, grn_obj *value) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *code; + + if (e->codes_curr != 1) { + return; + } + + code = e->codes; + if (code->op != GRN_OP_GET_VALUE) { + return; + } + + if (!code->value) { + return; + } + + switch (code->value->header.type) { + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + grn_obj_get_value(ctx, code->value, id, value); + break; + default : + break; + } +} + +static void grn_obj_get_value_column_index(grn_ctx *ctx, grn_obj *index_column, grn_id id, grn_obj *value) { grn_ii *ii = (grn_ii *)index_column; grn_obj_ensure_bulk(ctx, value); - GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id)); + if (id) { + GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id)); + } else { + GRN_UINT32_SET(ctx, value, 0); + } value->header.domain = GRN_DB_UINT32; } @@ -5970,15 +6795,19 @@ grn_obj_get_value_column_vector(grn_ctx *ctx, grn_obj *obj, lexicon = grn_ctx_at(ctx, DB_OBJ(obj)->range); if (lexicon && !GRN_OBJ_TABLEP(lexicon) && (lexicon->header.flags & GRN_OBJ_KEY_VAR_SIZE)) { - grn_obj v_; grn_obj_ensure_vector(ctx, value); - GRN_TEXT_INIT(&v_, 0); - grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_); - grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_)); - GRN_OBJ_FIN(ctx, &v_); + if (id) { + grn_obj v_; + GRN_TEXT_INIT(&v_, 0); + grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_); + grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_)); + GRN_OBJ_FIN(ctx, &v_); + } } else { grn_obj_ensure_bulk(ctx, value); - grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + if (id) { + grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + } value->header.type = GRN_UVECTOR; if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { value->header.flags |= GRN_OBJ_WITH_WEIGHT; @@ -5994,7 +6823,6 @@ grn_obj * grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) { GRN_API_ENTER; - if (!id) { goto exit; } if (!obj) { ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed"); goto exit; @@ -6022,20 +6850,24 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) case GRN_ACCESSOR : grn_obj_ensure_bulk(ctx, value); value = grn_accessor_get_value(ctx, (grn_accessor *)obj, id, value); - value->header.domain = grn_obj_get_range(ctx, obj); + break; + case GRN_EXPR : + grn_obj_get_value_expr(ctx, obj, id, value); break; case GRN_TABLE_PAT_KEY : { grn_pat *pat = (grn_pat *)obj; uint32_t size = pat->value_size; grn_obj_ensure_bulk(ctx, value); - if (grn_bulk_space(ctx, value, size)) { - MERR("grn_bulk_space failed"); - goto exit; - } - { - char *curr = GRN_BULK_CURR(value); - grn_pat_get_value(ctx, pat, id, curr - size); + if (id) { + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_pat_get_value(ctx, pat, id, curr - size); + } } value->header.type = GRN_BULK; value->header.domain = grn_obj_get_range(ctx, obj); @@ -6046,19 +6878,34 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) break; case GRN_TABLE_HASH_KEY : { - grn_hash *hash = (grn_hash *)obj; - uint32_t size = hash->value_size; + grn_bool processed = GRN_FALSE; grn_obj_ensure_bulk(ctx, value); - if (grn_bulk_space(ctx, value, size)) { - MERR("grn_bulk_space failed"); - goto exit; - } - { - char *curr = GRN_BULK_CURR(value); - grn_hash_get_value(ctx, hash, id, curr - size); - } - value->header.type = GRN_BULK; value->header.domain = grn_obj_get_range(ctx, obj); + if (id) { + if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) { + grn_obj *domain; + domain = grn_ctx_at(ctx, value->header.domain); + if (GRN_OBJ_TABLEP(domain)) { + grn_id subrec_id; + if (grn_table_get_subrecs(ctx, obj, id, &subrec_id, NULL, 1) == 1) { + GRN_RECORD_SET(ctx, value, subrec_id); + processed = GRN_TRUE; + } + } + } + if (!processed) { + grn_hash *hash = (grn_hash *)obj; + uint32_t size = hash->value_size; + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_hash_get_value(ctx, hash, id, curr - size); + } + } + } } break; case GRN_TABLE_NO_KEY : @@ -6066,13 +6913,15 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) grn_array *array = (grn_array *)obj; uint32_t size = array->value_size; grn_obj_ensure_bulk(ctx, value); - if (grn_bulk_space(ctx, value, size)) { - MERR("grn_bulk_space failed"); - goto exit; - } - { - char *curr = GRN_BULK_CURR(value); - grn_array_get_value(ctx, array, id, curr - size); + if (id) { + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_array_get_value(ctx, array, id, curr - size); + } } value->header.type = GRN_BULK; value->header.domain = grn_obj_get_range(ctx, obj); @@ -6085,7 +6934,9 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) break; case GRN_OBJ_COLUMN_SCALAR : grn_obj_ensure_bulk(ctx, value); - grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + if (id) { + grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + } value->header.type = GRN_BULK; break; default : @@ -6095,12 +6946,12 @@ grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) value->header.domain = grn_obj_get_range(ctx, obj); break; case GRN_COLUMN_FIX_SIZE : - { + grn_obj_ensure_bulk(ctx, value); + value->header.type = GRN_BULK; + value->header.domain = grn_obj_get_range(ctx, obj); + if (id) { unsigned int element_size; void *v = grn_ra_ref(ctx, (grn_ra *)obj, id); - grn_obj_ensure_bulk(ctx, value); - value->header.type = GRN_BULK; - value->header.domain = grn_obj_get_range(ctx, obj); if (v) { element_size = ((grn_ra *)obj)->header->element_size; grn_bulk_write(ctx, value, v, element_size); @@ -6195,17 +7046,17 @@ grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valueb GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); #endif break; - case GRN_INFO_SUPPORT_LZO : + case GRN_INFO_SUPPORT_LZ4 : if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { ERR(GRN_INVALID_ARGUMENT, - "failed to open value buffer for GRN_INFO_LZO_SUPPORT"); + "failed to open value buffer for GRN_INFO_LZ4_SUPPORT"); goto exit; } -#ifdef GRN_WITH_LZO +#ifdef GRN_WITH_LZ4 GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); -#else /* GRN_WITH_LZO */ +#else /* GRN_WITH_LZ4 */ GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); -#endif /* GRN_WITH_LZO */ +#endif /* GRN_WITH_LZ4 */ break; default : if (!obj) { @@ -6810,7 +7661,7 @@ grn_obj_set_info_token_filters(grn_ctx *ctx, grn_obj *token_filters) { grn_obj *current_token_filters; - unsigned int i, n_token_filters; + unsigned int i, n_current_token_filters, n_token_filters; grn_obj token_filter_names; switch (table->header.type) { @@ -6832,9 +7683,12 @@ grn_obj_set_info_token_filters(grn_ctx *ctx, return ctx->rc; } + n_current_token_filters = + GRN_BULK_VSIZE(current_token_filters) / sizeof(grn_obj *); + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + GRN_TEXT_INIT(&token_filter_names, 0); GRN_BULK_REWIND(current_token_filters); - n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); for (i = 0; i < n_token_filters; i++) { grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i); char token_filter_name[GRN_TABLE_MAX_KEY_SIZE]; @@ -6842,6 +7696,9 @@ grn_obj_set_info_token_filters(grn_ctx *ctx, GRN_PTR_PUT(ctx, current_token_filters, token_filter); + if (i > 0) { + GRN_TEXT_PUTC(ctx, &token_filter_names, ','); + } token_filter_name_size = grn_obj_name(ctx, token_filter, token_filter_name, @@ -6851,9 +7708,11 @@ grn_obj_set_info_token_filters(grn_ctx *ctx, token_filter_name, token_filter_name_size); } - GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:set_token_filters %.*s", - (int)GRN_BULK_VSIZE(&token_filter_names), - GRN_BULK_HEAD(&token_filter_names)); + if (n_token_filters > 0 || n_token_filters != n_current_token_filters) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:set_token_filters %.*s", + (int)GRN_BULK_VSIZE(&token_filter_names), + GRN_BULK_HEAD(&token_filter_names)); + } GRN_OBJ_FIN(ctx, &token_filter_names); grn_obj_spec_save(ctx, DB_OBJ(table)); @@ -6946,21 +7805,6 @@ grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, GRN_API_RETURN(GRN_SUCCESS); } -grn_bool -grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj) -{ - grn_id id; - - if (!obj) { return GRN_FALSE; } - - id = grn_obj_id(ctx, obj); - if (id == GRN_ID_NIL) { - return GRN_FALSE; - } else { - return id < GRN_N_RESERVED_TYPES; - } -} - static void grn_hook_free(grn_ctx *ctx, grn_hook *h) { @@ -7879,7 +8723,7 @@ grn_token_filters_unpack(grn_ctx *ctx, unsigned int element_size; unsigned int i, n_token_filter_ids; - if (grn_vector_size(ctx, spec_vector) < SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) { + if (grn_vector_size(ctx, spec_vector) <= SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) { return; } @@ -8070,6 +8914,9 @@ grn_ctx_at(grn_ctx *ctx, grn_id id) } } res = vp->ptr; + if (res && res->header.type == GRN_PROC) { + grn_plugin_ensure_registered(ctx, res); + } } } exit : @@ -8399,10 +9246,14 @@ grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj) return ctx->rc; } - grn_obj_get_range_info(ctx, domain_obj, &domain, &flags); - if (GRN_OBJ_TABLEP(domain_obj) && - domain_obj->header.type != GRN_TABLE_NO_KEY) { - domain = domain_obj->header.domain; + if (grn_column_is_index(ctx, domain_obj)) { + domain = GRN_DB_UINT32; + } else { + grn_obj_get_range_info(ctx, domain_obj, &domain, &flags); + if (GRN_OBJ_TABLEP(domain_obj) && + domain_obj->header.type != GRN_TABLE_NO_KEY) { + domain = domain_obj->header.domain; + } } return grn_obj_reinit(ctx, obj, domain, flags); } @@ -8481,6 +9332,18 @@ grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size) case GRN_ACCESSOR_GET_NSUBRECS : name = GRN_COLUMN_NAME_NSUBRECS; break; + case GRN_ACCESSOR_GET_MAX : + name = GRN_COLUMN_NAME_MAX; + break; + case GRN_ACCESSOR_GET_MIN : + name = GRN_COLUMN_NAME_MIN; + break; + case GRN_ACCESSOR_GET_SUM : + name = GRN_COLUMN_NAME_SUM; + break; + case GRN_ACCESSOR_GET_AVG : + name = GRN_COLUMN_NAME_AVG; + break; case GRN_ACCESSOR_GET_COLUMN_VALUE : case GRN_ACCESSOR_GET_DB_OBJ : case GRN_ACCESSOR_LOOKUP : @@ -8544,6 +9407,26 @@ grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf) GRN_COLUMN_NAME_NSUBRECS, GRN_COLUMN_NAME_NSUBRECS_LEN); break; + case GRN_ACCESSOR_GET_MAX : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_MAX, + GRN_COLUMN_NAME_MAX_LEN); + break; + case GRN_ACCESSOR_GET_MIN : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_MIN, + GRN_COLUMN_NAME_MIN_LEN); + break; + case GRN_ACCESSOR_GET_SUM : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_SUM, + GRN_COLUMN_NAME_SUM_LEN); + break; + case GRN_ACCESSOR_GET_AVG : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_AVG, + GRN_COLUMN_NAME_AVG_LEN); + break; case GRN_ACCESSOR_GET_COLUMN_VALUE : grn_column_name_(ctx, a->obj, buf); if (a->next) { GRN_TEXT_PUTC(ctx, buf, '.'); } @@ -8751,7 +9634,7 @@ typedef struct { grn_id id; uint32_t size; const void *value; -} sort_entry; +} sort_reference_entry; enum { KEY_ID = 0, @@ -8783,8 +9666,9 @@ enum { } while (0) inline static int -compare_value(grn_ctx *ctx, sort_entry *a, sort_entry *b, - grn_table_sort_key *keys, int n_keys) +compare_reference(grn_ctx *ctx, + sort_reference_entry *a, sort_reference_entry *b, + grn_table_sort_key *keys, int n_keys) { int i; uint8_t type; @@ -8880,73 +9764,82 @@ compare_value(grn_ctx *ctx, sort_entry *a, sort_entry *b, } inline static void -swap(sort_entry *a, sort_entry *b) +swap_reference(sort_reference_entry *a, sort_reference_entry *b) { - sort_entry c_ = *a; + sort_reference_entry c_ = *a; *a = *b; *b = c_; } -inline static sort_entry * -part(grn_ctx *ctx, sort_entry *b, sort_entry *e, grn_table_sort_key *keys, int n_keys) +inline static sort_reference_entry * +part_reference(grn_ctx *ctx, + sort_reference_entry *b, sort_reference_entry *e, + grn_table_sort_key *keys, int n_keys) { - sort_entry *c; + sort_reference_entry *c; intptr_t d = e - b; - if (compare_value(ctx, b, e, keys, n_keys)) { - swap(b, e); + if (compare_reference(ctx, b, e, keys, n_keys)) { + swap_reference(b, e); } if (d < 2) { return NULL; } c = b + (d >> 1); - if (compare_value(ctx, b, c, keys, n_keys)) { - swap(b, c); + if (compare_reference(ctx, b, c, keys, n_keys)) { + swap_reference(b, c); } else { - if (compare_value(ctx, c, e, keys, n_keys)) { - swap(c, e); + if (compare_reference(ctx, c, e, keys, n_keys)) { + swap_reference(c, e); } } if (d < 3) { return NULL; } b++; - swap(b, c); + swap_reference(b, c); c = b; for (;;) { do { b++; - } while (compare_value(ctx, c, b, keys, n_keys)); + } while (compare_reference(ctx, c, b, keys, n_keys)); do { e--; - } while (compare_value(ctx, e, c, keys, n_keys)); + } while (compare_reference(ctx, e, c, keys, n_keys)); if (b >= e) { break; } - swap(b, e); + swap_reference(b, e); } - swap(c, e); + swap_reference(c, e); return e; } static void -_sort(grn_ctx *ctx, sort_entry *head, sort_entry *tail, int from, int to, - grn_table_sort_key *keys, int n_keys) +sort_reference(grn_ctx *ctx, + sort_reference_entry *head, sort_reference_entry *tail, + int from, int to, + grn_table_sort_key *keys, int n_keys) { - sort_entry *c; - if (head < tail && (c = part(ctx, head, tail, keys, n_keys))) { + sort_reference_entry *c; + if (head < tail && (c = part_reference(ctx, head, tail, keys, n_keys))) { intptr_t m = c - head + 1; - if (from < m - 1) { _sort(ctx, head, c - 1, from, to, keys, n_keys); } - if (m < to) { _sort(ctx, c + 1, tail, from - m, to - m, keys, n_keys); } + if (from < m - 1) { + sort_reference(ctx, head, c - 1, from, to, keys, n_keys); + } + if (m < to) { + sort_reference(ctx, c + 1, tail, from - m, to - m, keys, n_keys); + } } } -static sort_entry * -pack(grn_ctx *ctx, grn_obj *table, sort_entry *head, sort_entry *tail, - grn_table_sort_key *keys, int n_keys) +static sort_reference_entry * +pack_reference(grn_ctx *ctx, grn_obj *table, + sort_reference_entry *head, sort_reference_entry *tail, + grn_table_sort_key *keys, int n_keys) { int i = 0; - sort_entry e, c; + sort_reference_entry e, c; grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); if (!tc) { return NULL; } if ((c.id = grn_table_cursor_next_inline(ctx, tc))) { c.value = grn_obj_get_value_(ctx, keys->key, c.id, &c.size); while ((e.id = grn_table_cursor_next_inline(ctx, tc))) { e.value = grn_obj_get_value_(ctx, keys->key, e.id, &e.size); - if (compare_value(ctx, &c, &e, keys, n_keys)) { + if (compare_reference(ctx, &c, &e, keys, n_keys)) { *head++ = e; } else { *tail-- = e; @@ -8961,6 +9854,336 @@ pack(grn_ctx *ctx, grn_obj *table, sort_entry *head, sort_entry *tail, } static int +grn_table_sort_reference(grn_ctx *ctx, grn_obj *table, + int offset, int limit, + grn_obj *result, + grn_table_sort_key *keys, int n_keys) +{ + int e, n; + sort_reference_entry *array, *ep; + e = offset + limit; + n = grn_table_size(ctx, table); + if (!(array = GRN_MALLOC(sizeof(sort_reference_entry) * n))) { + return 0; + } + if ((ep = pack_reference(ctx, table, array, array + n - 1, keys, n_keys))) { + intptr_t m = ep - array + 1; + if (offset < m - 1) { + sort_reference(ctx, array, ep - 1, offset, e, keys, n_keys); + } + if (m < e) { + sort_reference(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys); + } + } + { + int i; + grn_id *v; + for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { + if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } + *v = ep->id; + } + GRN_FREE(array); + return i; + } +} + + +typedef struct { + grn_id id; + grn_obj value; +} sort_value_entry; + +inline static int +compare_value(grn_ctx *ctx, + sort_value_entry *a, sort_value_entry *b, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + int i; + uint8_t type; + uint32_t as, bs; + const unsigned char *ap, *bp; + for (i = 0; i < n_keys; i++, keys++) { + if (i) { + GRN_BULK_REWIND(a_buffer); + GRN_BULK_REWIND(b_buffer); + if (keys->flags & GRN_TABLE_SORT_DESC) { + grn_obj_get_value(ctx, keys->key, b->id, a_buffer); + grn_obj_get_value(ctx, keys->key, a->id, b_buffer); + } else { + grn_obj_get_value(ctx, keys->key, a->id, a_buffer); + grn_obj_get_value(ctx, keys->key, b->id, b_buffer); + } + ap = (const unsigned char *)GRN_BULK_HEAD(a_buffer); + as = GRN_BULK_VSIZE(a_buffer); + bp = (const unsigned char *)GRN_BULK_HEAD(b_buffer); + bs = GRN_BULK_VSIZE(b_buffer); + } else { + if (keys->flags & GRN_TABLE_SORT_DESC) { + ap = (const unsigned char *)GRN_BULK_HEAD(&b->value); + as = GRN_BULK_VSIZE(&b->value); + bp = (const unsigned char *)GRN_BULK_HEAD(&a->value); + bs = GRN_BULK_VSIZE(&a->value); + } else { + ap = (const unsigned char *)GRN_BULK_HEAD(&a->value); + as = GRN_BULK_VSIZE(&a->value); + bp = (const unsigned char *)GRN_BULK_HEAD(&b->value); + bs = GRN_BULK_VSIZE(&b->value); + } + } + type = keys->offset; + switch (type) { + case KEY_ID : + if (ap != bp) { return ap > bp; } + break; + case KEY_BULK : + for (;; ap++, bp++, as--, bs--) { + if (!as) { if (bs) { return 0; } else { break; } } + if (!bs) { return 1; } + if (*ap < *bp) { return 0; } + if (*ap > *bp) { return 1; } + } + break; + case KEY_INT8 : + CMPNUM(int8_t); + break; + case KEY_INT16 : + CMPNUM(int16_t); + break; + case KEY_INT32 : + CMPNUM(int32_t); + break; + case KEY_INT64 : + CMPNUM(int64_t); + break; + case KEY_UINT8 : + CMPNUM(uint8_t); + break; + case KEY_UINT16 : + CMPNUM(uint16_t); + break; + case KEY_UINT32 : + CMPNUM(uint32_t); + break; + case KEY_UINT64 : + CMPNUM(uint64_t); + break; + case KEY_FLOAT32 : + if (as) { + if (bs) { + float va = *((float *)(ap)); + float vb = *((float *)(bp)); + if (va < vb || va > vb) { return va > vb; } + } else { + return 1; + } + } else { + if (bs) { return 0; } + } + break; + case KEY_FLOAT64 : + if (as) { + if (bs) { + double va = *((double *)(ap)); + double vb = *((double *)(bp)); + if (va < vb || va > vb) { return va > vb; } + } else { + return 1; + } + } else { + if (bs) { return 0; } + } + break; + } + } + return 0; +} + +inline static void +swap_value(sort_value_entry *a, sort_value_entry *b) +{ + sort_value_entry c_ = *a; + *a = *b; + *b = c_; +} + +inline static sort_value_entry * +part_value(grn_ctx *ctx, + sort_value_entry *b, sort_value_entry *e, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + sort_value_entry *c; + intptr_t d = e - b; + if (compare_value(ctx, b, e, keys, n_keys, a_buffer, b_buffer)) { + swap_value(b, e); + } + if (d < 2) { return NULL; } + c = b + (d >> 1); + if (compare_value(ctx, b, c, keys, n_keys, a_buffer, b_buffer)) { + swap_value(b, c); + } else { + if (compare_value(ctx, c, e, keys, n_keys, a_buffer, b_buffer)) { + swap_value(c, e); + } + } + if (d < 3) { return NULL; } + b++; + swap_value(b, c); + c = b; + for (;;) { + do { + b++; + } while (compare_value(ctx, c, b, keys, n_keys, a_buffer, b_buffer)); + do { + e--; + } while (compare_value(ctx, e, c, keys, n_keys, a_buffer, b_buffer)); + if (b >= e) { break; } + swap_value(b, e); + } + swap_value(c, e); + return e; +} + +static void +sort_value(grn_ctx *ctx, + sort_value_entry *head, sort_value_entry *tail, + int from, int to, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + sort_value_entry *c; + if (head < tail && (c = part_value(ctx, head, tail, keys, n_keys, + a_buffer, b_buffer))) { + intptr_t m = c - head + 1; + if (from < m - 1) { + sort_value(ctx, head, c - 1, from, to, keys, n_keys, a_buffer, b_buffer); + } + if (m < to) { + sort_value(ctx, c + 1, tail, from - m, to - m, keys, n_keys, + a_buffer, b_buffer); + } + } +} + +static sort_value_entry * +pack_value(grn_ctx *ctx, grn_obj *table, + sort_value_entry *head, sort_value_entry *tail, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + int i = 0; + sort_value_entry e, c; + grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { return NULL; } + if ((c.id = grn_table_cursor_next_inline(ctx, tc))) { + GRN_TEXT_INIT(&c.value, 0); + grn_obj_get_value(ctx, keys->key, c.id, &c.value); + while ((e.id = grn_table_cursor_next_inline(ctx, tc))) { + GRN_TEXT_INIT(&e.value, 0); + grn_obj_get_value(ctx, keys->key, e.id, &e.value); + if (compare_value(ctx, &c, &e, keys, n_keys, a_buffer, b_buffer)) { + *head++ = e; + } else { + *tail-- = e; + } + i++; + } + *head = c; + i++; + } + grn_table_cursor_close(ctx, tc); + return i > 2 ? head : NULL; +} + +static int +grn_table_sort_value(grn_ctx *ctx, grn_obj *table, + int offset, int limit, + grn_obj *result, + grn_table_sort_key *keys, int n_keys) +{ + int e, n; + sort_value_entry *array, *ep; + e = offset + limit; + n = grn_table_size(ctx, table); + if (!(array = GRN_MALLOC(sizeof(sort_value_entry) * n))) { + return 0; + } + { + grn_obj a_buffer; + grn_obj b_buffer; + GRN_TEXT_INIT(&a_buffer, 0); + GRN_TEXT_INIT(&b_buffer, 0); + if ((ep = pack_value(ctx, table, array, array + n - 1, keys, n_keys, + &a_buffer, &b_buffer))) { + intptr_t m = ep - array + 1; + if (offset < m - 1) { + sort_value(ctx, array, ep - 1, offset, e, keys, n_keys, + &a_buffer, &b_buffer); + } + if (m < e) { + sort_value(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys, + &a_buffer, &b_buffer); + } + } + GRN_OBJ_FIN(ctx, &a_buffer); + GRN_OBJ_FIN(ctx, &b_buffer); + } + { + int i; + grn_id *v; + for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { + if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } + *v = ep->id; + } + GRN_FREE(array); + return i; + } +} + +static grn_bool +is_compressed_column(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + if (obj->header.type != GRN_COLUMN_VAR_SIZE) { + return GRN_FALSE; + } + + return (obj->header.flags & (GRN_OBJ_COMPRESS_ZLIB | GRN_OBJ_COMPRESS_LZ4)); +} + +static grn_bool +is_sub_record_accessor(grn_ctx *ctx, grn_obj *obj) +{ + grn_accessor *accessor; + + if (!obj) { + return GRN_FALSE; + } + + if (obj->header.type != GRN_ACCESSOR) { + return GRN_FALSE; + } + + for (accessor = (grn_accessor *)obj; accessor; accessor = accessor->next) { + switch (accessor->action) { + case GRN_ACCESSOR_GET_VALUE : + if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(accessor->obj)) { + return GRN_TRUE; + } + break; + default : + break; + } + } + + return GRN_FALSE; +} + +static int range_is_idp(grn_obj *obj) { if (obj && obj->header.type == GRN_ACCESSOR) { @@ -8979,7 +10202,6 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, grn_rc rc; grn_obj *index; int n, e, i = 0; - sort_entry *array, *ep; GRN_API_ENTER; if (!n_keys || !keys) { WARN(GRN_INVALID_ARGUMENT, "keys is null"); @@ -9034,8 +10256,17 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, } } else { int j; + grn_bool have_compressed_column = GRN_FALSE; + grn_bool have_sub_record_accessor = GRN_FALSE; + grn_bool have_index_value_get = GRN_FALSE; grn_table_sort_key *kp; for (kp = keys, j = n_keys; j; kp++, j--) { + if (is_compressed_column(ctx, kp->key)) { + have_compressed_column = GRN_TRUE; + } + if (is_sub_record_accessor(ctx, kp->key)) { + have_sub_record_accessor = GRN_TRUE; + } if (range_is_idp(kp->key)) { kp->offset = KEY_ID; } else { @@ -9101,25 +10332,21 @@ grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, } } } else { + if (kp->key->header.type == GRN_COLUMN_INDEX) { + have_index_value_get = GRN_TRUE; + } kp->offset = KEY_UINT32; } } } - if (!(array = GRN_MALLOC(sizeof(sort_entry) * n))) { - goto exit; - } - if ((ep = pack(ctx, table, array, array + n - 1, keys, n_keys))) { - intptr_t m = ep - array + 1; - if (offset < m - 1) { _sort(ctx, array, ep - 1, offset, e, keys, n_keys); } - if (m < e) { _sort(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys); } - } - { - grn_id *v; - for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { - if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } - *v = ep->id; - } - GRN_FREE(array); + if (have_compressed_column || + have_sub_record_accessor || + have_index_value_get) { + i = grn_table_sort_value(ctx, table, offset, limit, result, + keys, n_keys); + } else { + i = grn_table_sort_reference(ctx, table, offset, limit, result, + keys, n_keys); } } exit : @@ -9207,6 +10434,7 @@ grn_db_init_builtin_types(grn_ctx *ctx) #endif grn_db_init_builtin_tokenizers(ctx); grn_db_init_builtin_normalizers(ctx); + grn_db_init_builtin_scorers(ctx); for (id = grn_db_curr_id(ctx, db) + 1; id < 128; id++) { grn_itoh(id, buf + 3, 2); grn_obj_register(ctx, db, buf, 5); @@ -9255,9 +10483,22 @@ grn_column_index_column_match(grn_ctx *ctx, grn_obj *obj, grn_operator op, { int n = 0; grn_obj **ip = indexbuf; + grn_hook_entry hook_entry; grn_hook *hooks; - for (hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + hook_entry = GRN_HOOK_INSERT; + break; + default : + hook_entry = GRN_HOOK_SET; + break; + } + + for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { default_set_value_hook_data *data = (void *)NEXT_ADDR(hooks); grn_obj *target = grn_ctx_at(ctx, data->target); if (target->header.type != GRN_COLUMN_INDEX) { continue; } @@ -9432,7 +10673,7 @@ grn_column_index_accessor(grn_ctx *ctx, grn_obj *obj, grn_operator op, while (a) { grn_hook *hooks; grn_bool found = GRN_FALSE; - grn_hook_entry entry = -1; + grn_hook_entry entry = (grn_hook_entry)-1; if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE && GRN_OBJ_INDEX_COLUMNP(a->obj)) { @@ -9451,7 +10692,7 @@ grn_column_index_accessor(grn_ctx *ctx, grn_obj *obj, grn_operator op, break; } - if (entry == -1) { + if (entry == (grn_hook_entry)-1) { break; } @@ -9832,7 +11073,7 @@ grn_table_tokenize(grn_ctx *ctx, grn_obj *table, grn_obj *buf, grn_bool addp) { grn_token_cursor *token_cursor = NULL; - grn_token_mode mode = addp ? GRN_TOKEN_ADD : GRN_TOKEN_GET; + grn_tokenize_mode mode = addp ? GRN_TOKENIZE_ADD : GRN_TOKENIZE_GET; GRN_API_ENTER; if (!(token_cursor = grn_token_cursor_open(ctx, table, str, str_len, mode, 0))) { goto exit; @@ -9844,7 +11085,7 @@ grn_table_tokenize(grn_ctx *ctx, grn_obj *table, goto exit; } } - while (token_cursor->status != GRN_TOKEN_DONE && token_cursor->status != GRN_TOKEN_DONE_SKIP) { + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE && token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) { grn_id tid; if ((tid = grn_token_cursor_next(ctx, token_cursor))) { GRN_RECORD_PUT(ctx, buf, tid); @@ -10258,7 +11499,7 @@ brace_close(grn_ctx *ctx, grn_loader *loader) (int)GRN_TEXT_LEN(key_column_name), GRN_TEXT_VALUE(key_column_name), column_name_size, column_name); - return; + goto exit; } key_column_name = value; v++; @@ -10271,7 +11512,62 @@ brace_close(grn_ctx *ctx, grn_loader *loader) } break; case GRN_TABLE_NO_KEY : - id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + { + grn_obj *v; + grn_bool found_id_column = GRN_FALSE; + for (v = value; v + 1 < ve; v = values_next(ctx, v)) { + char *column_name = GRN_TEXT_VALUE(v); + unsigned int column_name_size = GRN_TEXT_LEN(v); + if (v->header.domain == GRN_DB_TEXT && + (name_equal(column_name, column_name_size, + GRN_COLUMN_NAME_ID))) { + grn_obj *id_column; + grn_obj *id_value; + if (found_id_column) { + GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column"); + goto exit; + } + found_id_column = GRN_TRUE; + id_column = v; + v = values_next(ctx, v); + id_value = v; + switch (id_value->header.type) { + case GRN_DB_UINT32 : + id = GRN_UINT32_VALUE(id_value); + break; + case GRN_DB_INT32 : + id = GRN_INT32_VALUE(id_value); + break; + default : + { + grn_obj casted_id_value; + GRN_UINT32_INIT(&casted_id_value, 0); + if (grn_obj_cast(ctx, id_value, &casted_id_value, GRN_FALSE)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, id_value); + ERR(GRN_INVALID_ARGUMENT, + "<%.*s>: failed to cast to <UInt32>: <%.*s>", + (int)column_name_size, column_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + grn_obj_unlink(ctx, &inspected); + goto exit; + } else { + id = GRN_UINT32_VALUE(&casted_id_value); + } + GRN_OBJ_FIN(ctx, &casted_id_value); + } + break; + } + } else { + v = values_next(ctx, v); + } + } + } + if (id == GRN_ID_NIL) { + id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + } break; default : break; @@ -10329,6 +11625,7 @@ brace_close(grn_ctx *ctx, grn_loader *loader) GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned"); } } + exit: loader->values_size = begin; } } @@ -10800,3 +12097,161 @@ grn_load(grn_ctx *ctx, grn_content_type input_type, ifexists, ifexists_len, each, each_len, 1); GRN_API_RETURN(ctx->rc); } + +static void +grn_db_recover_database(grn_ctx *ctx, grn_obj *db) +{ + if (!grn_obj_is_locked(ctx, db)) { + return; + } + + ERR(GRN_OBJECT_CORRUPT, + "[db][recover] database may be broken. Please re-create the database"); +} + +static void +grn_db_recover_table(grn_ctx *ctx, grn_obj *table) +{ + if (!grn_obj_is_locked(ctx, table)) { + return; + } + + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, table, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[db][recover] table may be broken: <%.*s>: " + "please truncate the table (or clear lock of the table) " + "and load data again", + (int)name_size, name); + } +} + +static void +grn_db_recover_data_column(grn_ctx *ctx, grn_obj *data_column) +{ + if (!grn_obj_is_locked(ctx, data_column)) { + return; + } + + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, data_column, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[db][recover] column may be broken: <%.*s>: " + "please truncate the column (or clear lock of the column) " + "and load data again", + (int)name_size, name); + } +} + +static void +grn_db_recover_index_column(grn_ctx *ctx, grn_obj *index_column) +{ + grn_ii *ii = (grn_ii *)index_column; + + if (!grn_obj_is_locked(ctx, index_column)) { + return; + } + + grn_ii_truncate(ctx, ii); + build_index(ctx, index_column); +} + +grn_rc +grn_db_recover(grn_ctx *ctx, grn_obj *db) +{ + grn_table_cursor *cursor; + grn_id id; + + GRN_API_ENTER; + + grn_db_recover_database(ctx, db); + if (ctx->rc != GRN_SUCCESS) { + GRN_API_RETURN(ctx->rc); + } + + cursor = grn_table_cursor_open(ctx, db, + NULL, 0, NULL, 0, + 0, -1, + GRN_CURSOR_BY_ID); + if (!cursor) { + GRN_API_RETURN(ctx->rc); + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + + if ((object = grn_ctx_at(ctx, id))) { + switch (object->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + grn_db_recover_table(ctx, object); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + grn_db_recover_data_column(ctx, object); + break; + case GRN_COLUMN_INDEX : + grn_db_recover_index_column(ctx, object); + break; + default: + break; + } + grn_obj_unlink(ctx, object); + } else { + ERRCLR(ctx); + } + + if (ctx->rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cursor); + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer) +{ + grn_obj *db; + grn_table_cursor *cursor; + grn_id id; + + GRN_API_ENTER; + + db = ctx->impl->db; + if (!db) { + ERR(GRN_INVALID_ARGUMENT, "DB isn't associated"); + GRN_API_RETURN(ctx->rc); + } + + cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + GRN_API_RETURN(ctx->rc); + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + + if ((object = grn_ctx_at(ctx, id))) { + if (grn_obj_is_table(ctx, object)) { + GRN_PTR_PUT(ctx, tables_buffer, object); + } else { + grn_obj_unlink(ctx, object); + } + } else { + if (ctx->rc != GRN_SUCCESS) { + ERRCLR(ctx); + } + } + } + grn_table_cursor_close(ctx, cursor); + + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/error.c b/storage/mroonga/vendor/groonga/lib/error.c index 322b29bff7a..e14ef3754fd 100644 --- a/storage/mroonga/vendor/groonga/lib/error.c +++ b/storage/mroonga/vendor/groonga/lib/error.c @@ -15,7 +15,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "error.h" +#include "grn_error.h" #ifdef HAVE_ERRNO_H #include <errno.h> @@ -28,17 +28,28 @@ const char * grn_current_error_message(void) { # define ERROR_MESSAGE_BUFFER_SIZE 4096 - int error_code = WSAGetLastError(); + int error_code = GetLastError(); static char message[ERROR_MESSAGE_BUFFER_SIZE]; + DWORD written_bytes; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - error_code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - message, - ERROR_MESSAGE_BUFFER_SIZE, - NULL); + written_bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error_code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + message, + ERROR_MESSAGE_BUFFER_SIZE, + NULL); + if (written_bytes >= 2) { + if (message[written_bytes - 1] == '\n') { + message[written_bytes - 1] = '\0'; + written_bytes--; + } + if (message[written_bytes - 1] == '\r') { + message[written_bytes - 1] = '\0'; + written_bytes--; + } + } return message; diff --git a/storage/mroonga/vendor/groonga/lib/expr.c b/storage/mroonga/vendor/groonga/lib/expr.c index dd70ebecb40..ef477eb77ee 100644 --- a/storage/mroonga/vendor/groonga/lib/expr.c +++ b/storage/mroonga/vendor/groonga/lib/expr.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2010-2014 Brazil + Copyright(C) 2010-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,33 +15,19 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" -#include "db.h" -#include "ctx_impl.h" +#include "grn.h" +#include "grn_db.h" +#include "grn_ctx_impl.h" #include <string.h> #include <float.h> -#include "ii.h" -#include "geo.h" -#include "expr.h" -#include "util.h" -#include "normalizer_in.h" -#include "mrb.h" +#include "grn_ii.h" +#include "grn_geo.h" +#include "grn_expr.h" +#include "grn_util.h" +#include "grn_normalizer.h" +#include "grn_mrb.h" #include "mrb/mrb_expr.h" -static inline int -function_proc_p(grn_obj *obj) -{ - return (obj && - obj->header.type == GRN_PROC && - ((grn_proc *)obj)->type == GRN_PROC_FUNCTION); -} - -static inline int -selector_proc_p(grn_obj *obj) -{ - return (function_proc_p(obj) && ((grn_proc *)obj)->selector); -} - grn_obj * grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, grn_obj_flags flags) { @@ -60,7 +46,7 @@ grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, grn_obj_flags flags) return res; } -static grn_hash * +grn_hash * grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars) { grn_hash *vars = NULL; @@ -131,6 +117,18 @@ grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data, } grn_obj * +grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data) +{ + uint32_t n; + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + if (pctx->proc) { + return (grn_obj *)grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, &n); + } else { + return NULL; + } +} + +grn_obj * grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, unsigned int name_size) { grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; @@ -170,7 +168,7 @@ grn_rc grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector) { grn_proc *proc_ = (grn_proc *)proc; - if (!function_proc_p(proc)) { + if (!grn_obj_is_function_proc(ctx, proc)) { return GRN_INVALID_ARGUMENT; } proc_->selector = selector; @@ -179,151 +177,6 @@ grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector) /* grn_expr */ -static const char *opstrs[] = { - "PUSH", - "POP", - "NOP", - "CALL", - "INTERN", - "GET_REF", - "GET_VALUE", - "AND", - "AND_NOT", - "OR", - "ASSIGN", - "STAR_ASSIGN", - "SLASH_ASSIGN", - "MOD_ASSIGN", - "PLUS_ASSIGN", - "MINUS_ASSIGN", - "SHIFTL_ASSIGN", - "SHIFTR_ASSIGN", - "SHIFTRR_ASSIGN", - "AND_ASSIGN", - "XOR_ASSIGN", - "OR_ASSIGN", - "JUMP", - "CJUMP", - "COMMA", - "BITWISE_OR", - "BITWISE_XOR", - "BITWISE_AND", - "BITWISE_NOT", - "EQUAL", - "NOT_EQUAL", - "LESS", - "GREATER", - "LESS_EQUAL", - "GREATER_EQUAL", - "IN", - "MATCH", - "NEAR", - "NEAR2", - "SIMILAR", - "TERM_EXTRACT", - "SHIFTL", - "SHIFTR", - "SHIFTRR", - "PLUS", - "MINUS", - "STAR", - "SLASH", - "MOD", - "DELETE", - "INCR", - "DECR", - "INCR_POST", - "DECR_POST", - "NOT", - "ADJUST", - "EXACT", - "LCP", - "PARTIAL", - "UNSPLIT", - "PREFIX", - "SUFFIX", - "GEO_DISTANCE1", - "GEO_DISTANCE2", - "GEO_DISTANCE3", - "GEO_DISTANCE4", - "GEO_WITHINP5", - "GEO_WITHINP6", - "GEO_WITHINP8", - "OBJ_SEARCH", - "EXPR_GET_VAR", - "TABLE_CREATE", - "TABLE_SELECT", - "TABLE_SORT", - "TABLE_GROUP", - "JSON_PUT" -}; - -static void -put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) -{ - int len; - char namebuf[GRN_TABLE_MAX_KEY_SIZE]; - if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) { - GRN_TEXT_PUT(ctx, buf, namebuf, len); - } else { - grn_text_otoj(ctx, buf, obj, NULL); - } -} - -grn_rc -grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr) -{ - uint32_t i, j; - grn_expr_var *var; - grn_expr_code *code; - grn_expr *e = (grn_expr *)expr; - grn_hash *vars = grn_expr_get_vars(ctx, expr, &i); - GRN_TEXT_PUTS(ctx, buf, "noname"); - GRN_TEXT_PUTC(ctx, buf, '('); - { - int i = 0; - grn_obj *value; - const char *name; - uint32_t name_len; - GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, { - if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); } - GRN_TEXT_PUT(ctx, buf, name, name_len); - GRN_TEXT_PUTC(ctx, buf, ':'); - put_value(ctx, buf, value); - }); - } - GRN_TEXT_PUTC(ctx, buf, ')'); - GRN_TEXT_PUTC(ctx, buf, '{'); - for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) { - if (j) { GRN_TEXT_PUTC(ctx, buf, ','); } - grn_text_itoa(ctx, buf, code->modify); - if (code->op == GRN_OP_PUSH) { - for (i = 0, var = e->vars; i < e->nvars; i++, var++) { - if (&var->value == code->value) { - GRN_TEXT_PUTC(ctx, buf, '?'); - if (var->name_size) { - GRN_TEXT_PUT(ctx, buf, var->name, var->name_size); - } else { - grn_text_itoa(ctx, buf, (int)i); - } - break; - } - } - if (i == e->nvars) { - put_value(ctx, buf, code->value); - } - } else { - if (code->value) { - put_value(ctx, buf, code->value); - GRN_TEXT_PUTC(ctx, buf, ' '); - } - GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]); - } - } - GRN_TEXT_PUTC(ctx, buf, '}'); - return GRN_SUCCESS; -} - grn_obj * grn_ctx_pop(grn_ctx *ctx) { @@ -929,7 +782,8 @@ grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, grn_operator op, ERR(GRN_INVALID_ARGUMENT, "invalid function call expression"); goto exit; } - if (!function_proc_p(proc)) { + if (!(grn_obj_is_function_proc(ctx, proc) || + grn_obj_is_scorer_proc(ctx, proc))) { grn_obj buffer; GRN_TEXT_INIT(&buffer, 0); @@ -1367,425 +1221,6 @@ grn_expr_compile(grn_ctx *ctx, grn_obj *expr) s1 = sp[-2];\ } while (0) -#define DO_COMPARE_SUB_NUMERIC(y,op) do {\ - switch ((y)->header.domain) {\ - case GRN_DB_INT8 :\ - r = (x_ op GRN_INT8_VALUE(y));\ - break;\ - case GRN_DB_UINT8 :\ - r = (x_ op GRN_UINT8_VALUE(y));\ - break;\ - case GRN_DB_INT16 :\ - r = (x_ op GRN_INT16_VALUE(y));\ - break;\ - case GRN_DB_UINT16 :\ - r = (x_ op GRN_UINT16_VALUE(y));\ - break;\ - case GRN_DB_INT32 :\ - r = (x_ op GRN_INT32_VALUE(y));\ - break;\ - case GRN_DB_UINT32 :\ - r = (x_ op GRN_UINT32_VALUE(y));\ - break;\ - case GRN_DB_INT64 :\ - r = (x_ op GRN_INT64_VALUE(y));\ - break;\ - case GRN_DB_TIME :\ - r = (GRN_TIME_PACK(x_,0) op GRN_INT64_VALUE(y));\ - break;\ - case GRN_DB_UINT64 :\ - r = (x_ op GRN_UINT64_VALUE(y));\ - break;\ - case GRN_DB_FLOAT :\ - r = (x_ op GRN_FLOAT_VALUE(y));\ - break;\ - default :\ - r = 0;\ - break;\ - }\ -} while (0) - -#define DO_COMPARE_SUB(op) do {\ - switch (y->header.domain) {\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - {\ - grn_obj y_;\ - GRN_OBJ_INIT(&y_, GRN_BULK, 0, x->header.domain);\ - if (grn_obj_cast(ctx, y, &y_, GRN_FALSE)) {\ - r = 0;\ - } else {\ - DO_COMPARE_SUB_NUMERIC(&y_, op);\ - }\ - GRN_OBJ_FIN(ctx, &y_);\ - }\ - break;\ - default :\ - DO_COMPARE_SUB_NUMERIC(y,op);\ - break;\ - }\ -} while (0) - -#define DO_COMPARE_BUILTIN(x,y,r,op) do {\ - switch (x->header.domain) {\ - case GRN_DB_INT8 :\ - {\ - int8_t x_ = GRN_INT8_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_UINT8 :\ - {\ - uint8_t x_ = GRN_UINT8_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_INT16 :\ - {\ - int16_t x_ = GRN_INT16_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_UINT16 :\ - {\ - uint16_t x_ = GRN_UINT16_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_INT32 :\ - {\ - int32_t x_ = GRN_INT32_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_UINT32 :\ - {\ - uint32_t x_ = GRN_UINT32_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_TIME :\ - {\ - int64_t x_ = GRN_INT64_VALUE(x);\ - switch (y->header.domain) {\ - case GRN_DB_INT32 :\ - r = (x_ op GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\ - break;\ - case GRN_DB_UINT32 :\ - r = (x_ op GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\ - break;\ - case GRN_DB_INT64 :\ - case GRN_DB_TIME :\ - r = (x_ op GRN_INT64_VALUE(y));\ - break;\ - case GRN_DB_UINT64 :\ - r = (x_ op GRN_UINT64_VALUE(y));\ - break;\ - case GRN_DB_FLOAT :\ - r = (x_ op GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\ - break;\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - {\ - const char *p_ = GRN_TEXT_VALUE(y);\ - int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ - r = (x_ op GRN_TIME_PACK(i_, 0));\ - }\ - break;\ - default :\ - r = 0;\ - break;\ - }\ - }\ - break;\ - case GRN_DB_INT64 :\ - {\ - int64_t x_ = GRN_INT64_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_UINT64 :\ - {\ - uint64_t x_ = GRN_UINT64_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_FLOAT :\ - {\ - double x_ = GRN_FLOAT_VALUE(x);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\ - int r_;\ - uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\ - if (la > lb) {\ - if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb))) {\ - r_ = 1;\ - }\ - } else {\ - if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), la))) {\ - r_ = la == lb ? 0 : -1;\ - }\ - }\ - r = (r_ op 0);\ - } else {\ - const char *q_ = GRN_TEXT_VALUE(x);\ - int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\ - DO_COMPARE_SUB(op);\ - }\ - break;\ - default :\ - r = 0;\ - break;\ - }\ -} while (0) - -#define DO_COMPARE(x, y, r, op) do {\ - if (x->header.domain >= GRN_N_RESERVED_TYPES) {\ - grn_obj *table;\ - table = grn_ctx_at(ctx, x->header.domain);\ - switch (table->header.type) {\ - case GRN_TABLE_HASH_KEY :\ - case GRN_TABLE_PAT_KEY :\ - {\ - grn_obj key;\ - int length;\ - GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\ - length = grn_table_get_key2(ctx, table, GRN_RECORD_VALUE(x), &key);\ - if (length > 0) {\ - grn_obj *x_original = x;\ - x = &key;\ - DO_COMPARE_BUILTIN((&key), y, r, op);\ - x = x_original;\ - } else {\ - r = 0;\ - }\ - GRN_OBJ_FIN(ctx, &key);\ - }\ - break;\ - default :\ - r = 0;\ - break;\ - }\ - grn_obj_unlink(ctx, table);\ - } else {\ - DO_COMPARE_BUILTIN(x, y, r, op);\ - }\ -} while (0) - -#define DO_EQ_SUB do {\ - switch (y->header.domain) {\ - case GRN_DB_INT8 :\ - r = (x_ == GRN_INT8_VALUE(y));\ - break;\ - case GRN_DB_UINT8 :\ - r = (x_ == GRN_UINT8_VALUE(y));\ - break;\ - case GRN_DB_INT16 :\ - r = (x_ == GRN_INT16_VALUE(y));\ - break;\ - case GRN_DB_UINT16 :\ - r = (x_ == GRN_UINT16_VALUE(y));\ - break;\ - case GRN_DB_INT32 :\ - r = (x_ == GRN_INT32_VALUE(y));\ - break;\ - case GRN_DB_UINT32 :\ - r = (x_ == GRN_UINT32_VALUE(y));\ - break;\ - case GRN_DB_INT64 :\ - r = (x_ == GRN_INT64_VALUE(y));\ - break;\ - case GRN_DB_TIME :\ - r = (GRN_TIME_PACK(x_,0) == GRN_INT64_VALUE(y));\ - break;\ - case GRN_DB_UINT64 :\ - r = (x_ == GRN_UINT64_VALUE(y));\ - break;\ - case GRN_DB_FLOAT :\ - r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\ - break;\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - {\ - const char *p_ = GRN_TEXT_VALUE(y);\ - int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ - r = (x_ == i_);\ - }\ - break;\ - default :\ - r = 0;\ - break;\ - }\ -} while (0) - -#define DO_EQ(x,y,r) do {\ - switch (x->header.domain) {\ - case GRN_DB_VOID :\ - r = 0;\ - break;\ - case GRN_DB_INT8 :\ - {\ - int8_t x_ = GRN_INT8_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_UINT8 :\ - {\ - uint8_t x_ = GRN_UINT8_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_INT16 :\ - {\ - int16_t x_ = GRN_INT16_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_UINT16 :\ - {\ - uint16_t x_ = GRN_UINT16_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_INT32 :\ - {\ - int32_t x_ = GRN_INT32_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_UINT32 :\ - {\ - uint32_t x_ = GRN_UINT32_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_INT64 :\ - {\ - int64_t x_ = GRN_INT64_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_TIME :\ - {\ - int64_t x_ = GRN_INT64_VALUE(x);\ - switch (y->header.domain) {\ - case GRN_DB_INT32 :\ - r = (x_ == GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\ - break;\ - case GRN_DB_UINT32 :\ - r = (x_ == GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\ - break;\ - case GRN_DB_INT64 :\ - case GRN_DB_TIME :\ - r = (x_ == GRN_INT64_VALUE(y));\ - break;\ - case GRN_DB_UINT64 :\ - r = (x_ == GRN_UINT64_VALUE(y));\ - break;\ - case GRN_DB_FLOAT :\ - r = (x_ == GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\ - break;\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - {\ - const char *p_ = GRN_TEXT_VALUE(y);\ - int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ - r = (x_ == GRN_TIME_PACK(i_, 0));\ - }\ - break;\ - default :\ - r = 0;\ - break;\ - }\ - }\ - break;\ - case GRN_DB_UINT64 :\ - {\ - uint64_t x_ = GRN_UINT64_VALUE(x);\ - DO_EQ_SUB;\ - }\ - break;\ - case GRN_DB_FLOAT :\ - {\ - double x_ = GRN_FLOAT_VALUE(x);\ - switch (y->header.domain) {\ - case GRN_DB_INT32 :\ - r = ((x_ <= GRN_INT32_VALUE(y)) && (x_ >= GRN_INT32_VALUE(y)));\ - break;\ - case GRN_DB_UINT32 :\ - r = ((x_ <= GRN_UINT32_VALUE(y)) && (x_ >= GRN_UINT32_VALUE(y)));\ - break;\ - case GRN_DB_INT64 :\ - case GRN_DB_TIME :\ - r = ((x_ <= GRN_INT64_VALUE(y)) && (x_ >= GRN_INT64_VALUE(y)));\ - break;\ - case GRN_DB_UINT64 :\ - r = ((x_ <= GRN_UINT64_VALUE(y)) && (x_ >= GRN_UINT64_VALUE(y)));\ - break;\ - case GRN_DB_FLOAT :\ - r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\ - break;\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - {\ - const char *p_ = GRN_TEXT_VALUE(y);\ - int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ - r = (x_ <= i_ && x_ >= i_);\ - }\ - break;\ - default :\ - r = 0;\ - break;\ - }\ - }\ - break;\ - case GRN_DB_SHORT_TEXT :\ - case GRN_DB_TEXT :\ - case GRN_DB_LONG_TEXT :\ - if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\ - uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\ - r = (la == lb && !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb));\ - } else {\ - const char *q_ = GRN_TEXT_VALUE(x);\ - int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\ - DO_EQ_SUB;\ - }\ - break;\ - default :\ - if ((x->header.domain == y->header.domain)) {\ - r = (GRN_BULK_VSIZE(x) == GRN_BULK_VSIZE(y) &&\ - !(memcmp(GRN_BULK_HEAD(x), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(x))));\ - } else {\ - grn_obj dest;\ - if (x->header.domain < y->header.domain) {\ - GRN_OBJ_INIT(&dest, GRN_BULK, 0, y->header.domain);\ - if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {\ - r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(y) &&\ - !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(y))); \ - }\ - } else {\ - GRN_OBJ_INIT(&dest, GRN_BULK, 0, x->header.domain);\ - if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {\ - r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(x) &&\ - !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(x), GRN_BULK_VSIZE(x))); \ - }\ - }\ - GRN_OBJ_FIN(ctx, &dest);\ - }\ - break;\ - }\ -} while (0) - #define GEO_RESOLUTION 3600000 #define GEO_RADIOUS 6357303 #define GEO_BES_C1 6334834 @@ -2230,7 +1665,8 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller) code++; \ } while (0) -#define ARITHMETIC_BINARY_OPERATION_DISPATCH(integer8_operation, \ +#define ARITHMETIC_BINARY_OPERATION_DISPATCH(operator, \ + integer8_operation, \ integer16_operation, \ integer32_operation, \ integer64_operation, \ @@ -2242,6 +1678,23 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller) grn_obj *x, *y; \ \ POP2ALLOC1(x, y, res); \ + if (x->header.type == GRN_VECTOR || y->header.type == GRN_VECTOR) { \ + grn_obj inspected_x; \ + grn_obj inspected_y; \ + GRN_TEXT_INIT(&inspected_x, 0); \ + GRN_TEXT_INIT(&inspected_y, 0); \ + grn_inspect(ctx, &inspected_x, x); \ + grn_inspect(ctx, &inspected_y, y); \ + ERR(GRN_INVALID_ARGUMENT, \ + "<%s> doesn't support vector: <%.*s> %s <%.*s>", \ + operator, \ + (int)GRN_TEXT_LEN(&inspected_x), GRN_TEXT_VALUE(&inspected_x), \ + operator, \ + (int)GRN_TEXT_LEN(&inspected_y), GRN_TEXT_VALUE(&inspected_y)); \ + GRN_OBJ_FIN(ctx, &inspected_x); \ + GRN_OBJ_FIN(ctx, &inspected_y); \ + goto exit; \ + } \ if (y != res) { \ res->header.domain = x->header.domain; \ } \ @@ -2667,7 +2120,9 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller) } \ if (GRN_BULK_VSIZE(var) != (sizeof(grn_obj *) + sizeof(grn_id))) { \ ERR(GRN_INVALID_ARGUMENT, \ - "invalid variable size: expected: %zu, actual: %zu", \ + "invalid variable size: " \ + "expected: %" GRN_FMT_SIZE \ + "actual: %" GRN_FMT_SIZE, \ (sizeof(grn_obj *) + sizeof(grn_id)), GRN_BULK_VSIZE(var)); \ goto exit; \ } \ @@ -2769,49 +2224,271 @@ grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller) } while (0) static grn_bool -pseudo_query_scan(grn_ctx *ctx, grn_obj *x, grn_obj *y) +string_is_contained(grn_ctx *ctx, + const char *text, unsigned int text_len, + const char *sub_text, unsigned int sub_text_len) +{ + /* TODO: Use more fast algorithm such as Boyer-Moore algorithm that + * is used in snip.c. */ + const char *text_end = text + text_len; + unsigned int sub_text_current = 0; + + for (; text < text_end; text++) { + if (text[0] == sub_text[sub_text_current]) { + sub_text_current++; + if (sub_text_current == sub_text_len) { + return GRN_TRUE; + } + } else { + sub_text_current = 0; + } + } + + return GRN_FALSE; +} + +static grn_bool +pseudo_query_scan_raw_text_raw_text(grn_ctx *ctx, + const char *x, unsigned int x_len, + const char *y, unsigned int y_len) { grn_obj *normalizer; - grn_obj *a = NULL, *b = NULL; + grn_obj *norm_x; + grn_obj *norm_y; + const char *norm_x_raw; + const char *norm_y_raw; + unsigned int norm_x_raw_length_in_bytes; + unsigned int norm_y_raw_length_in_bytes; grn_bool matched = GRN_FALSE; + if (x_len == 0 || y_len == 0) { + return GRN_FALSE; + } + normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + norm_x = grn_string_open(ctx, x, x_len, normalizer, 0); + norm_y = grn_string_open(ctx, y, y_len, normalizer, 0); + grn_string_get_normalized(ctx, norm_x, + &norm_x_raw, &norm_x_raw_length_in_bytes, + NULL); + grn_string_get_normalized(ctx, norm_y, + &norm_y_raw, &norm_y_raw_length_in_bytes, + NULL); + matched = string_is_contained(ctx, + norm_x_raw, norm_x_raw_length_in_bytes, + norm_y_raw, norm_y_raw_length_in_bytes); + + grn_obj_close(ctx, norm_x); + grn_obj_close(ctx, norm_y); + grn_obj_unlink(ctx, normalizer); + + return matched; +} + +static grn_bool +pseudo_query_scan_record_text(grn_ctx *ctx, grn_obj *record, grn_obj *table, + grn_obj *y) +{ + grn_obj *normalizer; + char x_key[GRN_TABLE_MAX_KEY_SIZE]; + int x_key_len; + grn_bool matched = GRN_FALSE; + + if (table->header.domain != GRN_DB_SHORT_TEXT) { + return GRN_FALSE; + } + + x_key_len = grn_table_get_key(ctx, table, GRN_RECORD_VALUE(record), + x_key, GRN_TABLE_MAX_KEY_SIZE); + grn_table_get_info(ctx, table, NULL, NULL, NULL, &normalizer, NULL); + if (normalizer) { + grn_obj *norm_y; + const char *norm_y_raw; + unsigned int norm_y_raw_length_in_bytes; + norm_y = grn_string_open(ctx, GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y), + normalizer, 0); + grn_string_get_normalized(ctx, norm_y, + &norm_y_raw, &norm_y_raw_length_in_bytes, + NULL); + matched = string_is_contained(ctx, + x_key, x_key_len, + norm_y_raw, norm_y_raw_length_in_bytes); + grn_obj_close(ctx, norm_y); + } else { + matched = pseudo_query_scan_raw_text_raw_text(ctx, + x_key, + x_key_len, + GRN_TEXT_VALUE(y), + GRN_TEXT_LEN(y)); + } + + return matched; +} + +static grn_bool +pseudo_query_scan_text_text(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + return pseudo_query_scan_raw_text_raw_text(ctx, + GRN_TEXT_VALUE(x), + GRN_TEXT_LEN(x), + GRN_TEXT_VALUE(y), + GRN_TEXT_LEN(y)); +} + +static grn_bool +pseudo_query_scan(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ switch (x->header.domain) { - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: - a = grn_string_open(ctx, GRN_TEXT_VALUE(x), GRN_TEXT_LEN(x), - normalizer, 0); - break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + switch (y->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return pseudo_query_scan_text_text(ctx, x, y); + default : + break; + } + return GRN_FALSE; default: - break; + { + grn_obj *domain; + domain = grn_ctx_at(ctx, x->header.domain); + if (GRN_OBJ_TABLEP(domain)) { + switch (y->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return pseudo_query_scan_record_text(ctx, x, domain, y); + default : + break; + } + } + } + return GRN_FALSE; } +} - switch (y->header.domain) { - case GRN_DB_SHORT_TEXT: - case GRN_DB_TEXT: - case GRN_DB_LONG_TEXT: - b = grn_string_open(ctx, GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y), - normalizer, 0); - break; - default: - break; +static grn_bool +pseudo_prefix_search_match(grn_ctx *ctx, + const char *x, unsigned int x_len, + const char *y, unsigned int y_len) +{ + return (x_len >= y_len && strncmp(x, y, y_len) == 0); +} + +static grn_bool +pseudo_prefix_search_raw_text_raw_text(grn_ctx *ctx, + const char *x, unsigned int x_len, + const char *y, unsigned int y_len) +{ + grn_obj *normalizer; + grn_obj *norm_x; + grn_obj *norm_y; + const char *norm_x_raw; + const char *norm_y_raw; + unsigned int norm_x_raw_len; + unsigned int norm_y_raw_len; + grn_bool matched = GRN_FALSE; + + normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + norm_x = grn_string_open(ctx, x, x_len, normalizer, 0); + norm_y = grn_string_open(ctx, y, y_len, normalizer, 0); + grn_string_get_normalized(ctx, norm_x, &norm_x_raw, &norm_x_raw_len, NULL); + grn_string_get_normalized(ctx, norm_y, &norm_y_raw, &norm_y_raw_len, NULL); + matched = pseudo_prefix_search_match(ctx, + norm_x_raw, norm_x_raw_len, + norm_y_raw, norm_y_raw_len); + + grn_obj_close(ctx, norm_x); + grn_obj_close(ctx, norm_y); + grn_obj_unlink(ctx, normalizer); + + return matched; +} + +static grn_bool +pseudo_prefix_search_record_text(grn_ctx *ctx, grn_obj *record, grn_obj *table, + grn_obj *y) +{ + grn_obj *normalizer; + char x_key[GRN_TABLE_MAX_KEY_SIZE]; + int x_key_len; + grn_bool matched = GRN_FALSE; + + if (table->header.domain != GRN_DB_SHORT_TEXT) { + return GRN_FALSE; } - /* normalized str doesn't contain '\0'. */ - if (a && b) { - const char *a_norm, *b_norm; - grn_string_get_normalized(ctx, a, &a_norm, NULL, NULL); - grn_string_get_normalized(ctx, b, &b_norm, NULL, NULL); - matched = (strstr(a_norm, b_norm) != NULL); + x_key_len = grn_table_get_key(ctx, table, GRN_RECORD_VALUE(record), + x_key, GRN_TABLE_MAX_KEY_SIZE); + grn_table_get_info(ctx, table, NULL, NULL, NULL, &normalizer, NULL); + if (normalizer) { + grn_obj *norm_y; + const char *norm_y_raw; + unsigned int norm_y_raw_len; + norm_y = grn_string_open(ctx, GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y), + normalizer, 0); + grn_string_get_normalized(ctx, norm_y, &norm_y_raw, &norm_y_raw_len, NULL); + matched = pseudo_prefix_search_match(ctx, + x_key, x_key_len, + norm_y_raw, norm_y_raw_len); + grn_obj_close(ctx, norm_y); + } else { + matched = pseudo_prefix_search_raw_text_raw_text(ctx, + x_key, + x_key_len, + GRN_TEXT_VALUE(y), + GRN_TEXT_LEN(y)); } - if (a) { grn_obj_close(ctx, a); } - if (b) { grn_obj_close(ctx, b); } + return matched; +} - if (normalizer) { grn_obj_unlink(ctx, normalizer); } +static grn_bool +pseudo_prefix_search_text_text(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + return pseudo_prefix_search_raw_text_raw_text(ctx, + GRN_TEXT_VALUE(x), + GRN_TEXT_LEN(x), + GRN_TEXT_VALUE(y), + GRN_TEXT_LEN(y)); +} - return matched; +static grn_bool +pseudo_prefix_search(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + switch (x->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + switch (y->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return pseudo_prefix_search_text_text(ctx, x, y); + default : + break; + } + return GRN_FALSE; + default: + { + grn_obj *domain; + domain = grn_ctx_at(ctx, x->header.domain); + if (GRN_OBJ_TABLEP(domain)) { + switch (y->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return pseudo_prefix_search_record_text(ctx, x, domain, y); + default : + break; + } + } + } + return GRN_FALSE; + } } inline static void @@ -2831,10 +2508,10 @@ grn_expr_exec_get_member(grn_ctx *ctx, GRN_TEXT_INIT(&values, 0); grn_obj_get_value(ctx, column, record_id, &values); - grn_obj_reinit(ctx, result, DB_OBJ(column)->range, 0); i = GRN_UINT32_VALUE(index); if (values.header.type == GRN_UVECTOR) { int n_elements; + grn_obj_reinit(ctx, result, DB_OBJ(column)->range, 0); n_elements = GRN_BULK_VSIZE(&values) / sizeof(grn_id); if (n_elements > i) { grn_id value; @@ -2843,11 +2520,14 @@ grn_expr_exec_get_member(grn_ctx *ctx, } } else { if (values.u.v.n_sections > i) { - grn_section *section = &(values.u.v.sections[i]); - grn_obj *body = values.u.v.body; - const char *value; - value = GRN_BULK_HEAD(body) + section->offset; - grn_bulk_write(ctx, result, value, section->length); + const char *content; + unsigned int content_length; + grn_id domain; + + content_length = grn_vector_get_element(ctx, &values, i, + &content, NULL, &domain); + grn_obj_reinit(ctx, result, domain, 0); + grn_bulk_write(ctx, result, content, content_length); } } @@ -2861,7 +2541,16 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) uint32_t stack_curr = ctx->impl->stack_curr; GRN_API_ENTER; if (expr->header.type == GRN_PROC) { - grn_proc_call(ctx, expr, nargs, expr); + grn_proc *proc = (grn_proc *)expr; + if (proc->type == GRN_PROC_COMMAND) { + grn_command_input *input; + input = grn_command_input_open(ctx, expr); + grn_command_run(ctx, expr, input); + grn_command_input_close(ctx, input); + GRN_API_RETURN(NULL); + } else { + grn_proc_call(ctx, expr, nargs, expr); + } } else { grn_expr *e = (grn_expr *)expr; register grn_obj **s_ = ctx->impl->stack, *s0 = NULL, *s1 = NULL, **sp, *vp = e->values; @@ -3218,12 +2907,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) case GRN_OP_GET_VALUE : { grn_obj *col, *rec; - grn_obj pat_value; - GRN_TEXT_INIT(&pat_value, 0); do { - uint32_t size; - const char *value; - grn_bool is_pat_key_accessor = GRN_FALSE; if (code->nargs == 1) { rec = v0; if (code->value) { @@ -3245,39 +2929,14 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col)); if (col) { grn_expr_take_obj(ctx, (grn_obj *)expr, col); } } - if (col) { - grn_obj_reinit_for(ctx, res, col); - if (col->header.type == GRN_ACCESSOR && - ((grn_accessor *)col)->action == GRN_ACCESSOR_GET_KEY && - ((grn_accessor *)col)->obj->header.type == GRN_TABLE_PAT_KEY) { - is_pat_key_accessor = GRN_TRUE; - GRN_BULK_REWIND(&pat_value); - grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), &pat_value); - value = GRN_BULK_HEAD(&pat_value); - size = GRN_BULK_VSIZE(&pat_value); - } else { - value = grn_obj_get_value_(ctx, col, GRN_RECORD_VALUE(rec), - &size); - } - } else { + if (!col) { ERR(GRN_INVALID_ARGUMENT, "col resolve failed"); - GRN_OBJ_FIN(ctx, &pat_value); goto exit; } - if (!is_pat_key_accessor && size == GRN_OBJ_GET_VALUE_IMD) { - GRN_RECORD_SET(ctx, res, (uintptr_t)value); - } else { - if (value) { - if (res->header.type == GRN_VECTOR) { - grn_vector_decode(ctx, res, value, size); - } else { - grn_bulk_write_from(ctx, res, value, 0, size); - } - } - } + grn_obj_reinit_for(ctx, res, col); + grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), res); code++; } while (code < ce && code->op == GRN_OP_GET_VALUE); - GRN_OBJ_FIN(ctx, &pat_value); } break; case GRN_OP_OBJ_SEARCH : @@ -3521,35 +3180,38 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_EQUAL : { - int r = GRN_FALSE; + grn_bool is_equal; grn_obj *x, *y; POP2ALLOC1(x, y, res); - DO_EQ(x, y, r); + is_equal = grn_operator_exec_equal(ctx, x, y); grn_obj_reinit(ctx, res, GRN_DB_INT32, 0); - GRN_INT32_SET(ctx, res, r); + GRN_INT32_SET(ctx, res, is_equal ? 1 : 0); } code++; break; case GRN_OP_NOT_EQUAL : { - int r = GRN_FALSE; + grn_bool is_not_equal; grn_obj *x, *y; POP2ALLOC1(x, y, res); - DO_EQ(x, y, r); + is_not_equal = grn_operator_exec_not_equal(ctx, x, y); grn_obj_reinit(ctx, res, GRN_DB_INT32, 0); - GRN_INT32_SET(ctx, res, 1 - r); + GRN_INT32_SET(ctx, res, is_not_equal ? 1 : 0); } code++; break; case GRN_OP_PREFIX : { grn_obj *x, *y; - POP2ALLOC1(x, y, res); - GRN_INT32_SET(ctx, res, - (GRN_TEXT_LEN(x) >= GRN_TEXT_LEN(y) && - !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y)))); - res->header.type = GRN_BULK; - res->header.domain = GRN_DB_INT32; + grn_bool matched; + POP1(y); + POP1(x); + WITH_SPSAVE({ + matched = pseudo_prefix_search(ctx, x, y); + }); + ALLOC1(res); + grn_obj_reinit(ctx, res, GRN_DB_INT32, 0); + GRN_INT32_SET(ctx, res, matched ? 1 : 0); } code++; break; @@ -3568,11 +3230,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_LESS : { - int r; + grn_bool r; grn_obj *x, *y; POP2ALLOC1(x, y, res); - DO_COMPARE(x, y, r, <); - GRN_INT32_SET(ctx, res, r); + r = grn_operator_exec_less(ctx, x, y); + GRN_INT32_SET(ctx, res, r ? 1 : 0); res->header.type = GRN_BULK; res->header.domain = GRN_DB_INT32; } @@ -3580,11 +3242,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_GREATER : { - int r; + grn_bool r; grn_obj *x, *y; POP2ALLOC1(x, y, res); - DO_COMPARE(x, y, r, >); - GRN_INT32_SET(ctx, res, r); + r = grn_operator_exec_greater(ctx, x, y); + GRN_INT32_SET(ctx, res, r ? 1 : 0); res->header.type = GRN_BULK; res->header.domain = GRN_DB_INT32; } @@ -3592,11 +3254,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_LESS_EQUAL : { - int r; + grn_bool r; grn_obj *x, *y; POP2ALLOC1(x, y, res); - DO_COMPARE(x, y, r, <=); - GRN_INT32_SET(ctx, res, r); + r = grn_operator_exec_less_equal(ctx, x, y); + GRN_INT32_SET(ctx, res, r ? 1 : 0); res->header.type = GRN_BULK; res->header.domain = GRN_DB_INT32; } @@ -3604,11 +3266,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_GREATER_EQUAL : { - int r; + grn_bool r; grn_obj *x, *y; POP2ALLOC1(x, y, res); - DO_COMPARE(x, y, r, >=); - GRN_INT32_SET(ctx, res, r); + r = grn_operator_exec_greater_equal(ctx, x, y); + GRN_INT32_SET(ctx, res, r ? 1 : 0); res->header.type = GRN_BULK; res->header.domain = GRN_DB_INT32; } @@ -3799,6 +3461,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_PLUS : ARITHMETIC_BINARY_OPERATION_DISPATCH( + "+", INTEGER_ARITHMETIC_OPERATION_PLUS, INTEGER_ARITHMETIC_OPERATION_PLUS, INTEGER_ARITHMETIC_OPERATION_PLUS, @@ -3847,6 +3510,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) ,); } else { ARITHMETIC_BINARY_OPERATION_DISPATCH( + "-", INTEGER_ARITHMETIC_OPERATION_MINUS, INTEGER_ARITHMETIC_OPERATION_MINUS, INTEGER_ARITHMETIC_OPERATION_MINUS, @@ -3865,6 +3529,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_STAR : ARITHMETIC_BINARY_OPERATION_DISPATCH( + "*", INTEGER_ARITHMETIC_OPERATION_STAR, INTEGER_ARITHMETIC_OPERATION_STAR, INTEGER_ARITHMETIC_OPERATION_STAR, @@ -3914,6 +3579,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_BITWISE_OR : ARITHMETIC_BINARY_OPERATION_DISPATCH( + "|", INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, @@ -3925,6 +3591,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_BITWISE_XOR : ARITHMETIC_BINARY_OPERATION_DISPATCH( + "^", INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, @@ -3936,6 +3603,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_BITWISE_AND : ARITHMETIC_BINARY_OPERATION_DISPATCH( + "&", INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, @@ -3947,6 +3615,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_SHIFTL : ARITHMETIC_BINARY_OPERATION_DISPATCH( + "<<", INTEGER_ARITHMETIC_OPERATION_SHIFTL, INTEGER_ARITHMETIC_OPERATION_SHIFTL, INTEGER_ARITHMETIC_OPERATION_SHIFTL, @@ -3958,6 +3627,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_SHIFTR : ARITHMETIC_BINARY_OPERATION_DISPATCH( + ">>", INTEGER_ARITHMETIC_OPERATION_SHIFTR, INTEGER_ARITHMETIC_OPERATION_SHIFTR, INTEGER_ARITHMETIC_OPERATION_SHIFTR, @@ -3969,6 +3639,7 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) break; case GRN_OP_SHIFTRR : ARITHMETIC_BINARY_OPERATION_DISPATCH( + ">>>", INTEGER8_ARITHMETIC_OPERATION_SHIFTRR, INTEGER16_ARITHMETIC_OPERATION_SHIFTRR, INTEGER32_ARITHMETIC_OPERATION_SHIFTRR, @@ -4010,10 +3681,11 @@ grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) case GRN_OP_NOT : { grn_obj *value; + grn_bool value_boolean; POP1ALLOC1(value, res); + GRN_TRUEP(ctx, value, value_boolean); grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); - grn_obj_cast(ctx, value, res, GRN_FALSE); - GRN_BOOL_SET(ctx, res, !GRN_BOOL_VALUE(res)); + GRN_BOOL_SET(ctx, res, !value_boolean); } code++; break; @@ -4066,6 +3738,8 @@ grn_expr_get_value(grn_ctx *ctx, grn_obj *expr, int offset) #define DEFAULT_TERM_EXTRACT_POLICY 0 #define DEFAULT_WEIGHT_VECTOR_SIZE 4096 +#define GRN_SCAN_INFO_MAX_N_ARGS 128 + struct _grn_scan_info { uint32_t start; uint32_t end; @@ -4076,9 +3750,10 @@ struct _grn_scan_info { grn_obj wv; grn_obj index; grn_obj *query; - grn_obj *args[8]; + grn_obj *args[GRN_SCAN_INFO_MAX_N_ARGS]; int max_interval; int similarity_threshold; + grn_obj *scorer; }; #define SI_FREE(si) do {\ @@ -4102,6 +3777,7 @@ struct _grn_scan_info { (si)->max_interval = DEFAULT_MAX_INTERVAL;\ (si)->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;\ (si)->start = (st);\ + (si)->scorer = NULL;\ } while (0) static scan_info ** @@ -4168,15 +3844,163 @@ put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, grn_operator op, int star return sis; } +/* TODO: Remove me if nobody doesn't want to reuse the implementation again. */ +#if 0 +static const char *opstrs[] = { + "PUSH", + "POP", + "NOP", + "CALL", + "INTERN", + "GET_REF", + "GET_VALUE", + "AND", + "AND_NOT", + "OR", + "ASSIGN", + "STAR_ASSIGN", + "SLASH_ASSIGN", + "MOD_ASSIGN", + "PLUS_ASSIGN", + "MINUS_ASSIGN", + "SHIFTL_ASSIGN", + "SHIFTR_ASSIGN", + "SHIFTRR_ASSIGN", + "AND_ASSIGN", + "XOR_ASSIGN", + "OR_ASSIGN", + "JUMP", + "CJUMP", + "COMMA", + "BITWISE_OR", + "BITWISE_XOR", + "BITWISE_AND", + "BITWISE_NOT", + "EQUAL", + "NOT_EQUAL", + "LESS", + "GREATER", + "LESS_EQUAL", + "GREATER_EQUAL", + "IN", + "MATCH", + "NEAR", + "NEAR2", + "SIMILAR", + "TERM_EXTRACT", + "SHIFTL", + "SHIFTR", + "SHIFTRR", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "MOD", + "DELETE", + "INCR", + "DECR", + "INCR_POST", + "DECR_POST", + "NOT", + "ADJUST", + "EXACT", + "LCP", + "PARTIAL", + "UNSPLIT", + "PREFIX", + "SUFFIX", + "GEO_DISTANCE1", + "GEO_DISTANCE2", + "GEO_DISTANCE3", + "GEO_DISTANCE4", + "GEO_WITHINP5", + "GEO_WITHINP6", + "GEO_WITHINP8", + "OBJ_SEARCH", + "EXPR_GET_VAR", + "TABLE_CREATE", + "TABLE_SELECT", + "TABLE_SORT", + "TABLE_GROUP", + "JSON_PUT" +}; + +static void +put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + int len; + char namebuf[GRN_TABLE_MAX_KEY_SIZE]; + if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) { + GRN_TEXT_PUT(ctx, buf, namebuf, len); + } else { + grn_text_otoj(ctx, buf, obj, NULL); + } +} + +static grn_rc +grn_expr_inspect_internal(grn_ctx *ctx, grn_obj *buf, grn_obj *expr) +{ + uint32_t i, j; + grn_expr_var *var; + grn_expr_code *code; + grn_expr *e = (grn_expr *)expr; + grn_hash *vars = grn_expr_get_vars(ctx, expr, &i); + GRN_TEXT_PUTS(ctx, buf, "noname"); + GRN_TEXT_PUTC(ctx, buf, '('); + { + int i = 0; + grn_obj *value; + const char *name; + uint32_t name_len; + GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, { + if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); } + GRN_TEXT_PUT(ctx, buf, name, name_len); + GRN_TEXT_PUTC(ctx, buf, ':'); + put_value(ctx, buf, value); + }); + } + GRN_TEXT_PUTC(ctx, buf, ')'); + GRN_TEXT_PUTC(ctx, buf, '{'); + for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) { + if (j) { GRN_TEXT_PUTC(ctx, buf, ','); } + grn_text_itoa(ctx, buf, code->modify); + if (code->op == GRN_OP_PUSH) { + for (i = 0, var = e->vars; i < e->nvars; i++, var++) { + if (&var->value == code->value) { + GRN_TEXT_PUTC(ctx, buf, '?'); + if (var->name_size) { + GRN_TEXT_PUT(ctx, buf, var->name, var->name_size); + } else { + grn_text_itoa(ctx, buf, (int)i); + } + break; + } + } + if (i == e->nvars) { + put_value(ctx, buf, code->value); + } + } else { + if (code->value) { + put_value(ctx, buf, code->value); + GRN_TEXT_PUTC(ctx, buf, ' '); + } + GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]); + } + } + GRN_TEXT_PUTC(ctx, buf, '}'); + return GRN_SUCCESS; +} #define EXPRLOG(name,expr) do {\ grn_obj strbuf;\ GRN_TEXT_INIT(&strbuf, 0);\ - grn_expr_inspect(ctx, &strbuf, (expr));\ + grn_expr_inspect_internal(ctx, &strbuf, (expr));\ GRN_TEXT_PUTC(ctx, &strbuf, '\0');\ GRN_LOG(ctx, GRN_LOG_NOTICE, "%s=(%s)", (name), GRN_TEXT_VALUE(&strbuf));\ GRN_OBJ_FIN(ctx, &strbuf);\ } while (0) +#endif + static void scan_info_put_index(grn_ctx *ctx, scan_info *si, grn_obj *index, uint32_t sid, int32_t weight) @@ -4243,6 +4067,7 @@ grn_scan_info_open(grn_ctx *ctx, int start) si->max_interval = DEFAULT_MAX_INTERVAL; si->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD; si->start = start; + si->scorer = NULL; return si; } @@ -4344,10 +4169,22 @@ grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold) si->similarity_threshold = similarity_threshold; } +grn_obj * +grn_scan_info_get_scorer(scan_info *si) +{ + return si->scorer; +} + +void +grn_scan_info_set_scorer(scan_info *si, grn_obj *scorer) +{ + si->scorer = scorer; +} + grn_bool grn_scan_info_push_arg(scan_info *si, grn_obj *arg) { - if (si->nargs >= 8) { + if (si->nargs >= GRN_SCAN_INFO_MAX_N_ARGS) { return GRN_FALSE; } @@ -4374,10 +4211,10 @@ scan_info_build_find_index_column_index(grn_ctx *ctx, uint32_t offset = 0; grn_obj *index; int sid = 0; - int32_t weight = 0; + int32_t weight; index = ec->value; - if (n_rest_codes > 2 && + if (n_rest_codes >= 2 && ec[1].value && (ec[1].value->header.domain == GRN_DB_INT32 || ec[1].value->header.domain == GRN_DB_UINT32) && @@ -4388,15 +4225,159 @@ scan_info_build_find_index_column_index(grn_ctx *ctx, sid = GRN_UINT32_VALUE(ec[1].value) + 1; } offset = 2; - weight = get_weight(ctx, ec + offset); - } else { - weight = get_weight(ctx, ec); } + weight = get_weight(ctx, ec + offset); scan_info_put_index(ctx, si, index, sid, weight); return offset; } +static uint32_t +scan_info_build_match_expr_codes(grn_ctx *ctx, scan_info *si, + grn_expr *expr, uint32_t i) +{ + grn_expr_code *ec; + grn_obj *index; + int sid; + + ec = &(expr->codes[i]); + if (!ec->value) { + return i + 1; + } + + switch (ec->value->header.type) { + case GRN_ACCESSOR : + if (grn_column_index(ctx, ec->value, si->op, &index, 1, &sid)) { + int32_t weight = get_weight(ctx, ec); + si->flags |= SCAN_ACCESSOR; + if (((grn_accessor *)ec->value)->next) { + scan_info_put_index(ctx, si, ec->value, sid, weight); + } else { + scan_info_put_index(ctx, si, index, sid, weight); + } + } + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + if (grn_column_index(ctx, ec->value, si->op, &index, 1, &sid)) { + scan_info_put_index(ctx, si, index, sid, get_weight(ctx, ec)); + } + break; + case GRN_COLUMN_INDEX : + { + uint32_t n_rest_codes; + uint32_t offset; + n_rest_codes = expr->codes_curr - i; + offset = scan_info_build_find_index_column_index(ctx, si, ec, + n_rest_codes, si->op); + i += offset; + } + break; + case GRN_PROC : + if (!grn_obj_is_scorer_proc(ctx, ec->value)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, ec->value); + ERR(GRN_INVALID_ARGUMENT, + "procedure must be scorer: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return expr->codes_curr; + } + si->scorer = ec->value; + i = scan_info_build_match_expr_codes(ctx, si, expr, i + 1); + if (expr->codes[i].op != GRN_OP_CALL) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, si->scorer); + ERR(GRN_INVALID_ARGUMENT, + "scorer must have only one argument: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return expr->codes_curr; + } + break; + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_obj_name(ctx, ec->value, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "invalid match target: <%.*s>", + name_size, name); + return expr->codes_curr; + } + break; + } + + return i + 1; +} + +static void +scan_info_build_match_expr(grn_ctx *ctx, scan_info *si, grn_expr *expr) +{ + uint32_t i; + i = 0; + while (i < expr->codes_curr) { + i = scan_info_build_match_expr_codes(ctx, si, expr, i); + } +} + +static void +scan_info_build_match(grn_ctx *ctx, scan_info *si) +{ + int sid; + grn_obj *index, **p = si->args, **pe = si->args + si->nargs; + for (; p < pe; p++) { + if ((*p)->header.type == GRN_EXPR) { + scan_info_build_match_expr(ctx, si, (grn_expr *)(*p)); + } else if (GRN_DB_OBJP(*p)) { + if (grn_column_index(ctx, *p, si->op, &index, 1, &sid)) { + scan_info_put_index(ctx, si, index, sid, 1); + } + } else if (GRN_ACCESSORP(*p)) { + si->flags |= SCAN_ACCESSOR; + if (grn_column_index(ctx, *p, si->op, &index, 1, &sid)) { + if (((grn_accessor *)(*p))->next) { + scan_info_put_index(ctx, si, *p, sid, 1); + } else { + scan_info_put_index(ctx, si, index, sid, 1); + } + } + } else { + switch (si->op) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + if (si->nargs == 3 && + *p == si->args[2] && + (*p)->header.domain == GRN_DB_INT32) { + si->max_interval = GRN_INT32_VALUE(*p); + } else { + si->query = *p; + } + break; + case GRN_OP_SIMILAR : + if (si->nargs == 3 && + *p == si->args[2] && + (*p)->header.domain == GRN_DB_INT32) { + si->similarity_threshold = GRN_INT32_VALUE(*p); + } else { + si->query = *p; + } + break; + default : + si->query = *p; + break; + } + } + } +} + static scan_info ** scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, grn_operator op, uint32_t size) @@ -4435,6 +4416,21 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, stat = SCAN_START; m++; break; + case GRN_OP_BITWISE_OR : + case GRN_OP_BITWISE_XOR : + case GRN_OP_BITWISE_AND : + case GRN_OP_BITWISE_NOT : + case GRN_OP_SHIFTL : + case GRN_OP_SHIFTR : + case GRN_OP_SHIFTRR : + case GRN_OP_PLUS : + case GRN_OP_MINUS : + case GRN_OP_STAR : + case GRN_OP_MOD : + if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; } + stat = SCAN_START; + if (m != o + 1) { return NULL; } + break; case GRN_OP_AND : case GRN_OP_OR : case GRN_OP_AND_NOT : @@ -4500,86 +4496,12 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, si->op = c->op; si->end = c - e->codes; sis[i++] = si; - { - int sid; - grn_obj *index, **p = si->args, **pe = si->args + si->nargs; - for (; p < pe; p++) { - if ((*p)->header.type == GRN_EXPR) { - uint32_t j; - grn_expr_code *ec; - grn_expr *e = (grn_expr *)(*p); - for (j = e->codes_curr, ec = e->codes; j--; ec++) { - if (ec->value) { - switch (ec->value->header.type) { - case GRN_ACCESSOR : - if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) { - int32_t weight = get_weight(ctx, ec); - si->flags |= SCAN_ACCESSOR; - if (((grn_accessor *)ec->value)->next) { - scan_info_put_index(ctx, si, ec->value, sid, weight); - } else { - scan_info_put_index(ctx, si, index, sid, weight); - } - } - break; - case GRN_COLUMN_FIX_SIZE : - case GRN_COLUMN_VAR_SIZE : - if (grn_column_index(ctx, ec->value, c->op, &index, 1, &sid)) { - scan_info_put_index(ctx, si, index, sid, get_weight(ctx, ec)); - } - break; - case GRN_COLUMN_INDEX : - { - uint32_t offset; - offset = scan_info_build_find_index_column_index(ctx, si, ec, - j, c->op); - j -= offset; - ec += offset; - } - break; - } - } - } - } else if (GRN_DB_OBJP(*p)) { - if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) { - scan_info_put_index(ctx, si, index, sid, 1); - } - } else if (GRN_ACCESSORP(*p)) { - si->flags |= SCAN_ACCESSOR; - if (grn_column_index(ctx, *p, c->op, &index, 1, &sid)) { - if (((grn_accessor *)(*p))->next) { - scan_info_put_index(ctx, si, *p, sid, 1); - } else { - scan_info_put_index(ctx, si, index, sid, 1); - } - } - } else { - switch (c->op) { - case GRN_OP_NEAR : - case GRN_OP_NEAR2 : - if (si->nargs == 3 && - *p == si->args[2] && - (*p)->header.domain == GRN_DB_INT32) { - si->max_interval = GRN_INT32_VALUE(*p); - } else { - si->query = *p; - } - break; - case GRN_OP_SIMILAR : - if (si->nargs == 3 && - *p == si->args[2] && - (*p)->header.domain == GRN_DB_INT32) { - si->similarity_threshold = GRN_INT32_VALUE(*p); - } else { - si->query = *p; - } - break; - default : - si->query = *p; - break; - } - } - } + scan_info_build_match(ctx, si); + if (ctx->rc != GRN_SUCCESS) { + int j; + for (j = 0; j < i; j++) { SI_FREE(sis[j]); } + GRN_FREE(sis); + return NULL; } si = NULL; break; @@ -4595,7 +4517,7 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, if (c->value == var) { stat = SCAN_VAR; } else { - if (si->nargs < 8) { + if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) { si->args[si->nargs++] = c->value; } if (stat == SCAN_START) { si->flags |= SCAN_PRE_CONST; } @@ -4610,7 +4532,7 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, case SCAN_CONST : case SCAN_VAR : stat = SCAN_COL1; - if (si->nargs < 8) { + if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) { si->args[si->nargs++] = c->value; } break; @@ -4628,6 +4550,7 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, "invalid expression: can't use column as a value: %.*s", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); + SI_FREE(si); for (j = 0; j < i; j++) { SI_FREE(sis[j]); } GRN_FREE(sis); return NULL; @@ -4694,6 +4617,43 @@ scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, return sis; } +void +grn_inspect_scan_info_list(grn_ctx *ctx, grn_obj *buffer, scan_info **sis, int n) +{ + int i; + + for (i = 0; i < n; i++) { + scan_info *si = sis[i]; + + grn_text_printf(ctx, buffer, "[%d]\n", i); + grn_text_printf(ctx, buffer, + " op: <%s>\n", + grn_operator_to_string(si->op)); + grn_text_printf(ctx, buffer, + " logical_op: <%s>\n", + grn_operator_to_string(si->logical_op)); + + GRN_TEXT_PUTS(ctx, buffer, " query: <"); + grn_inspect(ctx, buffer, si->query); + GRN_TEXT_PUTS(ctx, buffer, ">\n"); + + grn_text_printf(ctx, buffer, + " expr: <%d..%d>\n", si->start, si->end); + } +} + +void +grn_p_scan_info_list(grn_ctx *ctx, scan_info **sis, int n) +{ + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect_scan_info_list(ctx, &inspected, sis, n); + printf("%.*s\n", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); +} + inline static int32_t exec_result_to_score(grn_ctx *ctx, grn_obj *result, grn_obj *score_buffer) { @@ -4719,8 +4679,8 @@ exec_result_to_score(grn_ctx *ctx, grn_obj *result, grn_obj *score_buffer) } static void -grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v, - grn_obj *res, grn_operator op) +grn_table_select_sequential(grn_ctx *ctx, grn_obj *table, grn_obj *expr, + grn_obj *v, grn_obj *res, grn_operator op) { int32_t score; grn_id id, *idp; @@ -4737,6 +4697,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v, while ((id = grn_table_cursor_next(ctx, tc))) { GRN_RECORD_SET(ctx, v, id); r = grn_expr_exec(ctx, expr, 0); + if (ctx->rc) { + break; + } score = exec_result_to_score(ctx, r, &score_buffer); if (score > 0) { grn_rset_recinfo *ri; @@ -4754,6 +4717,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v, grn_hash_cursor_get_key(ctx, hc, (void **) &idp); GRN_RECORD_SET(ctx, v, *idp); r = grn_expr_exec(ctx, expr, 0); + if (ctx->rc) { + break; + } score = exec_result_to_score(ctx, r, &score_buffer); if (score > 0) { grn_rset_recinfo *ri; @@ -4772,6 +4738,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v, grn_hash_cursor_get_key(ctx, hc, (void **) &idp); GRN_RECORD_SET(ctx, v, *idp); r = grn_expr_exec(ctx, expr, 0); + if (ctx->rc) { + break; + } score = exec_result_to_score(ctx, r, &score_buffer); if (score > 0) { grn_hash_cursor_delete(ctx, hc, NULL); @@ -4786,6 +4755,9 @@ grn_table_select_(grn_ctx *ctx, grn_obj *table, grn_obj *expr, grn_obj *v, grn_hash_cursor_get_key(ctx, hc, (void **) &idp); GRN_RECORD_SET(ctx, v, *idp); r = grn_expr_exec(ctx, expr, 0); + if (ctx->rc) { + break; + } score = exec_result_to_score(ctx, r, &score_buffer); if (score > 0) { grn_rset_recinfo *ri; @@ -4854,13 +4826,29 @@ grn_table_select_index_range_column(grn_ctx *ctx, grn_obj *table, min, min_size, max, max_size, offset, limit, flags); if (cursor) { - grn_id index_id; - while ((index_id = grn_table_cursor_next(ctx, cursor))) { - grn_ii_at(ctx, (grn_ii *)index, index_id, - (grn_hash *)res, logical_op); + uint32_t sid; + int32_t weight; + grn_obj *index_cursor; + + sid = GRN_UINT32_VALUE_AT(&(si->wv), 0); + weight = GRN_INT32_VALUE_AT(&(si->wv), 1); + index_cursor = grn_index_cursor_open(ctx, cursor, index, + GRN_ID_NIL, GRN_ID_MAX, 0); + if (index_cursor) { + grn_posting *posting; + while ((posting = grn_index_cursor_next(ctx, index_cursor, NULL))) { + if (sid == 0 || posting->sid == sid) { + grn_ii_posting ii_posting; + ii_posting.rid = posting->rid; + ii_posting.sid = posting->sid; + ii_posting.weight = posting->weight * weight; + grn_ii_posting_add(ctx, &ii_posting, (grn_hash *)res, logical_op); + } + } + processed = GRN_TRUE; + grn_obj_unlink(ctx, index_cursor); } grn_table_cursor_close(ctx, cursor); - processed = GRN_TRUE; } grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op); @@ -4913,11 +4901,21 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table, { int i; + grn_obj weight_vector; + grn_search_optarg optarg; + GRN_INT32_INIT(&weight_vector, GRN_OBJ_VECTOR); + memset(&optarg, 0, sizeof(grn_search_optarg)); + if (si->op == GRN_OP_MATCH) { + optarg.mode = GRN_OP_EXACT; + } else { + optarg.mode = si->op; + } for (i = n_accessors - 1; i > 0; i--) { grn_rc rc = GRN_SUCCESS; grn_accessor *accessor; grn_obj *index; + int section; grn_obj *domain; grn_obj *target; grn_obj *next_res; @@ -4926,12 +4924,28 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table, accessor = (grn_accessor *)GRN_PTR_VALUE_AT(accessor_stack, i - 1); target = accessor->obj; - if (grn_column_index(ctx, target, GRN_OP_EQUAL, &index, 1, NULL) == 0) { + if (grn_column_index(ctx, target, GRN_OP_EQUAL, &index, 1, §ion) == 0) { grn_obj_unlink(ctx, current_res); current_res = NULL; break; } + if (section > 0) { + int j; + int weight_position = section - 1; + + GRN_BULK_REWIND(&weight_vector); + GRN_INT32_SET_AT(ctx, &weight_vector, weight_position, 1); + optarg.weight_vector = &(GRN_INT32_VALUE(&weight_vector)); + optarg.vector_size = GRN_BULK_VSIZE(&weight_vector) / sizeof(int32_t); + for (j = 0; j < weight_position - 1; j++) { + optarg.weight_vector[j] = 0; + } + } else { + optarg.weight_vector = NULL; + optarg.vector_size = 1; + } + { grn_obj *range; range = grn_ctx_at(ctx, DB_OBJ(index)->range); @@ -4954,14 +4968,14 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table, if (domain->header.type == GRN_TABLE_NO_KEY) { rc = grn_ii_sel(ctx, (grn_ii *)index, (const char *)next_record_id, sizeof(grn_id), - (grn_hash *)next_res, next_op, NULL); + (grn_hash *)next_res, next_op, &optarg); } else { char key[GRN_TABLE_MAX_KEY_SIZE]; int key_len; key_len = grn_table_get_key(ctx, domain, *next_record_id, key, GRN_TABLE_MAX_KEY_SIZE); rc = grn_ii_sel(ctx, (grn_ii *)index, key, key_len, - (grn_hash *)next_res, next_op, NULL); + (grn_hash *)next_res, next_op, &optarg); } if (rc != GRN_SUCCESS) { break; @@ -4986,6 +5000,7 @@ grn_table_select_index_range_accessor(grn_ctx *ctx, grn_obj *table, break; } } + GRN_OBJ_FIN(ctx, &weight_vector); } return current_res == res; @@ -5202,6 +5217,7 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si, optarg.vector_size = 1; optarg.proc = NULL; optarg.max_size = 0; + optarg.scorer = si->scorer; ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; for (; j--; ip++, wp += 2) { uint32_t sid = (uint32_t) wp[0]; @@ -5250,7 +5266,7 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si, } break; case GRN_OP_CALL : - if (selector_proc_p(si->args[0])) { + if (grn_obj_is_selector_proc(ctx, si->args[0])) { grn_rc rc; grn_proc *proc = (grn_proc *)(si->args[0]); rc = proc->selector(ctx, table, index, si->nargs, si->args, @@ -5276,7 +5292,7 @@ grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si, } else { switch (si->op) { case GRN_OP_CALL : - if (selector_proc_p(si->args[0])) { + if (grn_obj_is_selector_proc(ctx, si->args[0])) { grn_rc rc; grn_proc *proc = (grn_proc *)(si->args[0]); rc = proc->selector(ctx, table, NULL, si->nargs, si->args, @@ -5361,11 +5377,13 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, if (ctx->rc) { break; } e->codes = codes + si->start; e->codes_curr = si->end - si->start + 1; - grn_table_select_(ctx, table, expr, v, res, si->logical_op); + grn_table_select_sequential(ctx, table, expr, v, + res, si->logical_op); } } GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, ":", "filter(%d)", grn_table_size(ctx, res)); + if (ctx->rc) { break; } } for (i = 0; i < n; i++) { scan_info *si = sis[i]; @@ -5377,7 +5395,7 @@ grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, e->codes_curr = codes_curr; } else { if (!ctx->rc) { - grn_table_select_(ctx, table, expr, v, res, op); + grn_table_select_sequential(ctx, table, expr, v, res, op); } } } @@ -5408,7 +5426,7 @@ grn_int32_value_at(grn_obj *obj, int offset) /* grn_expr_create_from_str */ -#include "snip.h" +#include "grn_snip.h" typedef struct { grn_ctx *ctx; @@ -5936,8 +5954,8 @@ section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg } #endif -#include "ecmascript.h" -#include "ecmascript.c" +#include "grn_ecmascript.h" +#include "grn_ecmascript.c" static grn_rc grn_expr_parser_open(grn_ctx *ctx) @@ -6090,7 +6108,7 @@ get_word_(grn_ctx *ctx, efs_info *q) GRN_INT32_PUT(ctx, &q->mode_stack, mode); return GRN_SUCCESS; - } else if (GRN_TEXT_LEN(&q->buf) > 1 && *end == GRN_QUERY_PREFIX) { + } else if (GRN_TEXT_LEN(&q->buf) > 0 && *end == GRN_QUERY_PREFIX) { q->cur = end + 1; GRN_INT32_PUT(ctx, &q->mode_stack, GRN_OP_PREFIX); break; @@ -6912,7 +6930,7 @@ grn_expr_parse(grn_ctx *ctx, grn_obj *expr, /* grn_obj strbuf; GRN_TEXT_INIT(&strbuf, 0); - grn_expr_inspect(ctx, &strbuf, expr); + grn_expr_inspect_internal(ctx, &strbuf, expr); GRN_TEXT_PUTC(ctx, &strbuf, '\0'); GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf)); GRN_OBJ_FIN(ctx, &strbuf); @@ -7156,3 +7174,24 @@ grn_expr_syntax_escape_query(grn_ctx *ctx, const char *query, int query_size, target_characters, GRN_QUERY_ESCAPE, escaped_query); } + +grn_rc +grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer) +{ + int n; + scan_info **sis; + + GRN_API_ENTER; + sis = scan_info_build(ctx, expr, &n, GRN_OP_OR, 0); + if (sis) { + int i; + grn_inspect_scan_info_list(ctx, buffer, sis, n); + for (i = 0; i < n; i++) { + SI_FREE(sis[i]); + } + GRN_FREE(sis); + } else { + GRN_TEXT_PUTS(ctx, buffer, "sequential search\n"); + } + GRN_API_RETURN(GRN_SUCCESS); +} diff --git a/storage/mroonga/vendor/groonga/lib/geo.c b/storage/mroonga/vendor/groonga/lib/geo.c index 1bb621487a8..21b50c4a1a4 100644 --- a/storage/mroonga/vendor/groonga/lib/geo.c +++ b/storage/mroonga/vendor/groonga/lib/geo.c @@ -15,9 +15,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "geo.h" -#include "pat.h" -#include "util.h" +#include "grn_geo.h" +#include "grn_pat.h" +#include "grn_util.h" #include <string.h> #include <stdlib.h> @@ -1989,13 +1989,13 @@ exit: return rc; } -int -grn_geo_estimate_in_rectangle(grn_ctx *ctx, - grn_obj *index, - grn_obj *top_left_point, - grn_obj *bottom_right_point) +uint32_t +grn_geo_estimate_size_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point) { - int n = 0; + uint32_t n = 0; int total_records; grn_rc rc; in_rectangle_data data; @@ -2004,7 +2004,6 @@ grn_geo_estimate_in_rectangle(grn_ctx *ctx, GRN_VOID_INIT(&(data.bottom_right_point_buffer)); if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point, "grn_geo_estimate_in_rectangle()", &data)) { - n = -1; goto exit; } @@ -2025,8 +2024,6 @@ grn_geo_estimate_in_rectangle(grn_ctx *ctx, if (rc == GRN_END_OF_DATA) { n = total_records; rc = GRN_SUCCESS; - } else { - n = -1; } goto exit; } @@ -2052,7 +2049,7 @@ grn_geo_estimate_in_rectangle(grn_ctx *ctx, (double)total_longitude_distance); } estimated_n_records = ceil(total_records * select_ratio); - n = (int)estimated_n_records; + n = (uint32_t)estimated_n_records; } exit : @@ -2061,6 +2058,25 @@ exit : return n; } +int +grn_geo_estimate_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point) +{ + uint32_t size; + + size = grn_geo_estimate_size_in_rectangle(ctx, + index, + top_left_point, + bottom_right_point); + if (ctx->rc != GRN_SUCCESS) { + return -1; + } + + return size; +} + grn_bool grn_geo_in_circle(grn_ctx *ctx, grn_obj *point, grn_obj *center, grn_obj *radius_or_point, diff --git a/storage/mroonga/vendor/groonga/lib/groonga_in.h b/storage/mroonga/vendor/groonga/lib/grn.h index d7ecff2808b..c33ad7f7ec4 100644 --- a/storage/mroonga/vendor/groonga/lib/groonga_in.h +++ b/storage/mroonga/vendor/groonga/lib/grn.h @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2012 Brazil +/* Copyright(C) 2009-2014 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,55 +16,55 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GROONGA_IN_H -#define GROONGA_IN_H +#ifndef GRN_H +#define GRN_H #ifdef HAVE_CONFIG_H -#include <config.h> +# include <config.h> #endif /* HAVE_CONFIG_H */ #ifdef __cplusplus -#define __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS #endif #ifdef HAVE_STDLIB_H -#include <stdlib.h> +# include <stdlib.h> #endif /* HAVE_STDLIB_H */ #ifdef HAVE_STDINT_H -#include <stdint.h> +# include <stdint.h> #endif /* HAVE_STDINT_H */ #ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> +# include <sys/types.h> #endif /* HAVE_SYS_TYPES_H */ #ifdef HAVE_SYS_PARAM_H -#include <sys/param.h> +# include <sys/param.h> #endif /* HAVE_SYS_PARAM_H */ #ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> +# include <sys/mman.h> #endif /* HAVE_SYS_MMAN_H */ #ifdef HAVE_SYS_TIME_H -#include <sys/time.h> +# include <sys/time.h> #endif /* HAVE_SYS_TIME_H */ #ifdef HAVE_SYS_RESOURCE_H -#include <sys/resource.h> +# include <sys/resource.h> #endif /* HAVE_SYS_RESOURCE_H */ #ifdef WIN32 -# define GRN_API __declspec(dllexport) +# define GRN_API __declspec(dllexport) #ifdef GROONGA_MAIN -# define GRN_VAR __declspec(dllimport) +# define GRN_VAR __declspec(dllimport) #else -# define GRN_VAR __declspec(dllexport) extern +# define GRN_VAR __declspec(dllexport) extern #endif /* GROONGA_MAIN */ #else -# define GRN_API -# define GRN_VAR extern +# define GRN_API +# define GRN_VAR extern #endif #ifdef HAVE_OPEN @@ -93,84 +93,93 @@ #ifdef WIN32 -#if defined(__GNUC__) && !defined(WINVER) +# if defined(__GNUC__) && !defined(WINVER) # include <w32api.h> # define WINVER WindowsXP -#endif /* defined(__GNUC__) && !defined(WINVER) */ - -#include <basetsd.h> -#include <process.h> -#include <winsock2.h> -#include <ws2tcpip.h> -#include <windows.h> -#include <stddef.h> -#include <windef.h> -#include <float.h> -#include <time.h> -#include <sys/types.h> - -#ifndef __GNUC__ -# define PATH_MAX (MAX_PATH - 1) -# ifndef __cplusplus -# define inline _inline +# endif /* defined(__GNUC__) && !defined(WINVER) */ + +# include <basetsd.h> +# include <process.h> +# include <winsock2.h> +# include <ws2tcpip.h> +# include <windows.h> +# include <stddef.h> +# include <windef.h> +# include <float.h> +# include <time.h> +# include <sys/types.h> + +# ifndef __GNUC__ +# define PATH_MAX (MAX_PATH - 1) +# ifndef __cplusplus +# define inline _inline +# endif # endif -#endif - -#ifndef __GNUC__ -# define snprintf(str, size, ...) _snprintf(str, size, __VA_ARGS__) -#endif /* __GNUC__ */ -#if !defined(__GNUC__) && _MSC_VER < 1500 -# define vsnprintf(str, size, format, ap) _vsnprintf(str, size, format, ap) -#endif /* !defined(__GNUC__) && _MSC_VER < 1500 */ -#define unlink(pathname) _unlink(pathname) -#define lseek(fd, offset, whence) _lseek(fd, offset, whence) -#define getpid() _getpid() -#if !defined(__GNUC__) && _MSC_VER < 1400 -# define fstat(fd, buf) _fstat(fd, buf) -#endif /* !defined(__GNUC__) && _MSC_VER < 1400 */ -#if !defined(strcasecmp) -# define strcasecmp(s1, s2) _stricmp(s1, s2) -#endif /* !defined(strcasecmp) */ -#ifdef __GNUC__ -#include <stdint.h> -#else -#define uint8_t UINT8 -#define int8_t INT8 -#define int_least8_t INT8 -#define uint_least8_t UINT8 -#define int16_t INT16 -#define uint16_t UINT16 -#define int32_t INT32 -#define uint32_t UINT32 -#define int64_t INT64 -#define uint64_t UINT64 -#define ssize_t SSIZE_T -#define pid_t int -#endif +# ifndef __GNUC__ +# define snprintf(str, size, ...) _snprintf(str, size, __VA_ARGS__) +# endif /* __GNUC__ */ +# if !defined(__GNUC__) && _MSC_VER < 1500 +# define vsnprintf(str, size, format, ap) _vsnprintf(str, size, format, ap) +# endif /* !defined(__GNUC__) && _MSC_VER < 1500 */ +# ifndef HAVE_UNLINK +# define unlink(pathname) _unlink(pathname) +# endif +# define getpid() _getpid() +# if !defined(__GNUC__) && _MSC_VER < 1400 +# define fstat(fd, buf) _fstat(fd, buf) +# endif /* !defined(__GNUC__) && _MSC_VER < 1400 */ +# ifdef HAVE__STRICMP +# ifdef strcasecmp +# undef strcasecmp +# endif /* strcasecmp */ +# define strcasecmp(s1, s2) _stricmp(s1, s2) +# endif /* defined(HAVE__STRICMP) */ + +# ifdef __GNUC__ +# include <stdint.h> +# else +typedef UINT8 uint8_t; +typedef INT8 int8_t; +typedef INT8 int_least8_t; +typedef UINT8 uint_least8_t; +typedef INT16 int16_t; +typedef UINT16 uint16_t; +typedef INT32 int32_t; +typedef UINT32 uint32_t; +typedef INT64 int64_t; +typedef UINT64 uint64_t; +typedef SSIZE_T ssize_t; +typedef int pid_t; +typedef int64_t off64_t; +# endif -#undef MSG_WAITALL -#define MSG_WAITALL 0 /* before Vista, not supported... */ -#define SHUT_RDWR SD_BOTH +# undef MSG_WAITALL +# define MSG_WAITALL 0 /* before Vista, not supported... */ +# define SHUT_RDWR SD_BOTH typedef SOCKET grn_sock; -#define grn_sock_close(sock) closesocket(sock) +# define grn_sock_close(sock) closesocket(sock) -#define CALLBACK __stdcall +# define CALLBACK __stdcall -#ifndef __GNUC__ -#include <intrin.h> -#include <sys/timeb.h> -#include <errno.h> -#endif +# ifndef __GNUC__ +# include <intrin.h> +# include <sys/timeb.h> +# include <errno.h> +# endif #else /* WIN32 */ -#define GROONGA_API +# define GROONGA_API -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif /* HAVE_UNISTD_H */ +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif /* HAVE_UNISTD_H */ + +# ifndef __off64_t_defined +typedef off_t off64_t; +# endif # ifndef PATH_MAX # if defined(MAXPATHLEN) @@ -192,90 +201,100 @@ typedef int grn_sock; #endif /* WIN32 */ #ifndef INT8_MAX -#define INT8_MAX (127) +# define INT8_MAX (127) #endif /* INT8_MAX */ #ifndef INT8_MIN -#define INT8_MIN (-128) +# define INT8_MIN (-128) #endif /* INT8_MIN */ #ifndef INT16_MAX -#define INT16_MAX (32767) +# define INT16_MAX (32767) #endif /* INT16_MAX */ #ifndef INT16_MIN -#define INT16_MIN (-32768) +# define INT16_MIN (-32768) #endif /* INT16_MIN */ #ifndef INT32_MAX -#define INT32_MAX (2147483647) +# define INT32_MAX (2147483647) #endif /* INT32_MAX */ #ifndef INT32_MIN -#define INT32_MIN (-2147483648) +# define INT32_MIN (-2147483648) #endif /* INT32_MIN */ #ifndef UINT32_MAX -#define UINT32_MAX (4294967295) +# define UINT32_MAX (4294967295) #endif /* UINT32_MAX */ #ifndef INT64_MAX -#define INT64_MAX (9223372036854775807) +# define INT64_MAX (9223372036854775807) #endif /* INT64_MAX */ #ifndef INT64_MIN -#define INT64_MIN (-9223372036854775808) +# define INT64_MIN (-9223372036854775808) #endif /* INT64_MIN */ + +#ifdef WIN32 +# define grn_lseek(fd, offset, whence) _lseeki64(fd, offset, whence) +#else /* WIN32 */ +# define grn_lseek(fd, offset, whence) lseek(fd, offset, whence) +#endif /* WIN32 */ + + #ifdef HAVE_PTHREAD_H -#include <pthread.h> +# include <pthread.h> typedef pthread_t grn_thread; -#define THREAD_CREATE(thread,func,arg) \ +typedef void * grn_thread_func_result; +# define GRN_THREAD_FUNC_RETURN_VALUE NULL +# define THREAD_CREATE(thread,func,arg) \ (pthread_create(&(thread), NULL, (func), (arg))) -#define THREAD_JOIN(thread) (pthread_join(thread, NULL)) +# define THREAD_JOIN(thread) (pthread_join(thread, NULL)) typedef pthread_mutex_t grn_mutex; -#define MUTEX_INIT(m) pthread_mutex_init(&m, NULL) -#define MUTEX_LOCK(m) pthread_mutex_lock(&m) -#define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m) -#define MUTEX_FIN(m) -#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED -# define MUTEX_INIT_SHARED(m) do {\ +# define MUTEX_INIT(m) pthread_mutex_init(&m, NULL) +# define MUTEX_LOCK(m) pthread_mutex_lock(&m) +# define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m) +# define MUTEX_FIN(m) +# ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED +# define MUTEX_INIT_SHARED(m) do {\ pthread_mutexattr_t mutexattr;\ pthread_mutexattr_init(&mutexattr);\ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);\ pthread_mutex_init(&m, &mutexattr);\ } while (0) -#else -# define MUTEX_INIT_SHARED MUTEX_INIT -#endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */ +# else +# define MUTEX_INIT_SHARED MUTEX_INIT +# endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */ typedef pthread_mutex_t grn_critical_section; -#define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL) -#define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs)) -#define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs)) -#define CRITICAL_SECTION_FIN(cs) +# define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL) +# define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs)) +# define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs)) +# define CRITICAL_SECTION_FIN(cs) typedef pthread_cond_t grn_cond; -#define COND_INIT(c) pthread_cond_init(&c, NULL) -#define COND_SIGNAL(c) pthread_cond_signal(&c) -#define COND_WAIT(c,m) pthread_cond_wait(&c, &m) -#define COND_BROADCAST(c) pthread_cond_broadcast(&c) -#ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED -# define COND_INIT_SHARED(c) do {\ +# define COND_INIT(c) pthread_cond_init(&c, NULL) +# define COND_SIGNAL(c) pthread_cond_signal(&c) +# define COND_WAIT(c,m) pthread_cond_wait(&c, &m) +# define COND_BROADCAST(c) pthread_cond_broadcast(&c) +# ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED +# define COND_INIT_SHARED(c) do {\ pthread_condattr_t condattr;\ pthread_condattr_init(&condattr);\ pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);\ pthread_cond_init(&c, &condattr);\ } while (0) -#else -# define COND_INIT_SHARED COND_INIT -#endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */ +# else +# define COND_INIT_SHARED COND_INIT +# endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */ typedef pthread_key_t grn_thread_key; -#define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr) -#define THREAD_KEY_DELETE(key) pthread_key_delete(key) -#define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value) -#define THREAD_GETSPECIFIC(key) pthread_getspecific(key) +# define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr) +# define THREAD_KEY_DELETE(key) pthread_key_delete(key) +# define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value) +# define THREAD_GETSPECIFIC(key) pthread_getspecific(key) #if USE_UYIELD extern int grn_uyield_count; @@ -305,35 +324,37 @@ typedef pthread_key_t grn_thread_key; #if !defined(_POSIX_PRIORITY_SCHEDULING) #define sched_yield() grn_nanosleep(1000000 * 20) #endif -#else /* USE_UYIELD */ +# else /* USE_UYIELD */ #define GRN_TEST_YIELD() do {} while (0) -#endif /* USE_UYIELD */ +# endif /* USE_UYIELD */ #else /* HAVE_PTHREAD_H */ /* todo */ typedef int grn_thread_key; -#define THREAD_KEY_CREATE(key,destr) -#define THREAD_KEY_DELETE(key) -#define THREAD_SETSPECIFIC(key) -#define THREAD_GETSPECIFIC(key,value) +# define THREAD_KEY_CREATE(key,destr) +# define THREAD_KEY_DELETE(key) +# define THREAD_SETSPECIFIC(key) +# define THREAD_GETSPECIFIC(key,value) -#ifdef WIN32 +# ifdef WIN32 typedef uintptr_t grn_thread; -#define THREAD_CREATE(thread,func,arg) \ - (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == NULL) -#define THREAD_JOIN(thread) \ - (WaitForSingleObject((thread), INFINITE) == WAIT_FAILED) +typedef unsigned int grn_thread_func_result; +# define GRN_THREAD_FUNC_RETURN_VALUE 0 +# define THREAD_CREATE(thread,func,arg) \ + (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == (grn_thread)0) +# define THREAD_JOIN(thread) \ + (WaitForSingleObject((HANDLE)(thread), INFINITE) == WAIT_FAILED) typedef HANDLE grn_mutex; -#define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL)) -#define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE) -#define MUTEX_UNLOCK(m) ReleaseMutex(m) -#define MUTEX_FIN(m) CloseHandle(m) +# define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL)) +# define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE) +# define MUTEX_UNLOCK(m) ReleaseMutex(m) +# define MUTEX_FIN(m) CloseHandle(m) typedef CRITICAL_SECTION grn_critical_section; -#define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs)) -#define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs)) -#define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs)) -#define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs)) +# define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs)) +# define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs)) +# define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs)) +# define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs)) typedef struct { @@ -344,14 +365,14 @@ typedef struct size_t was_broadcast_; } grn_cond; -#define COND_INIT(c) do { \ +# define COND_INIT(c) do { \ (c).waiters_count_ = 0; \ (c).sema_ = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); \ MUTEX_INIT((c).waiters_count_lock_); \ (c).waiters_done_ = CreateEvent(NULL, FALSE, FALSE, NULL); \ } while (0) -#define COND_SIGNAL(c) do { \ +# define COND_SIGNAL(c) do { \ MUTEX_LOCK((c).waiters_count_lock_); \ { \ int have_waiters = (c).waiters_count_ > 0; \ @@ -362,7 +383,7 @@ typedef struct } \ } while (0) -#define COND_BROADCAST(c) do { \ +# define COND_BROADCAST(c) do { \ MUTEX_LOCK((c).waiters_count_lock_); \ { \ int have_waiters = (c).waiters_count_ > 0; \ @@ -382,7 +403,7 @@ typedef struct } \ } while (0) -#define COND_WAIT(c,m) do { \ +# define COND_WAIT(c,m) do { \ MUTEX_LOCK((c).waiters_count_lock_); \ (c).waiters_count_++; \ MUTEX_UNLOCK((c).waiters_count_lock_); \ @@ -401,24 +422,24 @@ typedef struct } \ } while (0) -#else /* WIN32 */ +# else /* WIN32 */ /* todo */ typedef int grn_cond; -#define COND_INIT(c) ((c) = 0) -#define COND_SIGNAL(c) -#define COND_WAIT(c,m) do { \ +# define COND_INIT(c) ((c) = 0) +# define COND_SIGNAL(c) +# define COND_WAIT(c,m) do { \ MUTEX_UNLOCK(m); \ grn_nanosleep(1000000); \ MUTEX_LOCK(m); \ } while (0) /* todo : must be enhanced! */ -#endif /* WIN32 */ +# endif /* WIN32 */ -#define MUTEX_INIT_SHARED MUTEX_INIT -#define COND_INIT_SHARED COND_INIT +# define MUTEX_INIT_SHARED MUTEX_INIT +# define COND_INIT_SHARED COND_INIT -#define GRN_TEST_YIELD() do {} while (0) +# define GRN_TEST_YIELD() do {} while (0) #endif /* HAVE_PTHREAD_H */ @@ -429,16 +450,12 @@ typedef int grn_cond; # define GRN_FMT_INT32U PRIu32 # define GRN_FMT_INT64D PRId64 # define GRN_FMT_INT64U PRIu64 -# define GRN_FMT_LLD "lld" -# define GRN_FMT_LLU "llu" #else /* HAVE_INTTYPES_H */ # ifdef WIN32 # define GRN_FMT_INT32D "I32d" # define GRN_FMT_INT32U "I32u" # define GRN_FMT_INT64D "I64d" # define GRN_FMT_INT64U "I64u" -# define GRN_FMT_LLD "I64d" -# define GRN_FMT_LLU "I64u" # else /* WIN32 */ # define GRN_FMT_INT32D "d" # define GRN_FMT_INT32U "u" @@ -449,11 +466,27 @@ typedef int grn_cond; # define GRN_FMT_INT64D "lld" # define GRN_FMT_INT64U "llu" # endif /* __x86_64__ */ -# define GRN_FMT_LLD "lld" -# define GRN_FMT_LLU "llu" # endif /* WIN32 */ #endif /* HAVE_INTTYPES_H */ +#ifdef WIN32 +# define GRN_FMT_LLD "I64d" +# define GRN_FMT_LLU "I64u" +# define GRN_FMT_SIZE "Iu" +# define GRN_FMT_SSIZE "Id" +# ifdef WIN64 +# define GRN_FMT_SOCKET GRN_FMT_INT64U +# else /* WIN64 */ +# define GRN_FMT_SOCKET "u" +# endif /* WIN64 */ +#else /* WIN32 */ +# define GRN_FMT_LLD "lld" +# define GRN_FMT_LLU "llu" +# define GRN_FMT_SIZE "zu" +# define GRN_FMT_SSIZE "zd" +# define GRN_FMT_SOCKET "d" +#endif /* WIN32 */ + #ifdef __GNUC__ # if (defined(__i386__) || defined(__x86_64__)) /* ATOMIC ADD */ /* @@ -486,6 +519,11 @@ typedef int grn_cond; /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) +# elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ +# define GRN_ATOMIC_ADD_EX(p,i,r) \ + (r = __atomic_fetch_add(p, i, __ATOMIC_SEQ_CST)) +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) # else /* ATOMIC ADD */ /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) @@ -505,13 +543,17 @@ typedef int grn_cond; # elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ # define GRN_SET_64BIT(p,v) \ __atomic_store_n(p, v, __ATOMIC_SEQ_CST) +# else +# warning Need atomic 64bit operation support. The current implementation may break data. +# define GRN_SET_64BIT(p,v) \ + (*(p) = (v)) # endif /* ATOMIC 64BIT SET */ # ifdef HAVE_MKOSTEMP # define GRN_MKOSTEMP(template,flags,mode) mkostemp(template,flags) # else /* HAVE_MKOSTEMP */ # define GRN_MKOSTEMP(template,flags,mode) \ - (mktemp(template), GRN_OPEN((template),flags,mode)) + (mktemp(template), GRN_OPEN((template),((flags)|O_RDWR|O_CREAT|O_EXCL),mode)) # endif /* HAVE_MKOSTEMP */ #elif (defined(WIN32) || defined (_WIN64)) /* __GNUC__ */ @@ -544,7 +586,7 @@ typedef int grn_cond; # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) # define GRN_MKOSTEMP(template,flags,mode) \ - (mktemp(template), GRN_OPEN((template),((flags)|O_BINARY),mode)) + (mktemp(template), GRN_OPEN((template),((flags)|O_RDWR|O_CREAT),mode)) #else /* __GNUC__ */ @@ -554,9 +596,6 @@ typedef int grn_cond; # define GRN_ATOMIC_ADD_EX(p,i,r) \ (r = atomic_add_32_nv(p, i) - i) /* todo */ -# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) -# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) -/* todo */ # define GRN_SET_64BIT(p,v) \ (void)atomic_swap_64(p, v) # endif /* ATOMIC ADD */ @@ -739,8 +778,6 @@ grn_str_greater(const uint8_t *ap, uint32_t as, const uint8_t *bp, uint32_t bs) GRN_API void grn_sleep(uint32_t seconds); GRN_API void grn_nanosleep(uint64_t nanoseconds); -#ifndef GROONGA_H -# include "groonga.h" -#endif /* GROONGA_H */ +#include <groonga.h> -#endif /* GROONGA_IN_H */ +#endif /* GRN_H */ diff --git a/storage/mroonga/vendor/groonga/lib/com.h b/storage/mroonga/vendor/groonga/lib/grn_com.h index c0690ccfe76..203ed56c88d 100644 --- a/storage/mroonga/vendor/groonga/lib/com.h +++ b/storage/mroonga/vendor/groonga/lib/grn_com.h @@ -18,17 +18,9 @@ #ifndef GRN_COM_H #define GRN_COM_H -#ifndef GROONGA_H -#include "groonga_in.h" -#endif /* GROONGA_H */ - -#ifndef GRN_STR_H -#include "str.h" -#endif /* GRN_STR_H */ - -#ifndef GRN_HASH_H -#include "hash.h" -#endif /* GRN_HASH_H */ +#include "grn.h" +#include "grn_str.h" +#include "grn_hash.h" #ifdef HAVE_NETDB_H #include <netdb.h> diff --git a/storage/mroonga/vendor/groonga/lib/ctx.h b/storage/mroonga/vendor/groonga/lib/grn_ctx.h index 656abfa94b9..dbf461e668e 100644 --- a/storage/mroonga/vendor/groonga/lib/ctx.h +++ b/storage/mroonga/vendor/groonga/lib/grn_ctx.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -18,13 +18,10 @@ #ifndef GRN_CTX_H #define GRN_CTX_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#include "grn.h" +#include "grn_error.h" -#ifdef HAVE_ERRNO_H #include <errno.h> -#endif /* HAVE_ERRNO_H */ #ifdef HAVE_SIGNAL_H #include <signal.h> @@ -35,9 +32,7 @@ #include <execinfo.h> #endif /* HAVE_EXECINFO_H */ -#ifndef GRN_IO_H -#include "io.h" -#endif /* GRN_IO_H */ +#include "grn_io.h" #ifdef __cplusplus extern "C" { @@ -157,8 +152,104 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx); } while (0) #ifdef WIN32 + +#define SYSTEM_ERROR_MESSAGE_BUFFER_SIZE 1024 #define SERR(str) do {\ grn_rc rc;\ + const char *system_message;\ + int error = GetLastError();\ + system_message = grn_current_error_message();\ + switch (error) {\ + case ERROR_FILE_NOT_FOUND :\ + case ERROR_PATH_NOT_FOUND :\ + rc = GRN_NO_SUCH_FILE_OR_DIRECTORY;\ + break;\ + case ERROR_TOO_MANY_OPEN_FILES :\ + rc = GRN_TOO_MANY_OPEN_FILES;\ + break;\ + case ERROR_ACCESS_DENIED :\ + rc = GRN_PERMISSION_DENIED;\ + break;\ + case ERROR_INVALID_HANDLE :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_ARENA_TRASHED :\ + rc = GRN_ADDRESS_IS_NOT_AVAILABLE;\ + break;\ + case ERROR_NOT_ENOUGH_MEMORY :\ + rc = GRN_NO_MEMORY_AVAILABLE;\ + break;\ + case ERROR_INVALID_BLOCK :\ + case ERROR_BAD_ENVIRONMENT :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_BAD_FORMAT :\ + rc = GRN_INVALID_FORMAT;\ + break;\ + case ERROR_INVALID_DATA :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_OUTOFMEMORY :\ + rc = GRN_NO_MEMORY_AVAILABLE;\ + break;\ + case ERROR_INVALID_DRIVE :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_WRITE_PROTECT :\ + rc = GRN_PERMISSION_DENIED;\ + break;\ + case ERROR_BAD_LENGTH :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_SEEK :\ + rc = GRN_INVALID_SEEK;\ + break;\ + case ERROR_NOT_SUPPORTED :\ + rc = GRN_OPERATION_NOT_SUPPORTED;\ + break;\ + case ERROR_NETWORK_ACCESS_DENIED :\ + rc = GRN_OPERATION_NOT_PERMITTED;\ + break;\ + case ERROR_FILE_EXISTS :\ + rc = GRN_FILE_EXISTS;\ + break;\ + case ERROR_INVALID_PARAMETER :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_BROKEN_PIPE :\ + rc = GRN_BROKEN_PIPE;\ + break;\ + case ERROR_CALL_NOT_IMPLEMENTED :\ + rc = GRN_FUNCTION_NOT_IMPLEMENTED;\ + break;\ + case ERROR_INVALID_NAME :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_BUSY_DRIVE :\ + case ERROR_PATH_BUSY :\ + rc = GRN_RESOURCE_BUSY;\ + break;\ + case ERROR_BAD_ARGUMENTS :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + case ERROR_BUSY :\ + rc = GRN_RESOURCE_BUSY;\ + break;\ + case ERROR_ALREADY_EXISTS :\ + rc = GRN_FILE_EXISTS;\ + break;\ + case ERROR_BAD_EXE_FORMAT :\ + rc = GRN_EXEC_FORMAT_ERROR;\ + break;\ + default:\ + rc = GRN_UNKNOWN_ERROR;\ + break;\ + }\ + ERR(rc, "syscall error '%s' (%s)[%d]", str, system_message, error);\ +} while (0) + +#define SOERR(str) do {\ + grn_rc rc;\ const char *m;\ int e = WSAGetLastError();\ switch (e) {\ @@ -235,12 +326,16 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx); m = "unknown error";\ break;\ }\ - ERR(rc, "syscall error '%s' (%s)", str, m);\ + ERR(rc, "socket error '%s' (%s)[%d]", str, m, e);\ } while (0) + #else /* WIN32 */ #define SERR(str) do {\ grn_rc rc;\ - switch (errno) {\ + int errno_keep = errno;\ + grn_bool show_errno = GRN_FALSE;\ + const char *system_message = grn_current_error_message();\ + switch (errno_keep) {\ case ELOOP : rc = GRN_TOO_MANY_SYMBOLIC_LINKS; break;\ case ENAMETOOLONG : rc = GRN_FILENAME_TOO_LONG; break;\ case ENOENT : rc = GRN_NO_SUCH_FILE_OR_DIRECTORY; break;\ @@ -286,10 +381,20 @@ GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx); case ETIMEDOUT : rc = GRN_OPERATION_TIMEOUT; break;\ case ECONNREFUSED: rc = GRN_CONNECTION_REFUSED; break;\ case EAGAIN: rc = GRN_OPERATION_WOULD_BLOCK; break;\ - default : rc = GRN_UNKNOWN_ERROR; break;\ + default :\ + rc = GRN_UNKNOWN_ERROR;\ + show_errno = GRN_TRUE;\ + break;\ + }\ + if (show_errno) {\ + ERR(rc, "syscall error '%s' (%s)[%d]", str, system_message, errno_keep); \ + } else {\ + ERR(rc, "syscall error '%s' (%s)", str, system_message);\ }\ - ERR(rc, "syscall error '%s' (%s)", str, strerror(errno));\ } while (0) + +#define SOERR(str) SERR(str) + #endif /* WIN32 */ #define GERR(rc,...) ERRSET(&grn_gctx, GRN_ERROR, (rc), __VA_ARGS__) @@ -453,6 +558,9 @@ typedef struct { uint8_t subrec_offset; uint8_t record_unit; uint8_t subrec_unit; + union { + grn_table_group_flags group; + } flags; // grn_obj_flags flags; } grn_db_obj; diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl.h b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h index 33f1402e6e1..9e0b5677497 100644 --- a/storage/mroonga/vendor/groonga/lib/ctx_impl.h +++ b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,11 +19,11 @@ #define GRN_CTX_IMPL_H #ifndef GRN_CTX_H -#include "ctx.h" +#include "grn_ctx.h" #endif /* GRN_CTX_H */ #ifndef GRN_COM_H -#include "com.h" +#include "grn_com.h" #endif /* GRN_COM_H */ #ifdef GRN_WITH_MESSAGE_PACK @@ -88,6 +88,9 @@ struct _grn_alloc_info int freed; char alloc_backtrace[4096]; char free_backtrace[4096]; + char *file; + int line; + char *func; grn_alloc_info *next; }; #endif @@ -96,8 +99,18 @@ struct _grn_alloc_info typedef struct _grn_mrb_data grn_mrb_data; struct _grn_mrb_data { mrb_state *state; + char base_directory[PATH_MAX]; struct RClass *module; struct RClass *object_class; + grn_hash *checked_procs; + grn_hash *registered_plugins; + struct { + grn_obj from; + grn_obj to; + } buffer; + struct { + struct RClass *time_class; + } builtin; }; #endif diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.h b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h index 6810d1fc097..61cf088b2ae 100644 --- a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.h +++ b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h @@ -19,8 +19,8 @@ #ifndef GRN_CTX_IMPL_MRB_H #define GRN_CTX_IMPL_MRB_H -#include "groonga_in.h" -#include "ctx.h" +#include "grn.h" +#include "grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/dat.h b/storage/mroonga/vendor/groonga/lib/grn_dat.h index d0c44b7035d..aefd044d0b7 100644 --- a/storage/mroonga/vendor/groonga/lib/dat.h +++ b/storage/mroonga/vendor/groonga/lib/grn_dat.h @@ -17,11 +17,11 @@ #ifndef GRN_DAT_H #define GRN_DAT_H -#ifndef GROONGA_IN_H -# include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#ifndef GRN_H +# include "grn.h" +#endif /* GRN_H */ -#include "db.h" +#include "grn_db.h" #ifdef __cplusplus extern "C" { @@ -58,20 +58,6 @@ struct _grn_dat_cursor { grn_id curr_rec; }; -typedef struct _grn_dat_scan_hit grn_dat_scan_hit; - -struct _grn_dat_scan_hit { - grn_id id; - unsigned int offset; - unsigned int length; -}; - -GRN_API int grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str, - unsigned int str_size, grn_dat_scan_hit *scan_hits, - unsigned int max_num_scan_hits, const char **str_rest); -GRN_API grn_id grn_dat_lcp_search(grn_ctx *ctx, grn_dat *dat, - const void *key, unsigned int key_size); - GRN_API grn_id grn_dat_curr_id(grn_ctx *ctx, grn_dat *dat); /* diff --git a/storage/mroonga/vendor/groonga/lib/db.h b/storage/mroonga/vendor/groonga/lib/grn_db.h index f2f95560b08..0eeab145e0e 100644 --- a/storage/mroonga/vendor/groonga/lib/db.h +++ b/storage/mroonga/vendor/groonga/lib/grn_db.h @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2013 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -17,19 +17,14 @@ #ifndef GRN_DB_H #define GRN_DB_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef GRN_STORE_H -#include "store.h" -#endif /* GRN_STORE_H */ +#include "grn.h" +#include "grn_ctx.h" +#include "grn_store.h" +#include "grn_rset.h" +#include <groonga/command.h> #include <groonga/token_filter.h> +#include <groonga/scorer.h> #ifdef __cplusplus extern "C" { @@ -40,30 +35,6 @@ extern "C" { #define GRN_N_RESERVED_TYPES 256 -typedef struct { - int score; - int n_subrecs; - int subrecs[1]; -} grn_rset_recinfo; - -typedef struct { - grn_id rid; - uint32_t sid; - uint32_t pos; -} grn_rset_posinfo; - -#define GRN_RSET_UTIL_BIT (0x80000000) - -#define GRN_RSET_SCORE_SIZE (sizeof(int)) - -#define GRN_RSET_N_SUBRECS(ri) ((ri)->n_subrecs & ~GRN_RSET_UTIL_BIT) - -#define GRN_RSET_SUBRECS_CMP(a,b,dir) (((a) - (b))*(dir)) -#define GRN_RSET_SUBRECS_NTH(subrecs,size,n) \ - ((int *)((byte *)subrecs + n * (GRN_RSET_SCORE_SIZE + size))) -#define GRN_RSET_SUBRECS_COPY(subrecs,size,n,src) \ - (memcpy(GRN_RSET_SUBRECS_NTH(subrecs, size, n), src, GRN_RSET_SCORE_SIZE + size)) - #define GRN_JSON_LOAD_OPEN_BRACKET 0x40000000 #define GRN_JSON_LOAD_OPEN_BRACE 0x40000001 @@ -113,7 +84,7 @@ int grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk); grn_table_cursor *grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table, grn_id min, grn_id max, int flags); -void grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, int score, +void grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score, grn_rset_posinfo *pi, int dir); grn_obj *grn_obj_graft(grn_ctx *ctx, grn_obj *obj); @@ -189,10 +160,16 @@ struct _grn_proc { union { struct { + grn_command_run_func *run; + } command; + struct { grn_token_filter_init_func *init; grn_token_filter_filter_func *filter; grn_token_filter_fin_func *fin; } token_filter; + struct { + grn_scorer_score_func *score; + } scorer; } callbacks; void *user_data; @@ -203,11 +180,14 @@ struct _grn_proc { // grn_obj results[16]; }; +#define GRN_PROC_GET_VARS() (grn_proc_get_vars(ctx, user_data)) #define GRN_PROC_GET_VAR(name) (grn_proc_get_var(ctx, user_data, name, strlen(name))) #define GRN_PROC_GET_VAR_BY_OFFSET(offset) (grn_proc_get_var_by_offset(ctx, user_data, offset)) #define GRN_PROC_GET_OR_ADD_VAR(name) (grn_proc_get_or_add_var(ctx, user_data, name, strlen(name))) #define GRN_PROC_ALLOC(domain, flags) (grn_proc_alloc(ctx, user_data, domain, flags)) +grn_obj *grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data); + grn_obj *grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, unsigned int name_size); @@ -245,6 +225,10 @@ enum { GRN_ACCESSOR_GET_VALUE, GRN_ACCESSOR_GET_SCORE, GRN_ACCESSOR_GET_NSUBRECS, + GRN_ACCESSOR_GET_MAX, + GRN_ACCESSOR_GET_MIN, + GRN_ACCESSOR_GET_SUM, + GRN_ACCESSOR_GET_AVG, GRN_ACCESSOR_GET_COLUMN_VALUE, GRN_ACCESSOR_GET_DB_OBJ, GRN_ACCESSOR_LOOKUP, @@ -329,8 +313,6 @@ struct _grn_expr { grn_expr_code *code0; }; -GRN_API grn_rc grn_expr_clear_vars(grn_ctx *ctx, grn_obj *expr); - grn_rc grn_expr_parser_close(grn_ctx *ctx); GRN_API grn_rc grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_bool addp); @@ -451,6 +433,7 @@ grn_rc grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj); void grn_expr_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *expr); GRN_API grn_rc grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr); +grn_hash *grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars); grn_obj *grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe); GRN_API void grn_load_(grn_ctx *ctx, grn_content_type input_type, diff --git a/storage/mroonga/vendor/groonga/lib/ecmascript.c b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c index e973f1281a4..80c596bc6b3 100644 --- a/storage/mroonga/vendor/groonga/lib/ecmascript.c +++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c @@ -4,10 +4,10 @@ /* First off, code is included that follows the "include" declaration ** in the input grammar file. */ #include <stdio.h> -#line 4 "ecmascript.lemon" +#line 4 "grn_ecmascript.lemon" #define assert GRN_ASSERT -#line 11 "ecmascript.c" +#line 11 "grn_ecmascript.c" /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ @@ -867,11 +867,11 @@ static void yy_destructor( */ case 74: /* suppress_unused_variable_warning */ { -#line 11 "ecmascript.lemon" +#line 11 "grn_ecmascript.lemon" (void)efsi; -#line 875 "ecmascript.c" +#line 875 "grn_ecmascript.c" } break; default: break; /* If no destructor action specified: do nothing */ @@ -1295,46 +1295,46 @@ static void yy_reduce( ** break; */ case 5: /* query ::= query query_element */ -#line 46 "ecmascript.lemon" +#line 46 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, grn_int32_value_at(&efsi->op_stack, -1), 2); } -#line 1303 "ecmascript.c" +#line 1303 "grn_ecmascript.c" break; case 6: /* query ::= query LOGICAL_AND query_element */ case 35: /* logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression */ yytestcase(yyruleno==35); -#line 49 "ecmascript.lemon" +#line 49 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2); } -#line 1311 "ecmascript.c" +#line 1311 "grn_ecmascript.c" break; case 7: /* query ::= query LOGICAL_AND_NOT query_element */ case 36: /* logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression */ yytestcase(yyruleno==36); -#line 52 "ecmascript.lemon" +#line 52 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2); } -#line 1319 "ecmascript.c" +#line 1319 "grn_ecmascript.c" break; case 8: /* query ::= query LOGICAL_OR query_element */ case 33: /* logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression */ yytestcase(yyruleno==33); -#line 55 "ecmascript.lemon" +#line 55 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2); } -#line 1327 "ecmascript.c" +#line 1327 "grn_ecmascript.c" break; case 11: /* query_element ::= RELATIVE_OP query_element */ -#line 62 "ecmascript.lemon" +#line 62 "grn_ecmascript.lemon" { int mode; GRN_INT32_POP(&efsi->mode_stack, mode); } -#line 1335 "ecmascript.c" +#line 1335 "grn_ecmascript.c" break; case 12: /* query_element ::= IDENTIFIER RELATIVE_OP query_element */ -#line 66 "ecmascript.lemon" +#line 66 "grn_ecmascript.lemon" { int mode; grn_obj *c; @@ -1358,310 +1358,310 @@ static void yy_reduce( break; } } -#line 1362 "ecmascript.c" +#line 1362 "grn_ecmascript.c" break; case 13: /* query_element ::= BRACEL expression BRACER */ case 14: /* query_element ::= EVAL primary_expression */ yytestcase(yyruleno==14); -#line 89 "ecmascript.lemon" +#line 89 "grn_ecmascript.lemon" { efsi->flags = efsi->default_flags; } -#line 1370 "ecmascript.c" +#line 1370 "grn_ecmascript.c" break; case 16: /* expression ::= expression COMMA assignment_expression */ -#line 97 "ecmascript.lemon" +#line 97 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); } -#line 1377 "ecmascript.c" +#line 1377 "grn_ecmascript.c" break; case 18: /* assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression */ -#line 102 "ecmascript.lemon" +#line 102 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ASSIGN, 2); } -#line 1384 "ecmascript.c" +#line 1384 "grn_ecmascript.c" break; case 19: /* assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression */ -#line 105 "ecmascript.lemon" +#line 105 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR_ASSIGN, 2); } -#line 1391 "ecmascript.c" +#line 1391 "grn_ecmascript.c" break; case 20: /* assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression */ -#line 108 "ecmascript.lemon" +#line 108 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH_ASSIGN, 2); } -#line 1398 "ecmascript.c" +#line 1398 "grn_ecmascript.c" break; case 21: /* assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression */ -#line 111 "ecmascript.lemon" +#line 111 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD_ASSIGN, 2); } -#line 1405 "ecmascript.c" +#line 1405 "grn_ecmascript.c" break; case 22: /* assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression */ -#line 114 "ecmascript.lemon" +#line 114 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS_ASSIGN, 2); } -#line 1412 "ecmascript.c" +#line 1412 "grn_ecmascript.c" break; case 23: /* assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression */ -#line 117 "ecmascript.lemon" +#line 117 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS_ASSIGN, 2); } -#line 1419 "ecmascript.c" +#line 1419 "grn_ecmascript.c" break; case 24: /* assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression */ -#line 120 "ecmascript.lemon" +#line 120 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL_ASSIGN, 2); } -#line 1426 "ecmascript.c" +#line 1426 "grn_ecmascript.c" break; case 25: /* assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression */ -#line 123 "ecmascript.lemon" +#line 123 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR_ASSIGN, 2); } -#line 1433 "ecmascript.c" +#line 1433 "grn_ecmascript.c" break; case 26: /* assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression */ -#line 126 "ecmascript.lemon" +#line 126 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR_ASSIGN, 2); } -#line 1440 "ecmascript.c" +#line 1440 "grn_ecmascript.c" break; case 27: /* assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression */ -#line 129 "ecmascript.lemon" +#line 129 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_ASSIGN, 2); } -#line 1447 "ecmascript.c" +#line 1447 "grn_ecmascript.c" break; case 28: /* assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression */ -#line 132 "ecmascript.lemon" +#line 132 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_XOR_ASSIGN, 2); } -#line 1454 "ecmascript.c" +#line 1454 "grn_ecmascript.c" break; case 29: /* assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression */ -#line 135 "ecmascript.lemon" +#line 135 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR_ASSIGN, 2); } -#line 1461 "ecmascript.c" +#line 1461 "grn_ecmascript.c" break; case 31: /* conditional_expression ::= logical_or_expression QUESTION assignment_expression COLON assignment_expression */ -#line 140 "ecmascript.lemon" +#line 140 "grn_ecmascript.lemon" { grn_expr *e = (grn_expr *)efsi->e; e->codes[yymsp[-3].minor.yy0].nargs = yymsp[-1].minor.yy0 - yymsp[-3].minor.yy0; e->codes[yymsp[-1].minor.yy0].nargs = e->codes_curr - yymsp[-1].minor.yy0 - 1; } -#line 1470 "ecmascript.c" +#line 1470 "grn_ecmascript.c" break; case 38: /* bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression */ -#line 160 "ecmascript.lemon" +#line 160 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_OR, 2); } -#line 1477 "ecmascript.c" +#line 1477 "grn_ecmascript.c" break; case 40: /* bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression */ -#line 165 "ecmascript.lemon" +#line 165 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_XOR, 2); } -#line 1484 "ecmascript.c" +#line 1484 "grn_ecmascript.c" break; case 42: /* bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression */ -#line 170 "ecmascript.lemon" +#line 170 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_AND, 2); } -#line 1491 "ecmascript.c" +#line 1491 "grn_ecmascript.c" break; case 44: /* equality_expression ::= equality_expression EQUAL relational_expression */ -#line 175 "ecmascript.lemon" +#line 175 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EQUAL, 2); } -#line 1498 "ecmascript.c" +#line 1498 "grn_ecmascript.c" break; case 45: /* equality_expression ::= equality_expression NOT_EQUAL relational_expression */ -#line 178 "ecmascript.lemon" +#line 178 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT_EQUAL, 2); } -#line 1505 "ecmascript.c" +#line 1505 "grn_ecmascript.c" break; case 47: /* relational_expression ::= relational_expression LESS shift_expression */ -#line 183 "ecmascript.lemon" +#line 183 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS, 2); } -#line 1512 "ecmascript.c" +#line 1512 "grn_ecmascript.c" break; case 48: /* relational_expression ::= relational_expression GREATER shift_expression */ -#line 186 "ecmascript.lemon" +#line 186 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER, 2); } -#line 1519 "ecmascript.c" +#line 1519 "grn_ecmascript.c" break; case 49: /* relational_expression ::= relational_expression LESS_EQUAL shift_expression */ -#line 189 "ecmascript.lemon" +#line 189 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS_EQUAL, 2); } -#line 1526 "ecmascript.c" +#line 1526 "grn_ecmascript.c" break; case 50: /* relational_expression ::= relational_expression GREATER_EQUAL shift_expression */ -#line 192 "ecmascript.lemon" +#line 192 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER_EQUAL, 2); } -#line 1533 "ecmascript.c" +#line 1533 "grn_ecmascript.c" break; case 51: /* relational_expression ::= relational_expression IN shift_expression */ -#line 195 "ecmascript.lemon" +#line 195 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_IN, 2); } -#line 1540 "ecmascript.c" +#line 1540 "grn_ecmascript.c" break; case 52: /* relational_expression ::= relational_expression MATCH shift_expression */ case 130: /* adjust_match_expression ::= IDENTIFIER MATCH STRING */ yytestcase(yyruleno==130); -#line 198 "ecmascript.lemon" +#line 198 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2); } -#line 1548 "ecmascript.c" +#line 1548 "grn_ecmascript.c" break; case 53: /* relational_expression ::= relational_expression NEAR shift_expression */ -#line 201 "ecmascript.lemon" +#line 201 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR, 2); } -#line 1555 "ecmascript.c" +#line 1555 "grn_ecmascript.c" break; case 54: /* relational_expression ::= relational_expression NEAR2 shift_expression */ -#line 204 "ecmascript.lemon" +#line 204 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR2, 2); } -#line 1562 "ecmascript.c" +#line 1562 "grn_ecmascript.c" break; case 55: /* relational_expression ::= relational_expression SIMILAR shift_expression */ -#line 207 "ecmascript.lemon" +#line 207 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SIMILAR, 2); } -#line 1569 "ecmascript.c" +#line 1569 "grn_ecmascript.c" break; case 56: /* relational_expression ::= relational_expression TERM_EXTRACT shift_expression */ -#line 210 "ecmascript.lemon" +#line 210 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_TERM_EXTRACT, 2); } -#line 1576 "ecmascript.c" +#line 1576 "grn_ecmascript.c" break; case 57: /* relational_expression ::= relational_expression LCP shift_expression */ -#line 213 "ecmascript.lemon" +#line 213 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LCP, 2); } -#line 1583 "ecmascript.c" +#line 1583 "grn_ecmascript.c" break; case 58: /* relational_expression ::= relational_expression PREFIX shift_expression */ -#line 216 "ecmascript.lemon" +#line 216 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PREFIX, 2); } -#line 1590 "ecmascript.c" +#line 1590 "grn_ecmascript.c" break; case 59: /* relational_expression ::= relational_expression SUFFIX shift_expression */ -#line 219 "ecmascript.lemon" +#line 219 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SUFFIX, 2); } -#line 1597 "ecmascript.c" +#line 1597 "grn_ecmascript.c" break; case 61: /* shift_expression ::= shift_expression SHIFTL additive_expression */ -#line 224 "ecmascript.lemon" +#line 224 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL, 2); } -#line 1604 "ecmascript.c" +#line 1604 "grn_ecmascript.c" break; case 62: /* shift_expression ::= shift_expression SHIFTR additive_expression */ -#line 227 "ecmascript.lemon" +#line 227 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR, 2); } -#line 1611 "ecmascript.c" +#line 1611 "grn_ecmascript.c" break; case 63: /* shift_expression ::= shift_expression SHIFTRR additive_expression */ -#line 230 "ecmascript.lemon" +#line 230 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR, 2); } -#line 1618 "ecmascript.c" +#line 1618 "grn_ecmascript.c" break; case 65: /* additive_expression ::= additive_expression PLUS multiplicative_expression */ case 127: /* adjuster ::= adjuster PLUS adjust_expression */ yytestcase(yyruleno==127); -#line 235 "ecmascript.lemon" +#line 235 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2); } -#line 1626 "ecmascript.c" +#line 1626 "grn_ecmascript.c" break; case 66: /* additive_expression ::= additive_expression MINUS multiplicative_expression */ -#line 238 "ecmascript.lemon" +#line 238 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 2); } -#line 1633 "ecmascript.c" +#line 1633 "grn_ecmascript.c" break; case 68: /* multiplicative_expression ::= multiplicative_expression STAR unary_expression */ case 129: /* adjust_expression ::= adjust_match_expression STAR DECIMAL */ yytestcase(yyruleno==129); -#line 243 "ecmascript.lemon" +#line 243 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2); } -#line 1641 "ecmascript.c" +#line 1641 "grn_ecmascript.c" break; case 69: /* multiplicative_expression ::= multiplicative_expression SLASH unary_expression */ -#line 246 "ecmascript.lemon" +#line 246 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH, 2); } -#line 1648 "ecmascript.c" +#line 1648 "grn_ecmascript.c" break; case 70: /* multiplicative_expression ::= multiplicative_expression MOD unary_expression */ -#line 249 "ecmascript.lemon" +#line 249 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD, 2); } -#line 1655 "ecmascript.c" +#line 1655 "grn_ecmascript.c" break; case 72: /* unary_expression ::= DELETE unary_expression */ -#line 254 "ecmascript.lemon" +#line 254 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DELETE, 1); } -#line 1662 "ecmascript.c" +#line 1662 "grn_ecmascript.c" break; case 73: /* unary_expression ::= INCR unary_expression */ -#line 257 "ecmascript.lemon" +#line 257 "grn_ecmascript.lemon" { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); @@ -1679,10 +1679,10 @@ static void yy_reduce( grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR, 1); } } -#line 1683 "ecmascript.c" +#line 1683 "grn_ecmascript.c" break; case 74: /* unary_expression ::= DECR unary_expression */ -#line 274 "ecmascript.lemon" +#line 274 "grn_ecmascript.lemon" { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); @@ -1700,66 +1700,66 @@ static void yy_reduce( grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR, 1); } } -#line 1704 "ecmascript.c" +#line 1704 "grn_ecmascript.c" break; case 75: /* unary_expression ::= PLUS unary_expression */ -#line 291 "ecmascript.lemon" +#line 291 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 1); } -#line 1711 "ecmascript.c" +#line 1711 "grn_ecmascript.c" break; case 76: /* unary_expression ::= MINUS unary_expression */ -#line 294 "ecmascript.lemon" +#line 294 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 1); } -#line 1718 "ecmascript.c" +#line 1718 "grn_ecmascript.c" break; case 77: /* unary_expression ::= NOT unary_expression */ -#line 297 "ecmascript.lemon" +#line 297 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT, 1); } -#line 1725 "ecmascript.c" +#line 1725 "grn_ecmascript.c" break; case 78: /* unary_expression ::= BITWISE_NOT unary_expression */ -#line 300 "ecmascript.lemon" +#line 300 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_NOT, 1); } -#line 1732 "ecmascript.c" +#line 1732 "grn_ecmascript.c" break; case 79: /* unary_expression ::= ADJUST unary_expression */ -#line 303 "ecmascript.lemon" +#line 303 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 1); } -#line 1739 "ecmascript.c" +#line 1739 "grn_ecmascript.c" break; case 80: /* unary_expression ::= EXACT unary_expression */ -#line 306 "ecmascript.lemon" +#line 306 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EXACT, 1); } -#line 1746 "ecmascript.c" +#line 1746 "grn_ecmascript.c" break; case 81: /* unary_expression ::= PARTIAL unary_expression */ -#line 309 "ecmascript.lemon" +#line 309 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PARTIAL, 1); } -#line 1753 "ecmascript.c" +#line 1753 "grn_ecmascript.c" break; case 82: /* unary_expression ::= UNSPLIT unary_expression */ -#line 312 "ecmascript.lemon" +#line 312 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_UNSPLIT, 1); } -#line 1760 "ecmascript.c" +#line 1760 "grn_ecmascript.c" break; case 84: /* postfix_expression ::= lefthand_side_expression INCR */ -#line 317 "ecmascript.lemon" +#line 317 "grn_ecmascript.lemon" { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); @@ -1777,10 +1777,10 @@ static void yy_reduce( grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR_POST, 1); } } -#line 1781 "ecmascript.c" +#line 1781 "grn_ecmascript.c" break; case 85: /* postfix_expression ::= lefthand_side_expression DECR */ -#line 334 "ecmascript.lemon" +#line 334 "grn_ecmascript.lemon" { grn_ctx *ctx = efsi->ctx; grn_expr *e = (grn_expr *)(efsi->e); @@ -1798,51 +1798,51 @@ static void yy_reduce( grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR_POST, 1); } } -#line 1802 "ecmascript.c" +#line 1802 "grn_ecmascript.c" break; case 88: /* call_expression ::= member_expression arguments */ -#line 355 "ecmascript.lemon" +#line 355 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_CALL, yymsp[0].minor.yy0); } -#line 1809 "ecmascript.c" +#line 1809 "grn_ecmascript.c" break; case 113: /* member_expression_part ::= BRACKETL expression BRACKETR */ -#line 391 "ecmascript.lemon" +#line 391 "grn_ecmascript.lemon" { grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GET_MEMBER, 2); } -#line 1816 "ecmascript.c" +#line 1816 "grn_ecmascript.c" break; case 115: /* arguments ::= PARENL argument_list PARENR */ -#line 396 "ecmascript.lemon" +#line 396 "grn_ecmascript.lemon" { yygotominor.yy0 = yymsp[-1].minor.yy0; } -#line 1821 "ecmascript.c" +#line 1821 "grn_ecmascript.c" break; case 116: /* argument_list ::= */ -#line 397 "ecmascript.lemon" +#line 397 "grn_ecmascript.lemon" { yygotominor.yy0 = 0; } -#line 1826 "ecmascript.c" +#line 1826 "grn_ecmascript.c" break; case 117: /* argument_list ::= assignment_expression */ -#line 398 "ecmascript.lemon" +#line 398 "grn_ecmascript.lemon" { yygotominor.yy0 = 1; } -#line 1831 "ecmascript.c" +#line 1831 "grn_ecmascript.c" break; case 118: /* argument_list ::= argument_list COMMA assignment_expression */ -#line 399 "ecmascript.lemon" +#line 399 "grn_ecmascript.lemon" { yygotominor.yy0 = yymsp[-2].minor.yy0 + 1; } -#line 1836 "ecmascript.c" +#line 1836 "grn_ecmascript.c" break; case 119: /* output_columns ::= */ -#line 401 "ecmascript.lemon" +#line 401 "grn_ecmascript.lemon" { yygotominor.yy0 = 0; } -#line 1843 "ecmascript.c" +#line 1843 "grn_ecmascript.c" break; case 120: /* output_columns ::= output_column */ -#line 404 "ecmascript.lemon" +#line 404 "grn_ecmascript.lemon" { if (yymsp[0].minor.yy0) { yygotominor.yy0 = 0; @@ -1850,10 +1850,10 @@ static void yy_reduce( yygotominor.yy0 = 1; } } -#line 1854 "ecmascript.c" +#line 1854 "grn_ecmascript.c" break; case 121: /* output_columns ::= output_columns COMMA output_column */ -#line 412 "ecmascript.lemon" +#line 412 "grn_ecmascript.lemon" { if (yymsp[0].minor.yy0) { yygotominor.yy0 = yymsp[-2].minor.yy0; @@ -1864,10 +1864,10 @@ static void yy_reduce( yygotominor.yy0 = 1; } } -#line 1868 "ecmascript.c" +#line 1868 "grn_ecmascript.c" break; case 122: /* output_column ::= STAR */ -#line 423 "ecmascript.lemon" +#line 423 "grn_ecmascript.lemon" { grn_ctx *ctx = efsi->ctx; grn_obj *expr = efsi->e; @@ -1905,21 +1905,21 @@ static void yy_reduce( yygotominor.yy0 = GRN_TRUE; } } -#line 1909 "ecmascript.c" +#line 1909 "grn_ecmascript.c" break; case 123: /* output_column ::= NONEXISTENT_COLUMN */ -#line 460 "ecmascript.lemon" +#line 460 "grn_ecmascript.lemon" { yygotominor.yy0 = GRN_TRUE; } -#line 1916 "ecmascript.c" +#line 1916 "grn_ecmascript.c" break; case 124: /* output_column ::= assignment_expression */ -#line 463 "ecmascript.lemon" +#line 463 "grn_ecmascript.lemon" { yygotominor.yy0 = GRN_FALSE; } -#line 1923 "ecmascript.c" +#line 1923 "grn_ecmascript.c" break; default: /* (0) input ::= query */ yytestcase(yyruleno==0); @@ -2033,7 +2033,7 @@ static void yy_syntax_error( ){ grn_expr_parserARG_FETCH; #define TOKEN (yyminor.yy0) -#line 17 "ecmascript.lemon" +#line 17 "grn_ecmascript.lemon" { grn_ctx *ctx = efsi->ctx; @@ -2055,7 +2055,7 @@ static void yy_syntax_error( GRN_OBJ_FIN(ctx, &message); } } -#line 2059 "ecmascript.c" +#line 2059 "grn_ecmascript.c" grn_expr_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */ } diff --git a/storage/mroonga/vendor/groonga/lib/ecmascript.h b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h index c8e74b2fb8f..c8e74b2fb8f 100644 --- a/storage/mroonga/vendor/groonga/lib/ecmascript.h +++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h diff --git a/storage/mroonga/vendor/groonga/lib/ecmascript.lemon b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon index 322d7ac8264..322d7ac8264 100644 --- a/storage/mroonga/vendor/groonga/lib/ecmascript.lemon +++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon diff --git a/storage/mroonga/vendor/groonga/lib/error.h b/storage/mroonga/vendor/groonga/lib/grn_error.h index f425e4644f1..2581f934135 100644 --- a/storage/mroonga/vendor/groonga/lib/error.h +++ b/storage/mroonga/vendor/groonga/lib/grn_error.h @@ -18,15 +18,15 @@ #ifndef GRN_ERROR_H #define GRN_ERROR_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#ifndef GRN_H +#include "grn.h" +#endif /* GRN_H */ #ifdef __cplusplus extern "C" { #endif -const char *grn_current_error_message(void); +GRN_API const char *grn_current_error_message(void); #ifdef __cplusplus } diff --git a/storage/mroonga/vendor/groonga/lib/expr.h b/storage/mroonga/vendor/groonga/lib/grn_expr.h index 67e134e47b9..0a21f72bb92 100644 --- a/storage/mroonga/vendor/groonga/lib/expr.h +++ b/storage/mroonga/vendor/groonga/lib/grn_expr.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013-2014 Brazil + Copyright(C) 2013-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,7 +19,7 @@ #ifndef GRN_EXPR_H #define GRN_EXPR_H -#include "db.h" +#include "grn_db.h" #ifdef __cplusplus extern "C" { @@ -59,6 +59,8 @@ int grn_scan_info_get_max_interval(scan_info *si); void grn_scan_info_set_max_interval(scan_info *si, int max_interval); int grn_scan_info_get_similarity_threshold(scan_info *si); void grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold); +grn_obj *grn_scan_info_get_scorer(scan_info *si); +void grn_scan_info_set_scorer(scan_info *si, grn_obj *scorer); grn_bool grn_scan_info_push_arg(scan_info *si, grn_obj *arg); grn_obj *grn_scan_info_get_arg(grn_ctx *ctx, scan_info *si, int i); diff --git a/storage/mroonga/vendor/groonga/lib/geo.h b/storage/mroonga/vendor/groonga/lib/grn_geo.h index b1e04061876..5becbe4f45c 100644 --- a/storage/mroonga/vendor/groonga/lib/geo.h +++ b/storage/mroonga/vendor/groonga/lib/grn_geo.h @@ -17,12 +17,12 @@ #ifndef GRN_GEO_H #define GRN_GEO_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#ifndef GRN_H +#include "grn.h" +#endif /* GRN_H */ -#include "ii.h" -#include "db.h" +#include "grn_ii.h" +#include "grn_db.h" #if defined(WIN32) || defined(__sun) # define _USE_MATH_DEFINES diff --git a/storage/mroonga/vendor/groonga/lib/hash.h b/storage/mroonga/vendor/groonga/lib/grn_hash.h index 6f2e68de246..44f5bcba0ed 100644 --- a/storage/mroonga/vendor/groonga/lib/hash.h +++ b/storage/mroonga/vendor/groonga/lib/grn_hash.h @@ -17,13 +17,8 @@ #ifndef GRN_HASH_H #define GRN_HASH_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ +#include "grn.h" +#include "grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/ii.h b/storage/mroonga/vendor/groonga/lib/grn_ii.h index 877200fff7c..0d44079a38c 100644 --- a/storage/mroonga/vendor/groonga/lib/ii.h +++ b/storage/mroonga/vendor/groonga/lib/grn_ii.h @@ -19,21 +19,10 @@ /* "ii" is for inverted index */ -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_HASH_H -#include "hash.h" -#endif /* GRN_HASH_H */ - -#ifndef GRN_IO_H -#include "io.h" -#endif /* GRN_IO_H */ - -#ifndef GRN_STORE_H -#include "store.h" -#endif /* GRN_STORE_H */ +#include "grn.h" +#include "grn_hash.h" +#include "grn_io.h" +#include "grn_store.h" #ifdef __cplusplus extern "C" { @@ -113,8 +102,6 @@ grn_rc grn_ii_updspec_close(grn_ctx *ctx, grn_ii_updspec *u); grn_rc grn_ii_updspec_add(grn_ctx *ctx, grn_ii_updspec *u, int pos, int32_t weight); int grn_ii_updspec_cmp(grn_ii_updspec *a, grn_ii_updspec *b); -uint32_t grn_ii_estimate_size(grn_ctx *ctx, grn_ii *ii, uint32_t key); - void grn_ii_expire(grn_ctx *ctx, grn_ii *ii); typedef struct { @@ -141,7 +128,6 @@ GRN_API grn_rc grn_ii_cursor_close(grn_ctx *ctx, grn_ii_cursor *c); uint32_t grn_ii_max_section(grn_ii *ii); -int grn_ii_check(grn_ii *ii); const char *grn_ii_path(grn_ii *ii); grn_obj *grn_ii_lexicon(grn_ii *ii); @@ -165,6 +151,7 @@ struct _grn_select_optarg { int (*func)(grn_ctx *, grn_hash *, const void *, int, void *); void *func_arg; int max_size; + grn_obj *scorer; }; GRN_API grn_rc grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id id, @@ -184,7 +171,7 @@ void grn_ii_resolve_sel_and(grn_ctx *ctx, grn_hash *s, grn_operator op); grn_rc grn_ii_at(grn_ctx *ctx, grn_ii *ii, grn_id id, grn_hash *s, grn_operator op); -void grn_ii_inspect_elements(grn_ctx *ctx, grn_ii *ii, grn_obj *buf); +void grn_ii_inspect_values(grn_ctx *ctx, grn_ii *ii, grn_obj *buf); void grn_ii_cursor_inspect(grn_ctx *ctx, grn_ii_cursor *c, grn_obj *buf); grn_rc grn_ii_build(grn_ctx *ctx, grn_ii *ii, uint64_t sparsity); diff --git a/storage/mroonga/vendor/groonga/lib/io.h b/storage/mroonga/vendor/groonga/lib/grn_io.h index 04c75919c5f..00a1c3a0936 100644 --- a/storage/mroonga/vendor/groonga/lib/io.h +++ b/storage/mroonga/vendor/groonga/lib/grn_io.h @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2012 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -17,30 +17,17 @@ #ifndef GRN_IO_H #define GRN_IO_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_ERROR_H -#include "error.h" -#endif /* GRN_ERROR_H */ +#include "grn.h" +#include "grn_error.h" #ifdef __cplusplus extern "C" { #endif #ifdef WIN32 -#ifdef WIN32_FMO_EACH -#define GRN_IO_FILE_SIZE 1073741824UL -#else /* FMO_EACH */ -#define GRN_IO_FILE_SIZE 134217728L -#endif /* FMO_EACH */ -#define GRN_IO_COPY grn_io_rdonly -#define GRN_IO_UPDATE grn_io_wronly +# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE) #else /* WIN32 */ -#define GRN_IO_FILE_SIZE 1073741824UL -#define GRN_IO_COPY grn_io_rdwr -#define GRN_IO_UPDATE grn_io_rdwr +# define GRN_IO_FILE_CREATE_MODE 0644 #endif /* WIN32 */ typedef enum { @@ -72,19 +59,19 @@ typedef struct { void *addr; uint32_t diff; int32_t cached; -#if defined(WIN32) && defined(WIN32_FMO_EACH) +#ifdef WIN32 HANDLE fmo; -#endif /* defined(WIN32) && defined(WIN32_FMO_EACH) */ - void *value; +#endif /* WIN32 */ + void *uncompressed_value; } grn_io_win; typedef struct { void *map; uint32_t nref; uint32_t count; -#if defined(WIN32) && defined(WIN32_FMO_EACH) +#ifdef WIN32 HANDLE fmo; -#endif /* defined(WIN32) && defined(WIN32_FMO_EACH) */ +#endif /* WIN32 */ } grn_io_mapinfo; typedef struct _grn_io_array_info grn_io_array_info; @@ -135,13 +122,8 @@ GRN_API void *grn_io_header(grn_io *io); void *grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, uint32_t offset, uint32_t size, grn_io_rw_mode mode); -grn_rc grn_io_win_mapv(grn_io_win **list, grn_ctx *ctx, int nent); grn_rc grn_io_win_unmap(grn_io_win *iw); -void *grn_io_win_map2(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, - uint32_t offset, uint32_t size, grn_io_rw_mode mode); -grn_rc grn_io_win_unmap2(grn_io_win *iw); - typedef struct _grn_io_ja_einfo grn_io_ja_einfo; typedef struct _grn_io_ja_ehead grn_io_ja_ehead; diff --git a/storage/mroonga/vendor/groonga/lib/mrb.h b/storage/mroonga/vendor/groonga/lib/grn_mrb.h index fe51e5e7670..7fae820d342 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb.h +++ b/storage/mroonga/vendor/groonga/lib/grn_mrb.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013 Brazil + Copyright(C) 2013-2014 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,8 +19,8 @@ #ifndef GRN_MRB_H #define GRN_MRB_H -#include "groonga_in.h" -#include "ctx.h" +#include "grn.h" +#include "grn_ctx.h" #ifdef GRN_WITH_MRUBY # include <mruby.h> @@ -34,6 +34,7 @@ extern "C" { GRN_API mrb_value grn_mrb_eval(grn_ctx *ctx, const char *script, int script_length); GRN_API mrb_value grn_mrb_load(grn_ctx *ctx, const char *path); GRN_API grn_rc grn_mrb_to_grn(grn_ctx *ctx, mrb_value mrb_object, grn_obj *grn_object); +GRN_API const char *grn_mrb_get_system_ruby_scripts_dir(grn_ctx *ctx); #endif #ifdef __cplusplus diff --git a/storage/mroonga/vendor/groonga/lib/normalizer_in.h b/storage/mroonga/vendor/groonga/lib/grn_normalizer.h index 201c789f626..8c7bfddf810 100644 --- a/storage/mroonga/vendor/groonga/lib/normalizer_in.h +++ b/storage/mroonga/vendor/groonga/lib/grn_normalizer.h @@ -15,20 +15,12 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_NORMALIZER_IN_H -#define GRN_NORMALIZER_IN_H +#ifndef GRN_NORMALIZER_H +#define GRN_NORMALIZER_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef GRN_DB_H -#include "db.h" -#endif /* GRN_DB_H */ +#include "grn.h" +#include "grn_ctx.h" +#include "grn_db.h" #ifdef __cplusplus extern "C" { @@ -49,4 +41,4 @@ grn_rc grn_db_init_builtin_normalizers(grn_ctx *ctx); } #endif -#endif /* GRN_NORMALIZER_IN_H */ +#endif /* GRN_NORMALIZER_H */ diff --git a/storage/mroonga/vendor/groonga/lib/output.h b/storage/mroonga/vendor/groonga/lib/grn_output.h index 7c8a3f7a769..63752e90bd9 100644 --- a/storage/mroonga/vendor/groonga/lib/output.h +++ b/storage/mroonga/vendor/groonga/lib/grn_output.h @@ -17,21 +17,10 @@ #ifndef GRN_OUTPUT_H #define GRN_OUTPUT_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef GRN_STORE_H -#include "store.h" -#endif /* GRN_STORE_H */ - -#ifndef GRN_CTX_IMPL_H -#include "ctx_impl.h" -#endif /* GRN_CTX_IMPL_H */ +#include "grn.h" +#include "grn_ctx.h" +#include "grn_store.h" +#include "grn_ctx_impl.h" #ifdef __cplusplus extern "C" { @@ -59,6 +48,21 @@ GRN_API void grn_output_bool(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_bool value); +GRN_API void grn_output_table_columns(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, + grn_obj_format *format); +GRN_API void grn_output_table_records(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, + grn_obj_format *format); + +grn_rc grn_output_format_set_columns(grn_ctx *ctx, grn_obj_format *format, + grn_obj *table, + const char *columns, int columns_len); + #define GRN_OUTPUT_ARRAY_OPEN(name,nelements) \ (grn_ctx_output_array_open(ctx, name, nelements)) #define GRN_OUTPUT_ARRAY_CLOSE() \ @@ -81,6 +85,10 @@ GRN_API void grn_output_bool(grn_ctx *ctx, grn_obj *outbuf, (grn_ctx_output_bool(ctx, value)) #define GRN_OUTPUT_OBJ(obj,format)\ (grn_ctx_output_obj(ctx, obj, format)) +#define GRN_OUTPUT_TABLE_COLUMNS(table,format)\ + (grn_ctx_output_table_columns(ctx, table, format)) +#define GRN_OUTPUT_TABLE_RECORDS(table,format)\ + (grn_ctx_output_table_records(ctx, table, format)) #ifdef __cplusplus } diff --git a/storage/mroonga/vendor/groonga/lib/pat.h b/storage/mroonga/vendor/groonga/lib/grn_pat.h index d2d10322c7c..763c6848a63 100644 --- a/storage/mroonga/vendor/groonga/lib/pat.h +++ b/storage/mroonga/vendor/groonga/lib/grn_pat.h @@ -17,12 +17,9 @@ #ifndef GRN_PAT_H #define GRN_PAT_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#include "db.h" -#include "hash.h" +#include "grn.h" +#include "grn_db.h" +#include "grn_hash.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/plugin_in.h b/storage/mroonga/vendor/groonga/lib/grn_plugin.h index 6f983089dc9..121c3143faf 100644 --- a/storage/mroonga/vendor/groonga/lib/plugin_in.h +++ b/storage/mroonga/vendor/groonga/lib/grn_plugin.h @@ -14,20 +14,12 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_PLUGIN_IN_H -#define GRN_PLUGIN_IN_H +#ifndef GRN_PLUGIN_H +#define GRN_PLUGIN_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef GRN_STORE_H -#include "store.h" -#endif /* GRN_STORE_H */ +#include "grn.h" +#include "grn_ctx.h" +#include "grn_store.h" #ifdef __cplusplus extern "C" { @@ -60,9 +52,10 @@ grn_rc grn_plugin_close(grn_ctx *ctx, grn_id id); grn_id grn_plugin_reference(grn_ctx *ctx, const char *filename); const char *grn_plugin_path(grn_ctx *ctx, grn_id id); char *grn_plugin_find_path(grn_ctx *ctx, const char *name); +void grn_plugin_ensure_registered(grn_ctx *ctx, grn_obj *proc); #ifdef __cplusplus } #endif -#endif /* GRN_PLUGIN_IN_H */ +#endif /* GRN_PLUGIN_H */ diff --git a/storage/mroonga/vendor/groonga/lib/proc.h b/storage/mroonga/vendor/groonga/lib/grn_proc.h index 1f7f81d5d97..fb01698ea69 100644 --- a/storage/mroonga/vendor/groonga/lib/proc.h +++ b/storage/mroonga/vendor/groonga/lib/grn_proc.h @@ -17,9 +17,7 @@ #ifndef GRN_PROC_H #define GRN_PROC_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#include "grn.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h b/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h new file mode 100644 index 00000000000..4c77ea5246e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_REQUEST_CANCELER_H +#define GRN_REQUEST_CANCELER_H + +#include "grn.h" + +grn_bool grn_request_canceler_init(void); +void grn_request_canceler_fin(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_REQUEST_CANCELER_H */ diff --git a/storage/mroonga/vendor/groonga/lib/grn_rset.h b/storage/mroonga/vendor/groonga/lib/grn_rset.h new file mode 100644 index 00000000000..4fa0d08355a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_rset.h @@ -0,0 +1,115 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GRN_RSET_H +#define GRN_RSET_H + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + double score; + int n_subrecs; + int subrecs[1]; +} grn_rset_recinfo; + +typedef struct { + grn_id rid; + uint32_t sid; + uint32_t pos; +} grn_rset_posinfo; + +#define GRN_RSET_UTIL_BIT (0x80000000) + +#define GRN_RSET_N_SUBRECS_SIZE (sizeof(int)) +#define GRN_RSET_MAX_SIZE (sizeof(int64_t)) +#define GRN_RSET_MIN_SIZE (sizeof(int64_t)) +#define GRN_RSET_SUM_SIZE (sizeof(int64_t)) +#define GRN_RSET_AVG_SIZE (sizeof(double)) + +#define GRN_RSET_SCORE_SIZE (sizeof(double)) + +#define GRN_RSET_N_SUBRECS(ri) ((ri)->n_subrecs & ~GRN_RSET_UTIL_BIT) + +#define GRN_RSET_SUBREC_SIZE(subrec_size) \ + (GRN_RSET_SCORE_SIZE + subrec_size) +#define GRN_RSET_SUBRECS_CMP(a,b,dir) (((a) - (b))*(dir)) +#define GRN_RSET_SUBRECS_NTH(subrecs,size,n) \ + ((double *)((byte *)subrecs + n * GRN_RSET_SUBREC_SIZE(size))) +#define GRN_RSET_SUBRECS_COPY(subrecs,size,n,src) \ + (memcpy(GRN_RSET_SUBRECS_NTH(subrecs, size, n), src, GRN_RSET_SUBREC_SIZE(size))) +#define GRN_RSET_SUBRECS_SIZE(subrec_size,n) \ + (GRN_RSET_SUBREC_SIZE(subrec_size) * n) + +uint32_t grn_rset_recinfo_calc_values_size(grn_ctx *ctx, + grn_table_group_flags flags); +void grn_rset_recinfo_update_calc_values(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + grn_obj *value); + +int64_t *grn_rset_recinfo_get_max_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +int64_t grn_rset_recinfo_get_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t max); + +int64_t *grn_rset_recinfo_get_min_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +int64_t grn_rset_recinfo_get_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t min); + +int64_t *grn_rset_recinfo_get_sum_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +int64_t grn_rset_recinfo_get_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t sum); + +double *grn_rset_recinfo_get_avg_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +double grn_rset_recinfo_get_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + double avg); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_RSET_H */ diff --git a/storage/mroonga/vendor/groonga/lib/grn_scorer.h b/storage/mroonga/vendor/groonga/lib/grn_scorer.h new file mode 100644 index 00000000000..898a83366b0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_scorer.h @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GRN_SCORER_H +#define GRN_SCORER_H + +#include "grn_ctx.h" +#include "grn_db.h" + +#include <groonga/scorer.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct _grn_scorer_matched_record { + grn_obj *table; + grn_obj *lexicon; + grn_id id; + grn_obj terms; + grn_obj term_weights; + uint32_t total_term_weights; + uint64_t n_documents; + uint32_t n_occurrences; + uint64_t n_candidates; + uint32_t n_tokens; + int weight; +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_SCORER_H */ diff --git a/storage/mroonga/vendor/groonga/lib/grn_scorers.h b/storage/mroonga/vendor/groonga/lib/grn_scorers.h new file mode 100644 index 00000000000..ed6c18c211a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_scorers.h @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GRN_SCORERS_H +#define GRN_SCORERS_H + +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +grn_rc grn_db_init_builtin_scorers(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_SCORERS_H */ diff --git a/storage/mroonga/vendor/groonga/lib/snip.h b/storage/mroonga/vendor/groonga/lib/grn_snip.h index 7a252921b3a..7c123e0c5f4 100644 --- a/storage/mroonga/vendor/groonga/lib/snip.h +++ b/storage/mroonga/vendor/groonga/lib/grn_snip.h @@ -17,15 +17,15 @@ #ifndef GRN_SNIP_H #define GRN_SNIP_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#ifndef GRN_H +#include "grn.h" +#endif /* GRN_H */ #ifndef GRN_STR_H -#include "str.h" +#include "grn_str.h" #endif /* GRN_STR_H */ -#include "db.h" +#include "grn_db.h" #define ASIZE 256U #define MAX_SNIP_TAG_COUNT 512U diff --git a/storage/mroonga/vendor/groonga/lib/store.h b/storage/mroonga/vendor/groonga/lib/grn_store.h index 719fe775bd9..742d11341fc 100644 --- a/storage/mroonga/vendor/groonga/lib/store.h +++ b/storage/mroonga/vendor/groonga/lib/grn_store.h @@ -17,21 +17,10 @@ #ifndef GRN_STORE_H #define GRN_STORE_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef GRN_HASH_H -#include "hash.h" -#endif /* GRN_HASH_H */ - -#ifndef GRN_IO_H -#include "io.h" -#endif /* GRN_IO_H */ +#include "grn.h" +#include "grn_ctx.h" +#include "grn_hash.h" +#include "grn_io.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/str.h b/storage/mroonga/vendor/groonga/lib/grn_str.h index 069250a70d8..ade8c04053e 100644 --- a/storage/mroonga/vendor/groonga/lib/str.h +++ b/storage/mroonga/vendor/groonga/lib/grn_str.h @@ -17,13 +17,8 @@ #ifndef GRN_STR_H #define GRN_STR_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_NFKC_H +#include "grn.h" #include <groonga/nfkc.h> -#endif /* GRN_NFKC_H */ #ifdef __cplusplus extern "C" { @@ -82,7 +77,7 @@ GRN_API grn_str *grn_str_open_(grn_ctx *ctx, const char *str, unsigned int str_l if (GRN_BULK_OUTP(buf)) {\ (buf)->u.b.curr += (len);\ } else {\ - (buf)->header.flags += (len);\ + (buf)->header.flags += (grn_obj_flags)(len);\ }\ } while (0) diff --git a/storage/mroonga/vendor/groonga/lib/string_in.h b/storage/mroonga/vendor/groonga/lib/grn_string.h index 55e2cb2cbcb..bb5905c84f8 100644 --- a/storage/mroonga/vendor/groonga/lib/string_in.h +++ b/storage/mroonga/vendor/groonga/lib/grn_string.h @@ -20,21 +20,21 @@ #ifndef GRN_STRING_H #define GRN_STRING_H -#ifndef GROONGA_IN_H -# include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#ifndef GRN_H +# include "grn.h" +#endif /* GRN_H */ #ifndef GRN_CTX_H -# include "ctx.h" +# include "grn_ctx.h" #endif /* GRN_CTX_H */ #ifndef GRN_DB_H -# include "db.h" +# include "grn_db.h" #endif /* GRN_DB_H */ #ifndef GRN_STR_H -# include "str.h" -#endif /* GRN_STR_IN_H */ +# include "grn_str.h" +#endif /* GRN_STR_H */ #ifdef __cplusplus extern "C" { @@ -62,4 +62,4 @@ grn_rc grn_string_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *string); } #endif -#endif /* GRN_STRING_IN_H */ +#endif /* GRN_STRING_H */ diff --git a/storage/mroonga/vendor/groonga/lib/token.h b/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h index 868930758ba..81175bc432f 100644 --- a/storage/mroonga/vendor/groonga/lib/token.h +++ b/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h @@ -14,24 +14,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_TOKEN_H -#define GRN_TOKEN_H +#ifndef GRN_TOKEN_CURSOR_H +#define GRN_TOKEN_CURSOR_H -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ - -#ifndef GRN_CTX_H -#include "ctx.h" -#endif /* GRN_CTX_H */ - -#ifndef GRN_DB_H -#include "db.h" -#endif /* GRN_DB_H */ - -#ifndef GRN_STR_H -#include "str.h" -#endif /* GRN_STR_H */ +#include "grn_ctx.h" +#include "grn_db.h" #include <groonga/tokenizer.h> @@ -40,15 +27,15 @@ extern "C" { #endif typedef enum { - GRN_TOKEN_DOING = 0, - GRN_TOKEN_DONE, - GRN_TOKEN_DONE_SKIP, - GRN_TOKEN_NOT_FOUND -} grn_token_status; + GRN_TOKEN_CURSOR_DOING = 0, + GRN_TOKEN_CURSOR_DONE, + GRN_TOKEN_CURSOR_DONE_SKIP, + GRN_TOKEN_CURSOR_NOT_FOUND +} grn_token_cursor_status; struct _grn_token { grn_obj data; - grn_tokenizer_status status; + grn_token_status status; }; typedef struct { @@ -58,9 +45,9 @@ typedef struct { uint32_t orig_blen; uint32_t curr_size; int32_t pos; - grn_token_mode mode; - grn_token_status status; - uint8_t force_prefix; + grn_tokenize_mode mode; + grn_token_cursor_status status; + grn_bool force_prefix; grn_obj_flags table_flags; grn_encoding encoding; grn_obj *tokenizer; @@ -70,26 +57,18 @@ typedef struct { grn_obj *nstr; } grn_token_cursor; -extern grn_obj *grn_token_uvector; - -grn_rc grn_token_init(void); -grn_rc grn_token_fin(void); - -#define GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER (0x01L<<0) +#define GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER (0x01L<<0) GRN_API grn_token_cursor *grn_token_cursor_open(grn_ctx *ctx, grn_obj *table, const char *str, size_t str_len, - grn_token_mode mode, + grn_tokenize_mode mode, unsigned int flags); GRN_API grn_id grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor); GRN_API grn_rc grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor); -grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx); -grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx); - #ifdef __cplusplus } #endif -#endif /* GRN_TOKEN_H */ +#endif /* GRN_TOKEN_CURSOR_H */ diff --git a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h new file mode 100644 index 00000000000..fb85fb76a48 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GRN_TOKENIZERS_H +#define GRN_TOKENIZERS_H + +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern grn_obj *grn_tokenizer_uvector; + +grn_rc grn_tokenizers_init(void); +grn_rc grn_tokenizers_fin(void); + +grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx); +grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_TOKENIZERS_H */ diff --git a/storage/mroonga/vendor/groonga/lib/grn_util.h b/storage/mroonga/vendor/groonga/lib/grn_util.h new file mode 100644 index 00000000000..84aa357e4e3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_util.h @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2010-2011 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef GRN_UTIL_H +#define GRN_UTIL_H + +#include "grn.h" +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API grn_rc grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *offset, int *limit); + +GRN_API const char *grn_win32_base_dir(void); +GRN_API char *grn_path_separator_to_system(char *dest, char *groonga_path); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_UTIL_H */ diff --git a/storage/mroonga/vendor/groonga/lib/hash.c b/storage/mroonga/vendor/groonga/lib/hash.c index fa5854a6a93..22491c5fc8b 100644 --- a/storage/mroonga/vendor/groonga/lib/hash.c +++ b/storage/mroonga/vendor/groonga/lib/hash.c @@ -15,13 +15,13 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "hash.h" -#include "output.h" +#include "grn_hash.h" +#include "grn_output.h" #include <string.h> #include <limits.h> -#include "store.h" -#include "normalizer_in.h" +#include "grn_store.h" +#include "grn_normalizer.h" /* grn_tiny_array */ diff --git a/storage/mroonga/vendor/groonga/lib/ii.c b/storage/mroonga/vendor/groonga/lib/ii.c index 5dc203865ad..3b5478f9ea7 100644 --- a/storage/mroonga/vendor/groonga/lib/ii.c +++ b/storage/mroonga/vendor/groonga/lib/ii.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2014 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -14,25 +14,34 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <stdio.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> -#include "ii.h" -#include "ctx_impl.h" -#include "token.h" -#include "pat.h" -#include "db.h" -#include "output.h" -#include "util.h" +#include "grn_ii.h" +#include "grn_ctx_impl.h" +#include "grn_token_cursor.h" +#include "grn_pat.h" +#include "grn_db.h" +#include "grn_output.h" +#include "grn_scorer.h" +#include "grn_util.h" + +#ifdef GRN_WITH_ONIGMO +# define GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH +#endif + +#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH +# include "grn_string.h" +# include <oniguruma.h> +#endif #define MAX_PSEG 0x20000 #define S_CHUNK (1 << GRN_II_W_CHUNK) #define W_SEGMENT 18 #define S_SEGMENT (1 << W_SEGMENT) -#define N_CHUNKS_PER_FILE (GRN_IO_FILE_SIZE >> W_SEGMENT) #define W_ARRAY_ELEMENT 3 #define S_ARRAY_ELEMENT (1 << W_ARRAY_ELEMENT) #define W_ARRAY (W_SEGMENT - W_ARRAY_ELEMENT) @@ -230,11 +239,11 @@ typedef struct { uint32_t recs[N_GARBAGES]; } grn_ii_ginfo; -#define WIN_MAP2(chunk,ctx,iw,seg,pos,size,mode)\ - grn_io_win_map2(chunk, ctx, iw,\ - ((seg) >> GRN_II_N_CHUNK_VARIATION),\ - (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK) + (pos),\ - size,mode) +#define WIN_MAP(chunk,ctx,iw,seg,pos,size,mode)\ + grn_io_win_map(chunk, ctx, iw,\ + ((seg) >> GRN_II_N_CHUNK_VARIATION),\ + (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK) + (pos),\ + size,mode) /* static int new_histogram[32]; static int free_histogram[32]; @@ -285,10 +294,10 @@ chunk_new(grn_ctx *ctx, grn_ii *ii, uint32_t *res, uint32_t size) iw_.addr = NULL; gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK]; while (*gseg != NOT_ASSIGNED) { - ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); + ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); //GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo); if (!ginfo) { - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } return GRN_NO_MEMORY_AVAILABLE; } if (ginfo->next != NOT_ASSIGNED || ginfo->nrecs > N_GARBAGES_TH) { @@ -300,15 +309,15 @@ chunk_new(grn_ctx *ctx, grn_ii *ii, uint32_t *res, uint32_t size) HEADER_CHUNK_OFF(ii, *gseg); *gseg = ginfo->next; } - if (iw_.addr) { grn_io_win_unmap2(&iw_); } - grn_io_win_unmap2(&iw); + if (iw_.addr) { grn_io_win_unmap(&iw_); } + grn_io_win_unmap(&iw); return GRN_SUCCESS; } - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } iw_ = iw; gseg = &ginfo->next; } - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } } vp = &ii->header->free_chunks[m - GRN_II_W_LEAST_CHUNK]; if (*vp == NOT_ASSIGNED) { @@ -358,24 +367,24 @@ chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t s gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK]; iw_.addr = NULL; while (*gseg != NOT_ASSIGNED) { - ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); + ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); // GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo); if (!ginfo) { - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } return GRN_NO_MEMORY_AVAILABLE; } if (ginfo->nrecs < N_GARBAGES) { break; } - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } iw_ = iw; gseg = &ginfo->next; } if (*gseg == NOT_ASSIGNED) { grn_rc rc; if ((rc = chunk_new(ctx, ii, gseg, S_GARBAGE))) { - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } return rc; } - ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); + ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); /* uint32_t i = 0; while (HEADER_CHUNK_AT(ii, i)) { @@ -386,7 +395,7 @@ chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t s GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo); */ if (!ginfo) { - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } return GRN_NO_MEMORY_AVAILABLE; } ginfo->head = 0; @@ -394,50 +403,15 @@ chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t s ginfo->nrecs = 0; ginfo->next = NOT_ASSIGNED; } - if (iw_.addr) { grn_io_win_unmap2(&iw_); } + if (iw_.addr) { grn_io_win_unmap(&iw_); } ginfo->recs[ginfo->head] = offset; if (++ginfo->head == N_GARBAGES) { ginfo->head = 0; } ginfo->nrecs++; - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); ii->header->ngarbages[m - GRN_II_W_LEAST_CHUNK]++; return GRN_SUCCESS; } -/* -inline static grn_rc -chunk_new(grn_ii *ii, uint32_t *res, uint32_t size) -{ - int i, j; - uint32_t n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK; - uint32_t base_seg = grn_io_base_seg(ii->chunk); - for (i = 0, j = -1; i < GRN_II_MAX_CHUNK; i++) { - if (HEADER_CHUNK_AT(ii, i)) { - j = i; - } else { - if (i == j + n) { - j++; - if (res) { *res = j; } - for (; j <= i; j++) { HEADER_CHUNK_ON(ii, j); } - return GRN_SUCCESS; - } - // todo : cut off - if ((i + base_seg)/ N_CHUNKS_PER_FILE != - (i + base_seg + 1) / N_CHUNKS_PER_FILE) { j = i; } - } - } - GRN_LOG(ctx, GRN_LOG_CRIT, "index full."); - return GRN_NO_MEMORY_AVAILABLE; -} - -static void -chunk_free(grn_ii *ii, int offset, uint32_t size1, uint32_t size2) -{ - uint32_t i = offset + ((size1 + S_CHUNK - 1) >> GRN_II_W_CHUNK); - uint32_t n = offset + ((size2 + S_CHUNK - 1) >> GRN_II_W_CHUNK); - for (; i < n; i++) { HEADER_CHUNK_OFF(ii, i); } -} -*/ - #define UNIT_SIZE 0x80 #define UNIT_MASK (UNIT_SIZE - 1) @@ -2487,21 +2461,25 @@ typedef struct { static grn_rc chunk_flush(grn_ctx *ctx, grn_ii *ii, chunk_info *cinfo, uint8_t *enc, uint32_t encsize) { - grn_rc rc; + grn_rc rc = GRN_SUCCESS; uint8_t *dc; uint32_t dcn; grn_io_win dw; - if (!(rc = chunk_new(ctx, ii, &dcn, encsize))) { - if ((dc = WIN_MAP2(ii->chunk, ctx, &dw, dcn, 0, encsize, grn_io_wronly))) { - memcpy(dc, enc, encsize); - grn_io_win_unmap2(&dw); - cinfo->segno = dcn; - cinfo->size = encsize; - rc = GRN_SUCCESS; - } else { - chunk_free(ctx, ii, dcn, 0, encsize); - rc = GRN_NO_MEMORY_AVAILABLE; + if (encsize) { + if (!(rc = chunk_new(ctx, ii, &dcn, encsize))) { + if ((dc = WIN_MAP(ii->chunk, ctx, &dw, dcn, 0, encsize, grn_io_wronly))) { + memcpy(dc, enc, encsize); + grn_io_win_unmap(&dw); + cinfo->segno = dcn; + cinfo->size = encsize; + } else { + chunk_free(ctx, ii, dcn, 0, encsize); + rc = GRN_NO_MEMORY_AVAILABLE; + } } + } else { + cinfo->segno = 0; + cinfo->size = 0; } return rc; } @@ -2517,7 +2495,7 @@ chunk_merge(grn_ctx *ctx, grn_ii *ii, buffer *sb, buffer_term *bt, uint32_t segno = cinfo->segno, size = cinfo->size, sdf = 0, ndf = 0; uint32_t *ridp = NULL, *sidp = NULL, *tfp, *weightp = NULL, *posp = NULL; docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = *bidp; - uint8_t *scp = WIN_MAP2(ii->chunk, ctx, &sw, segno, 0, size, grn_io_rdonly); + uint8_t *scp = WIN_MAP(ii->chunk, ctx, &sw, segno, 0, size, grn_io_rdonly); if (scp) { uint16_t nextb = *nextbp; uint32_t snn = 0, *srp, *ssp = NULL, *stp, *sop = NULL, *snp; @@ -2558,7 +2536,7 @@ chunk_merge(grn_ctx *ctx, grn_ii *ii, buffer *sb, buffer_term *bt, ndf = ridp - dv[0].data; } datavec_fin(ctx, rdv); - grn_io_win_unmap2(&sw); + grn_io_win_unmap(&sw); } else { rc = GRN_NO_MEMORY_AVAILABLE; } @@ -2621,6 +2599,7 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, uint64_t spos = 0; int32_t balance = 0; uint32_t *ridp, *sidp = NULL, *tfp, *weightp = NULL, *posp, nchunks = 0; + uint32_t nvchunks = 0; chunk_info *cinfo = NULL; grn_id crid = GRN_ID_NIL; docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = {0, 0}; @@ -2667,6 +2646,12 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, return rc; } } + if (cinfo[i].size) { + nvchunks++; + } else { + crid -= cinfo[i].dgap; + cinfo[i + 1].dgap += cinfo[i].dgap; + } } } if (sce > scp) { @@ -2739,21 +2724,21 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, memset(bt, 0, sizeof(buffer_term)); nterms_void++; } else { - if (!ndf && !nchunks) { + if (!ndf && !nvchunks) { a[0] = 0; a[1] = 0; lexicon_delete(ctx, ii, tid, h); memset(bt, 0, sizeof(buffer_term)); nterms_void++; } else if ((ii->header->flags & GRN_OBJ_WITH_SECTION) - && !nchunks && ndf == 1 && lid.rid < 0x100000 && + && !nvchunks && ndf == 1 && lid.rid < 0x100000 && lid.sid < 0x800 && lid.tf == 1 && lid.weight == 0) { a[0] = (lid.rid << 12) + (lid.sid << 1) + 1; a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0; memset(bt, 0, sizeof(buffer_term)); nterms_void++; } else if (!(ii->header->flags & GRN_OBJ_WITH_SECTION) - && !nchunks && ndf == 1 && lid.tf == 1 && lid.weight == 0) { + && !nvchunks && ndf == 1 && lid.tf == 1 && lid.weight == 0) { a[0] = (lid.rid << 1) + 1; a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0; memset(bt, 0, sizeof(buffer_term)); @@ -2779,13 +2764,15 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, } dcp0 = dcp; a[1] = (bt->size_in_chunk ? a[1] : 0) + (ndf - sdf) + balance; - if (nchunks) { + if (nvchunks) { int i; - GRN_B_ENC(nchunks, dcp); + GRN_B_ENC(nvchunks, dcp); for (i = 0; i < nchunks; i++) { - GRN_B_ENC(cinfo[i].segno, dcp); - GRN_B_ENC(cinfo[i].size, dcp); - GRN_B_ENC(cinfo[i].dgap, dcp); + if (cinfo[i].size) { + GRN_B_ENC(cinfo[i].segno, dcp); + GRN_B_ENC(cinfo[i].size, dcp); + GRN_B_ENC(cinfo[i].dgap, dcp); + } } } encsize = grn_p_encv(ctx, dv, ii->n_elements, dcp); @@ -2830,18 +2817,23 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, !chunk_flush(ctx, ii, &cinfo[nchunks], dcp, encsize)) { int i; cinfo[nchunks].dgap = lid.rid - crid; - nchunks++; + nvchunks++; dcp = dcp0; - GRN_B_ENC(nchunks, dcp); - for (i = 0; i < nchunks; i++) { - GRN_B_ENC(cinfo[i].segno, dcp); - GRN_B_ENC(cinfo[i].size, dcp); - GRN_B_ENC(cinfo[i].dgap, dcp); + GRN_B_ENC(nvchunks, dcp); + for (i = 0; i <= nchunks; i++) { + if (cinfo[i].size) { + GRN_B_ENC(cinfo[i].segno, dcp); + GRN_B_ENC(cinfo[i].size, dcp); + GRN_B_ENC(cinfo[i].dgap, dcp); + } } GRN_LOG(ctx, GRN_LOG_NOTICE, "split (%d) encsize=%d", tid, encsize); bt->tid |= CHUNK_SPLIT; } else { dcp += encsize; + if (!nvchunks) { + bt->tid &= ~CHUNK_SPLIT; + } } bt->pos_in_chunk = (uint32_t)(dcp0 - dc); bt->size_in_chunk = (uint32_t)(dcp - dcp0); @@ -2863,7 +2855,7 @@ buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, } static void -fake_map2(grn_ctx *ctx, grn_io *io, grn_io_win *iw, void *addr, uint32_t seg, uint32_t size) +fake_map(grn_ctx *ctx, grn_io *io, grn_io_win *iw, void *addr, uint32_t seg, uint32_t size) { iw->ctx = ctx; iw->diff = 0; @@ -2894,8 +2886,8 @@ buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) uint32_t max_dest_chunk_size = sb->header.chunk_size + S_SEGMENT; if ((dc = GRN_MALLOC(max_dest_chunk_size * 2))) { if ((scn = sb->header.chunk) == NOT_ASSIGNED || - (sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0, - sb->header.chunk_size, grn_io_rdonly))) { + (sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, + sb->header.chunk_size, grn_io_rdonly))) { uint16_t n = sb->header.nterms; memset(db, 0, S_SEGMENT); memcpy(db->terms, sb->terms, n * sizeof(buffer_term)); @@ -2908,12 +2900,12 @@ buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) } if (!actual_chunk_size || !(rc = chunk_new(ctx, ii, &dcn, actual_chunk_size))) { db->header.chunk = actual_chunk_size ? dcn : NOT_ASSIGNED; - fake_map2(ctx, ii->chunk, &dw, dc, dcn, actual_chunk_size); - if (!(rc = grn_io_win_unmap2(&dw))) { + fake_map(ctx, ii->chunk, &dw, dc, dcn, actual_chunk_size); + if (!(rc = grn_io_win_unmap(&dw))) { buffer_segment_update(ii, seg, ds); ii->header->total_chunk_size += actual_chunk_size; if (scn != NOT_ASSIGNED) { - grn_io_win_unmap2(&sw); + grn_io_win_unmap(&sw); chunk_free(ctx, ii, scn, 0, sb->header.chunk_size); ii->header->total_chunk_size -= sb->header.chunk_size; } @@ -2922,15 +2914,15 @@ buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) if (actual_chunk_size) { chunk_free(ctx, ii, dcn, 0, actual_chunk_size); } - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { GRN_FREE(dc); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { GRN_FREE(dc); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { GRN_FREE(dc); @@ -2991,7 +2983,7 @@ grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg) GRN_OUTPUT_CSTR("void chunk size"); GRN_OUTPUT_INT64(sb->header.chunk_size); } else { - if ((sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0, sb->header.chunk_size, grn_io_rdonly))) { + if ((sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, sb->header.chunk_size, grn_io_rdonly))) { GRN_OUTPUT_CSTR("chunk size"); GRN_OUTPUT_INT64(sb->header.chunk_size); } else { @@ -3133,7 +3125,7 @@ grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg) } GRN_OUTPUT_MAP_CLOSE(); datavec_fin(ctx, rdv); - if (sc) { grn_io_win_unmap2(&sw); } + if (sc) { grn_io_win_unmap(&sw); } buffer_close(ctx, ii, pseg); } @@ -3236,8 +3228,8 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) if ((dc0 = GRN_MALLOC(max_dest_chunk_size * 2))) { if ((dc1 = GRN_MALLOC(max_dest_chunk_size * 2))) { if ((scn = sb->header.chunk) == NOT_ASSIGNED || - (sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0, - sb->header.chunk_size, grn_io_rdonly))) { + (sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, + sb->header.chunk_size, grn_io_rdonly))) { term_split(ctx, ii->lexicon, sb, db0, db1); if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db0, dc0))) { actual_db0_chunk_size = db0->header.chunk_size; @@ -3249,8 +3241,8 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) if (!actual_db0_chunk_size || !(rc = chunk_new(ctx, ii, &dcn0, actual_db0_chunk_size))) { db0->header.chunk = actual_db0_chunk_size ? dcn0 : NOT_ASSIGNED; - fake_map2(ctx, ii->chunk, &dw0, dc0, dcn0, actual_db0_chunk_size); - if (!(rc = grn_io_win_unmap2(&dw0))) { + fake_map(ctx, ii->chunk, &dw0, dc0, dcn0, actual_db0_chunk_size); + if (!(rc = grn_io_win_unmap(&dw0))) { if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db1, dc1))) { actual_db1_chunk_size = db1->header.chunk_size; if (actual_db1_chunk_size >= max_dest_chunk_size) { @@ -3260,8 +3252,8 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) } if (!actual_db1_chunk_size || !(rc = chunk_new(ctx, ii, &dcn1, actual_db1_chunk_size))) { - fake_map2(ctx, ii->chunk, &dw1, dc1, dcn1, actual_db1_chunk_size); - if (!(rc = grn_io_win_unmap2(&dw1))) { + fake_map(ctx, ii->chunk, &dw1, dc1, dcn1, actual_db1_chunk_size); + if (!(rc = grn_io_win_unmap(&dw1))) { db1->header.chunk = actual_db1_chunk_size ? dcn1 : NOT_ASSIGNED; buffer_segment_update(ii, dls0, dps0); buffer_segment_update(ii, dls1, dps1); @@ -3271,7 +3263,7 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) ii->header->total_chunk_size += actual_db0_chunk_size; ii->header->total_chunk_size += actual_db1_chunk_size; if (scn != NOT_ASSIGNED) { - grn_io_win_unmap2(&sw); + grn_io_win_unmap(&sw); chunk_free(ctx, ii, scn, 0, sb->header.chunk_size); ii->header->total_chunk_size -= sb->header.chunk_size; } @@ -3283,21 +3275,21 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); } GRN_FREE(dc1); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { if (actual_db0_chunk_size) { chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); } GRN_FREE(dc1); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { if (actual_db0_chunk_size) { chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); } GRN_FREE(dc1); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { if (actual_db0_chunk_size) { @@ -3305,17 +3297,17 @@ buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) } GRN_FREE(dc1); GRN_FREE(dc0); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { GRN_FREE(dc1); GRN_FREE(dc0); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { GRN_FREE(dc1); GRN_FREE(dc0); - if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); } + if (scn != NOT_ASSIGNED) { grn_io_win_unmap(&sw); } } } else { GRN_FREE(dc1); @@ -3984,16 +3976,16 @@ chunk_is_reused(grn_ctx *ctx, grn_ii *ii, grn_ii_cursor *c, uint32_t offset, uin gseg = ii->header->garbages[m - GRN_II_W_LEAST_CHUNK]; while (gseg != NOT_ASSIGNED) { grn_io_win iw; - grn_ii_ginfo *ginfo = WIN_MAP2(ii->chunk, ctx, &iw, gseg, 0, S_GARBAGE, grn_io_rdwr); + grn_ii_ginfo *ginfo = WIN_MAP(ii->chunk, ctx, &iw, gseg, 0, S_GARBAGE, grn_io_rdwr); if (!ginfo) { break; } for (i = 0; i < ginfo->nrecs; i++) { if (ginfo->recs[i] == offset) { - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); return 0; } } gseg = ginfo->next; - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } return 1; } @@ -4047,8 +4039,8 @@ grn_ii_cursor_open(grn_ctx *ctx, grn_ii *ii, grn_id tid, } c->ppseg = &ii->header->binfo[LSEG(pos)]; if (bt->size_in_chunk && (chunk = c->buf->header.chunk) != NOT_ASSIGNED) { - if (!(c->cp = WIN_MAP2(ii->chunk, ctx, &c->iw, chunk, bt->pos_in_chunk, - bt->size_in_chunk, grn_io_rdonly))) { + if (!(c->cp = WIN_MAP(ii->chunk, ctx, &c->iw, chunk, bt->pos_in_chunk, + bt->size_in_chunk, grn_io_rdonly))) { buffer_close(ctx, ii, c->buffer_pseg); GRN_FREE(c); c = NULL; @@ -4069,7 +4061,7 @@ grn_ii_cursor_open(grn_ctx *ctx, grn_ii *ii, grn_id tid, } if (!(c->cinfo = GRN_MALLOCN(chunk_info, c->nchunks))) { buffer_close(ctx, ii, c->buffer_pseg); - grn_io_win_unmap2(&c->iw); + grn_io_win_unmap(&c->iw); GRN_FREE(c); c = NULL; goto exit; @@ -4162,11 +4154,11 @@ grn_ii_cursor_next(grn_ctx *ctx, grn_ii_cursor *c) uint8_t *cp; grn_io_win iw; uint32_t size = c->cinfo[c->curr_chunk].size; - if (size && (cp = WIN_MAP2(c->ii->chunk, ctx, &iw, - c->cinfo[c->curr_chunk].segno, 0, - size, grn_io_rdonly))) { + if (size && (cp = WIN_MAP(c->ii->chunk, ctx, &iw, + c->cinfo[c->curr_chunk].segno, 0, + size, grn_io_rdonly))) { grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); if (chunk_is_reused(ctx, c->ii, c, c->cinfo[c->curr_chunk].segno, size)) { GRN_LOG(ctx, GRN_LOG_WARNING, @@ -4340,7 +4332,7 @@ grn_ii_cursor_close(grn_ctx *ctx, grn_ii_cursor *c) datavec_fin(ctx, c->rdv); if (c->cinfo) { GRN_FREE(c->cinfo); } if (c->buf) { buffer_close(ctx, c->ii, c->buffer_pseg); } - if (c->cp) { grn_io_win_unmap2(&c->iw); } + if (c->cp) { grn_io_win_unmap(&c->iw); } GRN_FREE(c); return GRN_SUCCESS; } @@ -4670,6 +4662,7 @@ inline static grn_rc index_del(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgram, const char *value, size_t value_len) { + grn_rc rc = GRN_SUCCESS; grn_hash *h; unsigned int token_flags = 0; grn_token_cursor *token_cursor; @@ -4702,12 +4695,16 @@ index_del(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgr grn_token_cursor_close(ctx, token_cursor); GRN_HASH_EACH(ctx, h, id, &tp, NULL, &u, { if (*tp) { - grn_ii_delete_one(ctx, ii, *tp, *u, NULL); + grn_rc r; + r = grn_ii_delete_one(ctx, ii, *tp, *u, NULL); + if (r) { + rc = r; + } } grn_ii_updspec_close(ctx, *u); }); grn_hash_close(ctx, h); - return GRN_SUCCESS; + return rc; } grn_rc @@ -4842,7 +4839,11 @@ grn_ii_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, unsigned i grn_hash_delete_by_id(ctx, new, eid, NULL); } } else { - grn_ii_delete_one(ctx, ii, *tp, *u, new); + grn_rc r; + r = grn_ii_delete_one(ctx, ii, *tp, *u, new); + if (r) { + rc = r; + } } grn_ii_updspec_close(ctx, *u); }); @@ -4867,7 +4868,8 @@ exit : static grn_rc grn_vector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, - grn_obj *in, grn_obj *out, grn_token_mode mode, grn_obj *posting) + grn_obj *in, grn_obj *out, grn_tokenize_mode mode, + grn_obj *posting) { int j; grn_id tid; @@ -4911,8 +4913,65 @@ grn_vector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, } static grn_rc -grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, - grn_obj *in, grn_obj *out) +grn_uvector2updspecs_data(grn_ctx *ctx, grn_ii *ii, grn_id rid, + unsigned int section, grn_obj *in, grn_obj *out, + grn_tokenize_mode mode, grn_obj *posting) +{ + int i, n; + grn_hash *h = (grn_hash *)out; + grn_obj *lexicon = ii->lexicon; + unsigned int element_size; + + n = grn_uvector_size(ctx, in); + element_size = grn_uvector_element_size(ctx, in); + for (i = 0; i < n; i++) { + grn_token_cursor *token_cursor; + unsigned int token_flags = 0; + const char *element; + + element = GRN_BULK_HEAD(in) + (element_size * i); + token_cursor = grn_token_cursor_open(ctx, lexicon, + element, element_size, + mode, token_flags); + if (!token_cursor) { + continue; + } + + while (!token_cursor->status) { + grn_id tid; + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + grn_ii_updspec **u; + + if (posting) { GRN_RECORD_PUT(ctx, posting, tid); } + if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&u, NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, section))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_open on grn_uvector2updspecs_data failed!"); + grn_token_cursor_close(ctx, token_cursor); + return GRN_NO_MEMORY_AVAILABLE; + } + } + if (grn_ii_updspec_add(ctx, *u, token_cursor->pos, 0)) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_add on grn_uvector2updspecs failed!"); + grn_token_cursor_close(ctx, token_cursor); + return GRN_NO_MEMORY_AVAILABLE; + } + } + } + + grn_token_cursor_close(ctx, token_cursor); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_uvector2updspecs_id(grn_ctx *ctx, grn_ii *ii, grn_id rid, + unsigned int section, grn_obj *in, grn_obj *out) { int i, n; grn_ii_updspec **u; @@ -4941,6 +5000,19 @@ grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, return GRN_SUCCESS; } +static grn_rc +grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, + unsigned int section, grn_obj *in, grn_obj *out, + grn_tokenize_mode mode, grn_obj *posting) +{ + if (in->header.domain < GRN_N_RESERVED_TYPES) { + return grn_uvector2updspecs_data(ctx, ii, rid, section, in, out, + mode, posting); + } else { + return grn_uvector2updspecs_id(ctx, ii, rid, section, in, out); + } +} + grn_rc grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, grn_obj *oldvalue, grn_obj *newvalue, grn_obj *posting) @@ -5001,7 +5073,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, rc = GRN_NO_MEMORY_AVAILABLE; } else { if (new_->header.type == GRN_UVECTOR) { - rc = grn_uvector2updspecs(ctx, ii, rid, section, new_, new); + rc = grn_uvector2updspecs(ctx, ii, rid, section, new_, new, + GRN_TOKEN_ADD, post); } else { grn_obj uvector; unsigned int weight = 0; @@ -5010,7 +5083,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, uvector.header.impl_flags |= GRN_OBJ_WITH_WEIGHT; } grn_uvector_add_element(ctx, &uvector, GRN_RECORD_VALUE(new_), weight); - rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, new); + rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, new, + GRN_TOKEN_ADD, post); GRN_OBJ_FIN(ctx, &uvector); } } @@ -5095,7 +5169,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, rc = GRN_NO_MEMORY_AVAILABLE; } else { if (old_->header.type == GRN_UVECTOR) { - rc = grn_uvector2updspecs(ctx, ii, rid, section, old_, old); + rc = grn_uvector2updspecs(ctx, ii, rid, section, old_, old, + GRN_TOKEN_DEL, NULL); } else { grn_obj uvector; unsigned int weight = 0; @@ -5104,7 +5179,8 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, uvector.header.impl_flags |= GRN_OBJ_WITH_WEIGHT; } grn_uvector_add_element(ctx, &uvector, GRN_RECORD_VALUE(old_), weight); - rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, old); + rc = grn_uvector2updspecs(ctx, ii, rid, section, &uvector, old, + GRN_TOKEN_DEL, NULL); GRN_OBJ_FIN(ctx, &uvector); } } @@ -5130,7 +5206,11 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, grn_hash_delete_by_id(ctx, n, eid, NULL); } } else { - grn_ii_delete_one(ctx, ii, *tp, *u, n); + grn_rc r; + r = grn_ii_delete_one(ctx, ii, *tp, *u, n); + if (r) { + rc = r; + } } grn_ii_updspec_close(ctx, *u); }); @@ -5362,7 +5442,7 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string, const char *key; uint32_t size; grn_rc rc = GRN_END_OF_DATA; - unsigned int token_flags = GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER; + unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER; grn_token_cursor *token_cursor = grn_token_cursor_open(ctx, lexicon, string, string_len, GRN_TOKEN_GET, @@ -5394,11 +5474,11 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string, tid = grn_token_cursor_next(ctx, token_cursor); if (token_cursor->force_prefix) { ef |= EX_PREFIX; } switch (token_cursor->status) { - case GRN_TOKEN_DOING : + case GRN_TOKEN_CURSOR_DOING : key = _grn_table_key(ctx, lexicon, tid, &size); ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, ef & EX_SUFFIX); break; - case GRN_TOKEN_DONE : + case GRN_TOKEN_CURSOR_DONE : ti = token_info_open(ctx, lexicon, ii, (const char *)token_cursor->curr, token_cursor->curr_size, 0, ef); /* @@ -5408,11 +5488,11 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string, token_cursor->orig_blen, token_cursor->pos, ef); */ break; - case GRN_TOKEN_NOT_FOUND : + case GRN_TOKEN_CURSOR_NOT_FOUND : ti = token_info_open(ctx, lexicon, ii, (char *)token_cursor->orig, token_cursor->orig_blen, 0, ef); break; - case GRN_TOKEN_DONE_SKIP : + case GRN_TOKEN_CURSOR_DONE_SKIP : *only_skip_token = GRN_TRUE; goto exit; default : @@ -5420,16 +5500,17 @@ token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string, } if (!ti) { goto exit ; } tis[(*n)++] = ti; - while (token_cursor->status == GRN_TOKEN_DOING) { + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { tid = grn_token_cursor_next(ctx, token_cursor); + if (token_cursor->force_prefix) { ef |= EX_PREFIX; } switch (token_cursor->status) { - case GRN_TOKEN_DONE_SKIP : + case GRN_TOKEN_CURSOR_DONE_SKIP : continue; - case GRN_TOKEN_DOING : + case GRN_TOKEN_CURSOR_DOING : key = _grn_table_key(ctx, lexicon, tid, &size); ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, EX_NONE); break; - case GRN_TOKEN_DONE : + case GRN_TOKEN_CURSOR_DONE : if (tid) { key = _grn_table_key(ctx, lexicon, tid, &size); ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, ef & EX_PREFIX); @@ -5460,7 +5541,7 @@ token_info_clear_offset(token_info **tis, uint32_t n) /* select */ inline static void -res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, uint32_t score, +res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, double score, grn_operator op) { grn_rset_recinfo *ri; @@ -5619,7 +5700,7 @@ typedef enum { grn_wv_constant } grn_wv_mode; -inline static int +inline static double get_weight(grn_ctx *ctx, grn_hash *s, grn_id rid, int sid, grn_wv_mode wvm, grn_select_optarg *optarg) { @@ -5656,7 +5737,7 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii, grn_rc rc = GRN_SUCCESS; grn_hash *h; grn_token_cursor *token_cursor; - unsigned int token_flags = GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER; + unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER; grn_obj *lexicon = ii->lexicon; if (!lexicon || !ii || !string || !string_len || !s || !optarg) { return GRN_INVALID_ARGUMENT; } if (!(h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(int), 0))) { @@ -5668,8 +5749,8 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii, return GRN_NO_MEMORY_AVAILABLE; } if (!(max_size = optarg->max_size)) { max_size = 1048576; } - while (token_cursor->status != GRN_TOKEN_DONE && - token_cursor->status != GRN_TOKEN_DONE_SKIP) { + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE && + token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) { if ((tid = grn_token_cursor_next(ctx, token_cursor))) { if (grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&w1, NULL)) { (*w1)++; } } @@ -5749,7 +5830,7 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii, if (rep) { while (grn_ii_cursor_next(ctx, c)) { pos = c->post; - if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg))) { + if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg)) > 0) { while (grn_ii_cursor_next_pos(ctx, c)) { res_add(ctx, s, (grn_rset_posinfo *) pos, *w1 * w2 * (1 + pos->weight), op); } @@ -5758,7 +5839,7 @@ grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii, } else { while (grn_ii_cursor_next(ctx, c)) { pos = c->post; - if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg))) { + if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg)) > 0) { res_add(ctx, s, (grn_rset_posinfo *) pos, *w1 * w2 * (pos->tf + pos->weight), op); } } @@ -5859,6 +5940,213 @@ grn_ii_term_extract(grn_ctx *ctx, grn_ii *ii, const char *string, return rc; } +#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH +static grn_bool +grn_ii_select_sequential_search_should_use(grn_ctx *ctx, + grn_ii *ii, + const char *raw_query, + unsigned int raw_query_len, + grn_hash *result, + grn_operator op, + grn_wv_mode wvm, + grn_select_optarg *optarg, + token_info **token_infos, + uint32_t n_token_infos, + double too_many_index_match_ratio) +{ + int n_sources; + + if (too_many_index_match_ratio < 0.0) { + return GRN_FALSE; + } + + if (op != GRN_OP_AND) { + return GRN_FALSE; + } + + if (optarg->mode != GRN_OP_EXACT) { + return GRN_FALSE; + } + + n_sources = ii->obj.source_size / sizeof(grn_id); + if (n_sources == 0) { + return GRN_FALSE; + } + + { + uint32_t i; + int n_existing_records; + + n_existing_records = GRN_HASH_SIZE(result); + for (i = 0; i < n_token_infos; i++) { + token_info *info = token_infos[i]; + if (n_existing_records <= (info->size * too_many_index_match_ratio)) { + return GRN_TRUE; + } + } + return GRN_FALSE; + } +} + +static void +grn_ii_select_sequential_search_body(grn_ctx *ctx, + grn_ii *ii, + grn_obj *normalizer, + grn_encoding encoding, + OnigRegex regex, + grn_hash *result, + grn_operator op, + grn_wv_mode wvm, + grn_select_optarg *optarg) +{ + int i, n_sources; + grn_id *source_ids = ii->obj.source; + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + n_sources = ii->obj.source_size / sizeof(grn_id); + for (i = 0; i < n_sources; i++) { + grn_id source_id = source_ids[i]; + grn_obj *source; + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + grn_obj *accessor; + + source = grn_ctx_at(ctx, source_id); + column_name_size = grn_column_name(ctx, source, + column_name, + GRN_TABLE_MAX_KEY_SIZE); + accessor = grn_obj_column(ctx, (grn_obj *)result, column_name, + column_name_size); + { + grn_hash_cursor *cursor; + grn_id id; + cursor = grn_hash_cursor_open(ctx, result, NULL, 0, NULL, 0, 0, -1, 0); + while ((id = grn_hash_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + OnigPosition position; + grn_obj *value; + const char *normalized_value; + unsigned int normalized_value_length; + + GRN_BULK_REWIND(&buffer); + grn_obj_get_value(ctx, accessor, id, &buffer); + value = grn_string_open_(ctx, + GRN_TEXT_VALUE(&buffer), + GRN_TEXT_LEN(&buffer), + normalizer, 0, encoding); + grn_string_get_normalized(ctx, value, + &normalized_value, &normalized_value_length, + NULL); + position = onig_search(regex, + normalized_value, + normalized_value + normalized_value_length, + normalized_value, + normalized_value + normalized_value_length, + NULL, + 0); + if (position != ONIG_MISMATCH) { + grn_rset_posinfo info; + double score; + info.rid = id; + info.sid = i + 1; + info.pos = 0; + score = get_weight(ctx, result, info.rid, info.sid, wvm, optarg); + res_add(ctx, result, &info, score, op); + } + grn_obj_unlink(ctx, value); + } + grn_hash_cursor_close(ctx, cursor); + } + grn_obj_unlink(ctx, accessor); + } + grn_obj_unlink(ctx, &buffer); +} + +static grn_bool +grn_ii_select_sequential_search(grn_ctx *ctx, + grn_ii *ii, + const char *raw_query, + unsigned int raw_query_len, + grn_hash *result, + grn_operator op, + grn_wv_mode wvm, + grn_select_optarg *optarg, + token_info **token_infos, + uint32_t n_token_infos) +{ + grn_bool processed = GRN_TRUE; + + { + /* Disabled by default. */ + double too_many_index_match_ratio = -1; + const char *too_many_index_match_ratio_env = + getenv("GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO"); + if (too_many_index_match_ratio_env) { + too_many_index_match_ratio = atof(too_many_index_match_ratio_env); + } + + if (!grn_ii_select_sequential_search_should_use(ctx, + ii, + raw_query, + raw_query_len, + result, + op, + wvm, + optarg, + token_infos, + n_token_infos, + too_many_index_match_ratio)) { + return GRN_FALSE; + } + } + + { + grn_encoding encoding; + grn_obj *normalizer; + int nflags = 0; + grn_obj *query; + const char *normalized_query; + unsigned int normalized_query_length; + + grn_table_get_info(ctx, ii->lexicon, + NULL, &encoding, NULL, &normalizer, NULL); + query = grn_string_open_(ctx, raw_query, raw_query_len, + normalizer, nflags, encoding); + grn_string_get_normalized(ctx, query, + &normalized_query, &normalized_query_length, + NULL); + { + OnigRegex regex; + int onig_result; + OnigErrorInfo error_info; + onig_result = onig_new(®ex, + normalized_query, + normalized_query + normalized_query_length, + ONIG_OPTION_NONE, + ONIG_ENCODING_UTF8, + ONIG_SYNTAX_ASIS, + &error_info); + if (onig_result == ONIG_NORMAL) { + grn_ii_select_sequential_search_body(ctx, ii, normalizer, encoding, + regex, result, op, wvm, optarg); + onig_free(regex); + } else { + char message[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_error_code_to_str(message, onig_result, error_info); + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][select][sequential] " + "failed to create regular expression object: %s", + message); + processed = GRN_FALSE; + } + } + grn_obj_unlink(ctx, query); + } + + return processed; +} +#endif + grn_rc grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len, grn_hash *s, grn_operator op, grn_select_optarg *optarg) @@ -5872,6 +6160,10 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_ grn_operator mode = GRN_OP_EXACT; grn_wv_mode wvm = grn_wv_none; grn_obj *lexicon = ii->lexicon; + grn_scorer_score_func *score_func = NULL; + void *score_func_user_data = NULL; + grn_scorer_matched_record record; + if (!lexicon || !ii || !s) { return GRN_INVALID_ARGUMENT; } if (optarg) { mode = optarg->mode; @@ -5938,6 +6230,30 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_ goto exit; } */ +#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH + if (grn_ii_select_sequential_search(ctx, ii, string, string_len, + s, op, wvm, optarg, tis, n)) { + goto exit; + } +#endif + + if (optarg && optarg->scorer) { + grn_proc *scorer = (grn_proc *)(optarg->scorer); + score_func = scorer->callbacks.scorer.score; + score_func_user_data = scorer->user_data; + record.table = grn_ctx_at(ctx, s->obj.header.domain); + record.lexicon = lexicon; + record.id = GRN_ID_NIL; + GRN_RECORD_INIT(&(record.terms), GRN_OBJ_VECTOR, lexicon->header.domain); + GRN_UINT32_INIT(&(record.term_weights), GRN_OBJ_VECTOR); + record.total_term_weights = 0; + record.n_documents = grn_table_size(ctx, record.table); + record.n_occurrences = 0; + record.n_candidates = 0; + record.n_tokens = 0; + record.weight = 0; + } + for (;;) { rid = (*tis)->p->rid; sid = (*tis)->p->sid; @@ -5951,11 +6267,18 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_ } } weight = get_weight(ctx, s, rid, sid, wvm, optarg); - if (tip == tie && weight) { + if (tip == tie && weight > 0) { grn_rset_posinfo pi = {rid, sid, 0}; if (orp || grn_hash_get(ctx, s, &pi, s->key_size, NULL)) { int count = 0, noccur = 0, pos = 0, score = 0, tscore = 0, min, max; + if (score_func) { + GRN_BULK_REWIND(&(record.terms)); + GRN_BULK_REWIND(&(record.term_weights)); + record.n_candidates = 0; + record.n_tokens = 0; + } + #define SKIP_OR_BREAK(pos) {\ if (token_info_skip_pos(ctx, ti, rid, sid, pos)) { break; } \ if (ti->p->rid != rid || ti->p->sid != sid) { \ @@ -5967,6 +6290,13 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_ if (n == 1 && !rep) { noccur = (*tis)->p->tf; tscore = (*tis)->p->weight; + if (score_func) { + GRN_RECORD_PUT(ctx, &(record.terms), (*tis)->cursors->bins[0]->id); + GRN_UINT32_PUT(ctx, &(record.term_weights), tscore); + record.n_occurrences = noccur; + record.n_candidates = (*tis)->size; + record.n_tokens = (*tis)->ntoken; + } } else if (mode == GRN_OP_NEAR) { bt_zap(bt); for (tip = tis; tip < tie; tip++) { @@ -6003,6 +6333,18 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_ score += ti->p->weight; count++; } else { score = ti->p->weight; count = 1; pos = ti->pos; + if (noccur == 0 && score_func) { + GRN_BULK_REWIND(&(record.terms)); + GRN_BULK_REWIND(&(record.term_weights)); + record.n_candidates = 0; + record.n_tokens = 0; + } + } + if (noccur == 0 && score_func) { + GRN_RECORD_PUT(ctx, &(record.terms), ti->cursors->bins[0]->id); + GRN_UINT32_PUT(ctx, &(record.term_weights), ti->p->weight); + record.n_candidates += ti->size; + record.n_tokens += ti->ntoken; } if (count == n) { if (rep) { pi.pos = pos; res_add(ctx, s, &pi, (score + 1) * weight, op); } @@ -6012,13 +6354,29 @@ grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_ } } } - if (noccur && !rep) { res_add(ctx, s, &pi, (noccur + tscore) * weight, op); } + if (noccur && !rep) { + double record_score; + if (score_func) { + record.id = rid; + record.weight = weight; + record.n_occurrences = noccur; + record.total_term_weights = tscore; + record_score = score_func(ctx, &record) * weight; + } else { + record_score = (noccur + tscore) * weight; + } + res_add(ctx, s, &pi, record_score, op); + } #undef SKIP_OR_BREAK } } if (token_info_skip(ctx, *tis, nrid, nsid)) { goto exit; } } exit : + if (score_func) { + GRN_OBJ_FIN(ctx, &(record.terms)); + GRN_OBJ_FIN(ctx, &(record.term_weights)); + } for (tip = tis; tip < tis + n; tip++) { if (*tip) { token_info_close(ctx, *tip); } } @@ -6046,7 +6404,7 @@ grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len ERRCLR(ctx); GRN_LOG(ctx, GRN_LOG_INFO, "grn_ii_sel > (%.*s)", string_len, string); { - grn_select_optarg arg = {GRN_OP_EXACT, 0, 0, NULL, 0, NULL, NULL, 0}; + grn_select_optarg arg = {GRN_OP_EXACT, 0, 0, NULL, 0, NULL, NULL, 0, NULL}; if (!s) { return GRN_INVALID_ARGUMENT; } if (optarg) { switch (optarg->mode) { @@ -6066,6 +6424,7 @@ grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len arg.weight_vector = optarg->weight_vector; arg.vector_size = optarg->vector_size; } + arg.scorer = optarg->scorer; } /* todo : support subrec grn_rset_init(ctx, s, grn_rec_document, 0, grn_rec_none, 0, 0); @@ -6198,11 +6557,11 @@ grn_ii_cursor_next_all(grn_ctx *ctx, grn_ii_cursor *c) uint8_t *cp; grn_io_win iw; uint32_t size = c->cinfo[c->curr_chunk].size; - if (size && (cp = WIN_MAP2(c->ii->chunk, ctx, &iw, - c->cinfo[c->curr_chunk].segno, 0, - size, grn_io_rdonly))) { + if (size && (cp = WIN_MAP(c->ii->chunk, ctx, &iw, + c->cinfo[c->curr_chunk].segno, 0, + size, grn_io_rdonly))) { grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } else { c->pc.rid = 0; break; @@ -6367,7 +6726,7 @@ grn_ii_cursor_inspect(grn_ctx *ctx, grn_ii_cursor *c, grn_obj *buf) } void -grn_ii_inspect_elements(grn_ctx *ctx, grn_ii *ii, grn_obj *buf) +grn_ii_inspect_values(grn_ctx *ctx, grn_ii *ii, grn_obj *buf) { grn_table_cursor *tc; GRN_TEXT_PUTS(ctx, buf, "["); @@ -6426,8 +6785,8 @@ typedef struct { } ii_buffer_counter; typedef struct { - off_t head; - off_t tail; + off64_t head; + off64_t tail; uint32_t nextsize; uint8_t *buffer; uint32_t buffersize; @@ -6450,7 +6809,7 @@ struct _grn_ii_buffer { char tmpfpath[PATH_MAX]; uint64_t update_buffer_size; // stuff for parsing - off_t filepos; + off64_t filepos; grn_id *block_buf; size_t block_buf_size; size_t block_pos; @@ -6521,7 +6880,7 @@ allocate_outbuf(grn_ctx *ctx, grn_ii_buffer *ii_buffer) bufsize_ = bufsize; } } - GRN_LOG(ctx, GRN_LOG_INFO, "flushing:%d bufsize:%zu", + GRN_LOG(ctx, GRN_LOG_INFO, "flushing:%d bufsize:%" GRN_FMT_SIZE, ii_buffer->nblocks, bufsize); return (uint8_t *)GRN_MALLOC(bufsize); } @@ -6679,7 +7038,7 @@ grn_ii_buffer_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer) size_t encsize; uint8_t *outbuf; ii_buffer_block *block; - GRN_LOG(ctx, GRN_LOG_NOTICE, "flushing:%d npostings:%zu", + GRN_LOG(ctx, GRN_LOG_NOTICE, "flushing:%d npostings:%" GRN_FMT_SIZE, ii_buffer->nblocks, ii_buffer->block_pos); if (!(block = block_new(ctx, ii_buffer))) { return; } if (!(outbuf = allocate_outbuf(ctx, ii_buffer))) { return; } @@ -6701,7 +7060,7 @@ grn_ii_buffer_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer) grn_table_size(ctx, ii_buffer->tmp_lexicon) * sizeof(ii_buffer_counter)); grn_obj_close(ctx, ii_buffer->tmp_lexicon); - GRN_LOG(ctx, GRN_LOG_NOTICE, "flushed: %d encsize:%zu", + GRN_LOG(ctx, GRN_LOG_NOTICE, "flushed: %d encsize:%" GRN_FMT_SIZE, ii_buffer->nblocks, encsize); ii_buffer->tmp_lexicon = NULL; ii_buffer->nblocks++; @@ -6719,9 +7078,10 @@ get_tmp_lexicon(grn_ctx *ctx, grn_ii_buffer *ii_buffer) grn_obj *range = grn_ctx_at(ctx, DB_OBJ(ii_buffer->lexicon)->range); grn_obj *tokenizer; grn_obj *normalizer; + grn_obj *token_filters; grn_obj_flags flags; grn_table_get_info(ctx, ii_buffer->lexicon, &flags, NULL, - &tokenizer, &normalizer, NULL); + &tokenizer, &normalizer, &token_filters); flags &= ~GRN_OBJ_PERSISTENT; tmp_lexicon = grn_table_create(ctx, NULL, 0, NULL, flags, domain, range); if (tmp_lexicon) { @@ -6730,6 +7090,8 @@ get_tmp_lexicon(grn_ctx *ctx, grn_ii_buffer *ii_buffer) GRN_INFO_DEFAULT_TOKENIZER, tokenizer); grn_obj_set_info(ctx, tmp_lexicon, GRN_INFO_NORMALIZER, normalizer); + grn_obj_set_info(ctx, tmp_lexicon, + GRN_INFO_TOKEN_FILTERS, token_filters); if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_PAT_KEY) { grn_pat_cache_enable(ctx, (grn_pat *)tmp_lexicon, PAT_CACHE_SIZE); } @@ -6857,8 +7219,8 @@ grn_ii_buffer_fetch(grn_ctx *ctx, grn_ii_buffer *ii_buffer, return; } } - if (lseek(ii_buffer->tmpfd, block->head, SEEK_SET) != block->head) { - SERR("lseek"); + if (grn_lseek(ii_buffer->tmpfd, block->head, SEEK_SET) != block->head) { + SERR("grn_lseek"); return; } if (read(ii_buffer->tmpfd, block->buffer, bytesize) != bytesize) { @@ -6870,7 +7232,8 @@ grn_ii_buffer_fetch(grn_ctx *ctx, grn_ii_buffer *ii_buffer, if (block->head >= block->tail) { if (block->head > block->tail) { GRN_LOG(ctx, GRN_LOG_WARNING, - "fetch error: %jd > %jd", block->head, block->tail); + "fetch error: %" GRN_FMT_INT64D " > %" GRN_FMT_INT64D, + block->head, block->tail); } block->rest = block->nextsize; block->nextsize = 0; @@ -6899,11 +7262,11 @@ grn_ii_buffer_chunk_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer) grn_io_win io_win; uint32_t chunk_number; chunk_new(ctx, ii_buffer->ii, &chunk_number, ii_buffer->packed_len); - GRN_LOG(ctx, GRN_LOG_INFO, "chunk:%d, packed_len:%zu", + GRN_LOG(ctx, GRN_LOG_INFO, "chunk:%d, packed_len:%" GRN_FMT_SIZE, chunk_number, ii_buffer->packed_len); - fake_map2(ctx, ii_buffer->ii->chunk, &io_win, ii_buffer->packed_buf, - chunk_number, ii_buffer->packed_len); - grn_io_win_unmap2(&io_win); + fake_map(ctx, ii_buffer->ii->chunk, &io_win, ii_buffer->packed_buf, + chunk_number, ii_buffer->packed_len); + grn_io_win_unmap(&io_win); ii_buffer->term_buffer->header.chunk = chunk_number; ii_buffer->term_buffer->header.chunk_size = ii_buffer->packed_len; ii_buffer->term_buffer->header.buffer_free = @@ -7165,11 +7528,15 @@ grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii, if (ii_buffer->counters) { ii_buffer->block_buf = GRN_MALLOCN(grn_id, II_BUFFER_BLOCK_SIZE); if (ii_buffer->block_buf) { + int open_flags = 0; +#ifdef WIN32 + open_flags |= O_BINARY; +#endif snprintf(ii_buffer->tmpfpath, PATH_MAX, "%sXXXXXX", grn_io_path(ii->seg)); ii_buffer->block_buf_size = II_BUFFER_BLOCK_SIZE; ii_buffer->tmpfd = GRN_MKOSTEMP(ii_buffer->tmpfpath, - O_WRONLY|O_CREAT|O_TRUNC, + open_flags, S_IRUSR|S_IWUSR); if (ii_buffer->tmpfd != -1) { grn_obj_flags flags; @@ -7283,7 +7650,7 @@ grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer) } datavec_fin(ctx, ii_buffer->data_vectors); GRN_LOG(ctx, GRN_LOG_NOTICE, - "tmpfile_size:%jd > total_chunk_size:%" GRN_FMT_INT64U, + "tmpfile_size:%" GRN_FMT_INT64D " > total_chunk_size:%" GRN_FMT_SIZE, ii_buffer->filepos, ii_buffer->total_chunk_size); GRN_CLOSE(ii_buffer->tmpfd); unlink(ii_buffer->tmpfpath); diff --git a/storage/mroonga/vendor/groonga/lib/io.c b/storage/mroonga/vendor/groonga/lib/io.c index 067832ee77b..2ea581b8db7 100644 --- a/storage/mroonga/vendor/groonga/lib/io.c +++ b/storage/mroonga/vendor/groonga/lib/io.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2012 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,25 +15,32 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" +#include <stdlib.h> #include <stdio.h> - -#ifndef __USE_GNU -#define __USE_GNU /* O_DIRECT */ -#endif /* __USE_GNU */ #include <fcntl.h> #include <string.h> #include <sys/stat.h> -#include "ctx.h" -#include "io.h" -#include "plugin_in.h" -#include "hash.h" -#include "ctx_impl.h" +#include "grn_ctx.h" +#include "grn_io.h" +#include "grn_plugin.h" +#include "grn_hash.h" +#include "grn_ctx_impl.h" #define GRN_IO_IDSTR "GROONGA:IO:00001" +#define GRN_IO_VERSION_DEFAULT 0 + +#define GRN_IO_FILE_SIZE_V1 1073741824UL + +#ifdef WIN32 +# define GRN_IO_FILE_SIZE_V0 134217728L +#else /* WIN32 */ +# define GRN_IO_FILE_SIZE_V0 GRN_IO_FILE_SIZE_V1 +#endif /* WIN32 */ + #ifndef O_BINARY # ifdef _O_BINARY # define O_BINARY _O_BINARY @@ -56,31 +63,42 @@ typedef struct _grn_io_fileinfo { #define IO_HEADER_SIZE 64 -inline static grn_rc grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize); +static uint32_t grn_io_version_default = GRN_IO_VERSION_DEFAULT; + +inline static grn_rc grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags); inline static void grn_fileinfo_init(fileinfo *fis, int nfis); inline static int grn_opened(fileinfo *fi); inline static grn_rc grn_close(grn_ctx *ctx, fileinfo *fi); -#if defined(WIN32) && defined(WIN32_FMO_EACH) -inline static void * grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, +#ifdef WIN32 +inline static void * grn_mmap(grn_ctx *ctx, grn_io *io, + HANDLE *fmo, fileinfo *fi, off_t offset, size_t length); -inline static int grn_munmap(grn_ctx *ctx, HANDLE *fmo, void *start, size_t length); -#define GRN_MMAP(ctx,fmo,fi,offset,length)\ - (grn_mmap((ctx), (fmo), (fi), (offset), (length))) -#define GRN_MUNMAP(ctx,fmo,start,length) (grn_munmap((ctx), (fmo), (start), (length))) -#else /* defined(WIN32) && defined(WIN32_FMO_EACH) */ -inline static void * grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length); -inline static int grn_munmap(grn_ctx *ctx, void *start, size_t length); -#define GRN_MUNMAP(ctx,fmo,start,length) (grn_munmap((ctx), (start), (length))) -#ifdef USE_FAIL_MALLOC -inline static void * grn_fail_mmap(grn_ctx *ctx, fileinfo *fi, +inline static int grn_munmap(grn_ctx *ctx, grn_io *io, + HANDLE *fmo, fileinfo *fi, + void *start, size_t length); +# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\ + (grn_mmap((ctx), (io), (fmo), (fi), (offset), (length))) +# define GRN_MUNMAP(ctx,io,fmo,fi,start,length)\ + (grn_munmap((ctx), (io), (fmo), (fi), (start), (length))) +#else /* WIN32 */ +inline static void * grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, + off_t offset, size_t length); +inline static int grn_munmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, + void *start, size_t length); +# define GRN_MUNMAP(ctx,io,fmo,fi,start,length) \ + (grn_munmap((ctx), (io), (fi), (start), (length))) +# ifdef USE_FAIL_MALLOC +inline static void * grn_fail_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length, const char* file, int line, const char *func); -#define GRN_MMAP(ctx,fmo,fi,offset,length) \ - (grn_fail_mmap((ctx), (fi), (offset), (length), __FILE__, __LINE__, __FUNCTION__)) -#else /* USE_FAIL_MALLOC */ -#define GRN_MMAP(ctx,fmo,fi,offset,length) (grn_mmap((ctx), (fi), (offset), (length))) -#endif /* USE_FAIL_MALLOC */ -#endif /* defined(WIN32) && defined(WIN32_FMO_EACH) */ +# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\ + (grn_fail_mmap((ctx), (io), (fi), (offset), (length),\ + __FILE__, __LINE__, __FUNCTION__)) +# else /* USE_FAIL_MALLOC */ +# define GRN_MMAP(ctx,io,fmo,fi,offset,length)\ + (grn_mmap((ctx), (io), (fi), (offset), (length))) +# endif /* USE_FAIL_MALLOC */ +#endif /* WIN32 */ inline static int grn_msync(grn_ctx *ctx, void *start, size_t length); inline static grn_rc grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset); inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset); @@ -88,6 +106,13 @@ inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t co grn_rc grn_io_init(void) { + const char *version_env; + + version_env = getenv("GRN_IO_VERSION"); + if (version_env) { + grn_io_version_default = atoi(version_env); + } + return GRN_SUCCESS; } @@ -97,17 +122,72 @@ grn_io_fin(void) return GRN_SUCCESS; } +static inline uint32_t +grn_io_compute_base(uint32_t header_size) +{ + uint32_t total_header_size; + total_header_size = IO_HEADER_SIZE + header_size; + return (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1); +} + +static inline uint32_t +grn_io_compute_base_segment(uint32_t base, uint32_t segment_size) +{ + return (base + segment_size - 1) / segment_size; +} + +static uint32_t +grn_io_compute_max_n_files(uint32_t segment_size, uint32_t max_segment, + unsigned int base_segument, unsigned long file_size) +{ + uint64_t last_segment_end; + last_segment_end = ((uint64_t)segment_size) * (max_segment + base_segument); + return (uint32_t)((last_segment_end + file_size - 1) / file_size); +} + +static inline unsigned long +grn_io_compute_file_size(uint32_t version) +{ + if (version == 0) { + return GRN_IO_FILE_SIZE_V0; + } else { + return GRN_IO_FILE_SIZE_V1; + } +} + +static inline uint32_t +grn_io_max_segment(grn_io *io) +{ + if (io->header->segment_tail) { + return io->header->segment_tail; + } else { + return io->header->max_segment; + } +} + +static uint32_t +grn_io_max_n_files(grn_io *io) +{ + unsigned long file_size; + + file_size = grn_io_compute_file_size(io->header->version); + return grn_io_compute_max_n_files(io->header->segment_size, + grn_io_max_segment(io), + io->base_seg, + file_size); +} + grn_io * grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, uint32_t max_segment, grn_io_mode mode, uint32_t flags) { grn_io *io; - unsigned int b; - uint32_t total_header_size; + uint32_t b; struct _grn_io_header *header; - total_header_size = IO_HEADER_SIZE + header_size; - b = (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1); - if ((header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, NULL, 0, b))) { + b = grn_io_compute_base(header_size); + header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, NULL, NULL, 0, b); + if (header) { + header->version = grn_io_version_default; header->header_size = header_size; header->segment_size = segment_size; header->max_segment = max_segment; @@ -117,8 +197,7 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, memcpy(header->idstr, GRN_IO_IDSTR, 16); if ((io = GRN_GMALLOCN(grn_io, 1))) { grn_io_mapinfo *maps = NULL; - if (((maps = GRN_GMALLOCN(grn_io_mapinfo, max_segment)) && - memset(maps, 0, sizeof(grn_io_mapinfo) * max_segment))) { + if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) { io->header = header; io->user_header = (((byte *) header) + IO_HEADER_SIZE); io->maps = maps; @@ -138,7 +217,7 @@ grn_io_create_tmp(uint32_t header_size, uint32_t segment_size, } GRN_GFREE(io); } - GRN_MUNMAP(&grn_gctx, NULL, header, b); + GRN_MUNMAP(&grn_gctx, NULL, NULL, NULL, header, b); } return NULL; } @@ -187,23 +266,28 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg { grn_io *io; fileinfo *fis; - unsigned int b, max_nfiles; - uint32_t bs, total_header_size; + uint32_t b, max_nfiles; + uint32_t bs; struct _grn_io_header *header; + uint32_t version = grn_io_version_default; + unsigned long file_size; + if (!path) { return grn_io_create_tmp(header_size, segment_size, max_segment, mode, flags); } if (!*path || (strlen(path) > PATH_MAX - 4)) { return NULL; } - total_header_size = IO_HEADER_SIZE + header_size; - b = (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1); - bs = (b + segment_size - 1) / segment_size; - max_nfiles = (unsigned int)( - ((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1) - / GRN_IO_FILE_SIZE); + b = grn_io_compute_base(header_size); + bs = grn_io_compute_base_segment(b, segment_size); + file_size = grn_io_compute_file_size(version); + max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment, + bs, file_size); if ((fis = GRN_GMALLOCN(fileinfo, max_nfiles))) { grn_fileinfo_init(fis, max_nfiles); - if (!grn_open(ctx, fis, path, O_RDWR|O_CREAT|O_EXCL, GRN_IO_FILE_SIZE)) { - if ((header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, &fis->fmo, fis, 0, b))) { + if (!grn_open(ctx, fis, path, O_RDWR|O_CREAT|O_EXCL)) { + header = (struct _grn_io_header *)GRN_MMAP(&grn_gctx, NULL, + &fis->fmo, fis, 0, b); + if (header) { + header->version = version; header->header_size = header_size; header->segment_size = segment_size; header->max_segment = max_segment; @@ -214,8 +298,7 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg grn_msync(ctx, header, b); if ((io = GRN_GMALLOCN(grn_io, 1))) { grn_io_mapinfo *maps = NULL; - if (((maps = GRN_GMALLOCN(grn_io_mapinfo, max_segment)) && - memset(maps, 0, sizeof(grn_io_mapinfo) * max_segment))) { + if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) { strncpy(io->path, path, PATH_MAX); io->header = header; io->user_header = (((byte *) header) + IO_HEADER_SIZE); @@ -236,7 +319,7 @@ grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, uint32_t seg } GRN_GFREE(io); } - GRN_MUNMAP(&grn_gctx, &fis->fmo, header, b); + GRN_MUNMAP(&grn_gctx, NULL, &fis->fmo, fis, header, b); } grn_close(ctx, fis); } @@ -419,10 +502,9 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) { grn_io *io; struct stat s; - fileinfo *fis; + fileinfo fi; uint32_t flags = 0; - unsigned int b, max_nfiles; - uint32_t total_header_size; + uint32_t b; uint32_t header_size = 0, segment_size = 0, max_segment = 0, bs; if (!path || !*path || (strlen(path) > PATH_MAX - 4)) { return NULL; } { @@ -444,17 +526,28 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) GRN_CLOSE(fd); if (!segment_size) { return NULL; } } - total_header_size = IO_HEADER_SIZE + header_size; - b = (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1); - bs = (b + segment_size - 1) / segment_size; - max_nfiles = (unsigned int)( - ((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1) - / GRN_IO_FILE_SIZE); - if (!(fis = GRN_GMALLOCN(fileinfo, max_nfiles))) { return NULL; } - grn_fileinfo_init(fis, max_nfiles); - if (!grn_open(ctx, fis, path, O_RDWR, GRN_IO_FILE_SIZE)) { + b = grn_io_compute_base(header_size); + bs = grn_io_compute_base_segment(b, segment_size); + grn_fileinfo_init(&fi, 1); + if (!grn_open(ctx, &fi, path, O_RDWR)) { struct _grn_io_header *header; - if ((header = GRN_MMAP(&grn_gctx, &fis->fmo, fis, 0, b))) { + header = GRN_MMAP(&grn_gctx, NULL, &(fi.fmo), &fi, 0, b); + if (header) { + unsigned long file_size; + unsigned int max_nfiles; + fileinfo *fis; + + file_size = grn_io_compute_file_size(header->version); + max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment, + bs, file_size); + fis = GRN_GMALLOCN(fileinfo, max_nfiles); + if (!fis) { + GRN_MUNMAP(&grn_gctx, NULL, &(fi.fmo), &fi, header, b); + grn_close(ctx, &fi); + return NULL; + } + grn_fileinfo_init(fis, max_nfiles); + memcpy(fis, &fi, sizeof(fileinfo)); if ((io = GRN_GMALLOC(sizeof(grn_io)))) { grn_io_mapinfo *maps = NULL; if ((maps = GRN_GCALLOC(sizeof(grn_io_mapinfo) * max_segment))) { @@ -482,51 +575,57 @@ grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) } GRN_GFREE(io); } - GRN_MUNMAP(&grn_gctx, &fis->fmo, header, b); + GRN_GFREE(fis); + GRN_MUNMAP(&grn_gctx, NULL, &(fi.fmo), &fi, header, b); } - grn_close(ctx, fis); + grn_close(ctx, &fi); } - GRN_GFREE(fis); return NULL; } grn_rc grn_io_close(grn_ctx *ctx, grn_io *io) { - int i; - grn_io_mapinfo *mi; - fileinfo *fi; - uint32_t bs = io->base_seg; - uint32_t max_segment = io->header->segment_tail - ? io->header->segment_tail : io->header->max_segment; - uint32_t segment_size = io->header->segment_size; - unsigned int max_nfiles = (unsigned int)( - ((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1) - / GRN_IO_FILE_SIZE); + uint32_t max_nfiles; + + max_nfiles = grn_io_max_n_files(io); grn_io_unregister(io); if (io->ainfo) { GRN_GFREE(io->ainfo); } if (io->maps) { - for (mi = io->maps, i = max_segment; i; mi++, i--) { + int i; + uint32_t max_segment; + uint32_t segment_size; + unsigned long file_size; + uint32_t segments_per_file; + + max_segment = grn_io_max_segment(io); + segment_size = io->header->segment_size; + file_size = grn_io_compute_file_size(io->header->version); + segments_per_file = file_size / segment_size; + for (i = 0; i < max_segment; i++) { + grn_io_mapinfo *mi; + mi = &(io->maps[i]); if (mi->map) { + fileinfo *fi = NULL; /* if (atomic_read(mi->nref)) { return STILL_IN_USE ; } */ -#ifdef WIN32 - if ((io->flags & GRN_IO_TEMPORARY)) { - GRN_GFREE(mi->map); - } else -#endif /* WIN32 */ - GRN_MUNMAP(&grn_gctx, &mi->fmo, mi->map, segment_size); + if (io->fis) { + uint32_t bseg = i + io->base_seg; + uint32_t fno = bseg / segments_per_file; + fi = &io->fis[fno]; + } + GRN_MUNMAP(&grn_gctx, io, &mi->fmo, fi, mi->map, segment_size); } } GRN_GFREE(io->maps); } -#ifdef WIN32 - if ((io->flags & GRN_IO_TEMPORARY)) { - GRN_GFREE(io->header); - } else -#endif /* WIN32 */ - GRN_MUNMAP(&grn_gctx, &io->fis->fmo, io->header, io->base); + GRN_MUNMAP(&grn_gctx, io, (io->fis ? &io->fis->fmo : NULL), + io->fis, io->header, io->base); if (io->fis) { - for (fi = io->fis, i = max_nfiles; i; fi++, i--) { grn_close(ctx, fi); } + int i; + for (i = 0; i < max_nfiles; i++) { + fileinfo *fi = &(io->fis[i]); + grn_close(ctx, fi); + } GRN_GFREE(io->fis); } GRN_GFREE(io); @@ -590,14 +689,13 @@ grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size) uint64_t tsize = 0; char buffer[PATH_MAX]; uint32_t nfiles; + if (io->header->curr_size) { - nfiles = (uint32_t) ((io->header->curr_size + GRN_IO_FILE_SIZE - 1) / GRN_IO_FILE_SIZE); + unsigned long file_size; + file_size = grn_io_compute_file_size(io->header->version); + nfiles = (uint32_t) ((io->header->curr_size + file_size - 1) / file_size); } else { - uint32_t bs = io->base_seg; - uint32_t max_segment = io->header->max_segment; - uint32_t segment_size = io->header->segment_size; - nfiles = (uint32_t) (((uint64_t)segment_size * (max_segment + bs) + GRN_IO_FILE_SIZE - 1) - / GRN_IO_FILE_SIZE); + nfiles = grn_io_max_n_files(io); } for (fno = 0; fno < nfiles; fno++) { gen_pathname(io->path, buffer, fno); @@ -675,7 +773,8 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, { uint32_t rest = 0, size = *value_len + sizeof(grn_io_ja_ehead); uint32_t segment_size = io->header->segment_size; - uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size; + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; uint32_t bseg = segment + io->base_seg; int fno = bseg / segments_per_file; fileinfo *fi = &io->fis[fno]; @@ -687,14 +786,14 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, *value_len = 0; return GRN_NO_MEMORY_AVAILABLE; } - if (pos + size > GRN_IO_FILE_SIZE) { - rest = pos + size - GRN_IO_FILE_SIZE; - size = GRN_IO_FILE_SIZE - pos; + if (pos + size > file_size) { + rest = pos + size - file_size; + size = file_size - pos; } if (!grn_opened(fi)) { char path[PATH_MAX]; gen_pathname(io->path, path, fno); - if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { + if (grn_open(ctx, fi, path, O_RDWR|O_CREAT)) { *value = NULL; *value_len = 0; GRN_FREE(v); @@ -742,14 +841,14 @@ grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, if (!grn_opened(fi)) { char path[PATH_MAX]; gen_pathname(io->path, path, fno); - if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { + if (grn_open(ctx, fi, path, O_RDWR|O_CREAT)) { *value = NULL; *value_len = 0; GRN_FREE(v); return ctx->rc; } } - size = rest > GRN_IO_FILE_SIZE ? GRN_IO_FILE_SIZE : rest; + size = rest > file_size ? file_size : rest; if (grn_pread(ctx, fi, vr, size, 0)) { *value = NULL; *value_len = 0; @@ -771,20 +870,21 @@ grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key, grn_rc rc; uint32_t rest = 0, size = value_len + sizeof(grn_io_ja_ehead); uint32_t segment_size = io->header->segment_size; - uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size; + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; uint32_t bseg = segment + io->base_seg; int fno = bseg / segments_per_file; fileinfo *fi = &io->fis[fno]; off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg; off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base; - if (pos + size > GRN_IO_FILE_SIZE) { - rest = pos + size - GRN_IO_FILE_SIZE; - size = GRN_IO_FILE_SIZE - pos; + if (pos + size > file_size) { + rest = pos + size - file_size; + size = file_size - pos; } if (!grn_opened(fi)) { char path[PATH_MAX]; gen_pathname(io->path, path, fno); - if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE))) { return rc; } + if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; } } if (value_len <= 256) { ja_element je; @@ -808,9 +908,9 @@ grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key, if (!grn_opened(fi)) { char path[PATH_MAX]; gen_pathname(io->path, path, fno); - if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE))) { return rc; } + if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; } } - size = rest > GRN_IO_FILE_SIZE ? GRN_IO_FILE_SIZE : rest; + size = rest > file_size ? file_size : rest; if ((rc = grn_pwrite(ctx, fi, vr, size, 0))) { return rc; } vr += size; rest -= size; @@ -825,7 +925,8 @@ grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key, { grn_rc rc; uint32_t segment_size = io->header->segment_size; - uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size; + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; uint32_t bseg = segment + io->base_seg; int fno = bseg / segments_per_file; fileinfo *fi = &io->fis[fno]; @@ -834,7 +935,7 @@ grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key, if (!grn_opened(fi)) { char path[PATH_MAX]; gen_pathname(io->path, path, fno); - if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE))) { return rc; } + if ((rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; } } { grn_io_ja_ehead eh; @@ -848,148 +949,6 @@ void * grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, uint32_t offset, uint32_t size, grn_io_rw_mode mode) { - byte *p; - off_t pos, base; - int fno; - uint32_t nseg, bseg; - uint32_t segment_size = io->header->segment_size; - uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size; - iw->ctx = ctx; - iw->diff = 0; - if (offset >= segment_size) { - segment += offset / segment_size; - offset = offset % segment_size; - } - nseg = (offset + size + segment_size - 1) / segment_size; - bseg = segment + io->base_seg; - fno = bseg / segments_per_file; - base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg; - pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base; - if (!size || !io || segment + nseg > io->header->max_segment || - fno != (bseg + nseg - 1) / segments_per_file) { - return NULL; - } - switch (mode) { - case grn_io_rdonly: - { - fileinfo *fi = &io->fis[fno]; - if (!grn_opened(fi)) { - char path[PATH_MAX]; - gen_pathname(io->path, path, fno); - if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { - return NULL; - } - } - if (!(p = GRN_MALLOC(size))) { return NULL; } - if (grn_pread(ctx, fi, p, size, pos)) { - GRN_FREE(p); - return NULL; - } - iw->addr = p; - } - break; - case grn_io_rdwr: - // if (nseg > 1) { /* auto unmap is not implemented yet */ - if (nseg > 0) { - fileinfo *fi = &io->fis[fno]; - if (!grn_opened(fi)) { - char path[PATH_MAX]; - gen_pathname(io->path, path, fno); - if (grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { - return NULL; - } - } - if (!(p = GRN_MMAP(&grn_gctx, &iw->fmo, fi, pos, (uint64_t)segment_size * nseg))) { - return NULL; - } - { - uint64_t tail = io->base + (uint64_t)segment_size * segment + offset + size; - if (tail > io->header->curr_size) { io->header->curr_size = tail; } - } - } else { - GRN_LOG(ctx, GRN_LOG_ALERT, "nseg == 0! in grn_io_win_map(%p, %u, %u, %u)", io, segment, offset, size); - // GRN_IO_SEG_REF(io, segment, p); if (!p) { return NULL; } - return NULL; - } - iw->addr = p + offset; - break; - case grn_io_wronly: - if (!(p = GRN_MALLOC(size))) { return NULL; } - memset(p, 0, size); - iw->cached = 0; - iw->addr = p; - break; - default : - return NULL; - } - iw->io = io; - iw->mode = mode; - iw->segment = segment; - iw->offset = offset; - iw->nseg = nseg; - iw->size = size; - iw->pos = pos; - return iw->addr; -} - -grn_rc -grn_io_win_unmap(grn_io_win *iw) -{ - grn_rc rc = GRN_SUCCESS; - grn_io *io = iw->io; - grn_ctx *ctx = iw->ctx; - uint32_t segment_size = io->header->segment_size; - uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size; - int nseg = iw->nseg; - switch (iw->mode) { - case grn_io_rdonly: - if (iw->addr) { GRN_FREE(iw->addr); } - iw->addr = NULL; - break; - case grn_io_rdwr: - // if (nseg > 1) { /* auto unmap is not implemented yet */ - if (nseg > 0) { - GRN_MUNMAP(&grn_gctx, &iw->fmo, ((byte *)iw->addr) - iw->offset, (uint64_t)segment_size * nseg); - } else { - if (iw->segment >= io->header->max_segment) { - rc = GRN_INVALID_ARGUMENT; - } else { - //GRN_IO_SEG_UNREF(io, iw->segment); - } - } - iw->addr = NULL; - break; - case grn_io_wronly: - { - int fno = (iw->segment + io->base_seg) / segments_per_file; - fileinfo *fi = &io->fis[fno]; - if (!grn_opened(fi)) { - char path[PATH_MAX]; - gen_pathname(io->path, path, fno); - rc = grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE); - } - if (!rc) { - if (!(rc = grn_pwrite(ctx, fi, iw->addr, iw->size, iw->pos))) { - { - uint64_t tail = io->base + (uint64_t)segment_size * iw->segment + iw->offset + iw->size; - if (tail > io->header->curr_size) { io->header->curr_size = tail; } - } - if (!iw->cached) { GRN_FREE(iw->addr); } - iw->addr = NULL; - } - } - } - break; - default : - rc = GRN_INVALID_ARGUMENT; - } - return rc; -} - -void * -grn_io_win_map2(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, - uint32_t offset, uint32_t size, grn_io_rw_mode mode) -{ uint32_t nseg, segment_size = io->header->segment_size; if (offset >= segment_size) { segment += offset / segment_size; @@ -1043,7 +1002,7 @@ grn_io_win_map2(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, } grn_rc -grn_io_win_unmap2(grn_io_win *iw) +grn_io_win_unmap(grn_io_win *iw) { if (!iw || !iw->io ||!iw->ctx) { return GRN_INVALID_ARGUMENT; } if (iw->cached) { @@ -1081,7 +1040,7 @@ grn_io_win_unmap2(grn_io_win *iw) } #define DO_MAP(io,fmo,fi,pos,size,segno,res) do {\ - if (((res) = GRN_MMAP(&grn_gctx, (fmo), (fi), (pos), (size)))) {\ + if (((res) = GRN_MMAP(&grn_gctx, (io), (fmo), (fi), (pos), (size)))) {\ uint32_t nmaps;\ if (io->max_map_seg < segno) { io->max_map_seg = segno; }\ GRN_ATOMIC_ADD_EX(&io->nmaps, 1, nmaps);\ @@ -1097,7 +1056,8 @@ grn_io_win_unmap2(grn_io_win *iw) if ((io->flags & GRN_IO_TEMPORARY)) {\ DO_MAP(io, &info->fmo, NULL, 0, segment_size, segno, info->map);\ } else {\ - uint32_t segments_per_file = GRN_IO_FILE_SIZE / segment_size;\ + unsigned long file_size = grn_io_compute_file_size(io->header->version);\ + uint32_t segments_per_file = file_size / segment_size;\ uint32_t bseg = segno + io->base_seg;\ uint32_t fno = bseg / segments_per_file;\ off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg;\ @@ -1106,7 +1066,7 @@ grn_io_win_unmap2(grn_io_win *iw) if (!grn_opened(fi)) {\ char path[PATH_MAX];\ gen_pathname(io->path, path, fno);\ - if (!grn_open(ctx, fi, path, O_RDWR|O_CREAT, GRN_IO_FILE_SIZE)) { \ + if (!grn_open(ctx, fi, path, O_RDWR|O_CREAT)) { \ DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map);\ }\ } else {\ @@ -1151,7 +1111,9 @@ grn_io_seg_expire(grn_ctx *ctx, grn_io *io, uint32_t segno, uint32_t nretry) } } else { uint32_t nmaps; - GRN_MUNMAP(&grn_gctx, &info->fmo, info->map, io->header->segment_size); + fileinfo *fi = &(io->fis[segno]); + GRN_MUNMAP(&grn_gctx, io, &info->fmo, fi, + info->map, io->header->segment_size); info->map = NULL; GRN_ATOMIC_ADD_EX(pnref, -(GRN_IO_MAX_REF + 1), nref); GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); @@ -1174,20 +1136,27 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) uint32_t nref, nmaps, *pnref = &io->nref; GRN_ATOMIC_ADD_EX(pnref, 1, nref); if (!nref && grn_gtick - io->count > count_thresh) { - uint32_t i = io->header->n_arrays; - grn_io_mapinfo *info = io->maps; - grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; - while (i--) { - memset(io->ainfo[i].addrs, 0, sizeof(void *) * array_specs[i].max_n_segments); + { + uint32_t i = io->header->n_arrays; + grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; + while (i--) { + memset(io->ainfo[i].addrs, 0, sizeof(void *) * array_specs[i].max_n_segments); + } } - for (m = io->max_map_seg; m; info++, m--) { - if (info->map) { - GRN_MUNMAP(&grn_gctx, &info->fmo, info->map, io->header->segment_size); - info->map = NULL; - info->nref = 0; - info->count = grn_gtick; - GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); - n++; + { + uint32_t fno; + for (fno = 0; fno < io->max_map_seg; fno++) { + grn_io_mapinfo *info = &(io->maps[fno]); + if (info->map) { + fileinfo *fi = &(io->fis[fno]); + GRN_MUNMAP(&grn_gctx, io, &info->fmo, fi, + info->map, io->header->segment_size); + info->map = NULL; + info->nref = 0; + info->count = grn_gtick; + GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); + n++; + } } } } @@ -1207,7 +1176,8 @@ grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) uint32_t nmaps, nref, *pnref = &info->nref; GRN_ATOMIC_ADD_EX(pnref, 1, nref); if (!nref && info->map && (grn_gtick - info->count) > count_thresh) { - GRN_MUNMAP(&grn_gctx, &info->fmo, info->map, io->header->segment_size); + GRN_MUNMAP(&grn_gctx, io, &info->fmo, NULL, + info->map, io->header->segment_size); GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); info->map = NULL; info->count = grn_gtick; @@ -1265,17 +1235,13 @@ grn_expire(grn_ctx *ctx, int count_thresh, uint32_t limit) void * grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length) { - return (mi->map = GRN_MMAP(ctx, &mi->fmo, NULL, 0, length)); + return (mi->map = GRN_MMAP(ctx, NULL, &mi->fmo, NULL, 0, length)); } void grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length) { - /* support WIN32 */ -#ifdef WIN32 - return GRN_FREE(mi->map); -#endif - GRN_MUNMAP(ctx, &mi->fmo, mi->map, length); + GRN_MUNMAP(ctx, NULL, &mi->fmo, NULL, mi->map, length); } grn_rc @@ -1345,59 +1311,25 @@ static size_t mmap_size = 0; #ifdef WIN32 -#ifdef WIN32_FMO_EACH - inline static grn_rc -grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize) +grn_open_v1(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) { - if ((flags & O_CREAT)) { - DWORD dwCreationDisposition; - if (flags & O_EXCL) { - dwCreationDisposition = CREATE_NEW; - } else { - dwCreationDisposition = OPEN_ALWAYS; - } - fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); - if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - return ctx->rc; - } - goto exit; - } - if ((flags & O_TRUNC)) { - CloseHandle(fi->fh); - fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - return ctx->rc; - } - goto exit; - } - /* O_RDWR only */ - fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - return ctx->rc; - } -exit: CRITICAL_SECTION_INIT(fi->cs); return GRN_SUCCESS; } inline static void * -grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length) +grn_mmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length) { void *res; if (!fi) { - if(fmo) { - *fmo = (HANDLE)0; + if (fmo) { + *fmo = NULL; } + /* TODO: Try to support VirtualAlloc() as anonymous mmap in POSIX. + * If VirtualAlloc() provides better performance rather than malloc(), + * we'll use it. + */ return GRN_GCALLOC(length); } /* CRITICAL_SECTION_ENTER(fi->cs); */ @@ -1406,7 +1338,10 @@ grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length) if (!*fmo) { return NULL; } res = MapViewOfFile(*fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length); if (!res) { - MERR("MapViewOfFile failed #%d <%zu>", GetLastError(), mmap_size); + SERR("MapViewOfFile"); + GRN_LOG(ctx, GRN_LOG_ERROR, + "MapViewOfFile(%lu,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + (DWORD)offset, length, mmap_size); return NULL; } /* CRITICAL_SECTION_LEAVE(fi->cs); */ @@ -1415,87 +1350,48 @@ grn_mmap(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, off_t offset, size_t length) } inline static int -grn_munmap(grn_ctx *ctx, HANDLE *fmo, void *start, size_t length) +grn_munmap_v1(grn_ctx *ctx, HANDLE *fmo, fileinfo *fi, + void *start, size_t length) { int r = 0; + + if (!fi) { + GRN_GFREE(start); + return r; + } + if (!fmo) { - GRN_FREE(start); + GRN_GFREE(start); + return r; } + if (*fmo) { if (UnmapViewOfFile(start)) { mmap_size -= length; } else { SERR("UnmapViewOfFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, "UnmapViewOfFile(%p,%d) failed <%zu>", start, length, mmap_size); + GRN_LOG(ctx, GRN_LOG_ERROR, + "UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); r = -1; } if (!CloseHandle(*fmo)) { SERR("CloseHandle"); - GRN_LOG(ctx, GRN_LOG_ERROR, "CloseHandle(%p,%d) failed <%zu>", start, length, mmap_size); + GRN_LOG(ctx, GRN_LOG_ERROR, + "CloseHandle(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); } *fmo = NULL; } else { - GRN_FREE(start); + GRN_GFREE(start); } - return r; -} -inline static grn_rc -grn_close(grn_ctx *ctx, fileinfo *fi) -{ - if (fi->fmo != NULL) { - GRN_LOG(ctx, GRN_LOG_ALERT, "file mapping object exists"); - } - if (fi->fh != INVALID_HANDLE_VALUE) { - CloseHandle(fi->fh); - CRITICAL_SECTION_FIN(fi->cs); - fi->fh = INVALID_HANDLE_VALUE; - } - return GRN_SUCCESS; + return r; } -#else /* WIN32_FMO_EACH */ inline static grn_rc -grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize) +grn_open_v0(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) { - /* may be wrong if flags is just only O_RDWR */ - if ((flags & O_CREAT)) { - DWORD dwCreationDisposition; - if (flags & O_EXCL) { - dwCreationDisposition = CREATE_NEW; - } else { - dwCreationDisposition = OPEN_ALWAYS; - } - fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); - if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - return ctx->rc; - } - goto exit; - } - if ((flags & O_TRUNC)) { - CloseHandle(fi->fh); - /* unable to assign OPEN_ALWAYS and TRUNCATE_EXISTING at once */ - fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - return ctx->rc; - } - goto exit; - } - /* O_RDWR only */ - fi->fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (fi->fh == INVALID_HANDLE_VALUE) { - SERR("CreateFile"); - return ctx->rc; - } -exit: /* signature may be wrong.. */ fi->fmo = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, NULL); /* open failed */ @@ -1506,20 +1402,21 @@ exit: /* failed again */ if (fi->fmo == NULL) { /* try to create fmo */ - fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, GRN_IO_FILE_SIZE, NULL); + fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, GRN_IO_FILE_SIZE_V0, NULL); } // funlock } if (fi->fmo != NULL) { - if (GetLastError() != ERROR_ALREADY_EXISTS ) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { CRITICAL_SECTION_INIT(fi->cs); return GRN_SUCCESS; } else { - GRN_LOG(ctx, GRN_LOG_ERROR, "fmo object already exists! handle=%d", fi->fh); + GRN_LOG(ctx, GRN_LOG_ERROR, "fmo object already exists! handle=%p", fi->fh); CloseHandle(fi->fmo); } } else { - GRN_LOG(ctx, GRN_LOG_ALERT, "failed to get FileMappingObject #%d", GetLastError()); + GRN_LOG(ctx, GRN_LOG_ALERT, + "failed to get FileMappingObject #%lu", GetLastError()); } CloseHandle(fi->fh); SERR("OpenFileMapping"); @@ -1527,11 +1424,11 @@ exit: } inline static void * -grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) +grn_mmap_v0(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) { void *res; if (!fi) { return GRN_GCALLOC(length); } - /* file must be exceeded to GRN_IO_FILE_SIZE when FileMappingObject created. + /* file must be exceeded to GRN_IO_FILE_SIZE_V0 when FileMappingObject created. and, after fmo created, it's not allowed to expand the size of file. DWORD tail = (DWORD)(offset + length); DWORD filesize = GetFileSize(fi->fh, NULL); @@ -1549,7 +1446,8 @@ grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) */ res = MapViewOfFile(fi->fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length); if (!res) { - MERR("MapViewOfFile failed #%d <%zu>", GetLastError(), mmap_size); + MERR("MapViewOfFile failed: <%" GRN_FMT_SIZE ">: %s", + mmap_size, grn_current_error_message()); return NULL; } mmap_size += length; @@ -1557,19 +1455,149 @@ grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) } inline static int -grn_munmap(grn_ctx *ctx, void *start, size_t length) +grn_munmap_v0(grn_ctx *ctx, fileinfo *fi, void *start, size_t length) { + if (!fi) { + GRN_GFREE(start); + return 0; + } + if (UnmapViewOfFile(start)) { mmap_size -= length; return 0; } else { SERR("UnmapViewOfFile"); - GRN_LOG(ctx, GRN_LOG_ERROR, "UnmapViewOfFile(%p,%d) failed <%zu>", start, length, mmap_size); + GRN_LOG(ctx, GRN_LOG_ERROR, + "UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); return -1; } } inline static grn_rc +grn_open_common(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + /* may be wrong if flags is just only O_RDWR */ + if ((flags & O_CREAT)) { + DWORD dwCreationDisposition; + if (flags & O_EXCL) { + dwCreationDisposition = CREATE_NEW; + } else { + dwCreationDisposition = OPEN_ALWAYS; + } + fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh == INVALID_HANDLE_VALUE) { + SERR("CreateFile"); + goto exit; + } + goto exit; + } + if ((flags & O_TRUNC)) { + CloseHandle(fi->fh); + /* unable to assign OPEN_ALWAYS and TRUNCATE_EXISTING at once */ + fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh == INVALID_HANDLE_VALUE) { + SERR("CreateFile"); + goto exit; + } + goto exit; + } + /* O_RDWR only */ + fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh == INVALID_HANDLE_VALUE) { + SERR("CreateFile"); + goto exit; + } + +exit : + return ctx->rc; +} + +inline static grn_rc +grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + grn_rc rc; + struct _grn_io_header io_header; + DWORD header_size; + DWORD read_bytes; + int version = grn_io_version_default; + + rc = grn_open_common(ctx, fi, path, flags); + if (rc != GRN_SUCCESS) { + return rc; + } + + if (!(flags & O_CREAT)) { + header_size = sizeof(struct _grn_io_header); + ReadFile(fi->fh, &io_header, header_size, &read_bytes, NULL); + if (read_bytes == header_size) { + version = io_header.version; + } + SetFilePointer(fi->fh, 0, NULL, FILE_BEGIN); + } + + if (version == 0) { + return grn_open_v0(ctx, fi, path, flags); + } else { + return grn_open_v1(ctx, fi, path, flags); + } +} + +inline static int +grn_guess_io_version(grn_ctx *ctx, grn_io *io, fileinfo *fi) +{ + if (io) { + return io->header->version; + } + + if (fi) { + if (fi->fmo) { + return 0; + } else { + return 1; + } + } + + return grn_io_version_default; +} + +inline static void * +grn_mmap(grn_ctx *ctx, grn_io *io, HANDLE *fmo, + fileinfo *fi, off_t offset, size_t length) +{ + int version; + + version = grn_guess_io_version(ctx, io, fi); + + if (version == 0) { + return grn_mmap_v0(ctx, fi, offset, length); + } else { + return grn_mmap_v1(ctx, fmo, fi, offset, length); + } +} + +inline static int +grn_munmap(grn_ctx *ctx, grn_io *io, + HANDLE *fmo, fileinfo *fi, void *start, size_t length) +{ + int version; + + version = grn_guess_io_version(ctx, io, fi); + + if (version == 0) { + return grn_munmap_v0(ctx, fi, start, length); + } else { + return grn_munmap_v1(ctx, fmo, fi, start, length); + } +} + +inline static grn_rc grn_close(grn_ctx *ctx, fileinfo *fi) { if (fi->fmo != NULL) { @@ -1583,7 +1611,6 @@ grn_close(grn_ctx *ctx, fileinfo *fi) } return GRN_SUCCESS; } -#endif /* WIN32_FMO_EACH */ inline static void grn_fileinfo_init(fileinfo *fis, int nfis) @@ -1620,7 +1647,9 @@ grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) SERR("ReadFile"); } else if (len != count) { /* todo : should retry ? */ - ERR(GRN_INPUT_OUTPUT_ERROR, "ReadFile %d != %d", count, len); + ERR(GRN_INPUT_OUTPUT_ERROR, + "ReadFile %" GRN_FMT_SIZE " != %lu", + count, len); } } CRITICAL_SECTION_LEAVE(fi->cs); @@ -1640,7 +1669,9 @@ grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) SERR("WriteFile"); } else if (len != count) { /* todo : should retry ? */ - ERR(GRN_INPUT_OUTPUT_ERROR, "WriteFile %d != %d", count, len); + ERR(GRN_INPUT_OUTPUT_ERROR, + "WriteFile %" GRN_FMT_SIZE " != %lu", + count, len); } } CRITICAL_SECTION_LEAVE(fi->cs); @@ -1650,10 +1681,10 @@ grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) #else /* WIN32 */ inline static grn_rc -grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags, size_t maxsize) +grn_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) { struct stat st; - if ((fi->fd = GRN_OPEN(path, flags, 0666)) == -1) { + if ((fi->fd = GRN_OPEN(path, flags, GRN_IO_FILE_CREATE_MODE)) == -1) { SERR(path); return ctx->rc; } @@ -1698,7 +1729,7 @@ grn_close(grn_ctx *ctx, fileinfo *fi) #include <sys/mman.h> inline static void * -grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) +grn_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, off_t offset, size_t length) { void *res; int fd, flags; @@ -1728,13 +1759,15 @@ grn_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length) #ifdef USE_FAIL_MALLOC inline static void * -grn_fail_mmap(grn_ctx *ctx, fileinfo *fi, off_t offset, size_t length, +grn_fail_mmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, + off_t offset, size_t length, const char* file, int line, const char *func) { if (grn_fail_malloc_check(length, file, line, func)) { return grn_mmap(ctx, fi, offset, length); } else { - MERR("fail_mmap(%zu,%d,%" GRN_FMT_LLU ") (%s:%d@%s) <%zu>", + MERR("fail_mmap(%" GRN_FMT_SIZE ",%d,%" GRN_FMT_LLU ") " + "(%s:%d@%s) <%" GRN_FMT_SIZE ">", length, fi ? fi->fd : 0, offset, file, line, func, mmap_size); return NULL; } @@ -1750,7 +1783,7 @@ grn_msync(grn_ctx *ctx, void *start, size_t length) } inline static int -grn_munmap(grn_ctx *ctx, void *start, size_t length) +grn_munmap(grn_ctx *ctx, grn_io *io, fileinfo *fi, void *start, size_t length) { int res; res = munmap(start, length); diff --git a/storage/mroonga/vendor/groonga/lib/mrb.c b/storage/mroonga/vendor/groonga/lib/mrb.c index f05949cef98..4d1e4b5a218 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb.c +++ b/storage/mroonga/vendor/groonga/lib/mrb.c @@ -16,8 +16,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "mrb.h" -#include "ctx_impl.h" +#include "grn_mrb.h" +#include "grn_ctx_impl.h" +#include "grn_util.h" #ifdef GRN_WITH_MRUBY # include <mruby/proc.h> @@ -25,19 +26,21 @@ # include <mruby/string.h> #endif +#include <ctype.h> + #define BUFFER_SIZE 2048 +#define E_LOAD_ERROR (mrb_class_get(mrb, "LoadError")) #ifdef GRN_WITH_MRUBY -#ifdef WIN32 +# ifdef WIN32 static char *win32_ruby_scripts_dir = NULL; static char win32_ruby_scripts_dir_buffer[PATH_MAX]; static const char * -grn_mrb_get_system_ruby_scripts_dir(void) +grn_mrb_get_default_system_ruby_scripts_dir(void) { if (!win32_ruby_scripts_dir) { const char *base_dir; const char *relative_path = GRN_RELATIVE_RUBY_SCRIPTS_DIR; - char *path; size_t base_dir_length; base_dir = grn_win32_base_dir(); @@ -50,13 +53,40 @@ grn_mrb_get_system_ruby_scripts_dir(void) return win32_ruby_scripts_dir; } -#else /* WIN32 */ +# else /* WIN32 */ static const char * -grn_mrb_get_system_ruby_scripts_dir(void) +grn_mrb_get_default_system_ruby_scripts_dir(void) { return GRN_RUBY_SCRIPTS_DIR; } -#endif /* WIN32 */ +# endif /* WIN32 */ + +const char * +grn_mrb_get_system_ruby_scripts_dir(grn_ctx *ctx) +{ + const char *ruby_scripts_dir; + + ruby_scripts_dir = getenv("GRN_RUBY_SCRIPTS_DIR"); + if (!ruby_scripts_dir) { + ruby_scripts_dir = grn_mrb_get_default_system_ruby_scripts_dir(); + } + + return ruby_scripts_dir; +} + +static grn_bool +grn_mrb_is_absolute_path(const char *path) +{ + if (path[0] == '/') { + return GRN_TRUE; + } + + if (isalpha(path[0]) && path[1] == ':' && path[2] == '/') { + return GRN_TRUE; + } + + return GRN_FALSE; +} static grn_bool grn_mrb_expand_script_path(grn_ctx *ctx, const char *path, char *expanded_path) @@ -65,13 +95,13 @@ grn_mrb_expand_script_path(grn_ctx *ctx, const char *path, char *expanded_path) char dir_last_char; int path_length, max_path_length; - if (path[0] == '/') { + if (grn_mrb_is_absolute_path(path)) { expanded_path[0] = '\0'; + } else if (path[0] == '.' && path[1] == '/') { + strcpy(expanded_path, ctx->impl->mrb.base_directory); + strcat(expanded_path, "/"); } else { - ruby_scripts_dir = getenv("GRN_RUBY_SCRIPTS_DIR"); - if (!ruby_scripts_dir) { - ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(); - } + ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(ctx); strcpy(expanded_path, ruby_scripts_dir); dir_last_char = ruby_scripts_dir[strlen(expanded_path) - 1]; @@ -120,25 +150,39 @@ grn_mrb_load(grn_ctx *ctx, const char *path) snprintf(message, BUFFER_SIZE - 1, "fopen: failed to open mruby script file: <%s>", expanded_path); SERR(message); - exception = mrb_exc_new(mrb, E_ARGUMENT_ERROR, + exception = mrb_exc_new(mrb, E_LOAD_ERROR, ctx->errbuf, strlen(ctx->errbuf)); mrb->exc = mrb_obj_ptr(exception); return mrb_nil_value(); } - parser = mrb_parser_new(mrb); - mrb_parser_set_filename(parser, expanded_path); - parser->s = parser->send = NULL; - parser->f = file; - mrb_parser_parse(parser, NULL); - fclose(file); - { - struct RProc *proc; - proc = mrb_generate_code(mrb, parser); - result = mrb_toplevel_run(mrb, proc); + char current_base_directory[PATH_MAX]; + char *last_directory; + + strcpy(current_base_directory, data->base_directory); + strcpy(data->base_directory, expanded_path); + last_directory = strrchr(data->base_directory, '/'); + if (last_directory) { + last_directory[0] = '\0'; + } + + parser = mrb_parser_new(mrb); + mrb_parser_set_filename(parser, expanded_path); + parser->s = parser->send = NULL; + parser->f = file; + mrb_parser_parse(parser, NULL); + fclose(file); + + { + struct RProc *proc; + proc = mrb_generate_code(mrb, parser); + result = mrb_toplevel_run(mrb, proc); + } + mrb_parser_free(parser); + + strcpy(data->base_directory, current_base_directory); } - mrb_parser_free(parser); return result; } diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c index a350c6b04f3..bd288af8491 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -24,7 +24,7 @@ #include <mruby/variable.h> #include <mruby/data.h> -#include "../db.h" +#include "../grn_db.h" #include "mrb_accessor.h" static struct mrb_data_type mrb_grn_accessor_type = { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h index 2aaf32f48f9..7b27e6375ec 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h @@ -19,8 +19,8 @@ #ifndef GRN_MRB_ACCESSOR_H #define GRN_MRB_ACCESSOR_H -#include "../ctx.h" -#include "../db.h" +#include "../grn_ctx.h" +#include "../grn_db.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c new file mode 100644 index 00000000000..f19bcfa9563 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> + +#include "mrb_array.h" + +static struct mrb_data_type mrb_grn_array_type = { + "Groonga::Array", + NULL +}; + +static mrb_value +mrb_grn_array_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_array_ptr; + + mrb_get_args(mrb, "o", &mrb_array_ptr); + DATA_TYPE(self) = &mrb_grn_array_type; + DATA_PTR(self) = mrb_cptr(mrb_array_ptr); + return self; +} + +void +grn_mrb_array_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "Array", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_array_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h new file mode 100644 index 00000000000..062281684ee --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_ARRAY_H +#define GRN_MRB_ARRAY_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_array_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_ARRAY_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c index ad428ea5bde..2a304b68781 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -24,8 +24,9 @@ #include <mruby/variable.h> #include <mruby/data.h> #include <mruby/numeric.h> +#include <mruby/string.h> -#include "../db.h" +#include "../grn_db.h" #include "mrb_bulk.h" static struct mrb_data_type mrb_grn_bulk_type = { @@ -33,33 +34,62 @@ static struct mrb_data_type mrb_grn_bulk_type = { NULL }; -static mrb_value -mrb_grn_bulk_initialize(mrb_state *mrb, mrb_value self) +grn_obj * +grn_mrb_value_to_bulk(mrb_state *mrb, mrb_value mrb_value_, grn_obj *bulk) { - mrb_value mrb_bulk_ptr; - - mrb_get_args(mrb, "o", &mrb_bulk_ptr); - DATA_TYPE(self) = &mrb_grn_bulk_type; - DATA_PTR(self) = mrb_cptr(mrb_bulk_ptr); - return self; -} + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + switch (mrb_type(mrb_value_)) { + case MRB_TT_FALSE : + if (mrb_nil_p(mrb_value_)) { + grn_obj_reinit(ctx, bulk, GRN_DB_VOID, 0); + } else { + grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, bulk, GRN_FALSE); + } + break; + case MRB_TT_TRUE : + grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, bulk, GRN_TRUE); + break; + case MRB_TT_FIXNUM : + grn_obj_reinit(ctx, bulk, GRN_DB_INT64, 0); + GRN_INT64_SET(ctx, bulk, mrb_fixnum(mrb_value_)); + break; + case MRB_TT_SYMBOL : + { + const char *name; + mrb_int name_length; -static mrb_value -mrb_grn_bulk_get_domain(mrb_state *mrb, mrb_value self) -{ - grn_obj *bulk; + grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0); + name = mrb_sym2name_len(mrb, mrb_symbol(mrb_value_), &name_length); + GRN_TEXT_SET(ctx, bulk, name, name_length); + } + break; + case MRB_TT_FLOAT : + grn_obj_reinit(ctx, bulk, GRN_DB_FLOAT, 0); + GRN_FLOAT_SET(ctx, bulk, mrb_float(mrb_value_)); + break; + case MRB_TT_STRING : + grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0); + GRN_TEXT_SET(ctx, bulk, RSTRING_PTR(mrb_value_), RSTRING_LEN(mrb_value_)); + break; + default : + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "unsupported object to convert to bulk: %S", + mrb_value_); + break; + } - bulk = DATA_PTR(self); - return mrb_fixnum_value(bulk->header.domain); + return bulk; } -static mrb_value -mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self) +mrb_value +grn_mrb_value_from_bulk(mrb_state *mrb, grn_obj *bulk) { - grn_obj *bulk; mrb_value mrb_value_; + grn_ctx *ctx = (grn_ctx *)mrb->ud; - bulk = DATA_PTR(self); switch (bulk->header.domain) { case GRN_DB_INT32 : { @@ -81,11 +111,26 @@ mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self) mrb_value_ = mrb_fixnum_value(value); } break; + case GRN_DB_TIME : + { + int64_t value; + int32_t sec; + int32_t usec; + + value = GRN_TIME_VALUE(bulk); + GRN_TIME_UNPACK(value, sec, usec); + mrb_value_ = mrb_funcall(mrb, + mrb_obj_value(ctx->impl->mrb.builtin.time_class), + "at", + 2, + mrb_fixnum_value(sec), + mrb_fixnum_value(usec)); + } + break; default : { #define MESSAGE_SIZE 4096 char message[MESSAGE_SIZE]; - grn_ctx *ctx = (grn_ctx *)mrb->ud; grn_obj *domain; char domain_name[GRN_TABLE_MAX_KEY_SIZE]; int domain_name_size; @@ -114,6 +159,32 @@ mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self) } static mrb_value +mrb_grn_bulk_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_bulk_ptr; + + mrb_get_args(mrb, "o", &mrb_bulk_ptr); + DATA_TYPE(self) = &mrb_grn_bulk_type; + DATA_PTR(self) = mrb_cptr(mrb_bulk_ptr); + return self; +} + +static mrb_value +mrb_grn_bulk_get_domain(mrb_state *mrb, mrb_value self) +{ + grn_obj *bulk; + + bulk = DATA_PTR(self); + return mrb_fixnum_value(bulk->header.domain); +} + +static mrb_value +mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self) +{ + return grn_mrb_value_from_bulk(mrb, DATA_PTR(self)); +} + +static mrb_value mrb_grn_bulk_equal(mrb_state *mrb, mrb_value self) { mrb_value mrb_other; diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h index 3be86584dc6..e85b81568da 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2014 Brazil + Copyright(C) 2014-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,8 +19,8 @@ #ifndef GRN_MRB_BULK_H #define GRN_MRB_BULK_H -#include "../ctx.h" -#include "../db.h" +#include "../grn_ctx.h" +#include "../grn_db.h" #ifdef __cplusplus extern "C" { @@ -28,6 +28,11 @@ extern "C" { void grn_mrb_bulk_init(grn_ctx *ctx); +mrb_value grn_mrb_value_from_bulk(mrb_state *mrb, grn_obj *bulk); +grn_obj *grn_mrb_value_to_bulk(mrb_state *mrb, + mrb_value mrb_value_, + grn_obj *bulk); + #ifdef __cplusplus } #endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c index 545f070d91c..1d3bbb69422 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013 Brazil + Copyright(C) 2013-2014 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,13 +16,42 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> #include <mruby/class.h> +#include <mruby/data.h> +#include "mrb_ctx.h" #include "mrb_column.h" +#include "mrb_converter.h" + +static mrb_value +mrb_grn_column_is_locked(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int is_locked; + + is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(is_locked != 0); +} + +static mrb_value +mrb_grn_column_get_table(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + + table = grn_column_table(ctx, DATA_PTR(self)); + if (!table) { + return mrb_nil_value(); + } + + return grn_mrb_value_from_grn_obj(mrb, table); +} void grn_mrb_column_init(grn_ctx *ctx) @@ -35,5 +64,11 @@ grn_mrb_column_init(grn_ctx *ctx) klass = mrb_define_class_under(mrb, module, "Column", object_class); MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "locked?", + mrb_grn_column_is_locked, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "table", + mrb_grn_column_get_table, MRB_ARGS_NONE()); } #endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h index 77e0dab82fd..abb99915fa5 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_COLUMN_H #define GRN_MRB_COLUMN_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c new file mode 100644 index 00000000000..0ff3a0d5b69 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c @@ -0,0 +1,180 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" +#include <groonga/command.h> + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> +#include <mruby/value.h> +#include <mruby/string.h> + +#include "mrb_ctx.h" +#include "mrb_command.h" + +static struct mrb_data_type mrb_grn_command_type = { + "Groonga::Command", + NULL +}; + +mrb_value +mrb_grn_command_instantiate(grn_ctx *ctx, grn_obj *command) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + mrb_value mrb_name; + struct RClass *command_class; + struct RClass *target_command_class; + mrb_value mrb_target_command_class; + mrb_value mrb_arguments[1]; + + name_size = grn_obj_name(ctx, command, name, GRN_TABLE_MAX_KEY_SIZE); + mrb_name = mrb_str_new(mrb, name, name_size); + + command_class = mrb_class_get_under(mrb, module, "Command"); + mrb_target_command_class = mrb_funcall(mrb, + mrb_obj_value(command_class), + "find_class", 1, mrb_name); + if (mrb_nil_p(mrb_target_command_class)) { + target_command_class = command_class; + } else { + target_command_class = mrb_class_ptr(mrb_target_command_class); + } + mrb_arguments[0] = mrb_cptr_value(mrb, command); + return mrb_obj_new(mrb, target_command_class, 1, mrb_arguments); +} + +static void +mrb_grn_command_run_wrapper(grn_ctx *ctx, + grn_obj *command, + grn_command_input *input, + void *user_data) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + int arena_index; + mrb_value mrb_command; + mrb_value mrb_input; + + arena_index = mrb_gc_arena_save(mrb); + mrb_command = mrb_grn_command_instantiate(ctx, command); + { + struct RClass *command_input_class; + mrb_value mrb_arguments[1]; + command_input_class = mrb_class_get_under(mrb, module, "CommandInput"); + mrb_arguments[0] = mrb_cptr_value(mrb, input); + mrb_input = mrb_obj_new(mrb, command_input_class, 1, mrb_arguments); + } + mrb_funcall(mrb, mrb_command, "run_internal", 1, mrb_input); + mrb_gc_arena_restore(mrb, arena_index); +} + +static mrb_value +mrb_grn_command_singleton_register(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_name; + mrb_value *mrb_arguments; + mrb_int n_arguments; + + mrb_get_args(mrb, "Sa", &mrb_name, &mrb_arguments, &n_arguments); + + { + grn_expr_var *vars; + mrb_int i; + + for (i = 0; i < n_arguments; i++) { + mrb_arguments[i] = mrb_convert_type(mrb, mrb_arguments[i], + MRB_TT_STRING, "String", "to_str"); + } + vars = GRN_MALLOCN(grn_expr_var, n_arguments); + for (i = 0; i < n_arguments; i++) { + mrb_value mrb_argument = mrb_arguments[i]; + grn_expr_var *var = &vars[i]; + var->name = RSTRING_PTR(mrb_argument); + var->name_size = RSTRING_LEN(mrb_argument); + GRN_TEXT_INIT(&(var->value), 0); + } + + grn_command_register(ctx, + RSTRING_PTR(mrb_name), + RSTRING_LEN(mrb_name), + mrb_grn_command_run_wrapper, + vars, + n_arguments, + NULL); + + for (i = 0; i < n_arguments; i++) { + grn_expr_var *var = &vars[i]; + GRN_OBJ_FIN(ctx, &(var->value)); + } + GRN_FREE(vars); + } + + grn_mrb_ctx_check(mrb); + + { + grn_mrb_data *data = &(ctx->impl->mrb); + struct RClass *command_class; + command_class = mrb_class_get_under(mrb, data->module, "Command"); + mrb_funcall(mrb, + mrb_obj_value(command_class), + "register_class", 2, mrb_name, klass); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_command_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_command_ptr; + + mrb_get_args(mrb, "o", &mrb_command_ptr); + DATA_TYPE(self) = &mrb_grn_command_type; + DATA_PTR(self) = mrb_cptr(mrb_command_ptr); + return self; +} + +void +grn_mrb_command_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *procedure_class; + struct RClass *klass; + + procedure_class = mrb_class_get_under(mrb, module, "Procedure"); + klass = mrb_define_class_under(mrb, module, "Command", procedure_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "register", + mrb_grn_command_singleton_register, + MRB_ARGS_REQ(2)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_command_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h new file mode 100644 index 00000000000..2b899df3a6d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_COMMAND_H +#define GRN_MRB_COMMAND_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_command_init(grn_ctx *ctx); + +mrb_value grn_mrb_command_instantiate(grn_ctx *ctx, grn_obj *command); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_COMMAND_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c new file mode 100644 index 00000000000..f39202398d1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c @@ -0,0 +1,122 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" +#include <groonga/command.h> + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> +#include <mruby/value.h> +#include <mruby/string.h> + +#include "mrb_ctx.h" +#include "mrb_command_input.h" + +static struct mrb_data_type mrb_grn_command_input_type = { + "Groonga::CommandInput", + NULL +}; + +static mrb_value +mrb_grn_command_input_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_command_input_ptr; + + mrb_get_args(mrb, "o", &mrb_command_input_ptr); + DATA_TYPE(self) = &mrb_grn_command_input_type; + DATA_PTR(self) = mrb_cptr(mrb_command_input_ptr); + return self; +} + +static mrb_value +mrb_grn_command_input_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_command_input *input; + mrb_value mrb_key_or_offset; + grn_obj *argument; + + input = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_key_or_offset); + + switch (mrb_type(mrb_key_or_offset)) { + case MRB_TT_FIXNUM : + { + mrb_int offset = mrb_fixnum(mrb_key_or_offset); + argument = grn_command_input_at(ctx, input, offset); + } + break; + case MRB_TT_SYMBOL : + { + mrb_sym mrb_key_symbol; + const char *key; + mrb_int key_length; + + mrb_key_symbol = mrb_symbol(mrb_key_or_offset); + key = mrb_sym2name_len(mrb, mrb_key_symbol, &key_length); + argument = grn_command_input_get(ctx, input, key, key_length); + } + break; + case MRB_TT_STRING : + { + mrb_value mrb_key = mrb_key_or_offset; + argument = grn_command_input_get(ctx, input, + RSTRING_PTR(mrb_key), + RSTRING_LEN(mrb_key)); + } + break; + default : + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "must be offset (as integer) or key (as symbol or string): %S", + mrb_key_or_offset); + break; + } + + if (!argument) { + return mrb_nil_value(); + } + + if (GRN_TEXT_LEN(argument) == 0) { + return mrb_nil_value(); + } + + return mrb_str_new_static(mrb, + GRN_TEXT_VALUE(argument), + GRN_TEXT_LEN(argument)); +} + +void +grn_mrb_command_input_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "CommandInput", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_command_input_initialize, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "[]", + mrb_grn_command_input_array_reference, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h new file mode 100644 index 00000000000..a4eb09779d1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_COMMAND_INPUT_H +#define GRN_MRB_COMMAND_INPUT_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_command_input_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_COMMAND_INPUT_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c index 2e7c41edbdf..9686feb8bc9 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c @@ -16,7 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" +#include "../grn_db.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -24,6 +25,7 @@ #include <mruby/data.h> #include "mrb_converter.h" +#include "mrb_bulk.h" struct RClass * grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object) @@ -34,12 +36,12 @@ grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object) data = &(ctx->impl->mrb); switch (object->header.type) { - case GRN_ACCESSOR : - klass = mrb_class_get_under(mrb, data->module, "Accessor"); - break; case GRN_BULK : klass = mrb_class_get_under(mrb, data->module, "Bulk"); break; + case GRN_ACCESSOR : + klass = mrb_class_get_under(mrb, data->module, "Accessor"); + break; case GRN_COLUMN_FIX_SIZE : klass = mrb_class_get_under(mrb, data->module, "FixedSizeColumn"); break; @@ -49,12 +51,30 @@ grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object) case GRN_COLUMN_INDEX : klass = mrb_class_get_under(mrb, data->module, "IndexColumn"); break; - case GRN_EXPR : - klass = mrb_class_get_under(mrb, data->module, "Expression"); + case GRN_TYPE : + klass = mrb_class_get_under(mrb, data->module, "Type"); break; case GRN_PROC : klass = mrb_class_get_under(mrb, data->module, "Procedure"); break; + case GRN_EXPR : + klass = mrb_class_get_under(mrb, data->module, "Expression"); + break; + case GRN_TABLE_NO_KEY : + klass = mrb_class_get_under(mrb, data->module, "Array"); + break; + case GRN_TABLE_HASH_KEY : + klass = mrb_class_get_under(mrb, data->module, "HashTable"); + break; + case GRN_TABLE_PAT_KEY : + klass = mrb_class_get_under(mrb, data->module, "PatriciaTrie"); + break; + case GRN_TABLE_DAT_KEY : + klass = mrb_class_get_under(mrb, data->module, "DoubleArrayTrie"); + break; + case GRN_DB : + klass = mrb_class_get_under(mrb, data->module, "Database"); + break; case GRN_VOID : klass = mrb_class_get_under(mrb, data->module, "Void"); break; @@ -90,4 +110,76 @@ grn_mrb_value_from_grn_obj(mrb_state *mrb, grn_obj *object) mrb_object = mrb_obj_new(mrb, mrb_class, 1, mrb_new_arguments); return mrb_object; } + +grn_id +grn_mrb_class_to_type(mrb_state *mrb, struct RClass *klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id type = GRN_DB_VOID; + + if (klass == mrb->nil_class) { + type = GRN_DB_VOID; + } else if (klass == mrb->true_class || + klass == mrb->false_class) { + type = GRN_DB_BOOL; + } else if (klass == mrb->symbol_class) { + type = GRN_DB_TEXT; + } else if (klass == mrb->fixnum_class) { + type = GRN_DB_INT64; + } else if (klass == mrb->float_class) { + type = GRN_DB_FLOAT; + } else if (klass == mrb->string_class) { + type = GRN_DB_TEXT; + } else if (klass == ctx->impl->mrb.builtin.time_class) { + type = GRN_DB_TIME; + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "unsupported class: %S", mrb_obj_value(klass)); + } + + return type; +} + +static mrb_value +mrb_grn_converter_singleton_convert(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *from = &(ctx->impl->mrb.buffer.from); + grn_obj *to = &(ctx->impl->mrb.buffer.to); + mrb_value mrb_from; + mrb_value mrb_to_class; + grn_id to_type; + + mrb_get_args(mrb, "oC", &mrb_from, &mrb_to_class); + + grn_mrb_value_to_bulk(mrb, mrb_from, from); + to_type = grn_mrb_class_to_type(mrb, mrb_class_ptr(mrb_to_class)); + grn_obj_reinit(ctx, to, to_type, 0); + { + grn_rc rc; + rc = grn_obj_cast(ctx, from, to, GRN_FALSE); + if (rc != GRN_SUCCESS) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "failed to convert to %S: %S", + mrb_to_class, + from); + } + } + + return grn_mrb_value_from_bulk(mrb, to); +} + +void +grn_mrb_converter_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module; + + module = mrb_define_module_under(mrb, data->module, "Converter"); + + mrb_define_singleton_method(mrb, (struct RObject *)module, "convert", + mrb_grn_converter_singleton_convert, + MRB_ARGS_REQ(2)); +} #endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h index 27223a8c0bf..3dfe5e5a01a 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h @@ -19,16 +19,19 @@ #ifndef GRN_MRB_CONVERTER_H #define GRN_MRB_CONVERTER_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { #endif -#ifdef GRN_WITH_MRUBY +void grn_mrb_converter_init(grn_ctx *ctx); + struct RClass *grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object); mrb_value grn_mrb_value_from_grn_obj(mrb_state *mrb, grn_obj *object); -#endif + +grn_id grn_mrb_class_to_grn_type(mrb_state *mrb, struct RClass *klass); +grn_id grn_mrb_value_to_grn_type(mrb_state *mrb, mrb_value value); #ifdef __cplusplus } diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c index 3f7bc36202d..f52342ae18e 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013-2014 Brazil + Copyright(C) 2013-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -25,7 +25,7 @@ #include <mruby/variable.h> #include <mruby/string.h> -#include "../mrb.h" +#include "../grn_mrb.h" #include "mrb_ctx.h" #include "mrb_converter.h" @@ -53,12 +53,22 @@ static mrb_value ctx_array_reference(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_id_or_name; grn_obj *object; - char *name; - int name_length; - mrb_get_args(mrb, "s", &name, &name_length); - object = grn_ctx_get(ctx, name, name_length); + mrb_get_args(mrb, "o", &mrb_id_or_name); + + if (mrb_fixnum_p(mrb_id_or_name)) { + grn_id id = mrb_fixnum(mrb_id_or_name); + object = grn_ctx_at(ctx, id); + } else { + mrb_value mrb_name; + mrb_name = mrb_convert_type(mrb, mrb_id_or_name, + MRB_TT_STRING, "String", "to_str"); + object = grn_ctx_get(ctx, + RSTRING_PTR(mrb_name), + RSTRING_LEN(mrb_name)); + } return grn_mrb_value_from_grn_obj(mrb, object); } @@ -187,6 +197,14 @@ ctx_set_error_message(mrb_state *mrb, mrb_value self) return error_message; } +static mrb_value +ctx_get_database(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return grn_mrb_value_from_grn_obj(mrb, grn_ctx_db(ctx)); +} + void grn_mrb_ctx_check(mrb_state *mrb) { @@ -568,10 +586,10 @@ grn_mrb_ctx_check(mrb_state *mrb) "zlib error: <%s>(%d)", ctx->errbuf, ctx->rc); break; - case GRN_LZO_ERROR: - error_class = mrb_class_get_under(mrb, module, "LzoError"); + case GRN_LZ4_ERROR: + error_class = mrb_class_get_under(mrb, module, "LZ4Error"); snprintf(message, MESSAGE_SIZE, - "LZO error: <%s>(%d)", + "LZ4 error: <%s>(%d)", ctx->errbuf, ctx->rc); break; case GRN_STACK_OVER_FLOW: @@ -690,8 +708,7 @@ grn_mrb_ctx_init(grn_ctx *ctx) mrb_define_method(mrb, klass, "error_message=", ctx_set_error_message, MRB_ARGS_REQ(1)); - grn_mrb_load(ctx, "context/error_level.rb"); - grn_mrb_load(ctx, "context/rc.rb"); - grn_mrb_load(ctx, "context.rb"); + mrb_define_method(mrb, klass, "database", ctx_get_database, + MRB_ARGS_NONE()); } #endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h index 5068d0d75e2..aa527bfec51 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h @@ -19,16 +19,14 @@ #ifndef GRN_MRB_CTX_H #define GRN_MRB_CTX_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { #endif void grn_mrb_ctx_init(grn_ctx *ctx); -#ifdef GRN_WITH_MRUBY void grn_mrb_ctx_check(mrb_state *mrb); -#endif #ifdef __cplusplus } diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c new file mode 100644 index 00000000000..22994104add --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c @@ -0,0 +1,124 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> + +#include "mrb_ctx.h" +#include "mrb_database.h" + +static struct mrb_data_type mrb_grn_database_type = { + "Groonga::Database", + NULL +}; + +static mrb_value +mrb_grn_database_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_database_ptr; + + mrb_get_args(mrb, "o", &mrb_database_ptr); + DATA_TYPE(self) = &mrb_grn_database_type; + DATA_PTR(self) = mrb_cptr(mrb_database_ptr); + return self; +} + +static mrb_value +mrb_grn_database_singleton_open(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *database; + char *path; + + mrb_get_args(mrb, "z", &path); + + database = grn_db_open(ctx, path); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, database)); +} + +static mrb_value +mrb_grn_database_singleton_create(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *database; + char *path; + + mrb_get_args(mrb, "z", &path); + + database = grn_db_create(ctx, path, NULL); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, database)); +} + +static mrb_value +mrb_grn_database_recover(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + grn_db_recover(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_database_is_locked(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int is_locked; + + is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(is_locked != 0); +} + +void +grn_mrb_database_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Database", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "open", + mrb_grn_database_singleton_open, + MRB_ARGS_REQ(1)); + mrb_define_singleton_method(mrb, (struct RObject *)klass, "create", + mrb_grn_database_singleton_create, + MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_database_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "recover", + mrb_grn_database_recover, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "locked?", + mrb_grn_database_is_locked, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h new file mode 100644 index 00000000000..fd319c55fd1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_DATABASE_H +#define GRN_MRB_DATABASE_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_database_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_DATABASE_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c new file mode 100644 index 00000000000..5c034090b29 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> + +#include "mrb_double_array_trie.h" + +static struct mrb_data_type mrb_grn_double_array_trie_type = { + "Groonga::DoubleArrayTrie", + NULL +}; + +static mrb_value +mrb_grn_double_array_trie_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_double_array_trie_ptr; + + mrb_get_args(mrb, "o", &mrb_double_array_trie_ptr); + DATA_TYPE(self) = &mrb_grn_double_array_trie_type; + DATA_PTR(self) = mrb_cptr(mrb_double_array_trie_ptr); + return self; +} + +void +grn_mrb_double_array_trie_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "DoubleArrayTrie", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_double_array_trie_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h new file mode 100644 index 00000000000..a69a94e556e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_DOUBLE_ARRAY_TRIE_H +#define GRN_MRB_DOUBLE_ARRAY_TRIE_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_double_array_trie_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_DOUBLE_ARRAY_TRIE_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c index 2f45cfc736e..a3513be1118 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c @@ -16,12 +16,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> -#include "../mrb.h" +#include "../grn_mrb.h" #include "mrb_error.h" void @@ -31,155 +31,164 @@ grn_mrb_error_init(grn_ctx *ctx) mrb_state *mrb = data->state; struct RClass *module = data->module; struct RClass *error_class; + struct RClass *groonga_error_class; error_class = mrb_define_class_under(mrb, module, "Error", mrb->eStandardError_class); + groonga_error_class = mrb_define_class_under(mrb, module, "GroongaError", + error_class); mrb_define_class_under(mrb, module, "EndOfData", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "UnknownError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "OperationNotPermitted", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoSuchFileOrDirectory", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoSuchProcess", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "InterruptedFunctionCall", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "InputOutputError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoSuchDeviceOrAddress", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ArgListTooLong", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ExecFormatError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "BadFileDescriptor", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoChildProcesses", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ResourceTemporarilyUnavailable", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NotEnoughSpace", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "PermissionDenied", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "BadAddress", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ResourceBusy", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "FileExists", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ImproperLink", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoSuchDevice", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NotDirectory", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "IsDirectory", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "InvalidArgument", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooManyOpenFilesInSystem", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooManyOpenFiles", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "InappropriateIOControlOperation", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "FileTooLarge", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoSpaceLeftOnDevice", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "InvalidSeek", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ReadOnlyFileSystem", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooManyLinks", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "BrokenPipe", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "DomainError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ResultTooLarge", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ResourceDeadlockAvoided", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoMemoryAvailable", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "FilenameTooLong", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoLocksAvailable", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "FunctionNotImplemented", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "DirectoryNotEmpty", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "IllegalByteSequence", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "SocketNotInitialized", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "OperationWouldBlock", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "AddressIsNotAvailable", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NetworkIsDown", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NoBuffer", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "SocketIsAlreadyConnected", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "SocketIsNotConnected", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "SocketIsAlreadyShutdowned", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "OperationTimeout", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ConnectionRefused", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "RangeError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TokenizerError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "FileCorrupt", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "InvalidFormat", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ObjectCorrupt", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooManySymbolicLinks", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NotSocket", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "OperationNotSupported", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "AddressIsInUse", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "ZlibError", - error_class); - mrb_define_class_under(mrb, module, "LzoError", - error_class); + groonga_error_class); + mrb_define_class_under(mrb, module, "LZ4Error", + groonga_error_class); mrb_define_class_under(mrb, module, "StackOverFlow", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "SyntaxError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "RetryMax", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "IncompatibleFileFormat", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "UpdateNotAllowed", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooSmallOffset", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooLargeOffset", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "TooSmallLimit", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "CASError", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "UnsupportedCommandVersion", - error_class); + groonga_error_class); mrb_define_class_under(mrb, module, "NormalizerError", - error_class); + groonga_error_class); + mrb_define_class_under(mrb, module, "TokenFilterError", + groonga_error_class); + mrb_define_class_under(mrb, module, "CommandError", + groonga_error_class); + mrb_define_class_under(mrb, module, "PluginError", + groonga_error_class); } #endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h index c59fabc12af..c68c58fa273 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_ERROR_H #define GRN_MRB_ERROR_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c index 3d0499c6b5c..df86d5579e4 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013-2014 Brazil + Copyright(C) 2013-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -25,10 +25,11 @@ #include <mruby/data.h> #include <mruby/string.h> #include <mruby/array.h> +#include <mruby/hash.h> -#include "../expr.h" -#include "../util.h" -#include "../mrb.h" +#include "../grn_expr.h" +#include "../grn_util.h" +#include "../grn_mrb.h" #include "mrb_accessor.h" #include "mrb_ctx.h" #include "mrb_expr.h" @@ -256,6 +257,33 @@ mrb_grn_scan_info_get_similarity_threshold(mrb_state *mrb, mrb_value self) } static mrb_value +mrb_grn_scan_info_set_scorer(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_value mrb_scorer; + + mrb_get_args(mrb, "o", &mrb_scorer); + si = DATA_PTR(self); + if (mrb_nil_p(mrb_scorer)) { + grn_scan_info_set_scorer(si, NULL); + } else { + grn_scan_info_set_scorer(si, DATA_PTR(mrb_scorer)); + } + return self; +} + +static mrb_value +mrb_grn_scan_info_get_scorer(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + grn_obj *scorer; + + si = DATA_PTR(self); + scorer = grn_scan_info_get_scorer(si); + return grn_mrb_value_from_grn_obj(mrb, scorer); +} + +static mrb_value mrb_grn_scan_info_get_arg(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; @@ -322,6 +350,41 @@ mrb_grn_expr_code_get_flags(mrb_state *mrb, mrb_value self) } static mrb_value +mrb_grn_expression_singleton_create(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_expr; + mrb_value mrb_table; + mrb_value mrb_new_arguments[1]; + grn_obj *expr, *variable = NULL; + + mrb_get_args(mrb, "o", &mrb_table); + if (mrb_nil_p(mrb_table)) { + expr = grn_expr_create(ctx, NULL, 0); + } else { + grn_obj *table = DATA_PTR(mrb_table); + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable); + } + + if (!expr) { + grn_mrb_ctx_check(mrb); + return mrb_nil_value(); + } + + mrb_new_arguments[0] = mrb_cptr_value(mrb, expr); + mrb_expr = mrb_obj_new(mrb, mrb_class_ptr(klass), 1, mrb_new_arguments); + { + mrb_value mrb_variable = mrb_nil_value(); + if (variable) { + mrb_variable = grn_mrb_value_from_grn_obj(mrb, variable); + } + mrb_iv_set(mrb, mrb_expr, mrb_intern_lit(mrb, "@variable"), mrb_variable); + } + + return mrb_expr; +} + +static mrb_value mrb_grn_expression_initialize(mrb_state *mrb, mrb_value self) { mrb_value mrb_expression_ptr; @@ -409,6 +472,170 @@ mrb_grn_expression_allocate_constant(mrb_state *mrb, mrb_value self) return grn_mrb_value_from_grn_obj(mrb, grn_object); } +static mrb_value +mrb_grn_expression_parse(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + char *query; + mrb_int query_size; + grn_obj *default_column = NULL; + grn_operator default_mode = GRN_OP_MATCH; + grn_operator default_operator = GRN_OP_AND; + grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT; + mrb_value mrb_options = mrb_nil_value(); + + expr = DATA_PTR(self); + mrb_get_args(mrb, "s|H", &query, &query_size, &mrb_options); + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_flags; + + mrb_flags = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "flags"))); + if (!mrb_nil_p(mrb_flags)) { + flags = mrb_fixnum(mrb_flags); + } + } + + grn_expr_parse(ctx, expr, query, query_size, default_column, + default_mode, default_operator, flags); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_append_object(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_object; + grn_obj *object; + grn_operator op; + int n_args; + + expr = DATA_PTR(self); + mrb_get_args(mrb, "oii", &mrb_object, &op, &n_args); + + object = DATA_PTR(mrb_object); + grn_expr_append_obj(ctx, expr, object, op, n_args); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_append_constant(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_constant; + grn_operator op; + int n_args; + + expr = DATA_PTR(self); + mrb_get_args(mrb, "oii", &mrb_constant, &op, &n_args); + + switch (mrb_type(mrb_constant)) { + case MRB_TT_FALSE : + if (mrb_nil_p(mrb_constant)) { + grn_obj constant; + GRN_VOID_INIT(&constant); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } else { + grn_obj constant; + GRN_BOOL_INIT(&constant, 0); + GRN_BOOL_SET(ctx, &constant, GRN_FALSE); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } + break; + case MRB_TT_TRUE : + { + grn_obj constant; + GRN_BOOL_INIT(&constant, 0); + GRN_BOOL_SET(ctx, &constant, GRN_TRUE); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } + break; + case MRB_TT_FIXNUM : + grn_expr_append_const_int(ctx, expr, mrb_fixnum(mrb_constant), op, n_args); + break; + case MRB_TT_SYMBOL : + { + const char *value; + mrb_int value_length; + + value = mrb_sym2name_len(mrb, mrb_symbol(mrb_constant), &value_length); + grn_expr_append_const_str(ctx, expr, value, value_length, op, n_args); + } + break; + case MRB_TT_FLOAT : + { + grn_obj constant; + GRN_FLOAT_INIT(&constant, 0); + GRN_FLOAT_SET(ctx, &constant, mrb_float(mrb_constant)); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } + break; + case MRB_TT_STRING : + grn_expr_append_const_str(ctx, expr, + RSTRING_PTR(mrb_constant), + RSTRING_LEN(mrb_constant), + op, n_args); + break; + default : + { + struct RClass *klass; + + klass = mrb_class(mrb, mrb_constant); + if (klass == ctx->impl->mrb.builtin.time_class) { + grn_obj constant; + mrb_value mrb_sec; + mrb_value mrb_usec; + + mrb_sec = mrb_funcall(mrb, mrb_constant, "to_i", 0); + mrb_usec = mrb_funcall(mrb, mrb_constant, "usec", 0); + GRN_TIME_INIT(&constant, 0); + GRN_TIME_SET(ctx, &constant, + GRN_TIME_PACK(mrb_fixnum(mrb_sec), mrb_fixnum(mrb_usec))); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "unsupported constant to append to expression: %S", + mrb_constant); + } + } + break; + } + + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_append_operator(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + grn_operator op; + int n_args; + + expr = DATA_PTR(self); + mrb_get_args(mrb, "ii", &op, &n_args); + + grn_expr_append_op(ctx, expr, op, n_args); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + void grn_mrb_expr_init(grn_ctx *ctx) { @@ -447,6 +674,10 @@ grn_mrb_expr_init(grn_ctx *ctx) mrb_grn_scan_info_get_similarity_threshold, MRB_ARGS_NONE()); mrb_define_method(mrb, klass, "similarity_threshold=", mrb_grn_scan_info_set_similarity_threshold, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "scorer", + mrb_grn_scan_info_get_scorer, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "scorer=", + mrb_grn_scan_info_set_scorer, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "get_arg", mrb_grn_scan_info_get_arg, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "push_arg", @@ -468,6 +699,11 @@ grn_mrb_expr_init(grn_ctx *ctx) klass = mrb_define_class_under(mrb, module, "Expression", object_class); MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "create", + mrb_grn_expression_singleton_create, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "initialize", mrb_grn_expression_initialize, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "codes", @@ -479,6 +715,16 @@ grn_mrb_expr_init(grn_ctx *ctx) mrb_define_method(mrb, klass, "allocate_constant", mrb_grn_expression_allocate_constant, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "parse", + mrb_grn_expression_parse, MRB_ARGS_ARG(1, 1)); + + mrb_define_method(mrb, klass, "append_object", + mrb_grn_expression_append_object, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "append_constant", + mrb_grn_expression_append_constant, MRB_ARGS_REQ(3)); + mrb_define_method(mrb, klass, "append_operator", + mrb_grn_expression_append_operator, MRB_ARGS_REQ(2)); + grn_mrb_load(ctx, "expression.rb"); grn_mrb_load(ctx, "scan_info.rb"); grn_mrb_load(ctx, "scan_info_data.rb"); diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h index 7fd5c66e9c5..687565dd6d9 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h @@ -19,8 +19,8 @@ #ifndef GRN_MRB_EXPR_H #define GRN_MRB_EXPR_H -#include "../ctx.h" -#include "../expr.h" +#include "../grn_ctx.h" +#include "../grn_expr.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c index d8df913f77d..130225029a2 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h index 938dcd76c7a..1037716c9f7 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_FIXED_SIZE_COLUMN_H #define GRN_MRB_FIXED_SIZE_COLUMN_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c new file mode 100644 index 00000000000..a5a4e797de2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> + +#include "mrb_hash_table.h" + +static struct mrb_data_type mrb_grn_hash_table_type = { + "Groonga::HashTable", + NULL +}; + +static mrb_value +mrb_grn_hash_table_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_hash_table_ptr; + + mrb_get_args(mrb, "o", &mrb_hash_table_ptr); + DATA_TYPE(self) = &mrb_grn_hash_table_type; + DATA_PTR(self) = mrb_cptr(mrb_hash_table_ptr); + return self; +} + +void +grn_mrb_hash_table_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "HashTable", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_hash_table_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h new file mode 100644 index 00000000000..223267b47d9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_HASH_TABLE_H +#define GRN_MRB_HASH_TABLE_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_hash_table_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_HASH_TABLE_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c index aa907b84a43..f55960716e9 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -32,6 +32,11 @@ grn_mrb_id_init(grn_ctx *ctx) id_module = mrb_define_module_under(mrb, module, "ID"); + mrb_define_const(mrb, id_module, "NIL", + mrb_fixnum_value(GRN_ID_NIL)); + mrb_define_const(mrb, id_module, "MAX", + mrb_fixnum_value(GRN_ID_MAX)); + mrb_define_const(mrb, id_module, "VOID", mrb_fixnum_value(GRN_DB_VOID)); mrb_define_const(mrb, id_module, "DB", diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h index f5b44358143..fcfd80384b5 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_ID_H #define GRN_MRB_ID_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c index 7bdf7528fc7..d91aa576e8e 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h index 10e0589bf93..307448fd4c3 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_INDEX_COLUMN_H #define GRN_MRB_INDEX_COLUMN_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c new file mode 100644 index 00000000000..f57d59d727c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c @@ -0,0 +1,128 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> +#include <mruby/string.h> +#include <mruby/hash.h> + +#include "mrb_ctx.h" +#include "mrb_index_cursor.h" + +static struct mrb_data_type mrb_grn_index_cursor_type = { + "Groonga::IndexCursor", + NULL +}; + +static mrb_value +mrb_grn_index_cursor_singleton_open_raw(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table_cursor; + mrb_value mrb_index; + mrb_value mrb_options = mrb_nil_value(); + grn_obj *index_cursor; + grn_table_cursor *table_cursor; + grn_obj *index; + grn_id rid_min = GRN_ID_NIL; + grn_id rid_max = GRN_ID_MAX; + int flags = 0; + + mrb_get_args(mrb, "oo|H", &mrb_table_cursor, &mrb_index, &mrb_options); + + table_cursor = DATA_PTR(mrb_table_cursor); + index = DATA_PTR(mrb_index); + if (!mrb_nil_p(mrb_options)) { + /* TODO */ + } + index_cursor = grn_index_cursor_open(ctx, table_cursor, index, + rid_min, rid_max, flags); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, index_cursor)); +} + +static mrb_value +mrb_grn_index_cursor_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_index_cursor_ptr; + + mrb_get_args(mrb, "o", &mrb_index_cursor_ptr); + DATA_TYPE(self) = &mrb_grn_index_cursor_type; + DATA_PTR(self) = mrb_cptr(mrb_index_cursor_ptr); + + return self; +} + +static mrb_value +mrb_grn_index_cursor_close(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *index_cursor; + + index_cursor = DATA_PTR(self); + if (index_cursor) { + DATA_PTR(self) = NULL; + grn_obj_close(ctx, index_cursor); + grn_mrb_ctx_check(mrb); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_index_cursor_count(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id term_id; + int n_records = 0; + + while (grn_index_cursor_next(ctx, DATA_PTR(self), &term_id)) { + n_records++; + } + + return mrb_fixnum_value(n_records); +} + +void +grn_mrb_index_cursor_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "IndexCursor", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "open_raw", + mrb_grn_index_cursor_singleton_open_raw, + MRB_ARGS_ARG(2, 1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_index_cursor_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "close", + mrb_grn_index_cursor_close, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "count", + mrb_grn_index_cursor_count, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h new file mode 100644 index 00000000000..afbad53db9f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_INDEX_CURSOR_H +#define GRN_MRB_INDEX_CURSOR_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_index_cursor_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_INDEX_CURSOR_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c index 4917694fa8a..884ca761e83 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -25,7 +25,7 @@ #include <mruby/variable.h> #include <mruby/string.h> -#include "../mrb.h" +#include "../grn_mrb.h" #include "mrb_logger.h" static mrb_value diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h index 5bfb62e98a2..358313b7ff9 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_LOGGER_H #define GRN_MRB_LOGGER_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c index 142a242b980..60398b91829 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" -#include "../util.h" +#include "../grn_ctx_impl.h" +#include "../grn_util.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -25,11 +25,22 @@ #include <mruby/class.h> #include <mruby/data.h> -#include "../mrb.h" -#include "mrb_obj.h" +#include "../grn_mrb.h" +#include "mrb_object.h" #include "mrb_converter.h" static mrb_value +object_get_id(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id id; + + id = grn_obj_id(ctx, DATA_PTR(self)); + + return mrb_fixnum_value(id); +} + +static mrb_value object_get_name(mrb_state *mrb, mrb_value self) { grn_ctx *ctx = (grn_ctx *)mrb->ud; @@ -111,8 +122,47 @@ object_equal(mrb_state *mrb, mrb_value self) } } +static mrb_value +object_close(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + + object = DATA_PTR(self); + if (!object) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "already closed object"); + } + + grn_obj_close(ctx, object); + DATA_PTR(self) = NULL; + + return mrb_nil_value(); +} + +static mrb_value +object_is_temporary(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + grn_obj_flags flags; + + object = DATA_PTR(self); + flags = object->header.flags; + return mrb_bool_value((flags & GRN_OBJ_PERSISTENT) != GRN_OBJ_PERSISTENT); +} + +static mrb_value +object_is_persistent(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + grn_obj_flags flags; + + object = DATA_PTR(self); + flags = object->header.flags; + return mrb_bool_value((flags & GRN_OBJ_PERSISTENT) == GRN_OBJ_PERSISTENT); +} + void -grn_mrb_obj_init(grn_ctx *ctx) +grn_mrb_object_init(grn_ctx *ctx) { grn_mrb_data *data = &(ctx->impl->mrb); mrb_state *mrb = data->state; @@ -123,12 +173,19 @@ grn_mrb_obj_init(grn_ctx *ctx) MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); data->object_class = klass; + mrb_define_method(mrb, klass, "id", object_get_id, MRB_ARGS_NONE()); mrb_define_method(mrb, klass, "name", object_get_name, MRB_ARGS_NONE()); mrb_define_method(mrb, klass, "find_index", object_find_index, MRB_ARGS_REQ(1)); mrb_define_method(mrb, klass, "grn_inspect", object_grn_inspect, MRB_ARGS_NONE()); mrb_define_method(mrb, klass, "==", object_equal, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "close", object_close, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "temporary?", object_is_temporary, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "persistent?", object_is_persistent, + MRB_ARGS_NONE()); grn_mrb_load(ctx, "index_info.rb"); } diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h new file mode 100644 index 00000000000..97a586c0f11 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_OBJECT_H +#define GRN_MRB_OBJECT_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_object_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_OBJECT_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c index 5a18d2e7023..ca2fc74a38a 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h index 2650cc9421d..683b9dacbd9 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_OPERATOR_H #define GRN_MRB_OPERATOR_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c new file mode 100644 index 00000000000..d2486f21c37 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> + +#include "mrb_patricia_trie.h" + +static struct mrb_data_type mrb_grn_patricia_trie_type = { + "Groonga::PatriciaTrie", + NULL +}; + +static mrb_value +mrb_grn_patricia_trie_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_patricia_trie_ptr; + + mrb_get_args(mrb, "o", &mrb_patricia_trie_ptr); + DATA_TYPE(self) = &mrb_grn_patricia_trie_type; + DATA_PTR(self) = mrb_cptr(mrb_patricia_trie_ptr); + return self; +} + +void +grn_mrb_patricia_trie_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "PatriciaTrie", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_patricia_trie_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h new file mode 100644 index 00000000000..f281b25969b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_PATRICIA_TRIE_H +#define GRN_MRB_PATRICIA_TRIE_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_patricia_trie_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_PATRICIA_TRIE_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c index fa9c677f2e6..3dfe78488df 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -41,6 +41,15 @@ mrb_grn_procedure_initialize(mrb_state *mrb, mrb_value self) return self; } +static mrb_value +mrb_grn_procedure_scorer_p(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *proc = DATA_PTR(self); + + return mrb_bool_value(grn_obj_is_scorer_proc(ctx, proc)); +} + void grn_mrb_procedure_init(grn_ctx *ctx) { @@ -54,5 +63,8 @@ grn_mrb_procedure_init(grn_ctx *ctx) MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); mrb_define_method(mrb, klass, "initialize", mrb_grn_procedure_initialize, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "scorer?", + mrb_grn_procedure_scorer_p, MRB_ARGS_NONE()); } #endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h index 16a4b32895c..36bd10fdab9 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_PROCEDURE_H #define GRN_MRB_PROCEDURE_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c new file mode 100644 index 00000000000..2b86fdb482b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c @@ -0,0 +1,226 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> +#include <mruby/hash.h> +#include <mruby/array.h> +#include <mruby/string.h> + +#include "mrb_ctx.h" +#include "mrb_table.h" +#include "mrb_converter.h" + +static mrb_value +mrb_grn_table_is_locked(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int is_locked; + + is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(is_locked != 0); +} + +static mrb_value +mrb_grn_table_get_size(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int size; + + size = grn_table_size(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_fixnum_value(size); +} + +static mrb_value +mrb_grn_table_is_empty(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int size; + + size = grn_table_size(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(size == 0); +} + +static mrb_value +mrb_grn_table_select(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + grn_obj *expr; + grn_obj *result = NULL; + grn_operator operator = GRN_OP_OR; + mrb_value mrb_expr; + mrb_value mrb_options = mrb_nil_value(); + + table = DATA_PTR(self); + mrb_get_args(mrb, "o|H", &mrb_expr, &mrb_options); + + expr = DATA_PTR(mrb_expr); + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_result; + mrb_value mrb_operator; + + mrb_result = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "result"))); + if (!mrb_nil_p(mrb_result)) { + result = DATA_PTR(mrb_result); + } + + mrb_operator = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "operator"))); + if (!mrb_nil_p(mrb_operator)) { + operator = mrb_fixnum(mrb_operator); + } + } + + result = grn_table_select(ctx, table, expr, result, operator); + grn_mrb_ctx_check(mrb); + + return grn_mrb_value_from_grn_obj(mrb, result); +} + +/* TODO: Fix memory leak on error */ +static mrb_value +mrb_grn_table_sort(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + grn_obj *result = NULL; + grn_table_sort_key *keys; + int i, n_keys; + int offset = 0; + int limit = -1; + mrb_value mrb_keys; + mrb_value mrb_options = mrb_nil_value(); + + table = DATA_PTR(self); + mrb_get_args(mrb, "o|H", &mrb_keys, &mrb_options); + + mrb_keys = mrb_convert_type(mrb, mrb_keys, + MRB_TT_ARRAY, "Array", "to_ary"); + + n_keys = RARRAY_LEN(mrb_keys); + keys = GRN_MALLOCN(grn_table_sort_key, n_keys); + for (i = 0; i < n_keys; i++) { + mrb_value mrb_sort_options; + mrb_value mrb_sort_key; + mrb_value mrb_sort_order; + + mrb_sort_options = RARRAY_PTR(mrb_keys)[i]; + mrb_sort_key = mrb_hash_get(mrb, mrb_sort_options, + mrb_symbol_value(mrb_intern_lit(mrb, "key"))); + switch (mrb_type(mrb_sort_key)) { + case MRB_TT_STRING : + keys[i].key = grn_obj_column(ctx, table, + RSTRING_PTR(mrb_sort_key), + RSTRING_LEN(mrb_sort_key)); + break; + case MRB_TT_SYMBOL : + { + const char *name; + mrb_int name_length; + name = mrb_sym2name_len(mrb, mrb_symbol(mrb_sort_key), &name_length); + keys[i].key = grn_obj_column(ctx, table, name, name_length); + } + break; + default : + /* TODO: free */ + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "sort key must be string or symbol: %S", + mrb_sort_key); + break; + } + + keys[i].flags = 0; + mrb_sort_order = + mrb_hash_get(mrb, mrb_sort_options, + mrb_symbol_value(mrb_intern_lit(mrb, "order"))); + if (mrb_nil_p(mrb_sort_order) || + (mrb_symbol(mrb_sort_order) == mrb_intern_lit(mrb, "ascending"))) { + keys[i].flags |= GRN_TABLE_SORT_ASC; + } else { + keys[i].flags |= GRN_TABLE_SORT_DESC; + } + } + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_offset; + mrb_value mrb_limit; + + mrb_offset = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "offset"))); + if (!mrb_nil_p(mrb_offset)) { + offset = mrb_fixnum(mrb_offset); + } + + mrb_limit = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "limit"))); + if (!mrb_nil_p(mrb_limit)) { + limit = mrb_fixnum(mrb_limit); + } + } + + result = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_NO_KEY, + NULL, table); + grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); + for (i = 0; i < n_keys; i++) { + grn_obj_unlink(ctx, keys[i].key); + } + GRN_FREE(keys); + grn_mrb_ctx_check(mrb); + + return grn_mrb_value_from_grn_obj(mrb, result); +} + +void +grn_mrb_table_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Table", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "locked?", + mrb_grn_table_is_locked, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "size", + mrb_grn_table_get_size, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "empty?", + mrb_grn_table_is_empty, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "select", + mrb_grn_table_select, MRB_ARGS_ARG(1, 1)); + mrb_define_method(mrb, klass, "sort", + mrb_grn_table_sort, MRB_ARGS_ARG(1, 1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h new file mode 100644 index 00000000000..000088fcf40 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_TABLE_H +#define GRN_MRB_TABLE_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_TABLE_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c new file mode 100644 index 00000000000..660596070d3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c @@ -0,0 +1,211 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> +#include <mruby/string.h> +#include <mruby/hash.h> + +#include "mrb_ctx.h" +#include "mrb_table_cursor.h" + +static struct mrb_data_type mrb_grn_table_cursor_type = { + "Groonga::TableCursor", + NULL +}; + +typedef union { + int64_t time_value; +} border_value_buffer; + +static void +mrb_value_to_border_value(mrb_state *mrb, + const char *type, + mrb_value mrb_border_value, + border_value_buffer *buffer, + void **border_value, + unsigned int *border_value_size) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + if (mrb_nil_p(mrb_border_value)) { + return; + } + + switch (mrb_type(mrb_border_value)) { + case MRB_TT_STRING : + *border_value = RSTRING_PTR(mrb_border_value); + *border_value_size = RSTRING_LEN(mrb_border_value); + break; + default : + { + struct RClass *klass; + + klass = mrb_class(mrb, mrb_border_value); + if (klass == ctx->impl->mrb.builtin.time_class) { + mrb_value mrb_sec; + mrb_value mrb_usec; + + mrb_sec = mrb_funcall(mrb, mrb_border_value, "to_i", 0); + mrb_usec = mrb_funcall(mrb, mrb_border_value, "usec", 0); + buffer->time_value = GRN_TIME_PACK(mrb_fixnum(mrb_sec), + mrb_fixnum(mrb_usec)); + *border_value = &(buffer->time_value); + *border_value_size = sizeof(buffer->time_value); + } else { + mrb_raisef(mrb, E_NOTIMP_ERROR, + "%s: only String and Time is supported for now: %S", + type, + mrb_border_value); + } + } + break; + } +} + +static mrb_value +mrb_grn_table_cursor_singleton_open_raw(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + mrb_value mrb_options = mrb_nil_value(); + grn_table_cursor *table_cursor; + grn_obj *table; + void *min = NULL; + unsigned int min_size = 0; + border_value_buffer min_buffer; + void *max = NULL; + unsigned int max_size = 0; + border_value_buffer max_buffer; + int offset = 0; + int limit = -1; + int flags = 0; + + mrb_get_args(mrb, "o|H", &mrb_table, &mrb_options); + + table = DATA_PTR(mrb_table); + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_min; + mrb_value mrb_max; + mrb_value mrb_flags; + + mrb_min = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "min"))); + mrb_value_to_border_value(mrb, "min", mrb_min, &min_buffer, &min, &min_size); + + mrb_max = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "max"))); + mrb_value_to_border_value(mrb, "max", mrb_max, &max_buffer, &max, &max_size); + + mrb_flags = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "flags"))); + if (!mrb_nil_p(mrb_flags)) { + flags = mrb_fixnum(mrb_flags); + } + } + table_cursor = grn_table_cursor_open(ctx, table, + min, min_size, + max, max_size, + offset, limit, flags); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, table_cursor)); +} + +static mrb_value +mrb_grn_table_cursor_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_table_cursor_ptr; + + mrb_get_args(mrb, "o", &mrb_table_cursor_ptr); + DATA_TYPE(self) = &mrb_grn_table_cursor_type; + DATA_PTR(self) = mrb_cptr(mrb_table_cursor_ptr); + + return self; +} + +static mrb_value +mrb_grn_table_cursor_close(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_table_cursor *table_cursor; + + table_cursor = DATA_PTR(self); + if (table_cursor) { + DATA_PTR(self) = NULL; + grn_table_cursor_close(ctx, table_cursor); + grn_mrb_ctx_check(mrb); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_cursor_next(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id id; + + id = grn_table_cursor_next(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_fixnum_value(id); +} + +static mrb_value +mrb_grn_table_cursor_count(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + int n_records = 0; + + while (grn_table_cursor_next(ctx, DATA_PTR(self)) != GRN_ID_NIL) { + n_records++; + } + + return mrb_fixnum_value(n_records); +} + +void +grn_mrb_table_cursor_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "TableCursor", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "open_raw", + mrb_grn_table_cursor_singleton_open_raw, + MRB_ARGS_ARG(1, 1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_table_cursor_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "close", + mrb_grn_table_cursor_close, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "next", + mrb_grn_table_cursor_next, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "count", + mrb_grn_table_cursor_count, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h new file mode 100644 index 00000000000..f05ab0977a1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_TABLE_CURSOR_H +#define GRN_MRB_TABLE_CURSOR_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_cursor_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_TABLE_CURSOR_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c new file mode 100644 index 00000000000..8b889fc5b47 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> + +#include "mrb_table_cursor_flags.h" + +void +grn_mrb_table_cursor_flags_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *flags_module; + + flags_module = mrb_define_module_under(mrb, module, "TableCursorFlags"); + + mrb_define_const(mrb, flags_module, "ASCENDING", + mrb_fixnum_value(GRN_CURSOR_ASCENDING)); + mrb_define_const(mrb, flags_module, "DESCENDING", + mrb_fixnum_value(GRN_CURSOR_DESCENDING)); + mrb_define_const(mrb, flags_module, "GE", + mrb_fixnum_value(GRN_CURSOR_GE)); + mrb_define_const(mrb, flags_module, "GT", + mrb_fixnum_value(GRN_CURSOR_GT)); + mrb_define_const(mrb, flags_module, "LE", + mrb_fixnum_value(GRN_CURSOR_LE)); + mrb_define_const(mrb, flags_module, "LT", + mrb_fixnum_value(GRN_CURSOR_LT)); + mrb_define_const(mrb, flags_module, "BY_KEY", + mrb_fixnum_value(GRN_CURSOR_BY_KEY)); + mrb_define_const(mrb, flags_module, "BY_ID", + mrb_fixnum_value(GRN_CURSOR_BY_ID)); + mrb_define_const(mrb, flags_module, "PREFIX", + mrb_fixnum_value(GRN_CURSOR_PREFIX)); + mrb_define_const(mrb, flags_module, "SIZE_BY_BIT", + mrb_fixnum_value(GRN_CURSOR_SIZE_BY_BIT)); + mrb_define_const(mrb, flags_module, "RK", + mrb_fixnum_value(GRN_CURSOR_RK)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h new file mode 100644 index 00000000000..f336cde9325 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_TABLE_CURSOR_FLAGS_H +#define GRN_MRB_TABLE_CURSOR_FLAGS_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_cursor_flags_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_TABLE_CURSOR_FLAGS_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c new file mode 100644 index 00000000000..9fe602e6c40 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/class.h> +#include <mruby/data.h> + +#include "mrb_ctx.h" +#include "mrb_type.h" + +static struct mrb_data_type mrb_grn_type_type = { + "Groonga::Type", + NULL +}; + +static mrb_value +mrb_grn_type_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_type_ptr; + + mrb_get_args(mrb, "o", &mrb_type_ptr); + DATA_TYPE(self) = &mrb_grn_type_type; + DATA_PTR(self) = mrb_cptr(mrb_type_ptr); + return self; +} + +void +grn_mrb_type_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Type", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_type_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h index 31d53240f9e..f86167443a6 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_obj.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013 Brazil + Copyright(C) 2014 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,19 +16,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GRN_MRB_OBJ_H -#define GRN_MRB_OBJ_H +#ifndef GRN_MRB_TYPE_H +#define GRN_MRB_TYPE_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { #endif -void grn_mrb_obj_init(grn_ctx *ctx); +void grn_mrb_type_init(grn_ctx *ctx); #ifdef __cplusplus } #endif -#endif /* GRN_MRB_OBJ_H */ +#endif /* GRN_MRB_TYPE_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c index 9073b326f85..153b28066d8 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h index d120f737671..c904e7023b1 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_VARIABLE_SIZE_COLUMN_H #define GRN_MRB_VARIABLE_SIZE_COLUMN_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c index 976c472be92..bdc451930f6 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../ctx_impl.h" +#include "../grn_ctx_impl.h" #ifdef GRN_WITH_MRUBY #include <mruby.h> @@ -24,7 +24,7 @@ #include <mruby/variable.h> #include <mruby/data.h> -#include "../db.h" +#include "../grn_db.h" #include "mrb_void.h" static struct mrb_data_type mrb_grn_void_type = { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h index a766cecb0b7..474d7804c73 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h @@ -19,7 +19,7 @@ #ifndef GRN_MRB_VOID_H #define GRN_MRB_VOID_H -#include "../ctx.h" +#include "../grn_ctx.h" #ifdef __cplusplus extern "C" { diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c new file mode 100644 index 00000000000..e14073e5fe2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c @@ -0,0 +1,223 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include <mruby.h> +#include <mruby/data.h> +#include <mruby/hash.h> +#include <mruby/string.h> + +#include "../grn_mrb.h" +#include "../grn_output.h" +#include "mrb_ctx.h" +#include "mrb_writer.h" + +static mrb_value +writer_write(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value target; + + mrb_get_args(mrb, "o", &target); + + switch (mrb_type(target)) { + case MRB_TT_FALSE : + GRN_OUTPUT_BOOL(GRN_FALSE); + break; + case MRB_TT_TRUE : + GRN_OUTPUT_BOOL(GRN_TRUE); + break; + case MRB_TT_FIXNUM : + GRN_OUTPUT_INT32(mrb_fixnum(target)); + break; + case MRB_TT_FLOAT : + GRN_OUTPUT_FLOAT(mrb_float(target)); + break; + case MRB_TT_STRING : + GRN_OUTPUT_STR(RSTRING_PTR(target), RSTRING_LEN(target)); + break; + default : + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "must be true, false, number, float or string: %S", target); + break; + } + + return mrb_nil_value(); +} + +static mrb_value +writer_open_array(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *name; + mrb_int n_elements; + + mrb_get_args(mrb, "zi", &name, &n_elements); + GRN_OUTPUT_ARRAY_OPEN(name, n_elements); + + return mrb_nil_value(); +} + +static mrb_value +writer_close_array(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + GRN_OUTPUT_ARRAY_CLOSE(); + + return mrb_nil_value(); +} + +static mrb_value +writer_open_map(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *name; + mrb_int n_elements; + + mrb_get_args(mrb, "zi", &name, &n_elements); + GRN_OUTPUT_MAP_OPEN(name, n_elements); + + return mrb_nil_value(); +} + +static mrb_value +writer_close_map(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + GRN_OUTPUT_MAP_CLOSE(); + + return mrb_nil_value(); +} + +static mrb_value +writer_write_table_columns(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + char *columns; + mrb_int columns_size; + grn_obj *table; + grn_obj_format format; + int n_hits = 0; + int offset = 0; + int limit = 0; + int hits_offset = 0; + + mrb_get_args(mrb, "os", &mrb_table, &columns, &columns_size); + + table = DATA_PTR(mrb_table); + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, hits_offset); + format.flags |= GRN_OBJ_FORMAT_WITH_COLUMN_NAMES; + { + grn_rc rc; + rc = grn_output_format_set_columns(ctx, &format, + table, columns, columns_size); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_mrb_ctx_check(mrb); + } + } + GRN_OUTPUT_TABLE_COLUMNS(table, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + + return mrb_nil_value(); +} + +static mrb_value +writer_write_table_records(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + mrb_value mrb_options = mrb_nil_value(); + char *columns; + mrb_int columns_size; + grn_obj *table; + grn_obj_format format; + int n_hits = 0; + int offset = 0; + int limit = -1; + int hits_offset = 0; + + mrb_get_args(mrb, "os|H", &mrb_table, &columns, &columns_size, &mrb_options); + + table = DATA_PTR(mrb_table); + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_offset; + mrb_value mrb_limit; + + mrb_offset = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "offset"))); + if (!mrb_nil_p(mrb_offset)) { + offset = mrb_fixnum(mrb_offset); + } + + mrb_limit = mrb_hash_get(mrb, mrb_options, + mrb_symbol_value(mrb_intern_lit(mrb, "limit"))); + if (!mrb_nil_p(mrb_limit)) { + limit = mrb_fixnum(mrb_limit); + } + } + if (limit < 0) { + limit = grn_table_size(ctx, table) + limit + 1; + } + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, hits_offset); + { + grn_rc rc; + rc = grn_output_format_set_columns(ctx, &format, + table, columns, columns_size); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_mrb_ctx_check(mrb); + } + } + GRN_OUTPUT_TABLE_RECORDS(table, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + + return mrb_nil_value(); +} + +void +grn_mrb_writer_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Writer", mrb->object_class); + + mrb_define_method(mrb, klass, "write", writer_write, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "open_array", + writer_open_array, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "close_array", + writer_close_array, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "open_map", + writer_open_map, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "close_map", + writer_close_map, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "write_table_columns", + writer_write_table_columns, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "write_table_records", + writer_write_table_records, MRB_ARGS_ARG(2, 1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h new file mode 100644 index 00000000000..a6b4a6b3a75 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_MRB_WRITER_H +#define GRN_MRB_WRITER_H + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_writer_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_MRB_WRITER_H */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb new file mode 100644 index 00000000000..c4e3e94bc4e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb @@ -0,0 +1,35 @@ +module Groonga + class Command + @@classes = {} + class << self + def register_class(name, klass) + @@classes[name] = klass + end + + def find_class(name) + @@classes[name] + end + end + + private + def context + @context ||= Context.instance + end + + def writer + @writer ||= context.writer + end + + def run_internal(input) + begin + run_body(input) + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + nil + rescue => error + context.record_error(:command_error, error) + nil + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb new file mode 100644 index 00000000000..96a99c80223 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb @@ -0,0 +1,169 @@ +module Groonga + module CommandLine + class Grndb + def initialize(argv) + @command, *@arguments = argv + @succeeded = true + @executed = false + @database_path = nil + end + + def run + slop = create_slop + rest = nil + begin + rest = slop.parse(@arguments) + rescue Slop::Error + $stderr.puts($!.message) + return false + end + + if slop.help? + $stdout.puts(slop.help) + return true + end + + unless @executed + if rest.empty? + $stderr.puts("No command is specified.") + else + $stderr.puts("Unknown command: <#{rest.first}>") + end + return false + end + + @succeeded + end + + private + def create_slop + slop = Slop.new + command_name = File.basename(@command) + slop.banner = "Usage: #{command_name} COMMAND [OPTIONS] DB_PATH" + slop_enable_help(slop) + + slop.command "check" do |command| + command.description "Check database" + slop_enable_help(command) + + command.run do |options, arguments| + run_command(options, arguments) do |database, new_arguments| + check(database, options, new_arguments) + end + end + end + + slop.command "recover" do |command| + command.description "Recover database" + slop_enable_help(command) + + command.run do |options, arguments| + run_command(options, arguments) do |database, new_arguments| + recover(database, options, new_arguments) + end + end + end + + slop + end + + def slop_enable_help(slop) + slop.on("-h", "--help", "Display this help message.", :tail => true) + end + + def open_database(arguments) + if arguments.empty? + $stderr.puts("Database path is missing") + @succeesed = false + return + end + + database = nil + @database_path, *rest_arguments = arguments + begin + database = Database.open(@database_path) + rescue Error => error + $stderr.puts("Failed to open database: <#{@database_path}>") + $stderr.puts(error.message) + @succeeded = false + return + end + + begin + yield(database, rest_arguments) + ensure + database.close + end + end + + def run_command(options, arguments) + @executed = true + + if options.help? + $stdout.puts(options.help) + return + end + + open_database(arguments) do |database| + yield(database) + end + end + + def recover(database, options, arguments) + begin + database.recover + rescue Error => error + $stderr.puts("Failed to recover database: <#{@database_path}>") + $stderr.puts(error.message) + @succeeded = false + end + end + + def check(database, options, arguments) + if database.locked? + message = + "Database is locked. " + + "It may be broken. " + + "Re-create the database." + $stdout.puts(message) + @succeeded = false + end + + database.each do |object| + case object + when IndexColumn + next unless object.locked? + message = + "[#{object.name}] Index column is locked. " + + "It may be broken. " + + "Re-create index by '#{@command} recover #{@database_path}'." + $stdout.puts(message) + @succeeded = false + when Column + next unless object.locked? + name = object.name + message = + "[#{name}] Data column is locked. " + + "It may be broken. " + + "(1) Truncate the column (truncate #{name}) or " + + "clear lock of the column (lock_clear #{name}) " + + "and (2) load data again." + $stdout.puts(message) + @succeeded = false + when Table + next unless object.locked? + name = object.name + message = + "[#{name}] Table is locked. " + + "It may be broken. " + + "(1) Truncate the table (truncate #{name}) or " + + "clear lock of the table (lock_clear #{name}) " + + "and (2) load data again." + $stdout.puts(message) + @succeeded = false + end + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb index 8ebe2c913b4..e65d6653110 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb @@ -1,3 +1,6 @@ +require "context/error_level" +require "context/rc" + module Groonga class Context def guard(fallback=nil) @@ -13,19 +16,37 @@ module Groonga @logger ||= Logger.new end + def writer + @writer ||= Writer.new + end + + def set_groonga_error(groonga_error) + set_error_raw(groonga_error.class.rc, + ErrorLevel::ERROR, + groonga_error.message, + groonga_error.backtrace) + end + def record_error(rc, error) rc = RC.find(rc) if rc.is_a?(Symbol) + set_error_raw(rc, ErrorLevel::ERROR, error.message, error.backtrace) + + logger.log_error(error) + end + + private + def set_error_raw(rc, error_level, message, backtrace) self.rc = rc.to_i - self.error_level = ErrorLevel.find(:error).to_i + self.error_level = error_level.to_i - backtrace = error.backtrace - entry = BacktraceEntry.parse(backtrace.first) - self.error_file = entry.file - self.error_line = entry.line - self.error_method = entry.method - self.error_message = error.message + self.error_message = message - logger.log_error(error) + if backtrace + entry = BacktraceEntry.parse(backtrace.first) + self.error_file = entry.file + self.error_line = entry.line + self.error_method = entry.method + end end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb index 2863c7f6195..f06b32d78b6 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb @@ -5,13 +5,19 @@ module Groonga class << self def find(name) - @@names[name] + @@names[name] || UNKNOWN_ERROR + end + + def register(name, code, error_class) + rc = new(name, code) + @@names[name] = rc + error_class.rc = rc if error_class + rc end end attr_reader :name def initialize(name, code) - @@names[name] = self @name = name @code = code end @@ -20,80 +26,164 @@ module Groonga @code end - SUCCESS = new(:success, 0) - END_OF_DATA = new(:end_of_data, 1) - UNKNOWN_ERROR = new(:unknown_error, -1) - OPERATION_NOT_PERMITTED = new(:operation_not_permitted, -2) - NO_SUCH_FILE_OR_DIRECTORY = new(:no_such_file_or_directory, -3) - NO_SUCH_PROCESS = new(:no_such_process, -4) - INTERRUPTED_FUNCTION_CALL = new(:interrupted_function_call, -5) - INPUT_OUTPUT_ERROR = new(:input_output_error, -6) - NO_SUCH_DEVICE_OR_ADDRESS = new(:no_such_device_or_address, -7) - ARG_LIST_TOO_LONG = new(:arg_list_too_long, -8) - EXEC_FORMAT_ERROR = new(:exec_format_error, -9) - BAD_FILE_DESCRIPTOR = new(:bad_file_descriptor, -10) - NO_CHILD_PROCESSES = new(:no_child_processes, -11) - RESOURCE_TEMPORARILY_UNAVAILABLE = new(:resource_temporarily_unavailable, -12) - NOT_ENOUGH_SPACE = new(:not_enough_space, -13) - PERMISSION_DENIED = new(:permission_denied, -14) - BAD_ADDRESS = new(:bad_address, -15) - RESOURCE_BUSY = new(:resource_busy, -16) - FILE_EXISTS = new(:file_exists, -17) - IMPROPER_LINK = new(:improper_link, -18) - NO_SUCH_DEVICE = new(:no_such_device, -19) - NOT_A_DIRECTORY = new(:not_a_directory, -20) - IS_A_DIRECTORY = new(:is_a_directory, -21) - INVALID_ARGUMENT = new(:invalid_argument, -22) - TOO_MANY_OPEN_FILES_IN_SYSTEM = new(:too_many_open_files_in_system, -23) - TOO_MANY_OPEN_FILES = new(:too_many_open_files, -24) - INAPPROPRIATE_IO_CONTROL_OPERATION = new(:inappropriate_io_control_operation, -25) - FILE_TOO_LARGE = new(:file_too_large, -26) - NO_SPACE_LEFT_ON_DEVICE = new(:no_space_left_on_device, -27) - INVALID_SEEK = new(:invalid_seek, -28) - READ_ONLY_FILE_SYSTEM = new(:read_only_file_system, -29) - TOO_MANY_LINKS = new(:too_many_links, -30) - BROKEN_PIPE = new(:broken_pipe, -31) - DOMAIN_ERROR = new(:domain_error, -32) - RESULT_TOO_LARGE = new(:result_too_large, -33) - RESOURCE_DEADLOCK_AVOIDED = new(:resource_deadlock_avoided, -34) - NO_MEMORY_AVAILABLE = new(:no_memory_available, -35) - FILENAME_TOO_LONG = new(:filename_too_long, -36) - NO_LOCKS_AVAILABLE = new(:no_locks_available, -37) - FUNCTION_NOT_IMPLEMENTED = new(:function_not_implemented, -38) - DIRECTORY_NOT_EMPTY = new(:directory_not_empty, -39) - ILLEGAL_BYTE_SEQUENCE = new(:illegal_byte_sequence, -40) - SOCKET_NOT_INITIALIZED = new(:socket_not_initialized, -41) - OPERATION_WOULD_BLOCK = new(:operation_would_block, -42) - ADDRESS_IS_NOT_AVAILABLE = new(:address_is_not_available, -43) - NETWORK_IS_DOWN = new(:network_is_down, -44) - NO_BUFFER = new(:no_buffer, -45) - SOCKET_IS_ALREADY_CONNECTED = new(:socket_is_already_connected, -46) - SOCKET_IS_NOT_CONNECTED = new(:socket_is_not_connected, -47) - SOCKET_IS_ALREADY_SHUTDOWNED = new(:socket_is_already_shutdowned, -48) - OPERATION_TIMEOUT = new(:operation_timeout, -49) - CONNECTION_REFUSED = new(:connection_refused, -50) - RANGE_ERROR = new(:range_error, -51) - TOKENIZER_ERROR = new(:tokenizer_error, -52) - FILE_CORRUPT = new(:file_corrupt, -53) - INVALID_FORMAT = new(:invalid_format, -54) - OBJECT_CORRUPT = new(:object_corrupt, -55) - TOO_MANY_SYMBOLIC_LINKS = new(:too_many_symbolic_links, -56) - NOT_SOCKET = new(:not_socket, -57) - OPERATION_NOT_SUPPORTED = new(:operation_not_supported, -58) - ADDRESS_IS_IN_USE = new(:address_is_in_use, -59) - ZLIB_ERROR = new(:zlib_error, -60) - LZO_ERROR = new(:lzo_error, -61) - STACK_OVER_FLOW = new(:stack_over_flow, -62) - SYNTAX_ERROR = new(:syntax_error, -63) - RETRY_MAX = new(:retry_max, -64) - INCOMPATIBLE_FILE_FORMAT = new(:incompatible_file_format, -65) - UPDATE_NOT_ALLOWED = new(:update_not_allowed, -66) - TOO_SMALL_OFFSET = new(:too_small_offset, -67) - TOO_LARGE_OFFSET = new(:too_large_offset, -68) - TOO_SMALL_LIMIT = new(:too_small_limit, -69) - CAS_ERROR = new(:cas_error, -70) - UNSUPPORTED_COMMAND_VERSION = new(:unsupported_command_version, -71) - NORMALIZER_ERROR = new(:normalizer_error, -72) + SUCCESS = + register(:success, 0, nil) + END_OF_DATA = + register(:end_of_data, 1, EndOfData) + UNKNOWN_ERROR = + register(:unknown_error, -1, UnknownError) + OPERATION_NOT_PERMITTED = + register(:operation_not_permitted, -2, OperationNotPermitted) + NO_SUCH_FILE_OR_DIRECTORY = + register(:no_such_file_or_directory, -3, NoSuchFileOrDirectory) + NO_SUCH_PROCESS = + register(:no_such_process, -4, NoSuchProcess) + INTERRUPTED_FUNCTION_CALL = + register(:interrupted_function_call, -5, InterruptedFunctionCall) + INPUT_OUTPUT_ERROR = + register(:input_output_error, -6, InputOutputError) + NO_SUCH_DEVICE_OR_ADDRESS = + register(:no_such_device_or_address, -7, NoSuchDeviceOrAddress) + ARG_LIST_TOO_LONG = + register(:arg_list_too_long, -8, ArgListTooLong) + EXEC_FORMAT_ERROR = + register(:exec_format_error, -9, ExecFormatError) + BAD_FILE_DESCRIPTOR = + register(:bad_file_descriptor, -10, BadFileDescriptor) + NO_CHILD_PROCESSES = + register(:no_child_processes, -11, NoChildProcesses) + RESOURCE_TEMPORARILY_UNAVAILABLE = + register(:resource_temporarily_unavailable, -12, + ResourceTemporarilyUnavailable) + NOT_ENOUGH_SPACE = + register(:not_enough_space, -13, NotEnoughSpace) + PERMISSION_DENIED = + register(:permission_denied, -14, PermissionDenied) + BAD_ADDRESS = + register(:bad_address, -15, BadAddress) + RESOURCE_BUSY = + register(:resource_busy, -16, ResourceBusy) + FILE_EXISTS = + register(:file_exists, -17, FileExists) + IMPROPER_LINK = + register(:improper_link, -18, ImproperLink) + NO_SUCH_DEVICE = + register(:no_such_device, -19, NoSuchDevice) + NOT_DIRECTORY = + register(:not_directory, -20, NotDirectory) + IS_DIRECTORY = + register(:is_directory, -21, IsDirectory) + INVALID_ARGUMENT = + register(:invalid_argument, -22, InvalidArgument) + TOO_MANY_OPEN_FILES_IN_SYSTEM = + register(:too_many_open_files_in_system, -23, TooManyOpenFilesInSystem) + TOO_MANY_OPEN_FILES = + register(:too_many_open_files, -24, TooManyOpenFiles) + INAPPROPRIATE_IO_CONTROL_OPERATION = + register(:inappropriate_io_control_operation, -25, + InappropriateIOControlOperation) + FILE_TOO_LARGE = + register(:file_too_large, -26, FileTooLarge) + NO_SPACE_LEFT_ON_DEVICE = + register(:no_space_left_on_device, -27, NoSpaceLeftOnDevice) + INVALID_SEEK = + register(:invalid_seek, -28, InvalidSeek) + READ_ONLY_FILE_SYSTEM = + register(:read_only_file_system, -29, ReadOnlyFileSystem) + TOO_MANY_LINKS = + register(:too_many_links, -30, TooManyLinks) + BROKEN_PIPE = + register(:broken_pipe, -31, BrokenPipe) + DOMAIN_ERROR = + register(:domain_error, -32, DomainError) + RESULT_TOO_LARGE = + register(:result_too_large, -33, ResultTooLarge) + RESOURCE_DEADLOCK_AVOIDED = + register(:resource_deadlock_avoided, -34, ResourceDeadlockAvoided) + NO_MEMORY_AVAILABLE = + register(:no_memory_available, -35, NoMemoryAvailable) + FILENAME_TOO_LONG = + register(:filename_too_long, -36, FilenameTooLong) + NO_LOCKS_AVAILABLE = + register(:no_locks_available, -37, NoLocksAvailable) + FUNCTION_NOT_IMPLEMENTED = + register(:function_not_implemented, -38, FunctionNotImplemented) + DIRECTORY_NOT_EMPTY = + register(:directory_not_empty, -39, DirectoryNotEmpty) + ILLEGAL_BYTE_SEQUENCE = + register(:illegal_byte_sequence, -40, IllegalByteSequence) + SOCKET_NOT_INITIALIZED = + register(:socket_not_initialized, -41, SocketNotInitialized) + OPERATION_WOULD_BLOCK = + register(:operation_would_block, -42, OperationWouldBlock) + ADDRESS_IS_NOT_AVAILABLE = + register(:address_is_not_available, -43, AddressIsNotAvailable) + NETWORK_IS_DOWN = + register(:network_is_down, -44, NetworkIsDown) + NO_BUFFER = + register(:no_buffer, -45, NoBuffer) + SOCKET_IS_ALREADY_CONNECTED = + register(:socket_is_already_connected, -46, SocketIsAlreadyConnected) + SOCKET_IS_NOT_CONNECTED = + register(:socket_is_not_connected, -47, SocketIsNotConnected) + SOCKET_IS_ALREADY_SHUTDOWNED = + register(:socket_is_already_shutdowned, -48, SocketIsAlreadyShutdowned) + OPERATION_TIMEOUT = + register(:operation_timeout, -49, OperationTimeout) + CONNECTION_REFUSED = + register(:connection_refused, -50, ConnectionRefused) + RANGE_ERROR = + register(:range_error, -51, RangeError) + TOKENIZER_ERROR = + register(:tokenizer_error, -52, TokenizerError) + FILE_CORRUPT = + register(:file_corrupt, -53, FileCorrupt) + INVALID_FORMAT = + register(:invalid_format, -54, InvalidFormat) + OBJECT_CORRUPT = + register(:object_corrupt, -55, ObjectCorrupt) + TOO_MANY_SYMBOLIC_LINKS = + register(:too_many_symbolic_links, -56, TooManySymbolicLinks) + NOT_SOCKET = + register(:not_socket, -57, NotSocket) + OPERATION_NOT_SUPPORTED = + register(:operation_not_supported, -58, OperationNotSupported) + ADDRESS_IS_IN_USE = + register(:address_is_in_use, -59, AddressIsInUse) + ZLIB_ERROR = + register(:zlib_error, -60, ZlibError) + LZ4_ERROR = + register(:lz4_error, -61, LZ4Error) + STACK_OVER_FLOW = + register(:stack_over_flow, -62, StackOverFlow) + SYNTAX_ERROR = + register(:syntax_error, -63, SyntaxError) + RETRY_MAX = + register(:retry_max, -64, RetryMax) + INCOMPATIBLE_FILE_FORMAT = + register(:incompatible_file_format, -65, IncompatibleFileFormat) + UPDATE_NOT_ALLOWED = + register(:update_not_allowed, -66, UpdateNotAllowed) + TOO_SMALL_OFFSET = + register(:too_small_offset, -67, TooSmallOffset) + TOO_LARGE_OFFSET = + register(:too_large_offset, -68, TooLargeOffset) + TOO_SMALL_LIMIT = + register(:too_small_limit, -69, TooSmallLimit) + CAS_ERROR = + register(:cas_error, -70, CASError) + UNSUPPORTED_COMMAND_VERSION = + register(:unsupported_command_version, -71, UnsupportedCommandVersion) + NORMALIZER_ERROR = + register(:normalizer_error, -72, NormalizerError) + TOKEN_FILTER_ERROR = + register(:token_filter_error, -73, TokenFilterError) + COMMAND_ERROR = + register(:command_error, -74, CommandError) + PLUGIN_ERROR = + register(:plugin_error, -75, PluginError) + + GroongaError.rc = UNKNOWN_ERROR end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb new file mode 100644 index 00000000000..54d9dc1a631 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb @@ -0,0 +1,39 @@ +module Groonga + class Database + def each + context = Context.instance + flags = + TableCursorFlags::ASCENDING | + TableCursorFlags::BY_ID + TableCursor.open(self, :flags => flags) do |cursor| + cursor.each do |id| + object = context[id] + yield(object) if object + end + end + end + + def each_table(options={}) + context = Context.instance + min = options[:prefix] + flags = 0 + if options[:order] == :descending + flags |= TableCursorFlags::DESCENDING + else + flags |= TableCursorFlags::ASCENDING + end + if options[:order_by] == :id + flags |= TableCursorFlags::BY_ID + else + flags |= TableCursorFlags::BY_KEY + end + flags |= TableCursorFlags::PREFIX if min + TableCursor.open(self, :min => min, :flags => flags) do |cursor| + cursor.each do |id| + object = context[id] + yield(object) if object.is_a?(Table) + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb new file mode 100644 index 00000000000..e39c904534a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb @@ -0,0 +1,16 @@ +module Groonga + class GroongaError + class << self + def rc + @rc + end + + def rc=(rc) + @rc = rc + end + end + end + + class ErrorMessage < Error + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb new file mode 100644 index 00000000000..8044066930a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb @@ -0,0 +1,18 @@ +module Groonga + class IndexCursor + class << self + def open(*arguments) + cursor = open_raw(*arguments) + if block_given? + begin + yield(cursor) + ensure + cursor.close + end + else + cursor + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb new file mode 100644 index 00000000000..7110437c200 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb @@ -0,0 +1,14 @@ +require "error" + +require "context" + +require "writer" + +require "database" +require "command" +require "table_cursor" +require "index_cursor" + +require "plugin_loader" + +require "eval_context" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb new file mode 100644 index 00000000000..c9a74a80dd9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb @@ -0,0 +1 @@ +require "backtrace_entry" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb index 06f99c14fc3..33021355824 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb @@ -3,7 +3,11 @@ module Groonga def log_error(error) log_level = Level::ERROR.to_i - message = "#{error.class}: #{error.message}" + if error.is_a?(Error) + message = error.message + else + message = "#{error.class}: #{error.message}" + end backtrace = error.backtrace first_raw_entry = backtrace.first if first_raw_entry diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb new file mode 100644 index 00000000000..09b972f120d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb @@ -0,0 +1,14 @@ +module Groonga + class PluginLoader + class << self + def load_file(path) + begin + load(path) + rescue => error + Context.instance.record_error(:plugin_error, error) + nil + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb new file mode 100644 index 00000000000..a824e92fa51 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb @@ -0,0 +1,68 @@ +$" = [__FILE__] + +class ScriptLoader + @@loading_paths = {} + + def initialize(path) + @base_path = path + end + + def load_once + if absolete_path?(@base_path) + loaded = load_once_path(@base_path) + if loaded.nil? + raise LoadError, error_message + else + loaded + end + else + $LOAD_PATH.each do |load_path| + unless absolete_path?(load_path) + load_path = File.expand_path(load_path) + end + loaded = load_once_path(File.join(load_path, @base_path)) + return loaded unless loaded.nil? + end + raise LoadError, error_message + end + end + + private + def error_message + "cannot load such file -- #{@base_path}" + end + + def absolete_path?(path) + path.start_with?("/") + end + + def load_once_path(path) + loaded = load_once_absolete_path(path) + return loaded unless loaded.nil? + + return nil unless File.extname(path).empty? + + load_once_absolete_path("#{path}.rb") + end + + def load_once_absolete_path(path) + return false if $".include?(path) + return false if @@loading_paths.key?(path) + + return nil unless File.file?(path) + + @@loading_paths[path] = true + load(path) + $" << path + @@loading_paths.delete(path) + + true + end +end + +module Kernel + def require(path) + loader = ScriptLoader.new(path) + loader.load_once + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb index cf0056d7fd3..64262f8f975 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb @@ -19,6 +19,9 @@ module Groonga if data.similarity_threshold self.similarity_threshold = data.similarity_threshold end + if data.scorer + self.scorer = data.scorer + end data.args.each do |arg| push_arg(arg) end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb index 5e258e90e5a..b002eaa14c0 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb @@ -41,6 +41,20 @@ module Groonga Operator::TERM_EXTRACT, ] + ARITHMETIC_OPERATORS = [ + Operator::BITWISE_OR, + Operator::BITWISE_XOR, + Operator::BITWISE_AND, + Operator::BITWISE_NOT, + Operator::SHIFTL, + Operator::SHIFTR, + Operator::SHIFTRR, + Operator::PLUS, + Operator::MINUS, + Operator::STAR, + Operator::MOD, + ] + LOGICAL_OPERATORS = [ Operator::AND, Operator::OR, @@ -89,7 +103,7 @@ module Groonga status = Status::COL1 data.args << code.value when Status::COL1 - raise "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>" + raise ErrorMessage, "invalid expression: can't use column as a value: <#{code.value.name}>: <#{@expression.grn_inspect}>" status = Status::COL2 when Status::COL2 # Do nothing @@ -114,7 +128,7 @@ module Groonga first_data = @data_list.first if (first_data.flags & ScanInfo::Flags::PUSH) == 0 or first_data.logical_op != @operator - raise "invalid expr" + raise ErrorMessage, "invalid expr" else first_data.flags &= ~ScanInfo::Flags::PUSH first_data.logical_op = @operator @@ -140,6 +154,11 @@ module Groonga return false if status > Status::CONST status = Status::START n_relation_expressions += 1 + when *ARITHMETIC_OPERATORS + return false if status < Status::COL1 + return false if status > Status::CONST + status = Status::START + return false if n_relation_expressions != (n_logical_expressions + 1) when *LOGICAL_OPERATORS return false if status != Status::START n_logical_expressions += 1 @@ -206,10 +225,12 @@ module Groonga new_data.flags = ScanInfo::Flags::POP new_data.logical_op = operator @data_list << new_data + break end else data.flags &= ~ScanInfo::Flags::PUSH data.logical_op = operator + break end else if n_dif_ops > 0 @@ -225,6 +246,7 @@ module Groonga @data_list[r..-1] + @data_list[j...r] end + break end end else @@ -235,7 +257,7 @@ module Groonga end if j < 0 - raise GRN_INVALID_ARGUMENT.new("unmatched nesting level") + raise ErrorMessage, "unmatched nesting level" end end end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb index 67d0bc3aef7..b0ebfea3cee 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb @@ -10,6 +10,7 @@ module Groonga attr_accessor :flags attr_accessor :max_interval attr_accessor :similarity_threshold + attr_accessor :scorer def initialize(start) @start = start @end = 0 @@ -21,6 +22,7 @@ module Groonga @flags = ScanInfo::Flags::PUSH @max_interval = nil @similarity_threshold = nil + @scorer = nil end def match_resolve_index @@ -57,7 +59,7 @@ module Groonga else message = "The first argument of NEAR/NEAR2 must be Expression, Accessor or Object: #{arg.class}" - raise message + raise ErrorMessage, message end self.query = @args[1] @@ -80,7 +82,7 @@ module Groonga else message = "The first argument of SIMILAR must be Expression, Accessor or Object: #{arg.class}" - raise message + raise ErrorMesesage, message end self.query = @args[1] @@ -107,28 +109,47 @@ module Groonga n_codes = codes.size i = 0 while i < n_codes - code = codes[i] - value = code.value - case value - when Accessor - match_resolve_index_expression_accessor(code) - when FixedSizeColumn, VariableSizeColumn - match_resolve_index_expression_data_column(code) - when IndexColumn - section_id = 0 - rest_n_codes = n_codes - i - if rest_n_codes >= 2 and - codes[i + 1].value.is_a?(Bulk) and - codes[i + 1].value.domain == ID::UINT32 and - codes[i + 2].op == Operator::GET_MEMBER - section_id = codes[i + 1].value.value + 1 - code = codes[i + 2] - i += 2 - end - put_index(value, section_id, code.weight) + i = match_resolve_index_expression_codes(codes, i, n_codes) + end + end + + def match_resolve_index_expression_codes(codes, i, n_codes) + code = codes[i] + value = code.value + case value + when Accessor + match_resolve_index_expression_accessor(code) + when FixedSizeColumn, VariableSizeColumn + match_resolve_index_expression_data_column(code) + when IndexColumn + section_id = 0 + rest_n_codes = n_codes - i + if rest_n_codes >= 2 and + codes[i + 1].value.is_a?(Bulk) and + (codes[i + 1].value.domain == ID::UINT32 or + codes[i + 1].value.domain == ID::INT32) and + codes[i + 2].op == Operator::GET_MEMBER + section_id = codes[i + 1].value.value + 1 + code = codes[i + 2] + i += 2 + end + put_index(value, section_id, code.weight) + when Procedure + unless value.scorer? + message = "procedure must be scorer: #{scorer.name}>" + raise ErrorMessage, message + end + @scorer = value + rest_n_codes = n_codes - i + if rest_n_codes == 0 + message = "match target is required as an argument: <#{scorer.name}>" + raise ErrorMessage, message end - i += 1 + i = match_resolve_index_expression_codes(codes, i + 1, n_codes) + when Table + raise ErrorMessage, "invalid match target: <#{value.name}>" end + i + 1 end def match_resolve_index_expression_accessor(expr_code) diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am index 93ade1627e6..fa90c59ce23 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am @@ -1,13 +1,24 @@ RUBY_SCRIPT_FILES = \ backtrace_entry.rb \ + command.rb \ + command_line/grndb.rb \ context.rb \ context/error_level.rb \ context/rc.rb \ + database.rb \ + error.rb \ eval_context.rb \ expression.rb \ + index_cursor.rb \ index_info.rb \ + initialize/pre.rb \ + initialize/post.rb \ logger.rb \ logger/level.rb \ + plugin_loader.rb \ + require.rb \ scan_info.rb \ scan_info_builder.rb \ - scan_info_data.rb + scan_info_data.rb \ + table_cursor.rb \ + writer.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb new file mode 100644 index 00000000000..a36d88d556d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb @@ -0,0 +1,26 @@ +module Groonga + class TableCursor + class << self + def open(*arguments) + cursor = open_raw(*arguments) + if block_given? + begin + yield(cursor) + ensure + cursor.close + end + else + cursor + end + end + end + + def each + loop do + id = self.next + return if id == Groonga::ID::NIL + yield(id) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb new file mode 100644 index 00000000000..de2bc2611e9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb @@ -0,0 +1,21 @@ +module Groonga + class Writer + def array(name, n_elements) + open_array(name, n_elements) + begin + yield + ensure + close_array + end + end + + def map(name, n_elements) + open_map(name, n_elements) + begin + yield + ensure + close_map + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/sources.am index 947607c7ecd..c4f02fca639 100644 --- a/storage/mroonga/vendor/groonga/lib/mrb/sources.am +++ b/storage/mroonga/vendor/groonga/lib/mrb/sources.am @@ -1,33 +1,59 @@ libgrnmrb_la_SOURCES = \ mrb_accessor.c \ mrb_accessor.h \ + mrb_array.c \ + mrb_array.h \ mrb_bulk.c \ mrb_bulk.h \ mrb_column.c \ mrb_column.h \ + mrb_command.c \ + mrb_command.h \ + mrb_command_input.c \ + mrb_command_input.h \ mrb_converter.c \ mrb_converter.h \ mrb_ctx.c \ mrb_ctx.h \ + mrb_database.c \ + mrb_database.h \ + mrb_double_array_trie.c \ + mrb_double_array_trie.h \ mrb_error.c \ mrb_error.h \ mrb_expr.c \ mrb_expr.h \ mrb_fixed_size_column.c \ mrb_fixed_size_column.h \ + mrb_hash_table.c \ + mrb_hash_table.h \ mrb_id.c \ mrb_id.h \ mrb_index_column.c \ mrb_index_column.h \ + mrb_index_cursor.c \ + mrb_index_cursor.h \ mrb_logger.c \ mrb_logger.h \ - mrb_obj.c \ - mrb_obj.h \ + mrb_object.c \ + mrb_object.h \ mrb_operator.c \ mrb_operator.h \ + mrb_patricia_trie.c \ + mrb_patricia_trie.h \ mrb_procedure.c \ mrb_procedure.h \ + mrb_table.c \ + mrb_table.h \ + mrb_table_cursor.c \ + mrb_table_cursor.h \ + mrb_table_cursor_flags.c \ + mrb_table_cursor_flags.h \ + mrb_type.c \ + mrb_type.h \ mrb_variable_size_column.c \ mrb_variable_size_column.h \ mrb_void.c \ - mrb_void.h + mrb_void.h \ + mrb_writer.c \ + mrb_writer.h diff --git a/storage/mroonga/vendor/groonga/lib/nfkc.c b/storage/mroonga/vendor/groonga/lib/nfkc.c index 252fb210e6e..30e06f94a34 100644 --- a/storage/mroonga/vendor/groonga/lib/nfkc.c +++ b/storage/mroonga/vendor/groonga/lib/nfkc.c @@ -17,10 +17,7 @@ don't edit this file by hand. it generated automatically by nfkc.rb */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - +#include "grn.h" #include <groonga/nfkc.h> #ifdef GRN_WITH_NFKC diff --git a/storage/mroonga/vendor/groonga/lib/normalizer.c b/storage/mroonga/vendor/groonga/lib/normalizer.c index 04719bdd463..27d34a4850b 100644 --- a/storage/mroonga/vendor/groonga/lib/normalizer.c +++ b/storage/mroonga/vendor/groonga/lib/normalizer.c @@ -18,8 +18,8 @@ #include <string.h> -#include "normalizer_in.h" -#include "string_in.h" +#include "grn_normalizer.h" +#include "grn_string.h" #include <groonga/normalizer.h> #include <groonga/tokenizer.h> diff --git a/storage/mroonga/vendor/groonga/lib/obj.c b/storage/mroonga/vendor/groonga/lib/obj.c new file mode 100644 index 00000000000..87850b6357b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/obj.c @@ -0,0 +1,106 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "grn.h" +#include "grn_db.h" +#include <groonga/obj.h> + +grn_bool +grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj) +{ + grn_id id; + + if (!obj) { return GRN_FALSE; } + + id = grn_obj_id(ctx, obj); + if (id == GRN_ID_NIL) { + return GRN_FALSE; + } else { + return id < GRN_N_RESERVED_TYPES; + } +} + +grn_bool +grn_obj_is_table(grn_ctx *ctx, grn_obj *obj) +{ + grn_bool is_table = GRN_FALSE; + + if (!obj) { + return GRN_FALSE; + } + + switch (obj->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + is_table = GRN_TRUE; + default : + break; + } + + return is_table; +} + +grn_bool +grn_obj_is_proc(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + return obj->header.type == GRN_PROC; +} + +grn_bool +grn_obj_is_function_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_FUNCTION; +} + +grn_bool +grn_obj_is_selector_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_function_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->selector != NULL; +} + +grn_bool +grn_obj_is_scorer_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_SCORER; +} diff --git a/storage/mroonga/vendor/groonga/lib/operator.c b/storage/mroonga/vendor/groonga/lib/operator.c new file mode 100644 index 00000000000..27aa5df5819 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/operator.c @@ -0,0 +1,596 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "grn.h" +#include "grn_db.h" +#include "grn_str.h" + +#include <string.h> + +static const char *operator_names[] = { + "push", + "pop", + "nop", + "call", + "intern", + "get_ref", + "get_value", + "and", + "and_not", + "or", + "assign", + "star_assign", + "slash_assign", + "mod_assign", + "plus_assign", + "minus_assign", + "shiftl_assign", + "shiftr_assign", + "shiftrr_assign", + "and_assign", + "xor_assign", + "or_assign", + "jump", + "cjump", + "comma", + "bitwise_or", + "bitwise_xor", + "bitwise_and", + "bitwise_not", + "equal", + "not_equal", + "less", + "greater", + "less_equal", + "greater_equal", + "in", + "match", + "near", + "near2", + "similar", + "term_extract", + "shiftl", + "shiftr", + "shiftrr", + "plus", + "minus", + "star", + "slash", + "mod", + "delete", + "incr", + "decr", + "incr_post", + "decr_post", + "not", + "adjust", + "exact", + "lcp", + "partial", + "unsplit", + "prefix", + "suffix", + "geo_distance1", + "geo_distance2", + "geo_distance3", + "geo_distance4", + "geo_withinp5", + "geo_withinp6", + "geo_withinp8", + "obj_search", + "expr_get_var", + "table_create", + "table_select", + "table_sort", + "table_group", + "json_put", + "get_member" +}; + +const char * +grn_operator_to_string(grn_operator op) +{ + if (GRN_OP_PUSH <= op && op <= GRN_OP_GET_MEMBER) { + return operator_names[op]; + } else { + return "unknown"; + } +} + +#define DO_EQ_SUB do {\ + switch (y->header.domain) {\ + case GRN_DB_INT8 :\ + r = (x_ == GRN_INT8_VALUE(y));\ + break;\ + case GRN_DB_UINT8 :\ + r = (x_ == GRN_UINT8_VALUE(y));\ + break;\ + case GRN_DB_INT16 :\ + r = (x_ == GRN_INT16_VALUE(y));\ + break;\ + case GRN_DB_UINT16 :\ + r = (x_ == GRN_UINT16_VALUE(y));\ + break;\ + case GRN_DB_INT32 :\ + r = (x_ == GRN_INT32_VALUE(y));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ == GRN_UINT32_VALUE(y));\ + break;\ + case GRN_DB_INT64 :\ + r = (x_ == GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_TIME :\ + r = (GRN_TIME_PACK(x_,0) == GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ == GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + const char *p_ = GRN_TEXT_VALUE(y);\ + int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ + r = (x_ == i_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ +} while (0) + +#define DO_EQ(x,y,r) do {\ + switch (x->header.domain) {\ + case GRN_DB_VOID :\ + r = GRN_FALSE;\ + break;\ + case GRN_DB_INT8 :\ + {\ + int8_t x_ = GRN_INT8_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_UINT8 :\ + {\ + uint8_t x_ = GRN_UINT8_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_INT16 :\ + {\ + int16_t x_ = GRN_INT16_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_UINT16 :\ + {\ + uint16_t x_ = GRN_UINT16_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_INT32 :\ + {\ + int32_t x_ = GRN_INT32_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_UINT32 :\ + {\ + uint32_t x_ = GRN_UINT32_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_INT64 :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_TIME :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + switch (y->header.domain) {\ + case GRN_DB_INT32 :\ + r = (x_ == GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ == GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + r = (x_ == GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ == GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = (x_ == GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + grn_obj time_value_;\ + GRN_TIME_INIT(&time_value_, 0);\ + if (grn_obj_cast(ctx, y, &time_value_, GRN_FALSE) == GRN_SUCCESS) {\ + r = (x_ == GRN_TIME_VALUE(&time_value_));\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &time_value_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + }\ + break;\ + case GRN_DB_UINT64 :\ + {\ + uint64_t x_ = GRN_UINT64_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_FLOAT :\ + {\ + double x_ = GRN_FLOAT_VALUE(x);\ + switch (y->header.domain) {\ + case GRN_DB_INT32 :\ + r = ((x_ <= GRN_INT32_VALUE(y)) && (x_ >= GRN_INT32_VALUE(y)));\ + break;\ + case GRN_DB_UINT32 :\ + r = ((x_ <= GRN_UINT32_VALUE(y)) && (x_ >= GRN_UINT32_VALUE(y)));\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + r = ((x_ <= GRN_INT64_VALUE(y)) && (x_ >= GRN_INT64_VALUE(y)));\ + break;\ + case GRN_DB_UINT64 :\ + r = ((x_ <= GRN_UINT64_VALUE(y)) && (x_ >= GRN_UINT64_VALUE(y)));\ + break;\ + case GRN_DB_FLOAT :\ + r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + const char *p_ = GRN_TEXT_VALUE(y);\ + int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ + r = (x_ <= i_ && x_ >= i_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + }\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\ + uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\ + r = (la == lb && !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb));\ + } else {\ + const char *q_ = GRN_TEXT_VALUE(x);\ + int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\ + DO_EQ_SUB;\ + }\ + break;\ + default :\ + if ((x->header.domain == y->header.domain)) {\ + r = (GRN_BULK_VSIZE(x) == GRN_BULK_VSIZE(y) &&\ + !(memcmp(GRN_BULK_HEAD(x), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(x))));\ + } else {\ + grn_obj dest;\ + if (x->header.domain < y->header.domain) {\ + GRN_OBJ_INIT(&dest, GRN_BULK, 0, y->header.domain);\ + if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {\ + r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(y) &&\ + !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(y))); \ + }\ + } else {\ + GRN_OBJ_INIT(&dest, GRN_BULK, 0, x->header.domain);\ + if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {\ + r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(x) &&\ + !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(x), GRN_BULK_VSIZE(x))); \ + }\ + }\ + GRN_OBJ_FIN(ctx, &dest);\ + }\ + break;\ + }\ +} while (0) + +grn_bool +grn_operator_exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r; + GRN_API_ENTER; + DO_EQ(x, y, r); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_not_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r; + GRN_API_ENTER; + DO_EQ(x, y, r); + GRN_API_RETURN(!r); +} + +#define DO_COMPARE_SUB_NUMERIC(y,op) do {\ + switch ((y)->header.domain) {\ + case GRN_DB_INT8 :\ + r = (x_ op GRN_INT8_VALUE(y));\ + break;\ + case GRN_DB_UINT8 :\ + r = (x_ op GRN_UINT8_VALUE(y));\ + break;\ + case GRN_DB_INT16 :\ + r = (x_ op GRN_INT16_VALUE(y));\ + break;\ + case GRN_DB_UINT16 :\ + r = (x_ op GRN_UINT16_VALUE(y));\ + break;\ + case GRN_DB_INT32 :\ + r = (x_ op GRN_INT32_VALUE(y));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ op GRN_UINT32_VALUE(y));\ + break;\ + case GRN_DB_INT64 :\ + r = (x_ op GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_TIME :\ + r = (GRN_TIME_PACK(x_,0) op GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ op GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = (x_ op GRN_FLOAT_VALUE(y));\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ +} while (0) + +#define DO_COMPARE_SUB(op) do {\ + switch (y->header.domain) {\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + grn_obj y_;\ + GRN_OBJ_INIT(&y_, GRN_BULK, 0, x->header.domain);\ + if (grn_obj_cast(ctx, y, &y_, GRN_FALSE)) {\ + r = GRN_FALSE;\ + } else {\ + DO_COMPARE_SUB_NUMERIC(&y_, op);\ + }\ + GRN_OBJ_FIN(ctx, &y_);\ + }\ + break;\ + default :\ + DO_COMPARE_SUB_NUMERIC(y,op);\ + break;\ + }\ +} while (0) + +#define DO_COMPARE_BUILTIN(x,y,r,op) do {\ + switch (x->header.domain) {\ + case GRN_DB_INT8 :\ + {\ + int8_t x_ = GRN_INT8_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT8 :\ + {\ + uint8_t x_ = GRN_UINT8_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_INT16 :\ + {\ + int16_t x_ = GRN_INT16_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT16 :\ + {\ + uint16_t x_ = GRN_UINT16_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_INT32 :\ + {\ + int32_t x_ = GRN_INT32_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT32 :\ + {\ + uint32_t x_ = GRN_UINT32_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_TIME :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + switch (y->header.domain) {\ + case GRN_DB_INT32 :\ + r = (x_ op GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ op GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + r = (x_ op GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ op GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = (x_ op GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + grn_obj time_value_;\ + GRN_TIME_INIT(&time_value_, 0);\ + if (grn_obj_cast(ctx, y, &time_value_, GRN_FALSE) == GRN_SUCCESS) {\ + r = (x_ op GRN_TIME_VALUE(&time_value_));\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &time_value_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + }\ + break;\ + case GRN_DB_INT64 :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT64 :\ + {\ + uint64_t x_ = GRN_UINT64_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_FLOAT :\ + {\ + double x_ = GRN_FLOAT_VALUE(x);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\ + int r_;\ + uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\ + if (la > lb) {\ + if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb))) {\ + r_ = 1;\ + }\ + } else {\ + if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), la))) {\ + r_ = la == lb ? 0 : -1;\ + }\ + }\ + r = (r_ op 0);\ + } else {\ + const char *q_ = GRN_TEXT_VALUE(x);\ + int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\ + DO_COMPARE_SUB(op);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ +} while (0) + +#define DO_COMPARE(x, y, r, op) do {\ + if (x->header.domain >= GRN_N_RESERVED_TYPES) {\ + grn_obj *table;\ + table = grn_ctx_at(ctx, x->header.domain);\ + switch (table->header.type) {\ + case GRN_TABLE_HASH_KEY :\ + case GRN_TABLE_PAT_KEY :\ + {\ + grn_obj key;\ + int length;\ + GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\ + length = grn_table_get_key2(ctx, table, GRN_RECORD_VALUE(x), &key);\ + if (length > 0) {\ + grn_obj *x_original = x;\ + x = &key;\ + DO_COMPARE_BUILTIN((&key), y, r, op);\ + x = x_original;\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &key);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + grn_obj_unlink(ctx, table);\ + } else {\ + DO_COMPARE_BUILTIN(x, y, r, op);\ + }\ +} while (0) + +grn_bool +grn_operator_exec_less(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r; + GRN_API_ENTER; + DO_COMPARE(x, y, r, <); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_greater(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r; + GRN_API_ENTER; + DO_COMPARE(x, y, r, >); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_less_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r; + GRN_API_ENTER; + DO_COMPARE(x, y, r, <=); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_greater_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r; + GRN_API_ENTER; + DO_COMPARE(x, y, r, >=); + GRN_API_RETURN(r); +} diff --git a/storage/mroonga/vendor/groonga/lib/output.c b/storage/mroonga/vendor/groonga/lib/output.c index 9b745c89a01..20bd2a8694a 100644 --- a/storage/mroonga/vendor/groonga/lib/output.c +++ b/storage/mroonga/vendor/groonga/lib/output.c @@ -15,15 +15,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef GROONGA_IN_H -#include "groonga_in.h" -#endif /* GROONGA_IN_H */ +#include "grn.h" #include <string.h> -#include "str.h" -#include "db.h" -#include "util.h" -#include "output.h" +#include "grn_str.h" +#include "grn_db.h" +#include "grn_util.h" +#include "grn_output.h" #define LEVELS (&ctx->impl->levels) #define DEPTH (GRN_BULK_VSIZE(LEVELS)>>2) @@ -521,10 +519,10 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, buf.header.domain = DB_OBJ(a->obj)->range; break; case GRN_ACCESSOR_GET_SCORE : - grn_obj_get_value(ctx, a->obj, id, &buf); { grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); - GRN_INT32_PUT(ctx, &buf, ri->score); + int32_t int32_score = ri->score; + GRN_INT32_PUT(ctx, &buf, int32_score); } buf.header.domain = GRN_DB_INT32; break; @@ -535,6 +533,42 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, } buf.header.domain = GRN_DB_INT32; break; + case GRN_ACCESSOR_GET_MAX : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t max; + max = grn_rset_recinfo_get_max(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, &buf, max); + } + buf.header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_MIN : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t min; + min = grn_rset_recinfo_get_min(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, &buf, min); + } + buf.header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_SUM : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t sum; + sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, &buf, sum); + } + buf.header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_AVG : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + double avg; + avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj); + GRN_FLOAT_PUT(ctx, &buf, avg); + } + buf.header.domain = GRN_DB_FLOAT; + break; case GRN_ACCESSOR_GET_COLUMN_VALUE : if ((a->obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) { if (a->next) { @@ -1023,6 +1057,7 @@ grn_output_table_header(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *table, grn_obj_format *format) { + if (format->nhits != -1) { grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); if (output_type == GRN_CONTENT_XML) { grn_text_itoa(ctx, outbuf, format->nhits); @@ -1030,6 +1065,7 @@ grn_output_table_header(grn_ctx *ctx, grn_obj *outbuf, grn_output_int32(ctx, outbuf, output_type, format->nhits); } grn_output_array_close(ctx, outbuf, output_type); + } } static inline int @@ -1105,6 +1141,20 @@ count_used_n_codes(grn_ctx *ctx, grn_expr_code *start, grn_expr_code *target) return n_codes; } +static grn_bool +is_score_accessor(grn_ctx *ctx, grn_obj *obj) +{ + grn_accessor *a; + + if (obj->header.type != GRN_ACCESSOR) { + return GRN_FALSE; + } + + for (a = (grn_accessor *)obj; a->next; a = a->next) { + } + return a->action == GRN_ACCESSOR_GET_SCORE; +} + static inline void grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, @@ -1112,11 +1162,18 @@ grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf, { grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); if (column) { - grn_id range_id; + grn_id range_id = GRN_ID_NIL; GRN_BULK_REWIND(buf); grn_column_name_(ctx, column, buf); grn_output_obj(ctx, outbuf, output_type, buf, NULL); - range_id = grn_obj_get_range(ctx, column); + if (column->header.type == GRN_COLUMN_INDEX) { + range_id = GRN_DB_UINT32; + } else if (is_score_accessor(ctx, column)) { + range_id = GRN_DB_INT32; + } + if (range_id == GRN_ID_NIL) { + range_id = grn_obj_get_range(ctx, column); + } if (range_id == GRN_ID_NIL) { grn_output_cstr(ctx, outbuf, output_type, "null"); } else { @@ -1139,6 +1196,46 @@ grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf, } static inline void +grn_output_table_column_by_expression(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_expr_code *code, + grn_expr_code *code_end, + grn_obj *buf) +{ + if (code_end <= code) { + grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); + grn_output_null(ctx, outbuf, output_type); + grn_output_null(ctx, outbuf, output_type); + grn_output_array_close(ctx, outbuf, output_type); + return; + } + + switch (code_end[-1].op) { + case GRN_OP_GET_MEMBER : + if ((code_end - code) == 3) { + grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); + + GRN_BULK_REWIND(buf); + grn_column_name_(ctx, code[0].value, buf); + GRN_TEXT_PUTC(ctx, buf, '['); + grn_inspect(ctx, buf, code[1].value); + GRN_TEXT_PUTC(ctx, buf, ']'); + + grn_output_obj(ctx, outbuf, output_type, buf, NULL); + grn_output_null(ctx, outbuf, output_type); + + grn_output_array_close(ctx, outbuf, output_type); + } else { + grn_output_table_column(ctx, outbuf, output_type, code->value, buf); + } + break; + default : + grn_output_table_column(ctx, outbuf, output_type, code->value, buf); + break; + } +} + +static inline void grn_output_table_columns_by_expression(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *table, grn_obj_format *format, @@ -1163,30 +1260,35 @@ grn_output_table_columns_by_expression(grn_ctx *ctx, grn_obj *outbuf, } have_comma = GRN_TRUE; - code_start_offset = previous_comma_offset + 1; if (is_first_comma) { + int n_used_codes; int code_end_offset; - int n_used_code; - grn_output_table_column(ctx, outbuf, output_type, - expr->codes[0].value, buf); + n_used_codes = count_used_n_codes(ctx, expr->codes, code - 1); + code_end_offset = code - expr->codes - n_used_codes; - code_end_offset = code - expr->codes - code_start_offset - 1; - n_used_code = count_used_n_codes(ctx, - expr->codes, - expr->codes + code_end_offset); - code_start_offset = code_end_offset - n_used_code + 1; + grn_output_table_column_by_expression(ctx, outbuf, output_type, + expr->codes, + expr->codes + code_end_offset, + buf); + code_start_offset = code_end_offset; is_first_comma = GRN_FALSE; + } else { + code_start_offset = previous_comma_offset + 1; } - grn_output_table_column(ctx, outbuf, output_type, - expr->codes[code_start_offset].value, buf); + grn_output_table_column_by_expression(ctx, outbuf, output_type, + expr->codes + code_start_offset, + code, + buf); previous_comma_offset = code - expr->codes; } if (!have_comma && expr->codes_curr > 0) { - grn_output_table_column(ctx, outbuf, output_type, - expr->codes[0].value, buf); + grn_output_table_column_by_expression(ctx, outbuf, output_type, + expr->codes, + code_end, + buf); } grn_output_array_close(ctx, outbuf, output_type); @@ -1209,7 +1311,7 @@ grn_output_table_columns_by_columns(grn_ctx *ctx, grn_obj *outbuf, grn_output_array_close(ctx, outbuf, output_type); } -static inline void +void grn_output_table_columns(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *table, grn_obj_format *format) @@ -1322,7 +1424,7 @@ grn_output_table_records_by_columns(grn_ctx *ctx, grn_obj *outbuf, } } -static inline void +void grn_output_table_records(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *table, grn_obj_format *format) @@ -1925,3 +2027,51 @@ grn_output_envelope(grn_ctx *ctx, break; } } + +static inline grn_bool +is_output_columns_format_v1(grn_ctx *ctx, + const char *output_columns, + unsigned int output_columns_len) +{ + unsigned int i; + + /* TODO: REMOVE ME. If new output_columns handler is marked as stable, + this check is removed. We need more error checks. */ + if (grn_ctx_get_command_version(ctx) == GRN_COMMAND_VERSION_1) { + return GRN_TRUE; + } + + for (i = 0; i < output_columns_len; i++) { + switch (output_columns[i]) { + case ',' : + case '(' : + case '[' : + return GRN_FALSE; + default : + break; + } + } + + return GRN_TRUE; +} + +grn_rc +grn_output_format_set_columns(grn_ctx *ctx, grn_obj_format *format, + grn_obj *table, + const char *columns, int columns_len) +{ + grn_rc rc; + + if (is_output_columns_format_v1(ctx, columns, columns_len)) { + rc = grn_obj_columns(ctx, table, columns, columns_len, &(format->columns)); + } else { + grn_obj *variable; + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, format->expression, variable); + rc = grn_expr_parse(ctx, format->expression, + columns, columns_len, NULL, + GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_OUTPUT_COLUMNS); + } + + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/pat.c b/storage/mroonga/vendor/groonga/lib/pat.c index 5b03e6132e9..add8469a009 100644 --- a/storage/mroonga/vendor/groonga/lib/pat.c +++ b/storage/mroonga/vendor/groonga/lib/pat.c @@ -14,13 +14,13 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <string.h> #include <limits.h> -#include "pat.h" -#include "output.h" -#include "util.h" -#include "normalizer_in.h" +#include "grn_pat.h" +#include "grn_output.h" +#include "grn_util.h" +#include "grn_normalizer.h" #define GRN_PAT_DELETED (GRN_ID_MAX + 1) @@ -749,16 +749,16 @@ _grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint return r; } -inline static int +inline static grn_bool chop(grn_ctx *ctx, grn_pat *pat, const char **key, const char *end, uint32_t *lkey) { size_t len = grn_charlen(ctx, *key, end); if (len) { *lkey += len; *key += len; - return **key; + return (end - *key) > 0; } else { - return 0; + return GRN_FALSE; } } diff --git a/storage/mroonga/vendor/groonga/lib/plugin.c b/storage/mroonga/vendor/groonga/lib/plugin.c index 3483cc9a5b0..7fd0fbd1971 100644 --- a/storage/mroonga/vendor/groonga/lib/plugin.c +++ b/storage/mroonga/vendor/groonga/lib/plugin.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2012-2013 Brazil + Copyright(C) 2012-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,22 +15,39 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" -#include "groonga/plugin.h" +#include "grn.h" +#include <groonga/plugin.h> #include <stdarg.h> #include <stdio.h> #include <string.h> -#include "db.h" -#include "plugin_in.h" -#include "ctx_impl.h" -#include "util.h" +#include <sys/stat.h> +#ifdef HAVE_DIRENT_H +# include <dirent.h> +#endif /* HAVE_DIRENT_H */ + +#ifndef S_ISREG +# ifdef _S_IFREG +# define S_ISREG(mode) (mode & _S_IFREG) +# endif /* _S_IFREG */ +#endif /* !S_ISREG */ + +#include "grn_db.h" +#include "grn_plugin.h" +#include "grn_ctx_impl.h" +#include "grn_util.h" + +#ifdef GRN_WITH_MRUBY +# include <mruby.h> +#endif /* GRN_WITH_MRUBY */ static grn_hash *grn_plugins = NULL; static grn_critical_section grn_plugins_lock; -#define PATHLEN(filename) (strlen(filename) + 1) +#ifdef GRN_WITH_MRUBY +static const char *grn_plugin_mrb_suffix = ".rb"; +#endif /* GRN_WITH_MRUBY */ #ifdef HAVE_DLFCN_H # include <dlfcn.h> @@ -71,7 +88,7 @@ grn_plugin_reference(grn_ctx *ctx, const char *filename) grn_plugin **plugin = NULL; CRITICAL_SECTION_ENTER(grn_plugins_lock); - id = grn_hash_get(&grn_gctx, grn_plugins, filename, PATHLEN(filename), + id = grn_hash_get(&grn_gctx, grn_plugins, filename, strlen(filename), (void **)&plugin); if (plugin) { (*plugin)->refcount++; @@ -89,6 +106,10 @@ grn_plugin_path(grn_ctx *ctx, grn_id id) const char *system_plugins_dir; size_t system_plugins_dir_size; + if (id == GRN_ID_NIL) { + return NULL; + } + CRITICAL_SECTION_ENTER(grn_plugins_lock); path = _grn_hash_key(&grn_gctx, grn_plugins, id, &key_size); CRITICAL_SECTION_LEAVE(grn_plugins_lock); @@ -114,7 +135,7 @@ grn_plugin_path(grn_ctx *ctx, grn_id id) #define GRN_PLUGIN_FUNC_PREFIX "grn_plugin_impl_" static grn_rc -grn_plugin_call_init (grn_ctx *ctx, grn_id id) +grn_plugin_call_init(grn_ctx *ctx, grn_id id) { grn_plugin *plugin; if (!grn_hash_get_value(&grn_gctx, grn_plugins, id, &plugin)) { @@ -126,6 +147,34 @@ grn_plugin_call_init (grn_ctx *ctx, grn_id id) return GRN_SUCCESS; } +#ifdef GRN_WITH_MRUBY +static grn_rc +grn_plugin_call_register_mrb(grn_ctx *ctx, grn_id id, grn_plugin *plugin) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *plugin_loader_class; + int arena_index; + + { + int added; + grn_hash_add(ctx, ctx->impl->mrb.registered_plugins, + &id, sizeof(grn_id), NULL, &added); + if (!added) { + return ctx->rc; + } + } + + arena_index = mrb_gc_arena_save(mrb); + plugin_loader_class = mrb_class_get_under(mrb, module, "PluginLoader"); + mrb_funcall(mrb, mrb_obj_value(plugin_loader_class), + "load_file", 1, mrb_str_new_cstr(mrb, ctx->impl->plugin_path)); + mrb_gc_arena_restore(mrb, arena_index); + return ctx->rc; +} +#endif /*GRN_WITH_MRUBY */ + static grn_rc grn_plugin_call_register(grn_ctx *ctx, grn_id id) { @@ -133,6 +182,11 @@ grn_plugin_call_register(grn_ctx *ctx, grn_id id) if (!grn_hash_get_value(&grn_gctx, grn_plugins, id, &plugin)) { return GRN_INVALID_ARGUMENT; } +#ifdef GRN_WITH_MRUBY + if (!plugin->dl) { + return grn_plugin_call_register_mrb(ctx, id, plugin); + } +#endif /* GRN_WITH_MRUBY */ if (plugin->register_func) { return plugin->register_func(ctx); } @@ -193,22 +247,63 @@ grn_plugin_initialize(grn_ctx *ctx, grn_plugin *plugin, return ctx->rc; } +#ifdef GRN_WITH_MRUBY +static grn_id +grn_plugin_open_mrb(grn_ctx *ctx, const char *filename, size_t filename_size) +{ + grn_id id = GRN_ID_NIL; + grn_plugin **plugin = NULL; + + id = grn_hash_add(&grn_gctx, grn_plugins, filename, filename_size, + (void **)&plugin, NULL); + if (!id) { + return id; + } + + *plugin = GRN_GMALLOCN(grn_plugin, 1); + if (!*plugin) { + grn_hash_delete_by_id(&grn_gctx, grn_plugins, id, NULL); + return GRN_ID_NIL; + } + + (*plugin)->dl = NULL; + (*plugin)->init_func = NULL; + (*plugin)->register_func = NULL; + (*plugin)->fin_func = NULL; + (*plugin)->refcount = 1; + + return id; +} +#endif /* GRN_WITH_MRUBY */ + grn_id grn_plugin_open(grn_ctx *ctx, const char *filename) { - grn_id id; + grn_id id = GRN_ID_NIL; grn_dl dl; grn_plugin **plugin = NULL; + size_t filename_size; + + filename_size = strlen(filename); CRITICAL_SECTION_ENTER(grn_plugins_lock); - if ((id = grn_hash_get(&grn_gctx, grn_plugins, filename, PATHLEN(filename), + if ((id = grn_hash_get(&grn_gctx, grn_plugins, filename, filename_size, (void **)&plugin))) { (*plugin)->refcount++; goto exit; } +#ifdef GRN_WITH_MRUBY + if (filename_size > strlen(grn_plugin_mrb_suffix) && + strcmp(filename + (filename_size - strlen(grn_plugin_mrb_suffix)), + grn_plugin_mrb_suffix) == 0) { + id = grn_plugin_open_mrb(ctx, filename, filename_size); + goto exit; + } +#endif /* GRN_WITH_MRUBY */ + if ((dl = grn_dl_open(filename))) { - if ((id = grn_hash_add(&grn_gctx, grn_plugins, filename, PATHLEN(filename), + if ((id = grn_hash_add(&grn_gctx, grn_plugins, filename, filename_size, (void **)&plugin, NULL))) { *plugin = GRN_GMALLOCN(grn_plugin, 1); if (*plugin) { @@ -270,11 +365,13 @@ grn_plugin_close(grn_ctx *ctx, grn_id id) rc = GRN_SUCCESS; goto exit; } - grn_plugin_call_fin(ctx, id); - if (!grn_dl_close(plugin->dl)) { - const char *label; - label = grn_dl_close_error_label(); - SERR(label); + if (plugin->dl) { + grn_plugin_call_fin(ctx, id); + if (!grn_dl_close(plugin->dl)) { + const char *label; + label = grn_dl_close_error_label(); + SERR(label); + } } GRN_GFREE(plugin); rc = grn_hash_delete_by_id(&grn_gctx, grn_plugins, id, NULL); @@ -369,8 +466,8 @@ grn_plugin_register_by_path(grn_ctx *ctx, const char *path) #ifdef WIN32 static char *win32_plugins_dir = NULL; static char win32_plugins_dir_buffer[PATH_MAX]; -const char * -grn_plugin_get_system_plugins_dir(void) +static const char * +grn_plugin_get_default_system_plugins_dir(void) { if (!win32_plugins_dir) { const char *base_dir; @@ -388,13 +485,126 @@ grn_plugin_get_system_plugins_dir(void) } #else /* WIN32 */ -const char * -grn_plugin_get_system_plugins_dir(void) +static const char * +grn_plugin_get_default_system_plugins_dir(void) { return GRN_PLUGINS_DIR; } #endif /* WIN32 */ +const char * +grn_plugin_get_system_plugins_dir(void) +{ + const char *plugins_dir; + + plugins_dir = getenv("GRN_PLUGINS_DIR"); + if (!plugins_dir) { + plugins_dir = grn_plugin_get_default_system_plugins_dir(); + } + + return plugins_dir; +} + +static char * +grn_plugin_find_path_raw(grn_ctx *ctx, const char *path) +{ + struct stat path_stat; + + if (stat(path, &path_stat) != 0) { + return NULL; + } + + if (!S_ISREG(path_stat.st_mode)) { + return NULL; + } + + return GRN_STRDUP(path); +} + +#if GRN_WITH_MRUBY +static char * +grn_plugin_find_path_mrb(grn_ctx *ctx, const char *path, size_t path_len) +{ + char mrb_path[PATH_MAX]; + const char *mrb_suffix = grn_plugin_mrb_suffix; + size_t mrb_path_len; + + mrb_path_len = path_len + strlen(mrb_suffix); + if (mrb_path_len >= PATH_MAX) { + ERR(GRN_FILENAME_TOO_LONG, + "too long plugin path: <%s%s>", + path, mrb_suffix); + return NULL; + } + + strcpy(mrb_path, path); + strcat(mrb_path, mrb_suffix); + return grn_plugin_find_path_raw(ctx, mrb_path); +} +#else /* GRN_WITH_MRUBY */ +static char * +grn_plugin_find_path_mrb(grn_ctx *ctx, const char *path, size_t path_len) +{ + return NULL; +} +#endif /* GRN_WITH_MRUBY */ + +static char * +grn_plugin_find_path_so(grn_ctx *ctx, const char *path, size_t path_len) +{ + char so_path[PATH_MAX]; + const char *so_suffix; + size_t so_path_len; + + so_suffix = grn_plugin_get_suffix(); + so_path_len = path_len + strlen(so_suffix); + if (so_path_len >= PATH_MAX) { + ERR(GRN_FILENAME_TOO_LONG, + "too long plugin path: <%s%s>", + path, so_suffix); + return NULL; + } + + strcpy(so_path, path); + strcat(so_path, so_suffix); + return grn_plugin_find_path_raw(ctx, so_path); +} + +static char * +grn_plugin_find_path_libs_so(grn_ctx *ctx, const char *path, size_t path_len) +{ + char libs_so_path[PATH_MAX]; + const char *base_name; + const char *so_suffix; + const char *libs_path = "/.libs"; + size_t libs_so_path_len; + + base_name = strrchr(path, '/'); + if (!base_name) { + return NULL; + } + + so_suffix = grn_plugin_get_suffix(); + libs_so_path_len = + base_name - path + + strlen(libs_path) + + strlen(base_name) + + strlen(so_suffix); + if (libs_so_path_len >= PATH_MAX) { + ERR(GRN_FILENAME_TOO_LONG, + "too long plugin path: <%.*s/.libs%s%s>", + (int)(base_name - path), path, base_name, so_suffix); + return NULL; + } + + libs_so_path[0] = '\0'; + strncat(libs_so_path, path, base_name - path); + strcat(libs_so_path, libs_path); + strcat(libs_so_path, base_name); + strcat(libs_so_path, so_suffix); + return grn_plugin_find_path_raw(ctx, libs_so_path); +} + char * grn_plugin_find_path(grn_ctx *ctx, const char *name) { @@ -402,8 +612,6 @@ grn_plugin_find_path(grn_ctx *ctx, const char *name) char dir_last_char; char path[PATH_MAX]; int name_length, max_name_length; - FILE *plugin_file; - char complemented_path[PATH_MAX], complemented_libs_path[PATH_MAX]; char *found_path = NULL; size_t path_len; @@ -411,10 +619,7 @@ grn_plugin_find_path(grn_ctx *ctx, const char *name) if (name[0] == '/') { path[0] = '\0'; } else { - plugins_dir = getenv("GRN_PLUGINS_DIR"); - if (!plugins_dir) { - plugins_dir = grn_plugin_get_system_plugins_dir(); - } + plugins_dir = grn_plugin_get_system_plugins_dir(); strcpy(path, plugins_dir); dir_last_char = plugins_dir[strlen(path) - 1]; @@ -434,50 +639,34 @@ grn_plugin_find_path(grn_ctx *ctx, const char *name) } strcat(path, name); - plugin_file = fopen(path, "r"); - if (plugin_file) { - fclose(plugin_file); - found_path = GRN_STRDUP(path); - } else { - path_len = strlen(path); - path_len += strlen(grn_plugin_get_suffix()); - if (path_len >= PATH_MAX) { - ERR(GRN_FILENAME_TOO_LONG, - "too long plugin path: <%s%s>", - path, grn_plugin_get_suffix()); - goto exit; - } - strcpy(complemented_path, path); - strcat(complemented_path, grn_plugin_get_suffix()); - plugin_file = fopen(complemented_path, "r"); - if (plugin_file) { - fclose(plugin_file); - found_path = GRN_STRDUP(complemented_path); - } else { - const char *base_name; - - base_name = strrchr(path, '/'); - if (base_name) { - path_len = base_name - path + strlen("/.libs") + strlen(base_name); - path_len += strlen(grn_plugin_get_suffix()); - if (path_len >= PATH_MAX) { - ERR(GRN_FILENAME_TOO_LONG, - "too long plugin path: <%.*s/.libs%s%s>", - (int)(base_name - path), path, base_name, grn_plugin_get_suffix()); - goto exit; - } - complemented_libs_path[0] = '\0'; - strncat(complemented_libs_path, path, base_name - path); - strcat(complemented_libs_path, "/.libs"); - strcat(complemented_libs_path, base_name); - strcat(complemented_libs_path, grn_plugin_get_suffix()); - plugin_file = fopen(complemented_libs_path, "r"); - if (plugin_file) { - fclose(plugin_file); - found_path = GRN_STRDUP(complemented_libs_path); - } - } - } + found_path = grn_plugin_find_path_raw(ctx, path); + if (found_path) { + goto exit; + } + + path_len = strlen(path); + found_path = grn_plugin_find_path_mrb(ctx, path, path_len); + if (found_path) { + goto exit; + } + if (ctx->rc) { + goto exit; + } + + found_path = grn_plugin_find_path_so(ctx, path, path_len); + if (found_path) { + goto exit; + } + if (ctx->rc) { + goto exit; + } + + found_path = grn_plugin_find_path_libs_so(ctx, path, path_len); + if (found_path) { + goto exit; + } + if (ctx->rc) { + goto exit; } exit : @@ -503,10 +692,7 @@ grn_plugin_register(grn_ctx *ctx, const char *name) prefix_separator = ""; suffix = ""; } else { - prefix = getenv("GRN_PLUGINS_DIR"); - if (!prefix) { - prefix = grn_plugin_get_system_plugins_dir(); - } + prefix = grn_plugin_get_system_plugins_dir(); if (prefix[strlen(prefix) - 1] != '/') { prefix_separator = "/"; } else { @@ -523,6 +709,57 @@ grn_plugin_register(grn_ctx *ctx, const char *name) GRN_API_RETURN(rc); } +void +grn_plugin_ensure_registered(grn_ctx *ctx, grn_obj *proc) +{ +#ifdef GRN_WITH_MRUBY + grn_id plugin_id; + const char *plugin_path; + uint32_t key_size; + grn_plugin *plugin; + int value_size; + + if (!ctx->impl->mrb.state) { + return; + } + + if (!(proc->header.flags & GRN_OBJ_CUSTOM_NAME)) { + return; + } + + { + grn_id id; + int added; + id = DB_OBJ(proc)->id; + grn_hash_add(ctx, ctx->impl->mrb.checked_procs, + &id, sizeof(grn_id), NULL, &added); + if (!added) { + return; + } + } + + plugin_id = DB_OBJ(proc)->range; + CRITICAL_SECTION_ENTER(grn_plugins_lock); + plugin_path = _grn_hash_key(&grn_gctx, grn_plugins, plugin_id, &key_size); + if (plugin_path) { + value_size = grn_hash_get_value(&grn_gctx, grn_plugins, plugin_id, &plugin); + } + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + if (!plugin_path) { + return; + } + + if (plugin->dl) { + return; + } + + ctx->impl->plugin_path = plugin_path; + grn_plugin_call_register_mrb(ctx, plugin_id, plugin); + ctx->impl->plugin_path = NULL; +#endif /* GRN_WITH_MRUBY */ +} + void * grn_plugin_malloc(grn_ctx *ctx, size_t size, const char *file, int line, const char *func) @@ -647,6 +884,12 @@ grn_plugin_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, } grn_obj * +grn_plugin_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data) +{ + return grn_proc_get_vars(ctx, user_data); +} + +grn_obj * grn_plugin_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, int name_size) { diff --git a/storage/mroonga/vendor/groonga/lib/proc.c b/storage/mroonga/vendor/groonga/lib/proc.c index 37b7ae67d35..03deb0c4b70 100644 --- a/storage/mroonga/vendor/groonga/lib/proc.c +++ b/storage/mroonga/vendor/groonga/lib/proc.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,17 +16,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "proc.h" -#include "ii.h" -#include "db.h" -#include "util.h" -#include "output.h" -#include "pat.h" -#include "geo.h" -#include "token.h" -#include "expr.h" +#include "grn_proc.h" +#include "grn_ii.h" +#include "grn_db.h" +#include "grn_util.h" +#include "grn_output.h" +#include "grn_pat.h" +#include "grn_geo.h" +#include "grn_token_cursor.h" +#include "grn_expr.h" #include <string.h> +#include <float.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> @@ -395,7 +396,7 @@ grn_parse_query_flags(grn_ctx *ctx, const char *query_flags, if (((query_flags_end - query_flags) >= (sizeof(#name) - 1)) &&\ (!memcmp(query_flags, #name, sizeof(#name) - 1))) {\ flags |= GRN_EXPR_ ## name;\ - query_flags += sizeof(#name);\ + query_flags += sizeof(#name) - 1;\ continue;\ } @@ -417,32 +418,6 @@ grn_parse_query_flags(grn_ctx *ctx, const char *query_flags, return flags; } -static inline grn_bool -is_output_columns_format_v1(grn_ctx *ctx, - const char *output_columns, - unsigned int output_columns_len) -{ - unsigned int i; - - /* TODO: REMOVE ME. If new output_columns handler is marked as stable, - this check is removed. We need more error checks. */ - if (grn_ctx_get_command_version(ctx) == GRN_COMMAND_VERSION_1) { - return GRN_TRUE; - } - - for (i = 0; i < output_columns_len; i++) { - switch (output_columns[i]) { - case ',' : - case '(' : - return GRN_FALSE; - default : - break; - } - } - - return GRN_TRUE; -} - static int grn_select_apply_adjuster_ensure_factor(grn_ctx *ctx, grn_obj *factor_object) { @@ -492,6 +467,7 @@ grn_select_apply_adjuster_adjust(grn_ctx *ctx, grn_obj *table, grn_obj *res, { grn_search_optarg options; + memset(&options, 0, sizeof(grn_search_optarg)); options.mode = GRN_OP_EXACT; options.similarity_threshold = 0; @@ -500,6 +476,7 @@ grn_select_apply_adjuster_adjust(grn_ctx *ctx, grn_obj *table, grn_obj *res, options.vector_size = factor_value; options.proc = NULL; options.max_size = 0; + options.scorer = NULL; grn_obj_search(ctx, index, value, res, GRN_OP_ADJUST, &options); } @@ -538,7 +515,335 @@ grn_select_apply_adjuster(grn_ctx *ctx, grn_obj *table, grn_obj *res, } } -grn_rc +static void +grn_select_output_columns(grn_ctx *ctx, grn_obj *res, + int n_hits, int offset, int limit, + const char *columns, int columns_len, + grn_obj *condition) +{ + grn_rc rc; + grn_obj_format format; + + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, offset); + format.flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| + GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; + rc = grn_output_format_set_columns(ctx, &format, res, columns, columns_len); + /* TODO: check rc */ + if (format.expression) { + grn_obj *condition_ptr; + condition_ptr = + grn_expr_get_or_add_var(ctx, format.expression, + GRN_SELECT_INTERNAL_VAR_CONDITION, + strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); + GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); + GRN_PTR_SET(ctx, condition_ptr, condition); + } + GRN_OUTPUT_OBJ(res, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); +} + +typedef struct { + const char *label; + unsigned int label_len; + const char *keys; + unsigned int keys_len; + const char *sortby; + unsigned int sortby_len; + const char *output_columns; + unsigned int output_columns_len; + int offset; + int limit; + grn_table_group_flags calc_types; + const char *calc_target_name; + unsigned int calc_target_name_len; +} drilldown_info; + +static grn_table_group_flags +grn_parse_table_group_calc_types(grn_ctx *ctx, + const char *calc_types, + unsigned int calc_types_len) +{ + grn_table_group_flags flags = 0; + const char *calc_types_end = calc_types + calc_types_len; + + while (calc_types < calc_types_end) { + if (*calc_types == ',' || *calc_types == ' ') { + calc_types += 1; + continue; + } + +#define CHECK_TABLE_GROUP_CALC_TYPE(name)\ + if (((calc_types_end - calc_types) >= (sizeof(#name) - 1)) &&\ + (!memcmp(calc_types, #name, sizeof(#name) - 1))) {\ + flags |= GRN_TABLE_GROUP_CALC_ ## name;\ + calc_types += sizeof(#name) - 1;\ + continue;\ + } + + CHECK_TABLE_GROUP_CALC_TYPE(COUNT); + CHECK_TABLE_GROUP_CALC_TYPE(MAX); + CHECK_TABLE_GROUP_CALC_TYPE(MIN); + CHECK_TABLE_GROUP_CALC_TYPE(SUM); + CHECK_TABLE_GROUP_CALC_TYPE(AVG); + +#define GRN_TABLE_GROUP_CALC_NONE 0 + CHECK_TABLE_GROUP_CALC_TYPE(NONE); +#undef GRN_TABLE_GROUP_CALC_NONE + + ERR(GRN_INVALID_ARGUMENT, "invalid table group calc type: <%.*s>", + (int)(calc_types_end - calc_types), calc_types); + return 0; +#undef CHECK_TABLE_GROUP_CALC_TYPE + } + + return flags; +} + +static void +drilldown_info_fill(grn_ctx *ctx, + drilldown_info *drilldown, + grn_obj *keys, + grn_obj *sortby, + grn_obj *output_columns, + grn_obj *offset, + grn_obj *limit, + grn_obj *calc_types, + grn_obj *calc_target) +{ + if (keys) { + drilldown->keys = GRN_TEXT_VALUE(keys); + drilldown->keys_len = GRN_TEXT_LEN(keys); + } else { + drilldown->keys = NULL; + drilldown->keys_len = 0; + } + + if (sortby) { + drilldown->sortby = GRN_TEXT_VALUE(sortby); + drilldown->sortby_len = GRN_TEXT_LEN(sortby); + } else { + drilldown->sortby = NULL; + drilldown->sortby_len = 0; + } + + if (output_columns) { + drilldown->output_columns = GRN_TEXT_VALUE(output_columns); + drilldown->output_columns_len = GRN_TEXT_LEN(output_columns); + } else { + drilldown->output_columns = NULL; + drilldown->output_columns_len = 0; + } + if (!drilldown->output_columns_len) { + drilldown->output_columns = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS; + drilldown->output_columns_len = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS); + } + + if (offset && GRN_TEXT_LEN(offset)) { + drilldown->offset = + grn_atoi(GRN_TEXT_VALUE(offset), GRN_BULK_CURR(offset), NULL); + } else { + drilldown->offset = 0; + } + + if (limit && GRN_TEXT_LEN(limit)) { + drilldown->limit = + grn_atoi(GRN_TEXT_VALUE(limit), GRN_BULK_CURR(limit), NULL); + } else { + drilldown->limit = DEFAULT_DRILLDOWN_LIMIT; + } + + if (calc_types && GRN_TEXT_LEN(calc_types)) { + drilldown->calc_types = + grn_parse_table_group_calc_types(ctx, + GRN_TEXT_VALUE(calc_types), + GRN_TEXT_LEN(calc_types)); + } else { + drilldown->calc_types = 0; + } + + if (calc_target && GRN_TEXT_LEN(calc_target)) { + drilldown->calc_target_name = GRN_TEXT_VALUE(calc_target); + drilldown->calc_target_name_len = GRN_TEXT_LEN(calc_target); + } else { + drilldown->calc_target_name = NULL; + drilldown->calc_target_name_len = 0; + } +} + +static void +grn_select_drilldown(grn_ctx *ctx, grn_obj *table, + grn_table_sort_key *keys, uint32_t n_keys, + drilldown_info *drilldown) +{ + uint32_t i; + for (i = 0; i < n_keys; i++) { + grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0}; + uint32_t n_hits; + int offset; + int limit; + + if (drilldown->calc_target_name) { + g.calc_target = grn_obj_column(ctx, table, + drilldown->calc_target_name, + drilldown->calc_target_name_len); + } + if (g.calc_target) { + g.flags |= drilldown->calc_types; + } + + grn_table_group(ctx, table, &keys[i], 1, &g, 1); + if (ctx->rc != GRN_SUCCESS) { + break; + } + n_hits = grn_table_size(ctx, g.table); + + offset = drilldown->offset; + limit = drilldown->limit; + grn_normalize_offset_and_limit(ctx, n_hits, &offset, &limit); + + if (drilldown->sortby_len) { + grn_table_sort_key *sort_keys; + uint32_t n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + drilldown->sortby, + drilldown->sortby_len, + g.table, &n_sort_keys); + if (sort_keys) { + grn_obj *sorted; + sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, + NULL, g.table); + if (sorted) { + grn_obj_format format; + grn_table_sort(ctx, g.table, offset, limit, + sorted, sort_keys, n_sort_keys); + GRN_OBJ_FORMAT_INIT(&format, n_hits, 0, limit, offset); + format.flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| + GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY; + grn_obj_columns(ctx, sorted, + drilldown->output_columns, + drilldown->output_columns_len, + &format.columns); + GRN_OUTPUT_OBJ(sorted, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_obj_unlink(ctx, sorted); + } + grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); + } + } else { + grn_obj_format format; + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, offset); + format.flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| + GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY; + grn_obj_columns(ctx, g.table, + drilldown->output_columns, + drilldown->output_columns_len, + &format.columns); + GRN_OUTPUT_OBJ(g.table, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + } + grn_obj_unlink(ctx, g.table); + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "drilldown(%d)", n_hits); + } +} + +static void +grn_select_drilldowns(grn_ctx *ctx, grn_obj *table, + drilldown_info *drilldowns, unsigned int n_drilldowns, + grn_obj *condition) +{ + unsigned int i; + + /* TODO: Remove invalid key drilldowns from the count. */ + GRN_OUTPUT_MAP_OPEN("DRILLDOWNS", n_drilldowns); + for (i = 0; i < n_drilldowns; i++) { + drilldown_info *drilldown = &(drilldowns[i]); + grn_table_sort_key *keys = NULL; + unsigned int n_keys; + uint32_t n_hits; + int offset; + int limit; + grn_table_group_result result = { + NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0, 0, NULL + }; + + keys = grn_table_sort_key_from_str(ctx, + drilldown->keys, + drilldown->keys_len, + table, &n_keys); + if (!keys) { + continue; + } + + GRN_OUTPUT_STR(drilldown->label, drilldown->label_len); + + result.key_begin = 0; + result.key_end = n_keys - 1; + if (n_keys > 1) { + result.max_n_subrecs = 1; + } + if (drilldown->calc_target_name) { + result.calc_target = grn_obj_column(ctx, table, + drilldown->calc_target_name, + drilldown->calc_target_name_len); + } + if (result.calc_target) { + result.flags |= drilldown->calc_types; + } + + grn_table_group(ctx, table, keys, n_keys, &result, 1); + n_hits = grn_table_size(ctx, result.table); + + offset = drilldown->offset; + limit = drilldown->limit; + grn_normalize_offset_and_limit(ctx, n_hits, &offset, &limit); + + if (drilldown->sortby_len) { + grn_table_sort_key *sort_keys; + uint32_t n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + drilldown->sortby, + drilldown->sortby_len, + result.table, &n_sort_keys); + if (sort_keys) { + grn_obj *sorted; + sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, + NULL, result.table); + if (sorted) { + grn_table_sort(ctx, result.table, offset, limit, + sorted, sort_keys, n_sort_keys); + grn_select_output_columns(ctx, sorted, n_hits, 0, limit, + drilldown->output_columns, + drilldown->output_columns_len, + condition); + grn_obj_unlink(ctx, sorted); + } + grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); + } + } else { + grn_select_output_columns(ctx, result.table, n_hits, offset, limit, + drilldown->output_columns, + drilldown->output_columns_len, + condition); + } + + grn_table_sort_key_close(ctx, keys, n_keys); + if (result.calc_target) { + grn_obj_unlink(ctx, result.calc_target); + } + grn_obj_unlink(ctx, result.table); + + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "drilldown(%d)[%.*s]", n_hits, + (int)(drilldown->label_len), drilldown->label); + } + GRN_OUTPUT_MAP_CLOSE(); +} + +static grn_rc grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, const char *match_columns, unsigned int match_columns_len, const char *query, unsigned int query_len, @@ -547,10 +852,8 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, const char *sortby, unsigned int sortby_len, const char *output_columns, unsigned int output_columns_len, int offset, int limit, - const char *drilldown, unsigned int drilldown_len, - const char *drilldown_sortby, unsigned int drilldown_sortby_len, - const char *drilldown_output_columns, unsigned int drilldown_output_columns_len, - int drilldown_offset, int drilldown_limit, + drilldown_info *drilldowns, + unsigned int n_drilldowns, const char *cache, unsigned int cache_len, const char *match_escalation_threshold, unsigned int match_escalation_threshold_len, const char *query_expander, unsigned int query_expander_len, @@ -559,20 +862,31 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, { uint32_t nkeys, nhits; uint16_t cacheable = 1, taintable = 0; - grn_obj_format format; grn_table_sort_key *keys; grn_obj *outbuf = ctx->impl->outbuf; grn_content_type output_type = ctx->impl->output_type; grn_obj *table_, *match_columns_ = NULL, *cond = NULL, *scorer_, *res = NULL, *sorted; char cache_key[GRN_TABLE_MAX_KEY_SIZE]; - uint32_t cache_key_size = table_len + 1 + match_columns_len + 1 + query_len + 1 + - filter_len + 1 + scorer_len + 1 + sortby_len + 1 + output_columns_len + 1 + - drilldown_len + 1 + drilldown_sortby_len + 1 + - drilldown_output_columns_len + 1 + match_escalation_threshold_len + 1 + - query_expander_len + 1 + query_flags_len + 1 + adjuster_len + 1 + - sizeof(grn_content_type) + sizeof(int) * 4; + uint32_t cache_key_size; long long int threshold, original_threshold = 0; grn_cache *cache_obj = grn_cache_current_get(ctx); + + cache_key_size = table_len + 1 + match_columns_len + 1 + query_len + 1 + + filter_len + 1 + scorer_len + 1 + sortby_len + 1 + output_columns_len + 1 + + match_escalation_threshold_len + 1 + + query_expander_len + 1 + query_flags_len + 1 + adjuster_len + 1 + + sizeof(grn_content_type) + sizeof(int) * 2; + { + unsigned int i; + for (i = 0; i < n_drilldowns; i++) { + drilldown_info *drilldown = &(drilldowns[i]); + cache_key_size += + drilldown->keys_len + 1 + + drilldown->sortby_len + 1 + + drilldown->output_columns_len + 1 + + sizeof(int) * 2; + } + } if (cache_key_size <= GRN_TABLE_MAX_KEY_SIZE) { grn_obj *cache_value; char *cp = cache_key; @@ -590,12 +904,18 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, cp += sortby_len; *cp++ = '\0'; memcpy(cp, output_columns, output_columns_len); cp += output_columns_len; *cp++ = '\0'; - memcpy(cp, drilldown, drilldown_len); - cp += drilldown_len; *cp++ = '\0'; - memcpy(cp, drilldown_sortby, drilldown_sortby_len); - cp += drilldown_sortby_len; *cp++ = '\0'; - memcpy(cp, drilldown_output_columns, drilldown_output_columns_len); - cp += drilldown_output_columns_len; *cp++ = '\0'; + { + unsigned int i; + for (i = 0; i < n_drilldowns; i++) { + drilldown_info *drilldown = &(drilldowns[i]); + memcpy(cp, drilldown->keys, drilldown->keys_len); + cp += drilldown->keys_len; *cp++ = '\0'; + memcpy(cp, drilldown->sortby, drilldown->sortby_len); + cp += drilldown->sortby_len; *cp++ = '\0'; + memcpy(cp, drilldown->output_columns, drilldown->output_columns_len); + cp += drilldown->output_columns_len; *cp++ = '\0'; + } + } memcpy(cp, match_escalation_threshold, match_escalation_threshold_len); cp += match_escalation_threshold_len; *cp++ = '\0'; memcpy(cp, query_expander, query_expander_len); @@ -607,8 +927,14 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, memcpy(cp, &output_type, sizeof(grn_content_type)); cp += sizeof(grn_content_type); memcpy(cp, &offset, sizeof(int)); cp += sizeof(int); memcpy(cp, &limit, sizeof(int)); cp += sizeof(int); - memcpy(cp, &drilldown_offset, sizeof(int)); cp += sizeof(int); - memcpy(cp, &drilldown_limit, sizeof(int)); cp += sizeof(int); + { + unsigned int i; + for (i = 0; i < n_drilldowns; i++) { + drilldown_info *drilldown = &(drilldowns[i]); + memcpy(cp, &(drilldown->offset), sizeof(int)); cp += sizeof(int); + memcpy(cp, &(drilldown->limit), sizeof(int)); cp += sizeof(int); + } + } cache_value = grn_cache_fetch(ctx, cache_obj, cache_key, cache_key_size); if (cache_value) { GRN_TEXT_PUT(ctx, outbuf, @@ -710,12 +1036,17 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, uint32_t ngkeys; grn_table_sort_key *gkeys = NULL; int result_size = 1; - if (!ctx->rc && drilldown_len) { - gkeys = grn_table_sort_key_from_str(ctx, - drilldown, drilldown_len, - res, &ngkeys); - if (gkeys) { - result_size += ngkeys; + if (!ctx->rc && n_drilldowns > 0) { + if (n_drilldowns == 1 && !drilldowns[0].label) { + gkeys = grn_table_sort_key_from_str(ctx, + drilldowns[0].keys, + drilldowns[0].keys_len, + res, &ngkeys); + if (gkeys) { + result_size += ngkeys; + } + } else { + result_size += 1; } } @@ -755,6 +1086,9 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { GRN_RECORD_SET(ctx, v, id); grn_expr_exec(ctx, scorer_, 0); + if (ctx->rc) { + break; + } } grn_table_cursor_close(ctx, tc); } @@ -775,120 +1109,30 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, grn_table_sort(ctx, res, offset, limit, sorted, keys, nkeys); GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, ":", "sort(%d)", limit); - GRN_OBJ_FORMAT_INIT(&format, nhits, 0, limit, offset); - format.flags = - GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| - GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; - if (is_output_columns_format_v1(ctx, output_columns, output_columns_len)) { - grn_obj_columns(ctx, sorted, output_columns, output_columns_len, - &format.columns); - } else { - grn_obj *v; - grn_obj *condition_ptr; - GRN_EXPR_CREATE_FOR_QUERY(ctx, sorted, format.expression, v); - grn_expr_parse(ctx, format.expression, - output_columns, output_columns_len, NULL, - GRN_OP_MATCH, GRN_OP_AND, - GRN_EXPR_SYNTAX_OUTPUT_COLUMNS); - condition_ptr = - grn_expr_get_or_add_var(ctx, format.expression, - GRN_SELECT_INTERNAL_VAR_CONDITION, - strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); - GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); - GRN_PTR_SET(ctx, condition_ptr, cond); - } - GRN_OUTPUT_OBJ(sorted, &format); - GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_select_output_columns(ctx, sorted, nhits, 0, limit, + output_columns, output_columns_len, cond); grn_obj_unlink(ctx, sorted); } grn_table_sort_key_close(ctx, keys, nkeys); } else { if (!ctx->rc) { - GRN_OBJ_FORMAT_INIT(&format, nhits, offset, limit, offset); - format.flags = - GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| - GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; - if (is_output_columns_format_v1(ctx, output_columns, output_columns_len)) { - grn_obj_columns(ctx, res, output_columns, output_columns_len, - &format.columns); - } else { - grn_obj *v; - grn_obj *condition_ptr; - GRN_EXPR_CREATE_FOR_QUERY(ctx, res, format.expression, v); - grn_expr_parse(ctx, format.expression, - output_columns, output_columns_len, NULL, - GRN_OP_MATCH, GRN_OP_AND, - GRN_EXPR_SYNTAX_OUTPUT_COLUMNS); - condition_ptr = - grn_expr_get_or_add_var(ctx, format.expression, - GRN_SELECT_INTERNAL_VAR_CONDITION, - strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); - GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); - GRN_PTR_SET(ctx, condition_ptr, cond); - } - GRN_OUTPUT_OBJ(res, &format); - GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_select_output_columns(ctx, res, nhits, offset, limit, + output_columns, output_columns_len, cond); } } GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, ":", "output(%d)", limit); - if (!ctx->rc && drilldown_len) { - uint32_t i; - grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0}; + if (!ctx->rc) { if (gkeys) { - for (i = 0; i < ngkeys; i++) { - if ((g.table = grn_table_create_for_group(ctx, NULL, 0, NULL, - gkeys[i].key, res, 0))) { - int n_drilldown_offset = drilldown_offset, - n_drilldown_limit = drilldown_limit; - - grn_table_group(ctx, res, &gkeys[i], 1, &g, 1); - nhits = grn_table_size(ctx, g.table); - - grn_normalize_offset_and_limit(ctx, nhits, - &n_drilldown_offset, &n_drilldown_limit); - - if (drilldown_sortby_len) { - if ((keys = grn_table_sort_key_from_str(ctx, - drilldown_sortby, drilldown_sortby_len, - g.table, &nkeys))) { - if ((sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, - NULL, g.table))) { - grn_table_sort(ctx, g.table, n_drilldown_offset, n_drilldown_limit, - sorted, keys, nkeys); - GRN_OBJ_FORMAT_INIT(&format, nhits, 0, - n_drilldown_limit, n_drilldown_offset); - format.flags = - GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| - GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY; - grn_obj_columns(ctx, sorted, - drilldown_output_columns, drilldown_output_columns_len, - &format.columns); - GRN_OUTPUT_OBJ(sorted, &format); - GRN_OBJ_FORMAT_FIN(ctx, &format); - grn_obj_unlink(ctx, sorted); - } - grn_table_sort_key_close(ctx, keys, nkeys); - } - } else { - GRN_OBJ_FORMAT_INIT(&format, nhits, n_drilldown_offset, - n_drilldown_limit, n_drilldown_offset); - format.flags = - GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| - GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY; - grn_obj_columns(ctx, g.table, drilldown_output_columns, - drilldown_output_columns_len, &format.columns); - GRN_OUTPUT_OBJ(g.table, &format); - GRN_OBJ_FORMAT_FIN(ctx, &format); - } - grn_obj_unlink(ctx, g.table); - } - GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, - ":", "drilldown(%d)", nhits); - } - grn_table_sort_key_close(ctx, gkeys, ngkeys); + drilldown_info *drilldown = &(drilldowns[0]); + grn_select_drilldown(ctx, res, gkeys, ngkeys, drilldown); + } else if (n_drilldowns > 0) { + grn_select_drilldowns(ctx, res, drilldowns, n_drilldowns, cond); } } + if (gkeys) { + grn_table_sort_key_close(ctx, gkeys, ngkeys); + } if (res != table_) { grn_obj_unlink(ctx, res); } } else { GRN_OUTPUT_ARRAY_OPEN("RESULT", 0); @@ -903,7 +1147,7 @@ grn_select(grn_ctx *ctx, const char *table, unsigned int table_len, } else { ERR(GRN_INVALID_ARGUMENT, "invalid table name: <%.*s>", table_len, table); } -exit: +exit : if (match_escalation_threshold_len) { grn_ctx_set_match_escalation_threshold(ctx, original_threshold); } @@ -917,9 +1161,46 @@ exit: return ctx->rc; } +static void +proc_select_find_all_drilldown_labels(grn_ctx *ctx, grn_user_data *user_data, + grn_obj *labels) +{ + grn_obj *vars = GRN_PROC_GET_VARS(); + grn_table_cursor *cursor; + cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0); + if (cursor) { + const char *prefix = "drilldown["; + int prefix_len = strlen(prefix); + const char *suffix = "].keys"; + int suffix_len = strlen(suffix); + while (grn_table_cursor_next(ctx, cursor)) { + void *key; + char *name; + int name_len; + name_len = grn_table_cursor_get_key(ctx, cursor, &key); + name = key; + if (name_len < (prefix_len + 1 + suffix_len)) { + continue; + } + if (strncmp(prefix, name, prefix_len) != 0) { + continue; + } + if (strncmp(suffix, name + name_len - suffix_len, suffix_len) != 0) { + continue; + } + grn_vector_add_element(ctx, labels, + name + prefix_len, + name_len - prefix_len - suffix_len, + 0, GRN_ID_NIL); + } + grn_table_cursor_close(ctx, cursor); + } +} + static grn_obj * proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { +#define MAX_N_DRILLDOWNS 10 int offset = GRN_TEXT_LEN(VAR(7)) ? grn_atoi(GRN_TEXT_VALUE(VAR(7)), GRN_BULK_CURR(VAR(7)), NULL) : 0; @@ -928,27 +1209,72 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) : DEFAULT_LIMIT; const char *output_columns = GRN_TEXT_VALUE(VAR(6)); uint32_t output_columns_len = GRN_TEXT_LEN(VAR(6)); - const char *drilldown_output_columns = GRN_TEXT_VALUE(VAR(11)); - uint32_t drilldown_output_columns_len = GRN_TEXT_LEN(VAR(11)); - int drilldown_offset = GRN_TEXT_LEN(VAR(12)) - ? grn_atoi(GRN_TEXT_VALUE(VAR(12)), GRN_BULK_CURR(VAR(12)), NULL) - : 0; - int drilldown_limit = GRN_TEXT_LEN(VAR(13)) - ? grn_atoi(GRN_TEXT_VALUE(VAR(13)), GRN_BULK_CURR(VAR(13)), NULL) - : DEFAULT_DRILLDOWN_LIMIT; + drilldown_info drilldowns[MAX_N_DRILLDOWNS]; + unsigned int n_drilldowns = 0; + grn_obj drilldown_labels; grn_obj *query_expansion = VAR(16); grn_obj *query_expander = VAR(18); grn_obj *adjuster = VAR(19); + if (GRN_TEXT_LEN(query_expander) == 0 && GRN_TEXT_LEN(query_expansion) > 0) { query_expander = query_expansion; } + if (!output_columns_len) { output_columns = DEFAULT_OUTPUT_COLUMNS; output_columns_len = strlen(DEFAULT_OUTPUT_COLUMNS); } - if (!drilldown_output_columns_len) { - drilldown_output_columns = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS; - drilldown_output_columns_len = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS); + + GRN_TEXT_INIT(&drilldown_labels, GRN_OBJ_VECTOR); + if (GRN_TEXT_LEN(VAR(9))) { + drilldown_info *drilldown = &(drilldowns[0]); + drilldown->label = NULL; + drilldown->label_len = 0; + drilldown_info_fill(ctx, drilldown, + VAR(9), VAR(10), VAR(11), VAR(12), VAR(13), + VAR(20), VAR(21)); + n_drilldowns++; + } else { + unsigned int i; + proc_select_find_all_drilldown_labels(ctx, user_data, &drilldown_labels); + n_drilldowns = grn_vector_size(ctx, &drilldown_labels); + for (i = 0; i < n_drilldowns; i++) { + drilldown_info *drilldown = &(drilldowns[i]); + const char *label; + int label_len; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + grn_obj *keys; + grn_obj *sortby; + grn_obj *output_columns; + grn_obj *offset; + grn_obj *limit; + grn_obj *calc_types; + grn_obj *calc_target; + + label_len = grn_vector_get_element(ctx, &drilldown_labels, i, + &label, NULL, NULL); + drilldown->label = label; + drilldown->label_len = label_len; + +#define GET_VAR(name)\ + snprintf(key_name, GRN_TABLE_MAX_KEY_SIZE,\ + "drilldown[%.*s]." # name, label_len, label);\ + name = GRN_PROC_GET_VAR(key_name); + + GET_VAR(keys); + GET_VAR(sortby); + GET_VAR(output_columns); + GET_VAR(offset); + GET_VAR(limit); + GET_VAR(calc_types); + GET_VAR(calc_target); + +#undef GET_VAR + + drilldown_info_fill(ctx, drilldown, + keys, sortby, output_columns, offset, limit, + calc_types, calc_target); + } } if (grn_select(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(1)), GRN_TEXT_LEN(VAR(1)), @@ -958,16 +1284,16 @@ proc_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) GRN_TEXT_VALUE(VAR(5)), GRN_TEXT_LEN(VAR(5)), output_columns, output_columns_len, offset, limit, - GRN_TEXT_VALUE(VAR(9)), GRN_TEXT_LEN(VAR(9)), - GRN_TEXT_VALUE(VAR(10)), GRN_TEXT_LEN(VAR(10)), - drilldown_output_columns, drilldown_output_columns_len, - drilldown_offset, drilldown_limit, + drilldowns, n_drilldowns, GRN_TEXT_VALUE(VAR(14)), GRN_TEXT_LEN(VAR(14)), GRN_TEXT_VALUE(VAR(15)), GRN_TEXT_LEN(VAR(15)), GRN_TEXT_VALUE(query_expander), GRN_TEXT_LEN(query_expander), GRN_TEXT_VALUE(VAR(17)), GRN_TEXT_LEN(VAR(17)), GRN_TEXT_VALUE(adjuster), GRN_TEXT_LEN(adjuster))) { } + GRN_OBJ_FIN(ctx, &drilldown_labels); +#undef MAX_N_DRILLDOWNS + return NULL; } @@ -1105,8 +1431,8 @@ grn_parse_column_create_flags(grn_ctx *ctx, const char *nptr, const char *end) } else if (!memcmp(nptr, "COMPRESS_ZLIB", 13)) { flags |= GRN_OBJ_COMPRESS_ZLIB; nptr += 13; - } else if (!memcmp(nptr, "COMPRESS_LZO", 12)) { - flags |= GRN_OBJ_COMPRESS_LZO; + } else if (!memcmp(nptr, "COMPRESS_LZ4", 12)) { + flags |= GRN_OBJ_COMPRESS_LZ4; nptr += 12; } else if (!memcmp(nptr, "WITH_SECTION", 12)) { flags |= GRN_OBJ_WITH_SECTION; @@ -1191,8 +1517,8 @@ grn_column_create_flags_to_text(grn_ctx *ctx, grn_obj *buf, grn_obj_flags flags) case GRN_OBJ_COMPRESS_ZLIB: GRN_TEXT_PUTS(ctx, buf, "|COMPRESS_ZLIB"); break; - case GRN_OBJ_COMPRESS_LZO: - GRN_TEXT_PUTS(ctx, buf, "|COMPRESS_LZO"); + case GRN_OBJ_COMPRESS_LZ4: + GRN_TEXT_PUTS(ctx, buf, "|COMPRESS_LZ4"); break; } if (flags & GRN_OBJ_PERSISTENT) { @@ -1374,7 +1700,7 @@ proc_table_create(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_d ERR(GRN_INVALID_ARGUMENT, "[table][create] should not create anonymous table"); } -exit: +exit : GRN_OUTPUT_BOOL(!ctx->rc); return NULL; } @@ -1427,7 +1753,7 @@ proc_table_rename(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_d (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)), (int)GRN_TEXT_LEN(VAR(1)), GRN_TEXT_VALUE(VAR(1))); } -exit: +exit : GRN_OUTPUT_BOOL(!rc); if (table) { grn_obj_unlink(ctx, table); } return NULL; @@ -1595,7 +1921,7 @@ proc_column_create(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_ } else { succeeded = GRN_FALSE; } -exit: +exit : GRN_OUTPUT_BOOL(succeeded); if (table) { grn_obj_unlink(ctx, table); } if (type) { grn_obj_unlink(ctx, type); } @@ -1687,7 +2013,7 @@ proc_column_rename(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_ (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0)), (int)GRN_TEXT_LEN(VAR(2)), GRN_TEXT_VALUE(VAR(2))); } -exit: +exit : GRN_OUTPUT_BOOL(!rc); if (column) { grn_obj_unlink(ctx, column); } if (table) { grn_obj_unlink(ctx, table); } @@ -1900,20 +2226,6 @@ proc_column_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_da return NULL; } -static grn_bool -is_table(grn_obj *obj) -{ - switch (obj->header.type) { - case GRN_TABLE_HASH_KEY: - case GRN_TABLE_PAT_KEY: - case GRN_TABLE_DAT_KEY: - case GRN_TABLE_NO_KEY: - return GRN_TRUE; - default: - return GRN_FALSE; - } -} - static int output_table_info(grn_ctx *ctx, grn_obj *table) { @@ -1948,7 +2260,6 @@ output_table_info(grn_ctx *ctx, grn_obj *table) static grn_obj * proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { - grn_table_cursor *cur; grn_obj tables; int n_top_level_elements; int n_elements_for_header = 1; @@ -1956,26 +2267,7 @@ proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat int i; GRN_PTR_INIT(&tables, GRN_OBJ_VECTOR, GRN_ID_NIL); - - if ((cur = grn_table_cursor_open(ctx, ctx->impl->db, NULL, 0, NULL, 0, 0, -1, 0))) { - grn_id id; - while ((id = grn_table_cursor_next(ctx, cur)) != GRN_ID_NIL) { - grn_obj *object; - if ((object = grn_ctx_at(ctx, id))) { - if (is_table(object)) { - GRN_PTR_PUT(ctx, &tables, object); - } else { - grn_obj_unlink(ctx, object); - } - } else { - if (ctx->rc != GRN_SUCCESS) { - ERRCLR(ctx); - } - } - } - grn_table_cursor_close(ctx, cur); - } - + grn_ctx_get_all_tables(ctx, &tables); n_tables = GRN_BULK_VSIZE(&tables) / sizeof(grn_obj *); n_top_level_elements = n_elements_for_header + n_tables; GRN_OUTPUT_ARRAY_OPEN("TABLE_LIST", n_top_level_elements); @@ -2016,7 +2308,7 @@ proc_table_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat GRN_OUTPUT_ARRAY_CLOSE(); for (i = 0; i < n_tables; i++) { - grn_obj *table = ((grn_obj **)GRN_BULK_HEAD(&tables))[i]; + grn_obj *table = GRN_PTR_VALUE_AT(&tables, i); output_table_info(ctx, table); grn_obj_unlink(ctx, table); } @@ -2081,7 +2373,8 @@ proc_shutdown(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) } static grn_obj * -proc_clearlock(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +proc_lock_clear(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) { int target_name_len; grn_obj *target_name; @@ -2099,7 +2392,7 @@ proc_clearlock(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data if (obj) { grn_obj_clear_lock(ctx, obj); } else { - ERR(GRN_INVALID_ARGUMENT, "[clearlock] target object not found: <%.*s>", + ERR(GRN_INVALID_ARGUMENT, "[lock_clear] target object not found: <%.*s>", target_name_len, GRN_TEXT_VALUE(target_name)); } GRN_OUTPUT_BOOL(!ctx->rc); @@ -2348,6 +2641,8 @@ exit : return NULL; } +static const size_t DUMP_FLUSH_THRESHOLD_SIZE = 256 * 1024; + static void dump_name(grn_ctx *ctx, grn_obj *outbuf, const char *name, int name_len) { @@ -2685,6 +2980,9 @@ dump_records(grn_ctx *ctx, grn_obj *outbuf, grn_obj *table) } } GRN_TEXT_PUTC(ctx, outbuf, ']'); + if (GRN_TEXT_LEN(outbuf) >= DUMP_FLUSH_THRESHOLD_SIZE) { + grn_ctx_output_flush(ctx, 0); + } } GRN_TEXT_PUTS(ctx, outbuf, "\n]\n"); GRN_TEXT_PUT(ctx, outbuf, GRN_TEXT_VALUE(&delete_commands), @@ -2936,6 +3234,7 @@ proc_dump(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) ctx->impl->output_type = GRN_CONTENT_NONE; ctx->impl->mime_type = "text/x-groonga-command-list"; dump_schema(ctx, outbuf); + grn_ctx_output_flush(ctx, 0); /* To update index columns correctly, we first create the whole schema, then load non-derivative records, while skipping records of index columns. That way, groonga will silently do the job of updating index columns for us. */ @@ -2945,7 +3244,7 @@ proc_dump(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) dump_all_records(ctx, outbuf); } - /* remove the last newline because another one will be added by the calller. + /* remove the last newline because another one will be added by the caller. maybe, the caller of proc functions currently doesn't consider the possibility of multiple-line output from proc functions. */ if (GRN_BULK_VSIZE(outbuf) > 0) { @@ -3106,37 +3405,56 @@ proc_check(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) static grn_obj * proc_truncate(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { - int table_name_len = GRN_TEXT_LEN(VAR(0)); - if (table_name_len == 0) { - ERR(GRN_INVALID_ARGUMENT, "table name is missing"); + const char *target_name; + int target_name_len; + + target_name_len = GRN_TEXT_LEN(VAR(0)); + if (target_name_len > 0) { + target_name = GRN_TEXT_VALUE(VAR(0)); } else { - const char *table_name = GRN_TEXT_VALUE(VAR(0)); - grn_obj *table = grn_ctx_get(ctx, table_name, table_name_len); - if (!table) { + target_name_len = GRN_TEXT_LEN(VAR(1)); + if (target_name_len == 0) { + ERR(GRN_INVALID_ARGUMENT, "[truncate] table name is missing"); + goto exit; + } + target_name = GRN_TEXT_VALUE(VAR(1)); + } + + { + grn_obj *target = grn_ctx_get(ctx, target_name, target_name_len); + if (!target) { ERR(GRN_INVALID_ARGUMENT, - "no such table: <%.*s>", table_name_len, table_name); - } else { - switch (table->header.type) { - case GRN_TABLE_HASH_KEY : - case GRN_TABLE_PAT_KEY : - case GRN_TABLE_DAT_KEY : - case GRN_TABLE_NO_KEY : - grn_table_truncate(ctx, table); - break; - default: - { - grn_obj buffer; - GRN_TEXT_INIT(&buffer, 0); - grn_inspect(ctx, &buffer, table); - ERR(GRN_INVALID_ARGUMENT, - "not a table object: %.*s", - (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); - GRN_OBJ_FIN(ctx, &buffer); - } - break; + "[truncate] no such target: <%.*s>", target_name_len, target_name); + goto exit; + } + + switch (target->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + grn_table_truncate(ctx, target); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + grn_column_truncate(ctx, target); + break; + default: + { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, target); + ERR(GRN_INVALID_ARGUMENT, + "[truncate] not a table nor column object: <%.*s>", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); } + break; } } + +exit : GRN_OUTPUT_BOOL(!ctx->rc); return NULL; } @@ -3161,7 +3479,7 @@ parse_normalize_flags(grn_ctx *ctx, grn_obj *flag_names) if (((names_end - names) >= (sizeof(#name) - 1)) &&\ (!memcmp(names, #name, sizeof(#name) - 1))) {\ flags |= GRN_STRING_ ## name;\ - names += sizeof(#name);\ + names += sizeof(#name) - 1;\ continue;\ } @@ -3373,16 +3691,16 @@ parse_tokenize_flags(grn_ctx *ctx, grn_obj *flag_names) #define CHECK_FLAG(name)\ if (((names_end - names) >= (sizeof(#name) - 1)) &&\ (!memcmp(names, #name, sizeof(#name) - 1))) {\ - flags |= GRN_TOKEN_ ## name;\ - names += sizeof(#name);\ + flags |= GRN_TOKEN_CURSOR_ ## name;\ + names += sizeof(#name) - 1;\ continue;\ } CHECK_FLAG(ENABLE_TOKENIZED_DELIMITER); -#define GRN_TOKEN_NONE 0 +#define GRN_TOKEN_CURSOR_NONE 0 CHECK_FLAG(NONE); -#undef GRN_TOKEN_NONE +#undef GRN_TOKEN_CURSOR_NONE ERR(GRN_INVALID_ARGUMENT, "[tokenize] invalid flag: <%.*s>", (int)(names_end - names), names); @@ -3399,7 +3717,7 @@ typedef struct { } tokenize_token; static void -output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_hash *lexicon) +output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_obj *lexicon) { int i, n_tokens; @@ -3415,8 +3733,8 @@ output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_hash *lexicon) GRN_OUTPUT_MAP_OPEN("TOKEN", 2); GRN_OUTPUT_CSTR("value"); - value_size = grn_hash_get_key(ctx, lexicon, token->id, - value, GRN_TABLE_MAX_KEY_SIZE); + value_size = grn_table_get_key(ctx, lexicon, token->id, + value, GRN_TABLE_MAX_KEY_SIZE); GRN_OUTPUT_STR(value, value_size); GRN_OUTPUT_CSTR("position"); @@ -3427,12 +3745,13 @@ output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_hash *lexicon) GRN_OUTPUT_ARRAY_CLOSE(); } -static grn_hash * +static grn_obj * create_lexicon_for_tokenize(grn_ctx *ctx, grn_obj *tokenizer_name, - grn_obj *normalizer_name) + grn_obj *normalizer_name, + grn_obj *token_filter_names) { - grn_hash *lexicon; + grn_obj *lexicon; grn_obj *tokenizer; grn_obj *normalizer = NULL; @@ -3488,35 +3807,39 @@ create_lexicon_for_tokenize(grn_ctx *ctx, } } - lexicon = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, 0, - GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_KEY_VAR_SIZE); - grn_obj_set_info(ctx, (grn_obj *)lexicon, + lexicon = grn_table_create(ctx, NULL, 0, + NULL, + GRN_OBJ_TABLE_HASH_KEY, + grn_ctx_at(ctx, GRN_DB_SHORT_TEXT), + NULL); + grn_obj_set_info(ctx, lexicon, GRN_INFO_DEFAULT_TOKENIZER, tokenizer); grn_obj_unlink(ctx, tokenizer); if (normalizer) { - grn_obj_set_info(ctx, (grn_obj *)lexicon, + grn_obj_set_info(ctx, lexicon, GRN_INFO_NORMALIZER, normalizer); grn_obj_unlink(ctx, normalizer); } + proc_table_create_set_token_filters(ctx, lexicon, token_filter_names); return lexicon; } static void -tokenize(grn_ctx *ctx, grn_hash *lexicon, grn_obj *string, grn_token_mode mode, +tokenize(grn_ctx *ctx, grn_obj *lexicon, grn_obj *string, grn_tokenize_mode mode, unsigned int flags, grn_obj *tokens) { grn_token_cursor *token_cursor; token_cursor = - grn_token_cursor_open(ctx, (grn_obj *)lexicon, + grn_token_cursor_open(ctx, lexicon, GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), mode, flags); if (!token_cursor) { return; } - while (token_cursor->status == GRN_TOKEN_DOING) { + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { grn_id token_id = grn_token_cursor_next(ctx, token_cursor); tokenize_token *current_token; if (token_id == GRN_ID_NIL) { @@ -3538,12 +3861,14 @@ proc_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) grn_obj *normalizer_name; grn_obj *flag_names; grn_obj *mode_name; + grn_obj *token_filter_names; tokenizer_name = VAR(0); string = VAR(1); normalizer_name = VAR(2); flag_names = VAR(3); mode_name = VAR(4); + token_filter_names = VAR(5); if (GRN_TEXT_LEN(tokenizer_name) == 0) { ERR(GRN_INVALID_ARGUMENT, "[tokenize] tokenizer name is missing"); @@ -3557,14 +3882,17 @@ proc_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) { unsigned int flags; - grn_hash *lexicon; + grn_obj *lexicon; flags = parse_tokenize_flags(ctx, flag_names); if (ctx->rc != GRN_SUCCESS) { return NULL; } - lexicon = create_lexicon_for_tokenize(ctx, tokenizer_name, normalizer_name); + lexicon = create_lexicon_for_tokenize(ctx, + tokenizer_name, + normalizer_name, + token_filter_names); if (!lexicon) { return NULL; } @@ -3573,41 +3901,91 @@ proc_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) (GRN_TEXT_LEN(mode_name) == strlen(name) &&\ memcmp(GRN_TEXT_VALUE(mode_name), name, strlen(name)) == 0) - if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("ADD")) { + { grn_obj tokens; GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL); - tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); - output_tokens(ctx, &tokens, lexicon); - GRN_OBJ_FIN(ctx, &tokens); - } else if (MODE_NAME_EQUAL("GET")) { - { - grn_token_cursor *token_cursor; - token_cursor = - grn_token_cursor_open(ctx, (grn_obj *)lexicon, - GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), - GRN_TOKEN_ADD, flags); - if (token_cursor) { - while (token_cursor->status == GRN_TOKEN_DOING) { - grn_token_cursor_next(ctx, token_cursor); - } - grn_token_cursor_close(ctx, token_cursor); - } - } - - { - grn_obj tokens; - GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL); + if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("ADD")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); + output_tokens(ctx, &tokens, lexicon); + } else if (MODE_NAME_EQUAL("GET")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); + GRN_BULK_REWIND(&tokens); tokenize(ctx, lexicon, string, GRN_TOKEN_GET, flags, &tokens); output_tokens(ctx, &tokens, lexicon); - GRN_OBJ_FIN(ctx, &tokens); + } else { + ERR(GRN_INVALID_ARGUMENT, "[tokenize] invalid mode: <%.*s>", + (int)GRN_TEXT_LEN(mode_name), GRN_TEXT_VALUE(mode_name)); } + GRN_OBJ_FIN(ctx, &tokens); + } +#undef MODE_NAME_EQUAL + + grn_obj_unlink(ctx, lexicon); + } + + return NULL; +} + +static grn_obj * +proc_table_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *table_name; + grn_obj *string; + grn_obj *flag_names; + grn_obj *mode_name; + + table_name = VAR(0); + string = VAR(1); + flag_names = VAR(2); + mode_name = VAR(3); + + if (GRN_TEXT_LEN(table_name) == 0) { + ERR(GRN_INVALID_ARGUMENT, "[table_tokenize] table name is missing"); + return NULL; + } + + if (GRN_TEXT_LEN(string) == 0) { + ERR(GRN_INVALID_ARGUMENT, "[table_tokenize] string is missing"); + return NULL; + } + + { + unsigned int flags; + grn_obj *lexicon; + + flags = parse_tokenize_flags(ctx, flag_names); + if (ctx->rc != GRN_SUCCESS) { + return NULL; + } + + lexicon = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_name), GRN_TEXT_LEN(table_name)); + + if (!lexicon) { + return NULL; + } + +#define MODE_NAME_EQUAL(name)\ + (GRN_TEXT_LEN(mode_name) == strlen(name) &&\ + memcmp(GRN_TEXT_VALUE(mode_name), name, strlen(name)) == 0) + + { + grn_obj tokens; + GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL); + if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("GET")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_GET, flags, &tokens); + output_tokens(ctx, &tokens, lexicon); + } else if (MODE_NAME_EQUAL("ADD")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); + output_tokens(ctx, &tokens, lexicon); } else { - ERR(GRN_INVALID_ARGUMENT, "[tokenize] invalid mode: <%.*s>", + ERR(GRN_INVALID_ARGUMENT, "[table_tokenize] invalid mode: <%.*s>", (int)GRN_TEXT_LEN(mode_name), GRN_TEXT_VALUE(mode_name)); } + GRN_OBJ_FIN(ctx, &tokens); + } #undef MODE_NAME_EQUAL - grn_hash_close(ctx, lexicon); + grn_obj_unlink(ctx, lexicon); } return NULL; @@ -4173,19 +4551,14 @@ selector_all_records(grn_ctx *ctx, grn_obj *table, grn_obj *index, int nargs, grn_obj **args, grn_obj *res, grn_operator op) { - grn_obj score; - - GRN_UINT32_INIT(&score, 0); - GRN_UINT32_SET(ctx, &score, 1); + grn_ii_posting posting; + memset(&posting, 0, sizeof(grn_ii_posting)); GRN_TABLE_EACH(ctx, table, 0, 0, id, NULL, NULL, NULL, { - grn_id result_id; - result_id = grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); - grn_obj_set_value(ctx, res, result_id, &score, GRN_OBJ_SET); + posting.rid = id; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, GRN_OP_OR); }); - GRN_OBJ_FIN(ctx, &score); - return ctx->rc; } @@ -4460,7 +4833,7 @@ run_query(grn_ctx *ctx, grn_obj *table, rc = ctx->rc; } -exit: +exit : if (match_columns) { grn_obj_unlink(ctx, match_columns); } @@ -4590,7 +4963,7 @@ run_sub_filter(grn_ctx *ctx, grn_obj *table, grn_obj_unlink(ctx, base_res); } -exit: +exit : if (scope_domain) { grn_obj_unlink(ctx, scope_domain); } @@ -4719,11 +5092,27 @@ typedef enum { typedef struct { grn_obj *value; grn_obj *min; + grn_obj casted_min; between_border_type min_border_type; grn_obj *max; + grn_obj casted_max; between_border_type max_border_type; } between_data; +static void +between_data_init(grn_ctx *ctx, between_data *data) +{ + GRN_VOID_INIT(&(data->casted_min)); + GRN_VOID_INIT(&(data->casted_max)); +} + +static void +between_data_fin(grn_ctx *ctx, between_data *data) +{ + GRN_OBJ_FIN(ctx, &(data->casted_min)); + GRN_OBJ_FIN(ctx, &(data->casted_max)); +} + static between_border_type between_parse_border(grn_ctx *ctx, grn_obj *border, const char *argument_description) @@ -4752,6 +5141,41 @@ between_parse_border(grn_ctx *ctx, grn_obj *border, } static grn_rc +between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain, + const char *target_argument_name) +{ + grn_rc rc; + + GRN_OBJ_INIT(destination, GRN_BULK, 0, domain); + rc = grn_obj_cast(ctx, source, destination, GRN_FALSE); + if (rc != GRN_SUCCESS) { + grn_obj inspected_source; + grn_obj *domain_object; + char domain_name[GRN_TABLE_MAX_KEY_SIZE]; + int domain_name_length; + + GRN_TEXT_INIT(&inspected_source, 0); + grn_inspect(ctx, &inspected_source, source); + + domain_object = grn_ctx_at(ctx, domain); + domain_name_length = + grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE); + + ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>", + target_argument_name, + (int)GRN_TEXT_LEN(&inspected_source), + GRN_TEXT_VALUE(&inspected_source), + domain_name_length, + domain_name); + + grn_obj_unlink(ctx, &inspected_source); + grn_obj_unlink(ctx, domain_object); + } + + return rc; +} + +static grn_rc between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data) { grn_rc rc = GRN_SUCCESS; @@ -4785,43 +5209,70 @@ between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data) goto exit; } + { + grn_id value_type; + if (data->value->header.type == GRN_BULK) { + value_type = data->value->header.domain; + } else { + value_type = grn_obj_get_range(ctx, data->value); + } + if (value_type != data->min->header.domain) { + rc = between_cast(ctx, data->min, &data->casted_min, value_type, "min"); + if (rc != GRN_SUCCESS) { + goto exit; + } + data->min = &(data->casted_min); + } + + if (value_type != data->max->header.domain) { + rc = between_cast(ctx, data->max, &data->casted_max, value_type, "max"); + if (rc != GRN_SUCCESS) { + goto exit; + } + data->max = &(data->casted_max); + } + } + exit : return rc; } -static grn_rc -between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain, - const char *target_argument_name) +static grn_bool +between_create_expr(grn_ctx *ctx, grn_obj *table, between_data *data, + grn_obj **expr, grn_obj **variable) { - grn_rc rc; - - GRN_OBJ_INIT(destination, GRN_BULK, 0, domain); - rc = grn_obj_cast(ctx, source, destination, GRN_FALSE); - if (rc != GRN_SUCCESS) { - grn_obj inspected_source; - grn_obj *domain_object; - char domain_name[GRN_TABLE_MAX_KEY_SIZE]; - int domain_name_length; - - GRN_TEXT_INIT(&inspected_source, 0); - grn_inspect(ctx, &inspected_source, source); - - domain_object = grn_ctx_at(ctx, domain); - domain_name_length = - grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, *expr, *variable); + if (!*expr) { + return GRN_FALSE; + } - ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>", - target_argument_name, - (int)GRN_TEXT_LEN(&inspected_source), - GRN_TEXT_VALUE(&inspected_source), - domain_name_length, - domain_name); + if (data->value->header.type == GRN_BULK) { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1); + } else { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1); + } + grn_expr_append_obj(ctx, *expr, data->min, GRN_OP_PUSH, 1); + if (data->min_border_type == BETWEEN_BORDER_INCLUDE) { + grn_expr_append_op(ctx, *expr, GRN_OP_GREATER_EQUAL, 2); + } else { + grn_expr_append_op(ctx, *expr, GRN_OP_GREATER, 2); + } - grn_obj_unlink(ctx, &inspected_source); - grn_obj_unlink(ctx, domain_object); + if (data->value->header.type == GRN_BULK) { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1); + } else { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1); + } + grn_expr_append_obj(ctx, *expr, data->max, GRN_OP_PUSH, 1); + if (data->max_border_type == BETWEEN_BORDER_INCLUDE) { + grn_expr_append_op(ctx, *expr, GRN_OP_LESS_EQUAL, 2); + } else { + grn_expr_append_op(ctx, *expr, GRN_OP_LESS, 2); } - return rc; + grn_expr_append_op(ctx, *expr, GRN_OP_AND, 2); + + return GRN_TRUE; } static grn_obj * @@ -4832,7 +5283,7 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) between_data data; grn_obj *condition = NULL; grn_obj *variable; - grn_obj *table; + grn_obj *table = NULL; grn_obj *between_expr; grn_obj *between_variable; grn_obj *result; @@ -4853,49 +5304,246 @@ func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) return found; } + between_data_init(ctx, &data); rc = between_parse_args(ctx, nargs, args, &data); if (rc != GRN_SUCCESS) { - return found; + goto exit; } table = grn_ctx_at(ctx, variable->header.domain); if (!table) { - return found; + goto exit; + } + if (!between_create_expr(ctx, table, &data, &between_expr, &between_variable)) { + goto exit; + } + + GRN_RECORD_SET(ctx, between_variable, GRN_RECORD_VALUE(variable)); + result = grn_expr_exec(ctx, between_expr, 0); + if (result) { + grn_bool result_boolean; + GRN_TRUEP(ctx, result, result_boolean); + if (result_boolean) { + GRN_BOOL_SET(ctx, found, GRN_TRUE); + } } - GRN_EXPR_CREATE_FOR_QUERY(ctx, table, between_expr, between_variable); - if (!between_expr) { + + grn_obj_unlink(ctx, between_expr); + grn_obj_unlink(ctx, table); + +exit : + between_data_fin(ctx, &data); + if (table) { grn_obj_unlink(ctx, table); - return found; } - grn_expr_append_obj(ctx, between_expr, data.value, GRN_OP_PUSH, 1); - grn_expr_append_obj(ctx, between_expr, data.min, GRN_OP_PUSH, 1); - if (data.min_border_type == BETWEEN_BORDER_INCLUDE) { - grn_expr_append_op(ctx, between_expr, GRN_OP_GREATER_EQUAL, 2); - } else { - grn_expr_append_op(ctx, between_expr, GRN_OP_GREATER, 2); + return found; +} + +static grn_bool +selector_between_sequential_search_should_use(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + grn_obj *index_table, + between_data *data, + grn_obj *res, + grn_operator op, + double too_many_index_match_ratio) +{ + int n_index_keys; + + if (too_many_index_match_ratio < 0.0) { + return GRN_FALSE; } - grn_expr_append_obj(ctx, between_expr, data.value, GRN_OP_PUSH, 1); - grn_expr_append_obj(ctx, between_expr, data.max, GRN_OP_PUSH, 1); - if (data.max_border_type == BETWEEN_BORDER_INCLUDE) { - grn_expr_append_op(ctx, between_expr, GRN_OP_LESS_EQUAL, 2); - } else { - grn_expr_append_op(ctx, between_expr, GRN_OP_LESS, 2); + if (op != GRN_OP_AND) { + return GRN_FALSE; } - grn_expr_append_op(ctx, between_expr, GRN_OP_AND, 2); + if (index->header.flags & GRN_OBJ_WITH_WEIGHT) { + return GRN_FALSE; + } - GRN_RECORD_SET(ctx, between_variable, GRN_RECORD_VALUE(variable)); - result = grn_expr_exec(ctx, between_expr, 0); - if (result && GRN_UINT32_VALUE(result) > 0) { - GRN_BOOL_SET(ctx, found, GRN_TRUE); + n_index_keys = grn_table_size(ctx, index_table); + if (n_index_keys == 0) { + return GRN_FALSE; } - grn_obj_unlink(ctx, between_expr); - grn_obj_unlink(ctx, table); + switch (index_table->header.domain) { + /* TODO: */ + /* case GRN_DB_INT8 : */ + /* case GRN_DB_UINT8 : */ + /* case GRN_DB_INT16 : */ + /* case GRN_DB_UINT16 : */ + /* case GRN_DB_INT32 : */ + /* case GRN_DB_UINT32 : */ + /* case GRN_DB_INT64 : */ + /* case GRN_DB_UINT64 : */ + /* case GRN_DB_FLOAT : */ + case GRN_DB_TIME : + break; + default : + return GRN_FALSE; + } - return found; + { + grn_table_cursor *cursor; + long long int all_min; + long long int all_max; + cursor = grn_table_cursor_open(ctx, index_table, + NULL, -1, + NULL, -1, + 0, 1, + GRN_CURSOR_BY_KEY | GRN_CURSOR_ASCENDING); + if (!cursor) { + return GRN_FALSE; + } + if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) { + grn_table_cursor_close(ctx, cursor); + return GRN_FALSE; + } + { + long long int *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + all_min = *key; + } + grn_table_cursor_close(ctx, cursor); + + cursor = grn_table_cursor_open(ctx, index_table, + NULL, 0, NULL, 0, + 0, 1, + GRN_CURSOR_BY_KEY | GRN_CURSOR_DESCENDING); + if (!cursor) { + return GRN_FALSE; + } + if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) { + grn_table_cursor_close(ctx, cursor); + return GRN_FALSE; + } + { + long long int *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + all_max = *key; + } + grn_table_cursor_close(ctx, cursor); + + /* + * We assume the following: + * * homogeneous index key distribution. + * * each index key matches only 1 record. + * TODO: Improve me. + */ + { + int n_existing_records; + int n_indexed_records; + long long int all_difference; + long long int argument_difference; + + n_existing_records = grn_table_size(ctx, res); + + all_difference = all_max - all_min; + if (all_difference <= 0) { + return GRN_FALSE; + } + argument_difference = + GRN_TIME_VALUE(data->max) - GRN_TIME_VALUE(data->min); + if (argument_difference <= 0) { + return GRN_FALSE; + } + n_indexed_records = + n_index_keys * ((double)argument_difference / (double)all_difference); + + /* + * Same as: + * ((n_existing_record / n_indexed_records) > too_many_index_match_ratio) + */ + if (n_existing_records > (n_indexed_records * too_many_index_match_ratio)) { + return GRN_FALSE; + } + } + } + + return GRN_TRUE; +} + +static grn_bool +selector_between_sequential_search(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, grn_obj *index_table, + between_data *data, + grn_obj *res, grn_operator op) +{ + double too_many_index_match_ratio = 0.01; + + { + const char *too_many_index_match_ratio_env = + getenv("GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO"); + if (too_many_index_match_ratio_env) { + too_many_index_match_ratio = atof(too_many_index_match_ratio_env); + } + } + + if (!selector_between_sequential_search_should_use( + ctx, table, index, index_table, data, res, op, + too_many_index_match_ratio)) { + return GRN_FALSE; + } + + { + int offset = 0; + int limit = -1; + int flags = 0; + grn_table_cursor *cursor; + grn_obj *expr; + grn_obj *variable; + grn_id id; + + if (!between_create_expr(ctx, table, data, &expr, &variable)) { + return GRN_FALSE; + } + + cursor = grn_table_cursor_open(ctx, res, + NULL, 0, + NULL, 0, + offset, limit, flags); + if (!cursor) { + grn_obj_unlink(ctx, expr); + return GRN_FALSE; + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_id record_id; + grn_obj *result; + { + grn_id *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + record_id = *key; + } + GRN_RECORD_SET(ctx, variable, record_id); + result = grn_expr_exec(ctx, expr, 0); + if (ctx->rc) { + break; + } + if (result) { + grn_bool result_boolean; + GRN_TRUEP(ctx, result, result_boolean); + if (result_boolean) { + grn_ii_posting posting; + posting.rid = record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + } + grn_obj_unlink(ctx, expr); + grn_table_cursor_close(ctx, cursor); + + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } + + return GRN_TRUE; } static grn_rc @@ -4908,9 +5556,6 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, int limit = -1; int flags = GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_KEY; between_data data; - grn_obj casted_min, casted_max; - grn_obj *used_min = NULL; - grn_obj *used_max = NULL; grn_obj *index_table = NULL; grn_table_cursor *cursor; grn_id id; @@ -4919,9 +5564,10 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, return GRN_INVALID_ARGUMENT; } + between_data_init(ctx, &data); rc = between_parse_args(ctx, nargs - 1, args + 1, &data); if (rc != GRN_SUCCESS) { - return rc; + goto exit; } if (data.min_border_type == BETWEEN_BORDER_EXCLUDE) { @@ -4932,31 +5578,16 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, } index_table = grn_ctx_at(ctx, index->header.domain); - if (data.min->header.domain == index_table->header.domain) { - used_min = data.min; - } else { - used_min = &casted_min; - rc = between_cast(ctx, data.min, &casted_min, index_table->header.domain, - "min"); - if (rc != GRN_SUCCESS) { - goto exit; - } - } - if (data.max->header.domain == index_table->header.domain) { - used_max = data.max; - } else { - used_max = &casted_max; - rc = between_cast(ctx, data.max, &casted_max, index_table->header.domain, - "max"); - if (rc != GRN_SUCCESS) { - goto exit; - } + if (selector_between_sequential_search(ctx, table, index, index_table, + &data, res, op)) { + goto exit; } + cursor = grn_table_cursor_open(ctx, index_table, - GRN_BULK_HEAD(used_min), - GRN_BULK_VSIZE(used_min), - GRN_BULK_HEAD(used_max), - GRN_BULK_VSIZE(used_max), + GRN_BULK_HEAD(data.min), + GRN_BULK_VSIZE(data.min), + GRN_BULK_HEAD(data.max), + GRN_BULK_VSIZE(data.max), offset, limit, flags); if (!cursor) { rc = ctx->rc; @@ -4970,12 +5601,7 @@ selector_between(grn_ctx *ctx, grn_obj *table, grn_obj *index, grn_table_cursor_close(ctx, cursor); exit : - if (used_min == &casted_min) { - grn_obj_unlink(ctx, &casted_min); - } - if (used_max == &casted_max) { - grn_obj_unlink(ctx, &casted_max); - } + between_data_fin(ctx, &data); if (index_table) { grn_obj_unlink(ctx, index_table); } @@ -5249,6 +5875,564 @@ func_highlight_full(grn_ctx *ctx, int nargs, grn_obj **args, return highlighted; } +static grn_obj * +func_in_values(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *found; + grn_obj *target_value; + int i; + + found = GRN_PROC_ALLOC(GRN_DB_BOOL, 0); + if (!found) { + return NULL; + } + GRN_BOOL_SET(ctx, found, GRN_FALSE); + + if (nargs < 1) { + ERR(GRN_INVALID_ARGUMENT, + "in_values(): wrong number of arguments (%d for 1..)", nargs); + return found; + } + + target_value = args[0]; + for (i = 1; i < nargs; i++) { + grn_obj *value = args[i]; + grn_bool result; + + result = grn_operator_exec_equal(ctx, target_value, value); + if (ctx->rc) { + break; + } + + if (result) { + GRN_BOOL_SET(ctx, found, GRN_TRUE); + break; + } + } + + return found; +} + +static grn_bool +is_reference_type_column(grn_ctx *ctx, grn_obj *column) +{ + grn_bool is_reference_type; + grn_obj *range; + + range = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); + switch (range->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + is_reference_type = GRN_TRUE; + break; + default : + is_reference_type = GRN_FALSE; + break; + } + grn_obj_unlink(ctx, range); + + return is_reference_type; +} + +static grn_obj * +selector_in_values_find_source(grn_ctx *ctx, grn_obj *index, grn_obj *res) +{ + grn_id source_id = GRN_ID_NIL; + grn_obj source_ids; + unsigned int n_source_ids; + + GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); + grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids); + n_source_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + if (n_source_ids == 1) { + source_id = GRN_UINT32_VALUE_AT(&source_ids, 0); + } + GRN_OBJ_FIN(ctx, &source_ids); + + if (source_id == GRN_ID_NIL) { + return NULL; + } else { + return grn_ctx_at(ctx, source_id); + } +} + +static grn_bool +selector_in_values_sequential_search(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int n_values, + grn_obj **values, + grn_obj *res, + grn_operator op) +{ + grn_obj *source; + int n_existing_records; + double too_many_index_match_ratio = 0.01; + + { + const char *too_many_index_match_ratio_env = + getenv("GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO"); + if (too_many_index_match_ratio_env) { + too_many_index_match_ratio = atof(too_many_index_match_ratio_env); + } + } + + if (too_many_index_match_ratio < 0.0) { + return GRN_FALSE; + } + + if (op != GRN_OP_AND) { + return GRN_FALSE; + } + + if (index->header.flags & GRN_OBJ_WITH_WEIGHT) { + return GRN_FALSE; + } + + n_existing_records = grn_table_size(ctx, res); + if (n_existing_records == 0) { + return GRN_TRUE; + } + + source = selector_in_values_find_source(ctx, index, res); + if (!source) { + return GRN_FALSE; + } + + if (!is_reference_type_column(ctx, source)) { + grn_obj_unlink(ctx, source); + return GRN_FALSE; + } + + { + grn_obj value_ids; + int i, n_value_ids; + int n_indexed_records = 0; + + { + grn_id range_id; + grn_obj *range; + + range_id = grn_obj_get_range(ctx, source); + range = grn_ctx_at(ctx, range_id); + if (!range) { + grn_obj_unlink(ctx, source); + return GRN_FALSE; + } + + GRN_RECORD_INIT(&value_ids, GRN_OBJ_VECTOR, range_id); + for (i = 0; i < n_values; i++) { + grn_obj *value = values[i]; + grn_id value_id; + + value_id = grn_table_get(ctx, range, + GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); + if (value_id == GRN_ID_NIL) { + continue; + } + GRN_RECORD_PUT(ctx, &value_ids, value_id); + } + grn_obj_unlink(ctx, range); + } + + n_value_ids = GRN_BULK_VSIZE(&value_ids) / sizeof(grn_id); + for (i = 0; i < n_value_ids; i++) { + grn_id value_id = GRN_RECORD_VALUE_AT(&value_ids, i); + n_indexed_records += grn_ii_estimate_size(ctx, (grn_ii *)index, value_id); + } + + /* + * Same as: + * ((n_existing_record / n_indexed_records) > too_many_index_match_ratio) + */ + if (n_existing_records > (n_indexed_records * too_many_index_match_ratio)) { + grn_obj_unlink(ctx, &value_ids); + grn_obj_unlink(ctx, source); + return GRN_FALSE; + } + + { + grn_obj *accessor; + char local_source_name[GRN_TABLE_MAX_KEY_SIZE]; + int local_source_name_length; + + local_source_name_length = grn_column_name(ctx, source, + local_source_name, + GRN_TABLE_MAX_KEY_SIZE); + grn_obj_unlink(ctx, source); + accessor = grn_obj_column(ctx, res, + local_source_name, + local_source_name_length); + { + grn_table_cursor *cursor; + grn_id record_id; + grn_obj record_value; + GRN_RECORD_INIT(&record_value, 0, grn_obj_id(ctx, res)); + cursor = grn_table_cursor_open(ctx, res, + NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_ASCENDING); + while ((record_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + GRN_BULK_REWIND(&record_value); + grn_obj_get_value(ctx, accessor, record_id, &record_value); + for (i = 0; i < n_value_ids; i++) { + grn_id value_id = GRN_RECORD_VALUE_AT(&value_ids, i); + if (value_id == GRN_RECORD_VALUE(&record_value)) { + grn_ii_posting posting; + posting.rid = record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + } + grn_table_cursor_close(ctx, cursor); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + GRN_OBJ_FIN(ctx, &record_value); + } + grn_obj_unlink(ctx, accessor); + } + grn_obj_unlink(ctx, &value_ids); + } + grn_obj_unlink(ctx, source); + + return GRN_TRUE; +} + +static grn_rc +selector_in_values(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + int i, n_values; + grn_obj **values; + + if (!index) { + return GRN_INVALID_ARGUMENT; + } + + if (nargs < 2) { + ERR(GRN_INVALID_ARGUMENT, + "in_values(): wrong number of arguments (%d for 1..)", nargs); + return ctx->rc; + } + + n_values = nargs - 2; + values = args + 2; + + if (n_values == 0) { + return rc; + } + + if (selector_in_values_sequential_search(ctx, table, index, + n_values, values, + res, op)) { + return ctx->rc; + } + + ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; + for (i = 0; i < n_values; i++) { + grn_obj *value = values[i]; + grn_search_optarg search_options; + memset(&search_options, 0, sizeof(grn_search_optarg)); + search_options.mode = GRN_OP_EXACT; + search_options.similarity_threshold = 0; + search_options.max_interval = 0; + search_options.weight_vector = NULL; + search_options.vector_size = 0; + search_options.proc = NULL; + search_options.max_size = 0; + search_options.scorer = NULL; + if (i == n_values - 1) { + ctx->flags &= ~GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; + } + rc = grn_obj_search(ctx, index, value, res, op, &search_options); + if (rc != GRN_SUCCESS) { + break; + } + } + + return rc; +} + +static grn_obj * +proc_range_filter(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *table_name = VAR(0); + grn_obj *column_name = VAR(1); + grn_obj *min = VAR(2); + grn_obj *min_border = VAR(3); + grn_obj *max = VAR(4); + grn_obj *max_border = VAR(5); + grn_obj *offset = VAR(6); + grn_obj *limit = VAR(7); + grn_obj *filter = VAR(8); + grn_obj *output_columns = VAR(9); + grn_obj *table; + grn_obj *res = NULL; + grn_obj *filter_expr = NULL; + grn_obj *filter_variable = NULL; + int real_offset; + int real_limit; + + table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_name), GRN_TEXT_LEN(table_name)); + if (!table) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] nonexistent table <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name)); + return NULL; + } + + if (GRN_TEXT_LEN(filter) > 0) { + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, filter_expr, filter_variable); + if (!filter_expr) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] failed to create expression"); + goto exit; + } + + grn_expr_parse(ctx, filter_expr, + GRN_TEXT_VALUE(filter), GRN_TEXT_LEN(filter), + NULL, GRN_OP_MATCH, GRN_OP_AND, GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + } + + res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + table, NULL); + if (!res) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] failed to result table"); + goto exit; + } + + { + grn_obj int32_value; + + GRN_INT32_INIT(&int32_value, 0); + + if (GRN_TEXT_LEN(offset) > 0) { + if (grn_obj_cast(ctx, offset, &int32_value, GRN_FALSE) != GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] invalid offset format: <%.*s>", + (int)GRN_TEXT_LEN(offset), GRN_TEXT_VALUE(offset)); + GRN_OBJ_FIN(ctx, &int32_value); + goto exit; + } + real_offset = GRN_INT32_VALUE(&int32_value); + } else { + real_offset = 0; + } + + GRN_BULK_REWIND(&int32_value); + + if (GRN_TEXT_LEN(limit) > 0) { + if (grn_obj_cast(ctx, limit, &int32_value, GRN_FALSE) != GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] invalid limit format: <%.*s>", + (int)GRN_TEXT_LEN(limit), GRN_TEXT_VALUE(limit)); + GRN_OBJ_FIN(ctx, &int32_value); + goto exit; + } + real_limit = GRN_INT32_VALUE(&int32_value); + } else { + real_limit = DEFAULT_LIMIT; + } + + GRN_OBJ_FIN(ctx, &int32_value); + } + { + grn_rc rc; + int original_offset = real_offset; + int original_limit = real_limit; + rc = grn_normalize_offset_and_limit(ctx, grn_table_size(ctx, table), + &real_offset, &real_limit); + switch (rc) { + case GRN_TOO_SMALL_OFFSET : + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] too small offset: <%d>", original_offset); + goto exit; + case GRN_TOO_LARGE_OFFSET : + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] too large offset: <%d>", original_offset); + goto exit; + case GRN_TOO_SMALL_LIMIT : + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] too small limit: <%d>", original_limit); + goto exit; + default : + break; + } + } + + if (real_limit != 0) { + grn_table_sort_key *sort_keys; + unsigned int n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + GRN_TEXT_VALUE(column_name), + GRN_TEXT_LEN(column_name), + table, + &n_sort_keys); + if (n_sort_keys == 1) { + grn_table_sort_key *sort_key; + grn_obj *index; + int n_indexes; + grn_operator op = GRN_OP_OR; + + sort_key = &(sort_keys[0]); + n_indexes = grn_column_index(ctx, sort_key->key, GRN_OP_LESS, + &index, 1, NULL); + if (n_indexes > 0) { + grn_obj *lexicon; + grn_table_cursor *table_cursor; + int table_cursor_flags = 0; + between_border_type min_border_type; + between_border_type max_border_type; + grn_obj real_min; + grn_obj real_max; + int n_records = 0; + grn_obj *index_cursor; + int index_cursor_flags = 0; + grn_posting *posting; + + lexicon = grn_ctx_at(ctx, index->header.domain); + if (sort_key->flags & GRN_TABLE_SORT_DESC) { + table_cursor_flags |= GRN_CURSOR_DESCENDING; + } else { + table_cursor_flags |= GRN_CURSOR_ASCENDING; + } + if (GRN_TEXT_LEN(min_border) > 0) { + min_border_type = between_parse_border(ctx, min_border, "min_border"); + } else { + min_border_type = BETWEEN_BORDER_INCLUDE; + } + if (GRN_TEXT_LEN(max_border) > 0) { + max_border_type = between_parse_border(ctx, max_border, "max_border"); + } else { + max_border_type = BETWEEN_BORDER_INCLUDE; + } + if (min_border_type == BETWEEN_BORDER_EXCLUDE) { + table_cursor_flags |= GRN_CURSOR_GT; + } + if (max_border_type == BETWEEN_BORDER_EXCLUDE) { + table_cursor_flags |= GRN_CURSOR_LT; + } + GRN_OBJ_INIT(&real_min, GRN_BULK, 0, lexicon->header.domain); + GRN_OBJ_INIT(&real_max, GRN_BULK, 0, lexicon->header.domain); + if (GRN_TEXT_LEN(min) > 0) { + grn_obj_cast(ctx, min, &real_min, GRN_FALSE); + } + if (GRN_TEXT_LEN(max) > 0) { + grn_obj_cast(ctx, max, &real_max, GRN_FALSE); + } + table_cursor = grn_table_cursor_open(ctx, lexicon, + GRN_BULK_HEAD(&real_min), + GRN_BULK_VSIZE(&real_min), + GRN_BULK_HEAD(&real_max), + GRN_BULK_VSIZE(&real_max), + 0, -1, table_cursor_flags); + index_cursor = grn_index_cursor_open(ctx, table_cursor, + index, GRN_ID_NIL, GRN_ID_NIL, + index_cursor_flags); + while ((posting = grn_index_cursor_next(ctx, index_cursor, NULL))) { + grn_bool result_boolean = GRN_FALSE; + + if (filter_expr) { + grn_obj *result; + GRN_RECORD_SET(ctx, filter_variable, posting->rid); + result = grn_expr_exec(ctx, filter_expr, 0); + if (ctx->rc) { + break; + } + if (result) { + GRN_TRUEP(ctx, result, result_boolean); + } + } else { + result_boolean = GRN_TRUE; + } + + if (result_boolean) { + if (n_records >= real_offset) { + grn_ii_posting ii_posting; + ii_posting.rid = posting->rid; + ii_posting.sid = posting->sid; + ii_posting.pos = posting->pos; + ii_posting.weight = posting->weight; + grn_ii_posting_add(ctx, &ii_posting, (grn_hash *)res, op); + } + n_records++; + if (n_records == real_limit) { + break; + } + } + } + grn_obj_unlink(ctx, index_cursor); + grn_table_cursor_close(ctx, table_cursor); + + GRN_OBJ_FIN(ctx, &real_min); + GRN_OBJ_FIN(ctx, &real_max); + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } + grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); + } + + if (ctx->rc == GRN_SUCCESS) { + const char *raw_output_columns; + int raw_output_columns_len; + + raw_output_columns = GRN_TEXT_VALUE(output_columns); + raw_output_columns_len = GRN_TEXT_LEN(output_columns); + if (raw_output_columns_len == 0) { + raw_output_columns = DEFAULT_OUTPUT_COLUMNS; + raw_output_columns_len = strlen(raw_output_columns); + } + grn_select_output_columns(ctx, res, -1, real_offset, real_limit, + raw_output_columns, + raw_output_columns_len, + filter_expr); + } + +exit : + if (filter_expr) { + grn_obj_unlink(ctx, filter_expr); + } + if (res) { + grn_obj_unlink(ctx, res); + } + + return NULL; +} + +static grn_obj * +proc_request_cancel(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *id = VAR(0); + grn_bool canceled; + + if (GRN_TEXT_LEN(id) == 0) { + ERR(GRN_INVALID_ARGUMENT, "[request_cancel] ID is missing"); + return NULL; + } + + canceled = grn_request_canceler_cancel(GRN_TEXT_VALUE(id), GRN_TEXT_LEN(id)); + + GRN_OUTPUT_MAP_OPEN("result", 2); + GRN_OUTPUT_CSTR("id"); + GRN_OUTPUT_STR(GRN_TEXT_VALUE(id), GRN_TEXT_LEN(id)); + GRN_OUTPUT_CSTR("canceled"); + GRN_OUTPUT_BOOL(canceled); + GRN_OUTPUT_MAP_CLOSE(); + + return NULL; +} + #define DEF_VAR(v,name_str) do {\ (v).name = (name_str);\ (v).name_size = GRN_STRLEN(name_str);\ @@ -5262,7 +6446,7 @@ func_highlight_full(grn_ctx *ctx, int nargs, grn_obj **args, void grn_db_init_builtin_query(grn_ctx *ctx) { - grn_expr_var vars[21]; + grn_expr_var vars[23]; DEF_VAR(vars[0], "name"); DEF_VAR(vars[1], "table"); @@ -5286,8 +6470,10 @@ grn_db_init_builtin_query(grn_ctx *ctx) DEF_VAR(vars[18], "query_flags"); DEF_VAR(vars[19], "query_expander"); DEF_VAR(vars[20], "adjuster"); - DEF_COMMAND("define_selector", proc_define_selector, 21, vars); - DEF_COMMAND("select", proc_select, 20, vars + 1); + DEF_VAR(vars[21], "drilldown_calc_types"); + DEF_VAR(vars[22], "drilldown_calc_target"); + DEF_COMMAND("define_selector", proc_define_selector, 23, vars); + DEF_COMMAND("select", proc_select, 22, vars + 1); DEF_VAR(vars[0], "values"); DEF_VAR(vars[1], "table"); @@ -5343,8 +6529,12 @@ grn_db_init_builtin_query(grn_ctx *ctx) DEF_COMMAND("shutdown", proc_shutdown, 0, vars); + /* Deprecated. Use "lock_clear" instead. */ + DEF_VAR(vars[0], "target_name"); + DEF_COMMAND("clearlock", proc_lock_clear, 1, vars); + DEF_VAR(vars[0], "target_name"); - DEF_COMMAND("clearlock", proc_clearlock, 1, vars); + DEF_COMMAND("lock_clear", proc_lock_clear, 1, vars); DEF_VAR(vars[0], "target_name"); DEF_VAR(vars[1], "threshold"); @@ -5377,8 +6567,9 @@ grn_db_init_builtin_query(grn_ctx *ctx) DEF_VAR(vars[0], "obj"); DEF_COMMAND("check", proc_check, 1, vars); - DEF_VAR(vars[0], "table"); - DEF_COMMAND("truncate", proc_truncate, 1, vars); + DEF_VAR(vars[0], "target_name"); + DEF_VAR(vars[1], "table"); + DEF_COMMAND("truncate", proc_truncate, 2, vars); DEF_VAR(vars[0], "normalizer"); DEF_VAR(vars[1], "string"); @@ -5390,7 +6581,14 @@ grn_db_init_builtin_query(grn_ctx *ctx) DEF_VAR(vars[2], "normalizer"); DEF_VAR(vars[3], "flags"); DEF_VAR(vars[4], "mode"); - DEF_COMMAND("tokenize", proc_tokenize, 5, vars); + DEF_VAR(vars[5], "token_filters"); + DEF_COMMAND("tokenize", proc_tokenize, 6, vars); + + DEF_VAR(vars[0], "table"); + DEF_VAR(vars[1], "string"); + DEF_VAR(vars[2], "flags"); + DEF_VAR(vars[3], "mode"); + DEF_COMMAND("table_tokenize", proc_table_tokenize, 4, vars); DEF_COMMAND("tokenizer_list", proc_tokenizer_list, 0, vars); @@ -5479,4 +6677,27 @@ grn_db_init_builtin_query(grn_ctx *ctx) grn_proc_create(ctx, "highlight_full", -1, GRN_PROC_FUNCTION, func_highlight_full, NULL, NULL, 0, NULL); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "in_values", -1, GRN_PROC_FUNCTION, + func_in_values, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_in_values); + } + + DEF_VAR(vars[0], "table"); + DEF_VAR(vars[1], "column"); + DEF_VAR(vars[2], "min"); + DEF_VAR(vars[3], "min_border"); + DEF_VAR(vars[4], "max"); + DEF_VAR(vars[5], "max_border"); + DEF_VAR(vars[6], "offset"); + DEF_VAR(vars[7], "limit"); + DEF_VAR(vars[8], "filter"); + DEF_VAR(vars[9], "output_columns"); + DEF_COMMAND("range_filter", proc_range_filter, 10, vars); + + DEF_VAR(vars[0], "id"); + DEF_COMMAND("request_cancel", proc_request_cancel, 1, vars); } diff --git a/storage/mroonga/vendor/groonga/lib/request_canceler.c b/storage/mroonga/vendor/groonga/lib/request_canceler.c new file mode 100644 index 00000000000..866292f73de --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/request_canceler.c @@ -0,0 +1,123 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "grn_ctx.h" +#include "grn_request_canceler.h" + +typedef struct _grn_request_canceler grn_request_canceler; +struct _grn_request_canceler { + grn_hash *entries; + grn_mutex mutex; +}; + +typedef struct _grn_request_canceler_entry grn_request_canceler_entry; +struct _grn_request_canceler_entry { + grn_ctx *ctx; +}; + +static grn_request_canceler *grn_the_request_canceler = NULL; + +grn_bool +grn_request_canceler_init(void) +{ + grn_ctx *ctx = &grn_gctx; + + grn_the_request_canceler = GRN_MALLOC(sizeof(grn_request_canceler)); + if (!grn_the_request_canceler) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[request-canceler] failed to allocate the global request canceler"); + return GRN_FALSE; + } + + grn_the_request_canceler->entries = + grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_request_canceler_entry), GRN_OBJ_KEY_VAR_SIZE); + if (!grn_the_request_canceler->entries) { + return GRN_FALSE; + } + MUTEX_INIT(grn_the_request_canceler->mutex); + + return GRN_TRUE; +} + +void +grn_request_canceler_register(grn_ctx *ctx, + const char *request_id, unsigned int size) +{ + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_hash *entries = grn_the_request_canceler->entries; + grn_id id; + void *value; + id = grn_hash_add(&grn_gctx, entries, request_id, size, &value, NULL); + if (id) { + grn_request_canceler_entry *entry = value; + entry->ctx = ctx; + } + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); +} + +void +grn_request_canceler_unregister(grn_ctx *ctx, + const char *request_id, unsigned int size) +{ + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_hash *entries = grn_the_request_canceler->entries; + grn_hash_delete(&grn_gctx, entries, request_id, size, NULL); + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); + + if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { + ERRSET(ctx, GRN_LOG_NOTICE, ctx->rc, + "[request-canceler] a request is canceled: <%.*s>", + size, request_id); + } +} + +grn_bool +grn_request_canceler_cancel(const char *request_id, unsigned int size) +{ + grn_bool canceled = GRN_FALSE; + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_hash *entries = grn_the_request_canceler->entries; + void *value; + if (grn_hash_get(&grn_gctx, entries, request_id, size, &value)) { + grn_request_canceler_entry *entry = value; + if (entry->ctx->rc == GRN_SUCCESS) { + entry->ctx->rc = GRN_INTERRUPTED_FUNCTION_CALL; + canceled = GRN_TRUE; + } + } + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); + return canceled; +} + +void +grn_request_canceler_fin(void) +{ + grn_ctx *ctx = &grn_gctx; + + grn_hash_close(ctx, grn_the_request_canceler->entries); + MUTEX_FIN(grn_the_request_canceler->mutex); + GRN_FREE(grn_the_request_canceler); + grn_the_request_canceler = NULL; +} diff --git a/storage/mroonga/vendor/groonga/lib/rset.c b/storage/mroonga/vendor/groonga/lib/rset.c new file mode 100644 index 00000000000..85a9e1c529e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/rset.c @@ -0,0 +1,324 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "grn_db.h" + +uint32_t +grn_rset_recinfo_calc_values_size(grn_ctx *ctx, grn_table_group_flags flags) +{ + uint32_t size = 0; + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + size += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + size += GRN_RSET_MIN_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_SUM) { + size += GRN_RSET_SUM_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_AVG) { + size += GRN_RSET_AVG_SIZE; + } + + return size; +} + +void +grn_rset_recinfo_update_calc_values(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + grn_obj *value) +{ + grn_table_group_flags flags; + byte *values; + grn_obj value_int64; + grn_obj value_float; + + flags = DB_OBJ(table)->flags.group; + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + GRN_INT64_INIT(&value_int64, 0); + GRN_FLOAT_INIT(&value_float, 0); + + if (flags & (GRN_TABLE_GROUP_CALC_MAX | + GRN_TABLE_GROUP_CALC_MIN | + GRN_TABLE_GROUP_CALC_SUM)) { + grn_obj_cast(ctx, value, &value_int64, GRN_FALSE); + } + if (flags & GRN_TABLE_GROUP_CALC_AVG) { + grn_obj_cast(ctx, value, &value_float, GRN_FALSE); + } + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + int64_t current_max = *((int64_t *)values); + int64_t value_raw = GRN_INT64_VALUE(&value_int64); + if (ri->n_subrecs == 1 || value_raw > current_max) { + *((int64_t *)values) = value_raw; + } + values += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + int64_t current_min = *((int64_t *)values); + int64_t value_raw = GRN_INT64_VALUE(&value_int64); + if (ri->n_subrecs == 1 || value_raw < current_min) { + *((int64_t *)values) = value_raw; + } + values += GRN_RSET_MIN_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_SUM) { + int64_t value_raw = GRN_INT64_VALUE(&value_int64); + *((int64_t *)values) += value_raw; + values += GRN_RSET_SUM_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_AVG) { + double current_average = *((double *)values); + double value_raw = GRN_FLOAT_VALUE(&value_float); + *((double *)values) += (value_raw - current_average) / ri->n_subrecs; + values += GRN_RSET_AVG_SIZE; + } + + GRN_OBJ_FIN(ctx, &value_float); + GRN_OBJ_FIN(ctx, &value_int64); +} + +int64_t * +grn_rset_recinfo_get_max_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_MAX)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + return (int64_t *)values; +} + +int64_t +grn_rset_recinfo_get_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + int64_t *max_address; + + max_address = grn_rset_recinfo_get_max_(ctx, ri, table); + if (max_address) { + return *max_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t max) +{ + int64_t *max_address; + + max_address = grn_rset_recinfo_get_max_(ctx, ri, table); + if (!max_address) { + return; + } + + *max_address = max; +} + +int64_t * +grn_rset_recinfo_get_min_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_MIN)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + values += GRN_RSET_MAX_SIZE; + } + + return (int64_t *)values; +} + +int64_t +grn_rset_recinfo_get_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + int64_t *min_address; + + min_address = grn_rset_recinfo_get_min_(ctx, ri, table); + if (min_address) { + return *min_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t min) +{ + int64_t *min_address; + + min_address = grn_rset_recinfo_get_min_(ctx, ri, table); + if (!min_address) { + return; + } + + *min_address = min; +} + +int64_t * +grn_rset_recinfo_get_sum_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_SUM)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + values += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + values += GRN_RSET_MIN_SIZE; + } + + return (int64_t *)values; +} + +int64_t +grn_rset_recinfo_get_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + int64_t *sum_address; + + sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table); + if (sum_address) { + return *sum_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t sum) +{ + int64_t *sum_address; + + sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table); + if (!sum_address) { + return; + } + + *sum_address = sum; +} + +double * +grn_rset_recinfo_get_avg_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_AVG)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + values += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + values += GRN_RSET_MIN_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_SUM) { + values += GRN_RSET_SUM_SIZE; + } + + return (double *)values; +} + +double +grn_rset_recinfo_get_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + double *avg_address; + + avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table); + if (avg_address) { + return *avg_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + double avg) +{ + double *avg_address; + + avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table); + if (!avg_address) { + return; + } + + *avg_address = avg; +} diff --git a/storage/mroonga/vendor/groonga/lib/scorer.c b/storage/mroonga/vendor/groonga/lib/scorer.c new file mode 100644 index 00000000000..f5bc0435108 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/scorer.c @@ -0,0 +1,134 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <string.h> + +#include "grn.h" +#include "grn_db.h" +#include "grn_scorer.h" +#include <groonga/scorer.h> + +grn_obj * +grn_scorer_matched_record_get_table(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->table; +} + +grn_obj * +grn_scorer_matched_record_get_lexicon(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->lexicon; +} + +grn_id +grn_scorer_matched_record_get_id(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->id; +} + +grn_obj * +grn_scorer_matched_record_get_terms(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return &(record->terms); +} + +grn_obj * +grn_scorer_matched_record_get_term_weights(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return &(record->term_weights); +} + +unsigned int +grn_scorer_matched_record_get_total_term_weights(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->total_term_weights; +} + +long long unsigned int +grn_scorer_matched_record_get_n_documents(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_documents; +} + +unsigned int +grn_scorer_matched_record_get_n_occurrences(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_occurrences; +} + +long long unsigned int +grn_scorer_matched_record_get_n_candidates(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_candidates; +} + +unsigned int +grn_scorer_matched_record_get_n_tokens(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_tokens; +} + +int +grn_scorer_matched_record_get_weight(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->weight; +} + +grn_rc +grn_scorer_register(grn_ctx *ctx, + const char *plugin_name_ptr, + int plugin_name_length, + grn_scorer_score_func *score) +{ + if (plugin_name_length == -1) { + plugin_name_length = strlen(plugin_name_ptr); + } + + { + grn_obj *scorer_object = grn_proc_create(ctx, + plugin_name_ptr, + plugin_name_length, + GRN_PROC_SCORER, + NULL, NULL, NULL, 0, NULL); + if (scorer_object == NULL) { + GRN_PLUGIN_ERROR(ctx, GRN_SCORER_ERROR, + "[scorer][%.*s] failed to grn_proc_create()", + plugin_name_length, plugin_name_ptr); + return ctx->rc; + } + + { + grn_proc *scorer = (grn_proc *)scorer_object; + scorer->callbacks.scorer.score = score; + } + } + + return GRN_SUCCESS; +} + diff --git a/storage/mroonga/vendor/groonga/lib/scorers.c b/storage/mroonga/vendor/groonga/lib/scorers.c new file mode 100644 index 00000000000..b039e011920 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/scorers.c @@ -0,0 +1,57 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <groonga/scorer.h> + +#include <math.h> + +static double +scorer_tf_idf(grn_ctx *ctx, grn_scorer_matched_record *record) +{ + double min_score = 1.0; + double tf; + double n_all_documents; + double n_candidates; + double n_tokens; + double n_estimated_match_documents; + + tf = grn_scorer_matched_record_get_n_occurrences(ctx, record) + + grn_scorer_matched_record_get_total_term_weights(ctx, record); + n_all_documents = grn_scorer_matched_record_get_n_documents(ctx, record); + n_candidates = grn_scorer_matched_record_get_n_candidates(ctx, record); + n_tokens = grn_scorer_matched_record_get_n_tokens(ctx, record); + n_estimated_match_documents = n_candidates / n_tokens; + + if (n_estimated_match_documents >= n_all_documents) { + return min_score; + } else { + double idf; + double tf_idf; + + idf = log(n_all_documents / n_estimated_match_documents); + tf_idf = tf * idf; + return fmax(tf_idf, min_score); + } +} + +grn_rc +grn_db_init_builtin_scorers(grn_ctx *ctx) +{ + grn_scorer_register(ctx, "scorer_tf_idf", -1, scorer_tf_idf); + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/snip.c b/storage/mroonga/vendor/groonga/lib/snip.c index 78c6ef54387..739ee345738 100644 --- a/storage/mroonga/vendor/groonga/lib/snip.c +++ b/storage/mroonga/vendor/groonga/lib/snip.c @@ -14,11 +14,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <string.h> #include <stddef.h> -#include "snip.h" -#include "ctx.h" +#include "grn_snip.h" +#include "grn_ctx.h" #if !defined MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) diff --git a/storage/mroonga/vendor/groonga/lib/sources.am b/storage/mroonga/vendor/groonga/lib/sources.am index 8b371081fe6..25e5df5fd4d 100644 --- a/storage/mroonga/vendor/groonga/lib/sources.am +++ b/storage/mroonga/vendor/groonga/lib/sources.am @@ -1,52 +1,65 @@ libgroonga_la_SOURCES = \ com.c \ - com.h \ + grn_com.h \ + command.c \ ctx.c \ - ctx.h \ - ctx_impl.h \ + grn_ctx.h \ + grn_ctx_impl.h \ ctx_impl_mrb.c \ - ctx_impl_mrb.h \ + grn_ctx_impl_mrb.h \ dat.cpp \ - dat.h \ + grn_dat.h \ db.c \ - db.h \ + grn_db.h \ error.c \ - error.h \ + grn_error.h \ expr.c \ - expr.h \ + grn_expr.h \ geo.c \ - geo.h \ - groonga_in.h \ + grn_geo.h \ + grn.h \ hash.c \ - hash.h \ + grn_hash.h \ ii.c \ - ii.h \ + grn_ii.h \ io.c \ - io.h \ + grn_io.h \ mrb.c \ - mrb.h \ + grn_mrb.h \ nfkc.c \ normalizer.c \ - normalizer_in.h \ + grn_normalizer.h \ + obj.c \ + operator.c \ output.c \ - output.h \ + grn_output.h \ pat.c \ - pat.h \ + grn_pat.h \ plugin.c \ - plugin_in.h \ + grn_plugin.h \ proc.c \ - proc.h \ + grn_proc.h \ + request_canceler.c \ + grn_request_canceler.h \ + rset.c \ + grn_rset.h \ + scorer.c \ + grn_scorer.h \ + scorers.c \ + grn_scorers.h \ snip.c \ - snip.h \ + grn_snip.h \ store.c \ - store.h \ + grn_store.h \ str.c \ - str.h \ + grn_str.h \ string.c \ - string_in.h \ - token.c \ - token.h \ + grn_string.h \ + token_cursor.c \ + grn_token_cursor.h \ tokenizer.c \ + tokenizers.c \ + grn_tokenizers.h \ token_filter.c \ util.c \ - util.h + grn_util.h diff --git a/storage/mroonga/vendor/groonga/lib/store.c b/storage/mroonga/vendor/groonga/lib/store.c index 3649611a560..6b3b01ce4be 100644 --- a/storage/mroonga/vendor/groonga/lib/store.c +++ b/storage/mroonga/vendor/groonga/lib/store.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2014 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -14,11 +14,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" -#include "str.h" -#include "store.h" -#include "ctx_impl.h" -#include "output.h" +#include "grn.h" +#include "grn_str.h" +#include "grn_store.h" +#include "grn_ctx_impl.h" +#include "grn_output.h" #include <string.h> /* rectangular arrays */ @@ -524,7 +524,7 @@ grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *va iw->size = 0; iw->addr = NULL; iw->pseg = pseg; - iw->value = NULL; + iw->uncompressed_value = NULL; if (pseg != JA_ESEG_VOID) { grn_ja_einfo *einfo = NULL; GRN_IO_SEG_REF(ja->io, pseg, einfo); @@ -545,7 +545,7 @@ grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *va } else { EINFO_DEC(ei, jag, vpos, vsize); } - grn_io_win_map2(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly); + grn_io_win_map(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly); } if (!iw->addr) { GRN_IO_SEG_UNREF(ja->io, pseg); } } @@ -557,13 +557,13 @@ grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *va grn_rc grn_ja_unref(grn_ctx *ctx, grn_io_win *iw) { - if (iw->value) { - GRN_FREE(iw->value); - iw->value = NULL; + if (iw->uncompressed_value) { + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; } else { if (!iw->addr) { return GRN_INVALID_ARGUMENT; } GRN_IO_SEG_UNREF(iw->io, iw->pseg); - if (!iw->tiny_p) { grn_io_win_unmap2(iw); } + if (!iw->tiny_p) { grn_io_win_unmap(iw); } } return GRN_SUCCESS; } @@ -711,7 +711,7 @@ exit : #define JA_N_GARBAGES_TH 10 -// todo : grn_io_win_map2 cause verbose copy when nseg > 1, it should be copied directly. +// todo : grn_io_win_map cause verbose copy when nseg > 1, it should be copied directly. static grn_rc grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id, uint32_t element_size, grn_ja_einfo *einfo, grn_io_win *iw) @@ -736,7 +736,7 @@ grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id, } else { if (i == j + n) { j++; - addr = grn_io_win_map2(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly); + addr = grn_io_win_map(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly); if (!addr) { grn_io_unlock(ja->io); return GRN_NO_MEMORY_AVAILABLE; @@ -864,7 +864,7 @@ grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id, vp->seg = 0; vp->pos = 0; } - iw->value = NULL; + iw->uncompressed_value = NULL; grn_io_unlock(ja->io); return GRN_SUCCESS; } @@ -883,11 +883,11 @@ set_value(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len, } memcpy(iw.addr, value, value_len); memset((byte *)iw.addr + value_len, 0, sizeof(uint32_t)); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } else { if ((rc = grn_ja_alloc(ctx, ja, id, value_len, einfo, &iw))) { return rc; } memcpy(iw.addr, value, value_len); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } return rc; } @@ -953,7 +953,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, memcpy(iw.addr, oldvalue, old_len); memcpy((byte *)iw.addr + old_len, value, value_len); memset((byte *)iw.addr + old_len + value_len, 0, sizeof(uint32_t)); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } } else { if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) { @@ -962,7 +962,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, } memcpy(iw.addr, oldvalue, old_len); memcpy((byte *)iw.addr + old_len, value, value_len); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } grn_ja_unref(ctx, &jw); } else { @@ -1003,7 +1003,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, memcpy(iw.addr, value, value_len); memcpy((byte *)iw.addr + value_len, oldvalue, old_len); memset((byte *)iw.addr + value_len + old_len, 0, sizeof(uint32_t)); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } } else { if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) { @@ -1012,7 +1012,7 @@ grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, } memcpy(iw.addr, value, value_len); memcpy((byte *)iw.addr + value_len, oldvalue, old_len); - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); } grn_ja_unref(ctx, &jw); } else { @@ -1103,7 +1103,7 @@ grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *vector, int flags) memcpy(iw.addr, GRN_BULK_HEAD(&header), sizeh); if (body) { memcpy((char *)iw.addr + sizeh, GRN_BULK_HEAD(body), sizev); } if (f) { memcpy((char *)iw.addr + sizeh + sizev, GRN_BULK_HEAD(&footer), sizef); } - grn_io_win_unmap2(&iw); + grn_io_win_unmap(&iw); rc = grn_ja_replace(ctx, ja, id, &einfo, NULL); } exit : @@ -1187,7 +1187,7 @@ grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *v void *zvalue; uint32_t zvalue_len; if (!(zvalue = grn_ja_ref_raw(ctx, ja, id, iw, &zvalue_len))) { - iw->value = NULL; + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } @@ -1196,74 +1196,74 @@ grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *v zstream.zalloc = Z_NULL; zstream.zfree = Z_NULL; if (inflateInit2(&zstream, 15 /* windowBits */) != Z_OK) { - iw->value = NULL; + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } - if (!(iw->value = GRN_MALLOC(*((uint64_t *)zvalue)))) { + if (!(iw->uncompressed_value = GRN_MALLOC(*((uint64_t *)zvalue)))) { inflateEnd(&zstream); - iw->value = NULL; + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } - zstream.next_out = (Bytef *)iw->value; + zstream.next_out = (Bytef *)iw->uncompressed_value; zstream.avail_out = *(uint64_t *)zvalue; if (inflate(&zstream, Z_FINISH) != Z_STREAM_END) { inflateEnd(&zstream); - GRN_FREE(iw->value); - iw->value = NULL; + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } *value_len = zstream.total_out; if (inflateEnd(&zstream) != Z_OK) { - GRN_FREE(iw->value); - iw->value = NULL; + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } - return iw->value; + return iw->uncompressed_value; } #endif /* GRN_WITH_ZLIB */ -#ifdef GRN_WITH_LZO -#include <lzo/lzo1x.h> +#ifdef GRN_WITH_LZ4 +#include <lz4.h> static void * -grn_ja_ref_lzo(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) +grn_ja_ref_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) { - void *lvalue; - uint32_t lvalue_len; - lzo_uint lout_len; - if (!(lvalue = grn_ja_ref_raw(ctx, ja, id, iw, &lvalue_len))) { - iw->value = NULL; + void *packed_value; + int packed_value_len; + void *lz4_value; + int lz4_value_len; + int original_value_len; + + if (!(packed_value = grn_ja_ref_raw(ctx, ja, id, iw, &packed_value_len))) { + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } - if (!(iw->value = GRN_MALLOC(*((uint64_t *)lvalue)))) { - iw->value = NULL; + original_value_len = *((uint64_t *)packed_value); + if (!(iw->uncompressed_value = GRN_MALLOC(original_value_len))) { + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } - lout_len = *((uint64_t *)lvalue); - switch (lzo1x_decompress((lzo_bytep)(((uint64_t *)lvalue) + 1), - lvalue_len, - (lzo_bytep)(iw->value), - &lout_len, - NULL)) { - case LZO_E_OK : - case LZO_E_INPUT_NOT_CONSUMED : - break; - default : - GRN_FREE(iw->value); - iw->value = NULL; + lz4_value = (void *)((uint64_t *)packed_value + 1); + lz4_value_len = packed_value_len - sizeof(uint64_t); + if (LZ4_decompress_safe((const char *)(lz4_value), + (char *)(iw->uncompressed_value), + lz4_value_len, + original_value_len) < 0) { + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; *value_len = 0; return NULL; } - *value_len = lout_len; - return iw->value; + *value_len = original_value_len; + return iw->uncompressed_value; } -#endif /* GRN_WITH_LZO */ +#endif /* GRN_WITH_LZ4 */ void * grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) @@ -1273,11 +1273,11 @@ grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_ return grn_ja_ref_zlib(ctx, ja, id, iw, value_len); } #endif /* GRN_WITH_ZLIB */ -#ifdef GRN_WITH_LZO - if (ja->header->flags & GRN_OBJ_COMPRESS_LZO) { - return grn_ja_ref_lzo(ctx, ja, id, iw, value_len); +#ifdef GRN_WITH_LZ4 + if (ja->header->flags & GRN_OBJ_COMPRESS_LZ4) { + return grn_ja_ref_lz4(ctx, ja, id, iw, value_len); } -#endif /* GRN_WITH_LZO */ +#endif /* GRN_WITH_LZ4 */ return grn_ja_ref_raw(ctx, ja, id, iw, value_len); } @@ -1359,34 +1359,48 @@ grn_ja_put_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, } #endif /* GRN_WITH_ZLIB */ -#ifdef GRN_WITH_LZO +#ifdef GRN_WITH_LZ4 inline static grn_rc -grn_ja_put_lzo(grn_ctx *ctx, grn_ja *ja, grn_id id, +grn_ja_put_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len, int flags, uint64_t *cas) { grn_rc rc; - void *lvalue, *lwork; - lzo_uint lvalue_len = value_len + value_len / 16 + 64 + 3; + void *packed_value; + int packed_value_len; + char *lz4_value; + int lz4_value_len; if (value_len == 0) { return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas); } - if (!(lvalue = GRN_MALLOC(lvalue_len + sizeof(uint64_t)))) { return GRN_NO_MEMORY_AVAILABLE; } - if (!(lwork = GRN_MALLOC(LZO1X_1_MEM_COMPRESS))) { GRN_FREE(lvalue); return GRN_NO_MEMORY_AVAILABLE; } - if (lzo1x_1_compress(value, value_len, (lzo_bytep)((uint64_t *)lvalue + 1), &lvalue_len, lwork) != LZO_E_OK) { - GRN_FREE(lwork); - GRN_FREE(lvalue); - ERR(GRN_LZO_ERROR, "lzo1x_1_compress"); + if (value_len > (uint32_t)LZ4_MAX_INPUT_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[ja][lz4] too large value size: <%u>: max: <%d>", + value_len, LZ4_MAX_INPUT_SIZE); + return ctx->rc; + } + + lz4_value_len = LZ4_compressBound(value_len); + + if (!(packed_value = GRN_MALLOC(lz4_value_len + sizeof(uint64_t)))) { + return GRN_NO_MEMORY_AVAILABLE; + } + lz4_value = (char *)((uint64_t *)packed_value + 1); + lz4_value_len = LZ4_compress((const char*)value, lz4_value, value_len); + + if (lz4_value_len <= 0) { + GRN_FREE(packed_value); + ERR(GRN_LZ4_ERROR, "LZ4_compress"); return ctx->rc; } - GRN_FREE(lwork); - *(uint64_t *)lvalue = value_len; - rc = grn_ja_put_raw(ctx, ja, id, lvalue, lvalue_len + sizeof(uint64_t), flags, cas); - GRN_FREE(lvalue); + *(uint64_t *)packed_value = value_len; + packed_value_len = lz4_value_len + sizeof(uint64_t); + rc = grn_ja_put_raw(ctx, ja, id, packed_value, packed_value_len, flags, cas); + GRN_FREE(packed_value); return rc; } -#endif /* GRN_WITH_LZO */ +#endif /* GRN_WITH_LZ4 */ grn_rc grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len, @@ -1397,11 +1411,11 @@ grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len, return grn_ja_put_zlib(ctx, ja, id, value, value_len, flags, cas); } #endif /* GRN_WITH_ZLIB */ -#ifdef GRN_WITH_LZO - if (ja->header->flags & GRN_OBJ_COMPRESS_LZO) { - return grn_ja_put_lzo(ctx, ja, id, value, value_len, flags, cas); +#ifdef GRN_WITH_LZ4 + if (ja->header->flags & GRN_OBJ_COMPRESS_LZ4) { + return grn_ja_put_lz4(ctx, ja, id, value, value_len, flags, cas); } -#endif /* GRN_WITH_LZO */ +#endif /* GRN_WITH_LZ4 */ return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas); } diff --git a/storage/mroonga/vendor/groonga/lib/str.c b/storage/mroonga/vendor/groonga/lib/str.c index 29e532a8021..f91b89c96c0 100644 --- a/storage/mroonga/vendor/groonga/lib/str.c +++ b/storage/mroonga/vendor/groonga/lib/str.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2013 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -14,13 +14,13 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <limits.h> #include <stdio.h> #include <stdarg.h> #include <string.h> -#include "db.h" -#include "str.h" +#include "grn_db.h" +#include "grn_str.h" #ifndef _ISOC99_SOURCE #define _ISOC99_SOURCE @@ -2441,14 +2441,20 @@ grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec) { time_t tsec; struct tm *t; -#ifdef HAVE_GMTIME_R +#ifdef HAVE__GMTIME64_S + struct tm tm; + tsec = (time_t)sec; + t = (gmtime_s(&tm, &tsec) == 0) ? &tm : NULL; +#else /* HAVE__GMTIME64_S */ +# ifdef HAVE_GMTIME_R struct tm tm; tsec = (time_t)sec; t = gmtime_r(&tsec, &tm); -#else /* HAVE_GMTIME_R */ +# else /* HAVE_GMTIME_R */ tsec = (time_t)sec; t = gmtime(&tsec); -#endif /* HAVE_GMTIME_R */ +# endif /* HAVE_GMTIME_R */ +#endif /* HAVE__GMTIME64_S */ if (t) { GRN_TEXT_SET(ctx, bulk, weekdays[t->tm_wday], 3); GRN_TEXT_PUTS(ctx, bulk, ", "); @@ -2576,10 +2582,10 @@ grn_text_atoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, grn_id id) buf.header.domain = GRN_DB_INT32; /* fix me */ break; case GRN_ACCESSOR_GET_SCORE : - grn_obj_get_value(ctx, a->obj, id, &buf); { grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); - GRN_INT32_PUT(ctx, &buf, ri->score); + int32_t int32_score = ri->score; + GRN_INT32_PUT(ctx, &buf, int32_score); } buf.header.domain = GRN_DB_INT32; break; @@ -2941,6 +2947,8 @@ grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, grn_obj_format *format) } } GRN_TEXT_PUTC(ctx, bulk, ']'); + GRN_OBJ_FIN(ctx, &value); + GRN_OBJ_FIN(ctx, &weight); } break; case GRN_PVECTOR : diff --git a/storage/mroonga/vendor/groonga/lib/string.c b/storage/mroonga/vendor/groonga/lib/string.c index f0fcf561b5e..132d51257ac 100644 --- a/storage/mroonga/vendor/groonga/lib/string.c +++ b/storage/mroonga/vendor/groonga/lib/string.c @@ -16,12 +16,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" +#include "grn.h" #include <string.h> -#include "string_in.h" -#include "normalizer_in.h" -#include "str.h" -#include "util.h" +#include "grn_string.h" +#include "grn_normalizer.h" +#include "grn_str.h" +#include "grn_util.h" #include <groonga/tokenizer.h> diff --git a/storage/mroonga/vendor/groonga/lib/token_cursor.c b/storage/mroonga/vendor/groonga/lib/token_cursor.c new file mode 100644 index 00000000000..d3e2e2d8523 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/token_cursor.c @@ -0,0 +1,357 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "grn_token_cursor.h" +#include "grn_string.h" +#include "grn_pat.h" +#include "grn_dat.h" + +static void +grn_token_cursor_open_initialize_token_filters(grn_ctx *ctx, + grn_token_cursor *token_cursor) +{ + grn_obj *token_filters = token_cursor->token_filters; + unsigned int i, n_token_filters; + + if (token_filters) { + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + } else { + n_token_filters = 0; + } + + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); + grn_proc *token_filter = (grn_proc *)token_filter_object; + + token_filter->user_data = + token_filter->callbacks.token_filter.init(ctx, + token_cursor->table, + token_cursor->mode); + } +} + +grn_token_cursor * +grn_token_cursor_open(grn_ctx *ctx, grn_obj *table, + const char *str, size_t str_len, + grn_tokenize_mode mode, unsigned int flags) +{ + grn_token_cursor *token_cursor; + grn_encoding encoding; + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj *token_filters; + grn_obj_flags table_flags; + if (grn_table_get_info(ctx, table, &table_flags, &encoding, &tokenizer, + &normalizer, &token_filters)) { + return NULL; + } + if (!(token_cursor = GRN_MALLOC(sizeof(grn_token_cursor)))) { return NULL; } + token_cursor->table = table; + token_cursor->mode = mode; + token_cursor->encoding = encoding; + token_cursor->tokenizer = tokenizer; + token_cursor->token_filters = token_filters; + token_cursor->orig = (const unsigned char *)str; + token_cursor->orig_blen = str_len; + token_cursor->curr = NULL; + token_cursor->nstr = NULL; + token_cursor->curr_size = 0; + token_cursor->pos = -1; + token_cursor->status = GRN_TOKEN_CURSOR_DOING; + token_cursor->force_prefix = GRN_FALSE; + if (tokenizer) { + grn_obj str_, flags_, mode_; + GRN_TEXT_INIT(&str_, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET_REF(&str_, str, str_len); + GRN_UINT32_INIT(&flags_, 0); + GRN_UINT32_SET(ctx, &flags_, flags); + GRN_UINT32_INIT(&mode_, 0); + GRN_UINT32_SET(ctx, &mode_, mode); + token_cursor->pctx.caller = NULL; + token_cursor->pctx.user_data.ptr = NULL; + token_cursor->pctx.proc = (grn_proc *)tokenizer; + token_cursor->pctx.hooks = NULL; + token_cursor->pctx.currh = NULL; + token_cursor->pctx.phase = PROC_INIT; + grn_ctx_push(ctx, &mode_); + grn_ctx_push(ctx, &str_); + grn_ctx_push(ctx, &flags_); + ((grn_proc *)tokenizer)->funcs[PROC_INIT](ctx, 1, &table, &token_cursor->pctx.user_data); + grn_obj_close(ctx, &flags_); + grn_obj_close(ctx, &str_); + grn_obj_close(ctx, &mode_); + } else { + int nflags = 0; + token_cursor->nstr = grn_string_open_(ctx, str, str_len, + normalizer, + nflags, + token_cursor->encoding); + if (token_cursor->nstr) { + const char *normalized; + grn_string_get_normalized(ctx, token_cursor->nstr, + &normalized, &(token_cursor->curr_size), NULL); + token_cursor->curr = (const unsigned char *)normalized; + } else { + ERR(GRN_TOKENIZER_ERROR, + "[token-cursor][open] failed to grn_string_open()"); + } + } + + grn_token_cursor_open_initialize_token_filters(ctx, token_cursor); + + if (ctx->rc) { + grn_token_cursor_close(ctx, token_cursor); + token_cursor = NULL; + } + return token_cursor; +} + +static int +grn_token_cursor_next_apply_token_filters(grn_ctx *ctx, + grn_token_cursor *token_cursor, + grn_obj *current_token_data, + grn_obj *status) +{ + grn_obj *token_filters = token_cursor->token_filters; + unsigned int i, n_token_filters; + grn_token current_token; + grn_token next_token; + + if (token_filters) { + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + } else { + n_token_filters = 0; + } + + GRN_TEXT_INIT(&(current_token.data), GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &(current_token.data), + GRN_TEXT_VALUE(current_token_data), + GRN_TEXT_LEN(current_token_data)); + current_token.status = GRN_INT32_VALUE(status); + GRN_TEXT_INIT(&(next_token.data), GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &(next_token.data), + GRN_TEXT_VALUE(&(current_token.data)), + GRN_TEXT_LEN(&(current_token.data))); + next_token.status = current_token.status; + + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); + grn_proc *token_filter = (grn_proc *)token_filter_object; + +#define SKIP_FLAGS\ + (GRN_TOKEN_SKIP |\ + GRN_TOKEN_SKIP_WITH_POSITION) + if (current_token.status & SKIP_FLAGS) { + break; + } +#undef SKIP_FLAGS + + token_filter->callbacks.token_filter.filter(ctx, + ¤t_token, + &next_token, + token_filter->user_data); + GRN_TEXT_SET(ctx, &(current_token.data), + GRN_TEXT_VALUE(&(next_token.data)), + GRN_TEXT_LEN(&(next_token.data))); + current_token.status = next_token.status; + } + + token_cursor->curr = + (const unsigned char *)GRN_TEXT_VALUE(&(current_token.data)); + token_cursor->curr_size = GRN_TEXT_LEN(&(current_token.data)); + + return current_token.status; +} + +grn_id +grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor) +{ + int status; + grn_id tid = GRN_ID_NIL; + grn_obj *table = token_cursor->table; + grn_obj *tokenizer = token_cursor->tokenizer; + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE) { + if (tokenizer) { + grn_obj *curr_, *stat_; + ((grn_proc *)tokenizer)->funcs[PROC_NEXT](ctx, 1, &table, &token_cursor->pctx.user_data); + stat_ = grn_ctx_pop(ctx); + curr_ = grn_ctx_pop(ctx); + status = grn_token_cursor_next_apply_token_filters(ctx, token_cursor, + curr_, stat_); + token_cursor->status = + ((status & GRN_TOKEN_LAST) || + (token_cursor->mode == GRN_TOKENIZE_GET && + (status & GRN_TOKEN_REACH_END))) + ? GRN_TOKEN_CURSOR_DONE : GRN_TOKEN_CURSOR_DOING; + token_cursor->force_prefix = GRN_FALSE; +#define SKIP_FLAGS \ + (GRN_TOKEN_SKIP | GRN_TOKEN_SKIP_WITH_POSITION) + if (status & SKIP_FLAGS) { + if (status & GRN_TOKEN_SKIP) { + token_cursor->pos++; + } + if (token_cursor->status == GRN_TOKEN_CURSOR_DONE && tid == GRN_ID_NIL) { + token_cursor->status = GRN_TOKEN_CURSOR_DONE_SKIP; + break; + } else { + continue; + } + } +#undef SKIP_FLAGS + if (status & GRN_TOKEN_FORCE_PREFIX) { + token_cursor->force_prefix = GRN_TRUE; + } + if (token_cursor->curr_size == 0) { + char tokenizer_name[GRN_TABLE_MAX_KEY_SIZE]; + int tokenizer_name_length; + tokenizer_name_length = + grn_obj_name(ctx, token_cursor->tokenizer, + tokenizer_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_WARN, + "[token_next] ignore an empty token: <%.*s>: <%.*s>", + tokenizer_name_length, tokenizer_name, + token_cursor->orig_blen, token_cursor->orig); + continue; + } + if (token_cursor->curr_size > GRN_TABLE_MAX_KEY_SIZE) { + GRN_LOG(ctx, GRN_WARN, + "[token_next] ignore too long token. " + "Token must be less than or equal to %d: <%d>(<%.*s>)", + GRN_TABLE_MAX_KEY_SIZE, + token_cursor->curr_size, + token_cursor->curr_size, token_cursor->curr); + continue; + } + if (status & GRN_TOKEN_UNMATURED) { + if (status & GRN_TOKEN_OVERLAP) { + if (token_cursor->mode == GRN_TOKENIZE_GET) { + token_cursor->pos++; + continue; + } + } else { + if (status & GRN_TOKEN_LAST) { + token_cursor->force_prefix = GRN_TRUE; + } + } + } + } else { + token_cursor->status = GRN_TOKEN_CURSOR_DONE; + } + if (token_cursor->mode == GRN_TOKENIZE_ADD) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + if (grn_io_lock(ctx, ((grn_pat *)table)->io, grn_lock_timeout)) { + tid = GRN_ID_NIL; + } else { + tid = grn_pat_add(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, + NULL, NULL); + grn_io_unlock(((grn_pat *)table)->io); + } + break; + case GRN_TABLE_DAT_KEY : + if (grn_io_lock(ctx, ((grn_dat *)table)->io, grn_lock_timeout)) { + tid = GRN_ID_NIL; + } else { + tid = grn_dat_add(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, + NULL, NULL); + grn_io_unlock(((grn_dat *)table)->io); + } + break; + case GRN_TABLE_HASH_KEY : + if (grn_io_lock(ctx, ((grn_hash *)table)->io, grn_lock_timeout)) { + tid = GRN_ID_NIL; + } else { + tid = grn_hash_add(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, + NULL, NULL); + grn_io_unlock(((grn_hash *)table)->io); + } + break; + case GRN_TABLE_NO_KEY : + if (token_cursor->curr_size == sizeof(grn_id)) { + tid = *((grn_id *)token_cursor->curr); + } else { + tid = GRN_ID_NIL; + } + break; + } + } else { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + tid = grn_pat_get(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, NULL); + break; + case GRN_TABLE_DAT_KEY : + tid = grn_dat_get(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, NULL); + break; + case GRN_TABLE_HASH_KEY : + tid = grn_hash_get(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, NULL); + break; + case GRN_TABLE_NO_KEY : + if (token_cursor->curr_size == sizeof(grn_id)) { + tid = *((grn_id *)token_cursor->curr); + } else { + tid = GRN_ID_NIL; + } + break; + } + } + if (tid == GRN_ID_NIL && token_cursor->status != GRN_TOKEN_CURSOR_DONE) { + token_cursor->status = GRN_TOKEN_CURSOR_NOT_FOUND; + } + token_cursor->pos++; + break; + } + return tid; +} + +static void +grn_token_cursor_close_token_filters(grn_ctx *ctx, + grn_token_cursor *token_cursor) +{ + grn_obj *token_filters = token_cursor->token_filters; + unsigned int i, n_token_filters; + + if (token_filters) { + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + } else { + n_token_filters = 0; + } + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); + grn_proc *token_filter = (grn_proc *)token_filter_object; + + token_filter->callbacks.token_filter.fin(ctx, token_filter->user_data); + } +} + +grn_rc +grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor) +{ + if (token_cursor) { + if (token_cursor->tokenizer) { + ((grn_proc *)token_cursor->tokenizer)->funcs[PROC_FIN](ctx, 1, &token_cursor->table, + &token_cursor->pctx.user_data); + } + grn_token_cursor_close_token_filters(ctx, token_cursor); + if (token_cursor->nstr) { + grn_obj_close(ctx, token_cursor->nstr); + } + GRN_FREE(token_cursor); + return GRN_SUCCESS; + } else { + return GRN_INVALID_ARGUMENT; + } +} diff --git a/storage/mroonga/vendor/groonga/lib/token_filter.c b/storage/mroonga/vendor/groonga/lib/token_filter.c index 910bb9a5715..c57650c2b55 100644 --- a/storage/mroonga/vendor/groonga/lib/token_filter.c +++ b/storage/mroonga/vendor/groonga/lib/token_filter.c @@ -18,8 +18,8 @@ #include <string.h> -#include "groonga_in.h" -#include "db.h" +#include "grn.h" +#include "grn_db.h" #include <groonga/token_filter.h> grn_rc diff --git a/storage/mroonga/vendor/groonga/lib/tokenizer.c b/storage/mroonga/vendor/groonga/lib/tokenizer.c index ac4628ba5de..ef9eb5bf7b5 100644 --- a/storage/mroonga/vendor/groonga/lib/tokenizer.c +++ b/storage/mroonga/vendor/groonga/lib/tokenizer.c @@ -15,18 +15,16 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" -#include "groonga/tokenizer.h" +#include "grn.h" +#include <groonga/tokenizer.h> -#include <stdarg.h> -#include <stdio.h> #include <string.h> -#include "ctx.h" -#include "db.h" -#include "str.h" -#include "string_in.h" -#include "token.h" +#include "grn_ctx.h" +#include "grn_db.h" +#include "grn_str.h" +#include "grn_string.h" +#include "grn_token_cursor.h" /* Just for backward compatibility. See grn_plugin_charlen() instead. @@ -102,7 +100,7 @@ grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args, { grn_obj *flags = grn_ctx_pop(ctx); grn_obj *query_str = grn_ctx_pop(ctx); - grn_obj *token_mode = grn_ctx_pop(ctx); + grn_obj *tokenize_mode = grn_ctx_pop(ctx); if (query_str == NULL) { GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "missing argument"); @@ -127,11 +125,12 @@ grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args, } else { query->flags = 0; } - if (token_mode) { - query->token_mode = GRN_UINT32_VALUE(token_mode); + if (tokenize_mode) { + query->tokenize_mode = GRN_UINT32_VALUE(tokenize_mode); } else { - query->token_mode = GRN_TOKEN_ADD; + query->tokenize_mode = GRN_TOKENIZE_ADD; } + query->token_mode = query->tokenize_mode; { grn_obj * const table = args[0]; @@ -176,7 +175,7 @@ grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args, } query->encoding = table_encoding; - if (query->flags & GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER) { + if (query->flags & GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER) { const char *normalized_string; unsigned int normalized_string_length; @@ -241,7 +240,7 @@ grn_tokenizer_token_fin(grn_ctx *ctx, grn_tokenizer_token *token) void grn_tokenizer_token_push(grn_ctx *ctx, grn_tokenizer_token *token, const char *str_ptr, unsigned int str_length, - grn_tokenizer_status status) + grn_token_status status) { GRN_TEXT_SET_REF(&token->str, str_ptr, str_length); GRN_UINT32_SET(ctx, &token->status, status); @@ -262,7 +261,7 @@ grn_tokenizer_tokenized_delimiter_next(grn_ctx *ctx, const char *end = str_ptr + str_length; const char *next_start = NULL; unsigned int token_length; - grn_tokenizer_status status; + grn_token_status status; for (current = start; current < end; current += char_length) { char_length = grn_charlen_(ctx, current, end, encoding); @@ -349,13 +348,13 @@ exit: GRN_API_RETURN(ctx->rc); } -grn_tokenizer_status +grn_token_status grn_token_get_status(grn_ctx *ctx, grn_token *token) { GRN_API_ENTER; if (!token) { ERR(GRN_INVALID_ARGUMENT, "token must not be NULL"); - GRN_API_RETURN(GRN_TOKENIZER_TOKEN_CONTINUE); + GRN_API_RETURN(GRN_TOKEN_CONTINUE); } GRN_API_RETURN(token->status); } @@ -363,7 +362,7 @@ grn_token_get_status(grn_ctx *ctx, grn_token *token) grn_rc grn_token_set_status(grn_ctx *ctx, grn_token *token, - grn_tokenizer_status status) + grn_token_status status) { GRN_API_ENTER; if (!token) { diff --git a/storage/mroonga/vendor/groonga/lib/token.c b/storage/mroonga/vendor/groonga/lib/tokenizers.c index 00b3de2ebdd..3f6df15a690 100644 --- a/storage/mroonga/vendor/groonga/lib/token.c +++ b/storage/mroonga/vendor/groonga/lib/tokenizers.c @@ -15,19 +15,13 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "groonga_in.h" #include <string.h> -#include <ctype.h> -#include "ctx_impl.h" -#include "token.h" -#include "pat.h" -#include "dat.h" -#include "hash.h" -#include "string_in.h" -#include "plugin_in.h" +#include "grn_token_cursor.h" +#include "grn_string.h" +#include "grn_plugin.h" #include <groonga/tokenizer.h> -grn_obj *grn_token_uvector = NULL; +grn_obj *grn_tokenizer_uvector = NULL; typedef struct { grn_tokenizer_token token; @@ -76,13 +70,13 @@ uvector_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) if (tokenizer->tail < p) { grn_tokenizer_token_push(ctx, &(tokenizer->token), (const char *)tokenizer->curr, 0, - GRN_TOKENIZER_TOKEN_LAST); + GRN_TOKEN_LAST); } else { - grn_tokenizer_status status; + grn_token_status status; if (tokenizer->tail == p) { - status = GRN_TOKENIZER_TOKEN_LAST; + status = GRN_TOKEN_LAST; } else { - status = GRN_TOKENIZER_TOKEN_CONTINUE; + status = GRN_TOKEN_CONTINUE; } grn_tokenizer_token_push(ctx, &(tokenizer->token), (const char *)tokenizer->curr, tokenizer->unit, @@ -177,7 +171,7 @@ delimited_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data size_t cl; const unsigned char *p = tokenizer->next, *r; const unsigned char *e = tokenizer->end; - grn_tokenizer_status status; + grn_token_status status; for (r = p; r < e; r += cl) { if (!(cl = grn_charlen_(ctx, (char *)r, (char *)e, tokenizer->query->encoding))) { @@ -200,9 +194,9 @@ delimited_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data } } if (r == e) { - status = GRN_TOKENIZER_LAST; + status = GRN_TOKEN_LAST; } else { - status = GRN_TOKENIZER_CONTINUE; + status = GRN_TOKEN_CONTINUE; } grn_tokenizer_token_push(ctx, &(tokenizer->token), @@ -356,7 +350,8 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) size_t cl; grn_ngram_tokenizer *tokenizer = user_data->ptr; const unsigned char *p = tokenizer->next, *r = p, *e = tokenizer->end; - int32_t len = 0, pos = tokenizer->pos + tokenizer->skip, status = 0; + int32_t len = 0, pos = tokenizer->pos + tokenizer->skip; + grn_token_status status = 0; const uint_least8_t *cp = tokenizer->ctypes ? tokenizer->ctypes + pos : NULL; if (cp && tokenizer->uni_alpha && GRN_STR_CTYPE(*cp) == GRN_CHAR_ALPHA) { while ((cl = grn_charlen_(ctx, (char *)r, (char *)e, @@ -398,7 +393,7 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) // todo : grn_pat_lcp_search if ((tid = grn_sym_common_prefix_search(sym, p))) { if (!(key = _grn_sym_key(sym, tid))) { - tokenizer->status = GRN_TOKEN_NOT_FOUND; + tokenizer->status = GRN_TOKEN_CURSOR_NOT_FOUND; return NULL; } len = grn_str_len(key, tokenizer->query->encoding, NULL); @@ -408,7 +403,7 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) if (r != p && pos + len - 1 <= tokenizer->tail) { continue; } p += strlen(key); if (!*p && tokenizer->mode == GRN_TOKEN_GET) { - tokenizer->status = GRN_TOKEN_DONE; + tokenizer->status = GRN_TOKEN_CURSOR_DONE; } } #endif /* PRE_DEFINED_UNSPLIT_WORDS */ @@ -433,10 +428,10 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) r += cl; } if (tokenizer->overlap) { - status |= GRN_TOKENIZER_TOKEN_OVERLAP; + status |= GRN_TOKEN_OVERLAP; } if (len < tokenizer->ngram_unit) { - status |= GRN_TOKENIZER_TOKEN_UNMATURED; + status |= GRN_TOKEN_UNMATURED; } tokenizer->overlap = (len > 1) ? 1 : 0; } @@ -446,11 +441,11 @@ ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) tokenizer->tail = pos + len - 1; if (p == r || tokenizer->next == e) { tokenizer->skip = 0; - status |= GRN_TOKENIZER_TOKEN_LAST; + status |= GRN_TOKEN_LAST; } else { tokenizer->skip = tokenizer->overlap ? 1 : len; } - if (r == e) { status |= GRN_TOKENIZER_TOKEN_REACH_END; } + if (r == e) { status |= GRN_TOKEN_REACH_END; } grn_tokenizer_token_push(ctx, &(tokenizer->token), (const char *)p, @@ -475,354 +470,26 @@ ngram_fin(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) /* external */ grn_rc -grn_token_init(void) +grn_tokenizers_init(void) { - static grn_proc _grn_token_uvector; - _grn_token_uvector.obj.db = NULL; - _grn_token_uvector.obj.id = GRN_ID_NIL; - _grn_token_uvector.obj.header.domain = GRN_ID_NIL; - _grn_token_uvector.obj.range = GRN_ID_NIL; - _grn_token_uvector.funcs[PROC_INIT] = uvector_init; - _grn_token_uvector.funcs[PROC_NEXT] = uvector_next; - _grn_token_uvector.funcs[PROC_FIN] = uvector_fin; - grn_token_uvector = (grn_obj *)&_grn_token_uvector; + static grn_proc _grn_tokenizer_uvector; + _grn_tokenizer_uvector.obj.db = NULL; + _grn_tokenizer_uvector.obj.id = GRN_ID_NIL; + _grn_tokenizer_uvector.obj.header.domain = GRN_ID_NIL; + _grn_tokenizer_uvector.obj.range = GRN_ID_NIL; + _grn_tokenizer_uvector.funcs[PROC_INIT] = uvector_init; + _grn_tokenizer_uvector.funcs[PROC_NEXT] = uvector_next; + _grn_tokenizer_uvector.funcs[PROC_FIN] = uvector_fin; + grn_tokenizer_uvector = (grn_obj *)&_grn_tokenizer_uvector; return GRN_SUCCESS; } grn_rc -grn_token_fin(void) +grn_tokenizers_fin(void) { return GRN_SUCCESS; } -static void -grn_token_cursor_open_initialize_token_filters(grn_ctx *ctx, - grn_token_cursor *token_cursor) -{ - grn_obj *token_filters = token_cursor->token_filters; - unsigned int i, n_token_filters; - - if (token_filters) { - n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); - } else { - n_token_filters = 0; - } - - for (i = 0; i < n_token_filters; i++) { - grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); - grn_proc *token_filter = (grn_proc *)token_filter_object; - - token_filter->user_data = - token_filter->callbacks.token_filter.init(ctx, - token_cursor->table, - token_cursor->mode); - } -} - -grn_token_cursor * -grn_token_cursor_open(grn_ctx *ctx, grn_obj *table, - const char *str, size_t str_len, - grn_token_mode mode, unsigned int flags) -{ - grn_token_cursor *token_cursor; - grn_encoding encoding; - grn_obj *tokenizer; - grn_obj *normalizer; - grn_obj *token_filters; - grn_obj_flags table_flags; - if (grn_table_get_info(ctx, table, &table_flags, &encoding, &tokenizer, - &normalizer, &token_filters)) { - return NULL; - } - if (!(token_cursor = GRN_MALLOC(sizeof(grn_token_cursor)))) { return NULL; } - token_cursor->table = table; - token_cursor->mode = mode; - token_cursor->encoding = encoding; - token_cursor->tokenizer = tokenizer; - token_cursor->token_filters = token_filters; - token_cursor->orig = (const unsigned char *)str; - token_cursor->orig_blen = str_len; - token_cursor->curr = NULL; - token_cursor->nstr = NULL; - token_cursor->curr_size = 0; - token_cursor->pos = -1; - token_cursor->status = GRN_TOKEN_DOING; - token_cursor->force_prefix = 0; - if (tokenizer) { - grn_obj str_, flags_, mode_; - GRN_TEXT_INIT(&str_, GRN_OBJ_DO_SHALLOW_COPY); - GRN_TEXT_SET_REF(&str_, str, str_len); - GRN_UINT32_INIT(&flags_, 0); - GRN_UINT32_SET(ctx, &flags_, flags); - GRN_UINT32_INIT(&mode_, 0); - GRN_UINT32_SET(ctx, &mode_, mode); - token_cursor->pctx.caller = NULL; - token_cursor->pctx.user_data.ptr = NULL; - token_cursor->pctx.proc = (grn_proc *)tokenizer; - token_cursor->pctx.hooks = NULL; - token_cursor->pctx.currh = NULL; - token_cursor->pctx.phase = PROC_INIT; - grn_ctx_push(ctx, &mode_); - grn_ctx_push(ctx, &str_); - grn_ctx_push(ctx, &flags_); - ((grn_proc *)tokenizer)->funcs[PROC_INIT](ctx, 1, &table, &token_cursor->pctx.user_data); - grn_obj_close(ctx, &flags_); - grn_obj_close(ctx, &str_); - grn_obj_close(ctx, &mode_); - } else { - int nflags = 0; - token_cursor->nstr = grn_string_open_(ctx, str, str_len, - normalizer, - nflags, - token_cursor->encoding); - if (token_cursor->nstr) { - const char *normalized; - grn_string_get_normalized(ctx, token_cursor->nstr, - &normalized, &(token_cursor->curr_size), NULL); - token_cursor->curr = (const unsigned char *)normalized; - } else { - ERR(GRN_TOKENIZER_ERROR, - "[token-cursor][open] failed to grn_string_open()"); - } - } - - grn_token_cursor_open_initialize_token_filters(ctx, token_cursor); - - if (ctx->rc) { - grn_token_cursor_close(ctx, token_cursor); - token_cursor = NULL; - } - return token_cursor; -} - -static int -grn_token_cursor_next_apply_token_filters(grn_ctx *ctx, - grn_token_cursor *token_cursor, - grn_obj *current_token_data, - grn_obj *status) -{ - grn_obj *token_filters = token_cursor->token_filters; - unsigned int i, n_token_filters; - grn_token current_token; - grn_token next_token; - - if (token_filters) { - n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); - } else { - n_token_filters = 0; - } - - GRN_TEXT_INIT(&(current_token.data), GRN_OBJ_DO_SHALLOW_COPY); - GRN_TEXT_SET(ctx, &(current_token.data), - GRN_TEXT_VALUE(current_token_data), - GRN_TEXT_LEN(current_token_data)); - current_token.status = GRN_INT32_VALUE(status); - GRN_TEXT_INIT(&(next_token.data), GRN_OBJ_DO_SHALLOW_COPY); - GRN_TEXT_SET(ctx, &(next_token.data), - GRN_TEXT_VALUE(&(current_token.data)), - GRN_TEXT_LEN(&(current_token.data))); - next_token.status = current_token.status; - - for (i = 0; i < n_token_filters; i++) { - grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); - grn_proc *token_filter = (grn_proc *)token_filter_object; - -#define SKIP_FLAGS\ - (GRN_TOKENIZER_TOKEN_SKIP |\ - GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION) - if (current_token.status & SKIP_FLAGS) { - break; - } -#undef SKIP_FLAGS - - token_filter->callbacks.token_filter.filter(ctx, - ¤t_token, - &next_token, - token_filter->user_data); - GRN_TEXT_SET(ctx, &(current_token.data), - GRN_TEXT_VALUE(&(next_token.data)), - GRN_TEXT_LEN(&(next_token.data))); - current_token.status = next_token.status; - } - - token_cursor->curr = - (const unsigned char *)GRN_TEXT_VALUE(&(current_token.data)); - token_cursor->curr_size = GRN_TEXT_LEN(&(current_token.data)); - - return current_token.status; -} - -grn_id -grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor) -{ - int status; - grn_id tid = GRN_ID_NIL; - grn_obj *table = token_cursor->table; - grn_obj *tokenizer = token_cursor->tokenizer; - while (token_cursor->status != GRN_TOKEN_DONE) { - if (tokenizer) { - grn_obj *curr_, *stat_; - ((grn_proc *)tokenizer)->funcs[PROC_NEXT](ctx, 1, &table, &token_cursor->pctx.user_data); - stat_ = grn_ctx_pop(ctx); - curr_ = grn_ctx_pop(ctx); - status = grn_token_cursor_next_apply_token_filters(ctx, token_cursor, - curr_, stat_); - token_cursor->status = - ((status & GRN_TOKENIZER_TOKEN_LAST) || - (token_cursor->mode == GRN_TOKEN_GET && - (status & GRN_TOKENIZER_TOKEN_REACH_END))) - ? GRN_TOKEN_DONE : GRN_TOKEN_DOING; - token_cursor->force_prefix = 0; -#define SKIP_FLAGS \ - (GRN_TOKENIZER_TOKEN_SKIP | GRN_TOKENIZER_TOKEN_SKIP_WITH_POSITION) - if (status & SKIP_FLAGS) { - if (status & GRN_TOKENIZER_TOKEN_SKIP) { - token_cursor->pos++; - } - if (token_cursor->status == GRN_TOKEN_DONE && tid == GRN_ID_NIL) { - token_cursor->status = GRN_TOKEN_DONE_SKIP; - break; - } else { - continue; - } - } -#undef SKIP_FLAGS - if (token_cursor->curr_size == 0) { - char tokenizer_name[GRN_TABLE_MAX_KEY_SIZE]; - int tokenizer_name_length; - tokenizer_name_length = - grn_obj_name(ctx, token_cursor->tokenizer, - tokenizer_name, GRN_TABLE_MAX_KEY_SIZE); - GRN_LOG(ctx, GRN_WARN, - "[token_next] ignore an empty token: <%.*s>: <%.*s>", - tokenizer_name_length, tokenizer_name, - token_cursor->orig_blen, token_cursor->orig); - continue; - } - if (token_cursor->curr_size > GRN_TABLE_MAX_KEY_SIZE) { - GRN_LOG(ctx, GRN_WARN, - "[token_next] ignore too long token. " - "Token must be less than or equal to %d: <%d>(<%.*s>)", - GRN_TABLE_MAX_KEY_SIZE, - token_cursor->curr_size, - token_cursor->curr_size, token_cursor->curr); - continue; - } - if (status & GRN_TOKENIZER_TOKEN_UNMATURED) { - if (status & GRN_TOKENIZER_TOKEN_OVERLAP) { - if (token_cursor->mode == GRN_TOKEN_GET) { token_cursor->pos++; continue; } - } else { - if (status & GRN_TOKENIZER_TOKEN_LAST) { token_cursor->force_prefix = 1; } - } - } - } else { - token_cursor->status = GRN_TOKEN_DONE; - } - if (token_cursor->mode == GRN_TOKEN_ADD) { - switch (table->header.type) { - case GRN_TABLE_PAT_KEY : - if (grn_io_lock(ctx, ((grn_pat *)table)->io, grn_lock_timeout)) { - tid = GRN_ID_NIL; - } else { - tid = grn_pat_add(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, - NULL, NULL); - grn_io_unlock(((grn_pat *)table)->io); - } - break; - case GRN_TABLE_DAT_KEY : - if (grn_io_lock(ctx, ((grn_dat *)table)->io, grn_lock_timeout)) { - tid = GRN_ID_NIL; - } else { - tid = grn_dat_add(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, - NULL, NULL); - grn_io_unlock(((grn_dat *)table)->io); - } - break; - case GRN_TABLE_HASH_KEY : - if (grn_io_lock(ctx, ((grn_hash *)table)->io, grn_lock_timeout)) { - tid = GRN_ID_NIL; - } else { - tid = grn_hash_add(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, - NULL, NULL); - grn_io_unlock(((grn_hash *)table)->io); - } - break; - case GRN_TABLE_NO_KEY : - if (token_cursor->curr_size == sizeof(grn_id)) { - tid = *((grn_id *)token_cursor->curr); - } else { - tid = GRN_ID_NIL; - } - break; - } - } else { - switch (table->header.type) { - case GRN_TABLE_PAT_KEY : - tid = grn_pat_get(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, NULL); - break; - case GRN_TABLE_DAT_KEY : - tid = grn_dat_get(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, NULL); - break; - case GRN_TABLE_HASH_KEY : - tid = grn_hash_get(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, NULL); - break; - case GRN_TABLE_NO_KEY : - if (token_cursor->curr_size == sizeof(grn_id)) { - tid = *((grn_id *)token_cursor->curr); - } else { - tid = GRN_ID_NIL; - } - break; - } - } - if (tid == GRN_ID_NIL && token_cursor->status != GRN_TOKEN_DONE) { - token_cursor->status = GRN_TOKEN_NOT_FOUND; - } - token_cursor->pos++; - break; - } - return tid; -} - -static void -grn_token_cursor_close_token_filters(grn_ctx *ctx, - grn_token_cursor *token_cursor) -{ - grn_obj *token_filters = token_cursor->token_filters; - unsigned int i, n_token_filters; - - if (token_filters) { - n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); - } else { - n_token_filters = 0; - } - for (i = 0; i < n_token_filters; i++) { - grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); - grn_proc *token_filter = (grn_proc *)token_filter_object; - - token_filter->callbacks.token_filter.fin(ctx, token_filter->user_data); - } -} - -grn_rc -grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor) -{ - if (token_cursor) { - if (token_cursor->tokenizer) { - ((grn_proc *)token_cursor->tokenizer)->funcs[PROC_FIN](ctx, 1, &token_cursor->table, - &token_cursor->pctx.user_data); - } - grn_token_cursor_close_token_filters(ctx, token_cursor); - if (token_cursor->nstr) { - grn_obj_close(ctx, token_cursor->nstr); - } - GRN_FREE(token_cursor); - return GRN_SUCCESS; - } else { - return GRN_INVALID_ARGUMENT; - } -} - grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx) { diff --git a/storage/mroonga/vendor/groonga/lib/util.c b/storage/mroonga/vendor/groonga/lib/util.c index 67f0ff32125..dd703b53928 100644 --- a/storage/mroonga/vendor/groonga/lib/util.c +++ b/storage/mroonga/vendor/groonga/lib/util.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2010-2014 Brazil +/* Copyright(C) 2010-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,11 +15,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "db.h" -#include "pat.h" -#include "ii.h" -#include "util.h" -#include "string_in.h" +#include "grn_db.h" +#include "grn_pat.h" +#include "grn_ii.h" +#include "grn_util.h" +#include "grn_string.h" #include <string.h> #include <stdio.h> @@ -254,6 +254,9 @@ grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) case GRN_PROC_TOKEN_FILTER : GRN_TEXT_PUTS(ctx, buf, "token-filter"); break; + case GRN_PROC_SCORER : + GRN_TEXT_PUTS(ctx, buf, "scorer"); + break; } GRN_TEXT_PUTS(ctx, buf, " "); @@ -275,6 +278,90 @@ grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) return GRN_SUCCESS; } +grn_rc +grn_expr_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + + GRN_TEXT_PUTS(ctx, buffer, "#<expr\n"); + { + int i = 0; + grn_obj *value; + const char *name; + uint32_t name_len; + unsigned int n_vars; + grn_hash *vars = grn_expr_get_vars(ctx, expr, &n_vars); + GRN_TEXT_PUTS(ctx, buffer, " vars:{"); + GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, { + if (i++) { + GRN_TEXT_PUTC(ctx, buffer, ','); + } + GRN_TEXT_PUTS(ctx, buffer, "\n "); + GRN_TEXT_PUT(ctx, buffer, name, name_len); + GRN_TEXT_PUTC(ctx, buffer, ':'); + grn_inspect_indented(ctx, buffer, value, " "); + }); + GRN_TEXT_PUTS(ctx, buffer, "\n },"); + } + + { + uint32_t i, j; + grn_expr_var *var; + grn_expr_code *code; + GRN_TEXT_PUTS(ctx, buffer, "\n codes:{"); + for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) { + if (j) { GRN_TEXT_PUTC(ctx, buffer, ','); } + GRN_TEXT_PUTS(ctx, buffer, "\n "); + grn_text_itoa(ctx, buffer, j); + GRN_TEXT_PUTS(ctx, buffer, ":<"); + GRN_TEXT_PUTS(ctx, buffer, grn_operator_to_string(code->op)); + GRN_TEXT_PUTS(ctx, buffer, "("); + for (i = 0, var = e->vars; i < e->nvars; i++, var++) { + if (i) { GRN_TEXT_PUTC(ctx, buffer, ','); } + GRN_TEXT_PUTC(ctx, buffer, '?'); + if (var->name_size) { + GRN_TEXT_PUT(ctx, buffer, var->name, var->name_size); + } else { + grn_text_itoa(ctx, buffer, (int)i); + } + } + GRN_TEXT_PUTS(ctx, buffer, "), "); + GRN_TEXT_PUTS(ctx, buffer, "modify:"); + grn_text_itoa(ctx, buffer, code->modify); + GRN_TEXT_PUTS(ctx, buffer, ", "); + GRN_TEXT_PUTS(ctx, buffer, "value:"); + grn_inspect_indented(ctx, buffer, code->value, " "); + GRN_TEXT_PUTS(ctx, buffer, ">"); + } + GRN_TEXT_PUTS(ctx, buffer, "\n }"); + } + + GRN_TEXT_PUTS(ctx, buffer, "\n>"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_pvector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *pvector) +{ + int i, n; + + GRN_TEXT_PUTS(ctx, buffer, "["); + n = GRN_BULK_VSIZE(pvector) / sizeof(grn_obj *); + for (i = 0; i < n; i++) { + grn_obj *element = GRN_PTR_VALUE_AT(pvector, i); + + if (i > 0) { + GRN_TEXT_PUTS(ctx, buffer, ", "); + } + + grn_inspect(ctx, buffer, element); + } + GRN_TEXT_PUTS(ctx, buffer, "]"); + + return GRN_SUCCESS; +} + static grn_rc grn_vector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *vector) { @@ -400,8 +487,8 @@ grn_store_inspect_body(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) case GRN_OBJ_COMPRESS_ZLIB : GRN_TEXT_PUTS(ctx, buf, "zlib"); break; - case GRN_OBJ_COMPRESS_LZO : - GRN_TEXT_PUTS(ctx, buf, "lzo"); + case GRN_OBJ_COMPRESS_LZ4 : + GRN_TEXT_PUTS(ctx, buf, "lz4"); break; default: break; @@ -481,9 +568,6 @@ grn_ii_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) GRN_TEXT_PUTS(ctx, buf, "NONE"); } - GRN_TEXT_PUTS(ctx, buf, " elements:"); - grn_ii_inspect_elements(ctx, (grn_ii *)obj, buf); - GRN_TEXT_PUTS(ctx, buf, ">"); return GRN_SUCCESS; @@ -499,6 +583,9 @@ grn_table_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) case GRN_TABLE_PAT_KEY: GRN_TEXT_PUTS(ctx, buf, "pat"); break; + case GRN_TABLE_DAT_KEY: + GRN_TEXT_PUTS(ctx, buf, "dat"); + break; case GRN_TABLE_NO_KEY: GRN_TEXT_PUTS(ctx, buf, "no_key"); break; @@ -742,6 +829,24 @@ grn_table_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) } static grn_rc +grn_db_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_db *db = (grn_db *)obj; + + GRN_TEXT_PUTS(ctx, buf, "#<db"); + + GRN_TEXT_PUTS(ctx, buf, " key_type:"); + grn_table_type_inspect(ctx, buf, db->keys); + + GRN_TEXT_PUTS(ctx, buf, " size:"); + grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj)); + + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +static grn_rc grn_geo_point_inspect_point(grn_ctx *ctx, grn_obj *buf, int point) { GRN_TEXT_PUTS(ctx, buf, "("); @@ -850,7 +955,6 @@ grn_json_load_open_brace_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) static grn_rc grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) { - grn_id id; grn_obj *table; grn_hash *cols; @@ -867,6 +971,11 @@ grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) } GRN_TEXT_PUTS(ctx, buf, " id:"); + if (GRN_BULK_VSIZE(obj) == 0) { + GRN_TEXT_PUTS(ctx, buf, "(no value)"); + } else { + grn_id id; + id = GRN_RECORD_VALUE(obj); grn_text_lltoa(ctx, buf, id); @@ -903,6 +1012,8 @@ grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) } else { GRN_TEXT_PUTS(ctx, buf, "(nonexistent)"); } + } + GRN_TEXT_PUTS(ctx, buf, ">"); if (table) { @@ -1008,8 +1119,8 @@ grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) } break; case GRN_PVECTOR : - /* TODO */ - break; + grn_pvector_inspect(ctx, buffer, obj); + return buffer; case GRN_VECTOR : grn_vector_inspect(ctx, buffer, obj); return buffer; @@ -1054,7 +1165,7 @@ grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) grn_table_inspect(ctx, buffer, obj); return buffer; case GRN_DB : - /* TODO */ + grn_db_inspect(ctx, buffer, obj); break; case GRN_COLUMN_FIX_SIZE : grn_ra_inspect(ctx, buffer, obj); @@ -1073,6 +1184,45 @@ grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) return buffer; } +grn_obj * +grn_inspect_indented(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj, + const char *indent) +{ + grn_obj sub_buffer; + + GRN_TEXT_INIT(&sub_buffer, 0); + grn_inspect(ctx, &sub_buffer, obj); + { + const char *inspected = GRN_TEXT_VALUE(&sub_buffer); + size_t inspected_size = GRN_TEXT_LEN(&sub_buffer); + size_t i, line_start; + + if (!buffer) { + buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT); + } + + line_start = 0; + for (i = 0; i < inspected_size; i++) { + if (inspected[i] == '\n') { + if (line_start != 0) { + GRN_TEXT_PUTS(ctx, buffer, indent); + } + GRN_TEXT_PUT(ctx, buffer, inspected + line_start, i + 1 - line_start); + line_start = i + 1; + } + } + if (line_start != 0) { + GRN_TEXT_PUTS(ctx, buffer, indent); + } + GRN_TEXT_PUT(ctx, buffer, + inspected + line_start, + inspected_size - line_start); + } + GRN_OBJ_FIN(ctx, &sub_buffer); + + return buffer; +} + void grn_p(grn_ctx *ctx, grn_obj *obj) { @@ -1095,6 +1245,17 @@ grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point) grn_obj_unlink(ctx, &obj); } +void +grn_p_ii_values(grn_ctx *ctx, grn_obj *ii) +{ + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + grn_ii_inspect_values(ctx, (grn_ii *)ii, &buffer); + printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + grn_obj_unlink(ctx, &buffer); +} + #ifdef WIN32 static char *win32_base_dir = NULL; const char * diff --git a/storage/mroonga/vendor/groonga/nginx_version b/storage/mroonga/vendor/groonga/nginx_version index de28578affc..f65dc1e213e 100644 --- a/storage/mroonga/vendor/groonga/nginx_version +++ b/storage/mroonga/vendor/groonga/nginx_version @@ -1 +1 @@ -1.7.6 +1.7.9 diff --git a/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt index 42a3045a415..89a28f50b99 100644 --- a/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright(C) 2012-2014 Brazil +# Copyright(C) 2012-2015 Brazil # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -19,3 +19,10 @@ add_subdirectory(table) add_subdirectory(query_expanders) add_subdirectory(ruby) add_subdirectory(token_filters) +add_subdirectory(sharding) + +if(GRN_WITH_MRUBY) + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/ruby_scripts.am RUBY_SCRIPTS) + install(FILES ${RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}") +endif() diff --git a/storage/mroonga/vendor/groonga/plugins/Makefile.am b/storage/mroonga/vendor/groonga/plugins/Makefile.am index 1d1abf1dee9..92007edd732 100644 --- a/storage/mroonga/vendor/groonga/plugins/Makefile.am +++ b/storage/mroonga/vendor/groonga/plugins/Makefile.am @@ -4,7 +4,15 @@ SUBDIRS = \ table \ query_expanders \ ruby \ - token_filters + token_filters \ + sharding EXTRA_DIST = \ CMakeLists.txt + +if WITH_MRUBY +dist_plugins_DATA = \ + $(ruby_scripts) +endif + +include ruby_scripts.am diff --git a/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt index 1e2a2c23b09..57d11abfbcb 100644 --- a/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/query_expanders/CMakeLists.txt @@ -27,6 +27,4 @@ set_target_properties(tsv_query_expander PROPERTIES PREFIX "" OUTPUT_NAME "tsv") target_link_libraries(tsv_query_expander libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS tsv_query_expander DESTINATION "${QUERY_EXPANDERS_DIR}") -endif() +install(TARGETS tsv_query_expander DESTINATION "${QUERY_EXPANDERS_DIR}") diff --git a/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c b/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c index 6b1fc51d6dc..1b9f177711a 100644 --- a/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c +++ b/storage/mroonga/vendor/groonga/plugins/query_expanders/tsv.c @@ -15,17 +15,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <groonga/plugin.h> - /* groonga's internal headers */ /* for grn_text_fgets(): We don't want to require stdio.h for groonga.h. What should we do? Should we split header file such as groonga/stdio.h? */ -#include <str.h> +#include <grn_str.h> + +#include <groonga/plugin.h> #include <stdio.h> #include <string.h> #ifdef HAVE__STRNICMP +# ifdef strncasecmp +# undef strncasecmp +# endif /* strncasecmp */ # define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n) #endif /* HAVE__STRNICMP */ @@ -42,7 +45,6 @@ get_system_synonyms_file(void) const char *base_dir; const char *relative_path = GRN_QUERY_EXPANDER_TSV_RELATIVE_SYNONYMS_FILE; char *synonyms_file; - char *path; size_t base_dir_length; base_dir = grn_plugin_win32_base_dir(); diff --git a/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt index d82b154098c..ba7deafe0d3 100644 --- a/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/ruby/CMakeLists.txt @@ -27,9 +27,7 @@ if(GRN_WITH_MRUBY) COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") set_target_properties(eval PROPERTIES PREFIX "") target_link_libraries(eval libgroonga) - if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS eval DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}") - endif() + install(TARGETS eval DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}") read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/load_sources.am RUBY_LOAD_SOURCES) add_library(load MODULE ${RUBY_LOAD_SOURCES}) @@ -38,7 +36,5 @@ if(GRN_WITH_MRUBY) COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") set_target_properties(load PROPERTIES PREFIX "") target_link_libraries(load libgroonga) - if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS load DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}") - endif() + install(TARGETS load DESTINATION "${GRN_RELATIVE_RUBY_PLUGINS_DIR}") endif() diff --git a/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h b/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h index 5314ea68fe5..57cab2885b1 100644 --- a/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h +++ b/storage/mroonga/vendor/groonga/plugins/ruby/ruby_plugin.h @@ -16,11 +16,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <mrb.h> -#include <output.h> -#include <db.h> -#include <ctx_impl.h> -#include <util.h> +#include <grn_mrb.h> +#include <grn_output.h> +#include <grn_db.h> +#include <grn_ctx_impl.h> +#include <grn_util.h> #include <groonga/plugin.h> diff --git a/storage/mroonga/vendor/groonga/plugins/ruby_scripts.am b/storage/mroonga/vendor/groonga/plugins/ruby_scripts.am new file mode 100644 index 00000000000..0262dbb94ef --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/ruby_scripts.am @@ -0,0 +1,2 @@ +ruby_scripts = \ + sharding.rb diff --git a/storage/mroonga/vendor/groonga/plugins/sharding.rb b/storage/mroonga/vendor/groonga/plugins/sharding.rb new file mode 100644 index 00000000000..8902d7e6c27 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding.rb @@ -0,0 +1,3 @@ +require "sharding/logical_enumerator" +require "sharding/logical_count" +require "sharding/logical_range_filter" diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt new file mode 100644 index 00000000000..8d0cdd976dc --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright(C) 2015 Brazil +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. +# +# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +if(GRN_WITH_MRUBY) + set(GRN_RELATIVE_SHARDING_PLUGINS_DIR "${GRN_RELATIVE_PLUGINS_DIR}/sharding") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/sources.am SHARDING_SCRIPTS) + install(FILES ${SHARDING_SCRIPTS} + DESTINATION "${GRN_RELATIVE_SHARDING_PLUGINS_DIR}") +endif() diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am b/storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am new file mode 100644 index 00000000000..8104ab6d729 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding/Makefile.am @@ -0,0 +1,9 @@ +EXTRA_DIST = \ + CMakeLists.txt + +if WITH_MRUBY +dist_sharding_plugins_DATA = \ + $(sharding_scripts) +endif + +include sources.am diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb b/storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb new file mode 100644 index 00000000000..ef993b40dc8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding/logical_count.rb @@ -0,0 +1,160 @@ +module Groonga + module Sharding + class LogicalCountCommand < Command + register("logical_count", + [ + "logical_table", + "shard_key", + "min", + "min_border", + "max", + "max_border", + "filter", + ]) + + def run_body(input) + enumerator = LogicalEnumerator.new("logical_count", input) + filter = input[:filter] + + total = 0 + enumerator.each do |table, shard_key, shard_range| + total += count_n_records(table, filter, + shard_key, shard_range, + enumerator.target_range) + end + writer.write(total) + end + + private + def count_n_records(table, filter, + shard_key, shard_range, + target_range) + cover_type = target_range.cover_type(shard_range) + return 0 if cover_type == :none + + if cover_type == :all + if filter.nil? + return table.size + else + return filtered_count_n_records(table, filter) + end + end + + use_range_index = false + range_index = nil + if filter.nil? + index_info = shard_key.find_index(Operator::LESS) + if index_info + range_index = index_info.index + use_range_index = true + end + end + + case cover_type + when :partial_min + if use_range_index + count_n_records_in_range(range_index, + target_range.min, target_range.min_border, + nil, nil) + else + filtered_count_n_records(table, filter) do |expression| + expression.append_object(shard_key, Operator::PUSH, 1) + expression.append_operator(Operator::GET_VALUE, 1) + expression.append_constant(target_range.min, Operator::PUSH, 1) + if target_range.min_border == :include + expression.append_operator(Operator::GREATER_EQUAL, 2) + else + expression.append_operator(Operator::GREATER, 2) + end + end + end + when :partial_max + if use_range_index + count_n_records_in_range(range_index, + nil, nil, + target_range.max, target_range.max_border) + else + filtered_count_n_records(table, filter) do |expression| + expression.append_object(shard_key, Operator::PUSH, 1) + expression.append_operator(Operator::GET_VALUE, 1) + expression.append_constant(target_range.max, Operator::PUSH, 1) + if target_range.max_border == :include + expression.append_operator(Operator::LESS_EQUAL, 2) + else + expression.append_operator(Operator::LESS, 2) + end + end + end + when :partial_min_and_max + if use_range_index + count_n_records_in_range(range_index, + target_range.min, target_range.min_border, + target_range.max, target_range.max_border) + else + filtered_count_n_records(table, filter) do |expression| + expression.append_object(context["between"], Operator::PUSH, 1) + expression.append_object(shard_key, Operator::PUSH, 1) + expression.append_operator(Operator::GET_VALUE, 1) + expression.append_constant(target_range.min, Operator::PUSH, 1) + expression.append_constant(target_range.min_border, + Operator::PUSH, 1) + expression.append_constant(target_range.max, Operator::PUSH, 1) + expression.append_constant(target_range.max_border, + Operator::PUSH, 1) + expression.append_operator(Operator::CALL, 5) + end + end + end + end + + def filtered_count_n_records(table, filter) + expression = nil + filtered_table = nil + + begin + expression = Expression.create(table) + if block_given? + yield(expression) + if filter + expression.parse(filter) + expression.append_operator(Operator::AND, 2) + end + else + expression.parse(filter) + end + filtered_table = table.select(expression) + filtered_table.size + ensure + filtered_table.close if filtered_table + expression.close if expression + end + end + + def count_n_records_in_range(range_index, + min, min_border, max, max_border) + flags = TableCursorFlags::BY_KEY + case min_border + when :include + flags |= TableCursorFlags::GE + when :exclude + flags |= TableCursorFlags::GT + end + case max_border + when :include + flags |= TableCursorFlags::LE + when :exclude + flags |= TableCursorFlags::LT + end + + TableCursor.open(range_index.table, + :min => min, + :max => max, + :flags => flags) do |table_cursor| + IndexCursor.open(table_cursor, range_index) do |index_cursor| + index_cursor.count + end + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb b/storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb new file mode 100644 index 00000000000..7ad5393ae77 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding/logical_enumerator.rb @@ -0,0 +1,170 @@ +module Groonga + module Sharding + class LogicalEnumerator + attr_reader :target_range + attr_reader :shard_key_name + def initialize(command_name, input) + @command_name = command_name + @input = input + initialize_parameters + end + + def each + prefix = "#{@logical_table}_" + context = Context.instance + context.database.each_table(:prefix => prefix, + :order_by => :key, + :order => :ascending) do |table| + shard_range_raw = table.name[prefix.size..-1] + + next unless /\A(\d{4})(\d{2})(\d{2})\z/ =~ shard_range_raw + shard_range = ShardRange.new($1.to_i, $2.to_i, $3.to_i) + + physical_shard_key_name = "#{table.name}.#{@shard_key_name}" + shard_key = context[physical_shard_key_name] + if shard_key.nil? + message = + "[#{@command_name}] shard_key doesn't exist: " + + "<#{physical_shard_key_name}>" + raise InvalidArgument, message + end + + yield(table, shard_key, shard_range) + end + end + + private + def initialize_parameters + @logical_table = @input[:logical_table] + if @logical_table.nil? + raise InvalidArgument, "[#{@command_name}] logical_table is missing" + end + + @shard_key_name = @input[:shard_key] + if @shard_key_name.nil? + raise InvalidArgument, "[#{@command_name}] shard_key is missing" + end + + @target_range = TargetRange.new(@command_name, @input) + end + + class ShardRange + attr_reader :year, :month, :day + def initialize(year, month, day) + @year = year + @month = month + @day = day + end + end + + class TargetRange + attr_reader :min, :min_border + attr_reader :max, :max_border + def initialize(command_name, input) + @command_name = command_name + @input = input + @min = parse_value(:min) + @min_border = parse_border(:min_border) + @max = parse_value(:max) + @max_border = parse_border(:max_border) + end + + def cover_type(shard_range) + return :all if @min.nil? and @max.nil? + + if @min and @max + return :none unless in_min?(shard_range) + return :none unless in_max?(shard_range) + min_partial_p = in_min_partial?(shard_range) + max_partial_p = in_max_partial?(shard_range) + if min_partial_p and max_partial_p + :partial_min_and_max + elsif min_partial_p + :partial_min + elsif max_partial_p + :partial_max + else + :all + end + elsif @min + return :none unless in_min?(shard_range) + if in_min_partial?(shard_range) + :partial_min + else + :all + end + else + return :none unless in_max?(shard_range) + if in_max_partial?(shard_range) + :partial_max + else + :all + end + end + end + + private + def parse_value(name) + value = @input[name] + return nil if value.nil? + + Converter.convert(value, Time) + end + + def parse_border(name) + border = @input[name] + return :include if border.nil? + + case border + when "include" + :include + when "exclude" + :exclude + else + message = + "[#{@command_name}] #{name} must be \"include\" or \"exclude\": " + + "<#{border}>" + raise InvalidArgument, message + end + end + + def in_min?(shard_range) + base_time = Time.local(shard_range.year, + shard_range.month, + shard_range.day + 1) + @min < base_time + end + + def in_min_partial?(shard_range) + return false unless @min.year == shard_range.year + return false unless @min.month == shard_range.month + return false unless @min.day == shard_range.day + + return true if @min_border == :exclude + + @min.hour != 0 and + @min.min != 0 and + @min.sec != 0 and + @min.usec != 0 + end + + def in_max?(shard_range) + max_base_time = Time.local(shard_range.year, + shard_range.month, + shard_range.day) + if @max_border == :include + @max >= max_base_time + else + @max > max_base_time + end + end + + def in_max_partial?(shard_range) + @max.year == shard_range.year and + @max.month == shard_range.month and + @max.day == shard_range.day + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb b/storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb new file mode 100644 index 00000000000..7e765f7d3c2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding/logical_range_filter.rb @@ -0,0 +1,186 @@ +module Groonga + module Sharding + class LogicalRangeFilterCommand < Command + register("logical_range_filter", + [ + "logical_table", + "shard_key", + "min", + "min_border", + "max", + "max_border", + "order", + "filter", + "offset", + "limit", + "output_columns", + ]) + + def run_body(input) + enumerator = LogicalEnumerator.new("logical_range_filter", input) + filter = input[:filter] + offset = (input[:offset] || 0).to_i + limit = (input[:limit] || 10).to_i + output_columns = input[:output_columns] || "_key, *" + + result_sets = [] + n_records = 0 + enumerator.each do |table, shard_key, shard_range| + result_set = filter_shard(table, filter, + shard_key, shard_range, + enumerator.target_range) + next if result_set.nil? + if result_set.empty? + result_set.close if result_set.temporary? + next + end + result_sets << result_set + n_records += result_set.size + break if n_records >= offset + limit + end + + if result_sets.empty? + n_elements = 0 + else + n_elements = 1 # for columns + result_sets.each do |result_set| + n_elements += result_set.size + end + end + + sort_keys = [ + { + :key => enumerator.shard_key_name, + :order => :ascending, + }, + ] + current_offset = offset + current_limit = limit + writer.array("RESULTSET", n_elements) do + first_result_set = result_sets.first + if first_result_set + writer.write_table_columns(first_result_set, output_columns) + end + result_sets.each do |result_set| + if result_set.size <= current_offset + current_offset -= result_set.size + next + end + sorted_result_set = result_set.sort(sort_keys, + :offset => current_offset, + :limit => current_limit) + writer.write_table_records(sorted_result_set, output_columns) + current_limit -= sorted_result_set.size + sorted_result_set.close + end + end + + result_sets.each do |result_set| + result_set.close if result_set.temporary? + end + end + + def filter_shard(table, filter, shard_key, shard_range, target_range) + cover_type = target_range.cover_type(shard_range) + return nil if cover_type == :none + + if cover_type == :all + if filter.nil? + return table + else + return filter_table(table, filter) + end + end + + use_range_index = false + range_index = nil + # TODO + # if filter.nil? + # index_info = shard_key.find_index(Operator::LESS) + # if index_info + # range_index = index_info.index + # use_range_index = true + # end + # end + + case cover_type + when :partial_min + if use_range_index + # TODO + # count_n_records_in_range(range_index, + # target_range.min, target_range.min_border, + # nil, nil) + else + filter_table(table, filter) do |expression| + expression.append_object(shard_key, Operator::PUSH, 1) + expression.append_operator(Operator::GET_VALUE, 1) + expression.append_constant(target_range.min, Operator::PUSH, 1) + if target_range.min_border == :include + expression.append_operator(Operator::GREATER_EQUAL, 2) + else + expression.append_operator(Operator::GREATER, 2) + end + end + end + when :partial_max + if use_range_index + # TODO + # count_n_records_in_range(range_index, + # nil, nil, + # target_range.max, target_range.max_border) + else + filter_table(table, filter) do |expression| + expression.append_object(shard_key, Operator::PUSH, 1) + expression.append_operator(Operator::GET_VALUE, 1) + expression.append_constant(target_range.max, Operator::PUSH, 1) + if target_range.max_border == :include + expression.append_operator(Operator::LESS_EQUAL, 2) + else + expression.append_operator(Operator::LESS, 2) + end + end + end + when :partial_min_and_max + if use_range_index + # TODO + # count_n_records_in_range(range_index, + # target_range.min, target_range.min_border, + # target_range.max, target_range.max_border) + else + filter_table(table, filter) do |expression| + expression.append_object(context["between"], Operator::PUSH, 1) + expression.append_object(shard_key, Operator::PUSH, 1) + expression.append_operator(Operator::GET_VALUE, 1) + expression.append_constant(target_range.min, Operator::PUSH, 1) + expression.append_constant(target_range.min_border, + Operator::PUSH, 1) + expression.append_constant(target_range.max, Operator::PUSH, 1) + expression.append_constant(target_range.max_border, + Operator::PUSH, 1) + expression.append_operator(Operator::CALL, 5) + end + end + end + end + + def filter_table(table, filter) + expression = nil + begin + expression = Expression.create(table) + if block_given? + yield(expression) + if filter + expression.parse(filter) + expression.append_operator(Operator::AND, 2) + end + else + expression.parse(filter) + end + table.select(expression) + ensure + expression.close if expression + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/plugins/sharding/sources.am b/storage/mroonga/vendor/groonga/plugins/sharding/sources.am new file mode 100644 index 00000000000..11b5382a6df --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/sharding/sources.am @@ -0,0 +1,4 @@ +sharding_scripts = \ + logical_count.rb \ + logical_enumerator.rb \ + logical_range_filter.rb diff --git a/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt index 72b86362c55..519193918b4 100644 --- a/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/suggest/CMakeLists.txt @@ -24,6 +24,4 @@ set_source_files_properties(${SUGGEST_SOURCES} COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") set_target_properties(suggest PROPERTIES PREFIX "") target_link_libraries(suggest libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS suggest DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/suggest") -endif() +install(TARGETS suggest DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/suggest") diff --git a/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c b/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c index 3e291b96d90..863ffcf13e3 100644 --- a/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c +++ b/storage/mroonga/vendor/groonga/plugins/suggest/suggest.c @@ -15,15 +15,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "ctx.h" -#include "db.h" -#include "ii.h" -#include "token.h" -#include "output.h" -#include <groonga/plugin.h> #include <string.h> +#include "grn_ctx.h" +#include "grn_db.h" +#include "grn_ii.h" +#include "grn_token_cursor.h" +#include "grn_output.h" +#include <groonga/plugin.h> + #ifdef HAVE__STRNICMP +# ifdef strncasecmp +# undef strncasecmp +# endif /* strcasecmp */ # define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n) #endif /* HAVE__STRNICMP */ @@ -130,12 +134,12 @@ grn_parse_suggest_types(grn_obj *text) return types; } -static int32_t +static double cooccurrence_search(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_id id, grn_obj *res, int query_type, int frequency_threshold, double conditional_probability_threshold) { - int32_t max_score = 0; + double max_score = 0.0; if (id) { grn_ii_cursor *c; grn_obj *co = grn_obj_column(ctx, items, CONST_STR_LEN("co")); @@ -194,7 +198,7 @@ cooccurrence_search(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_id i boost >= 0) { grn_rset_recinfo *ri; void *value; - int32_t score = pfreq; + double score = pfreq; int added; if (max_score < score + boost) { max_score = score + boost; } /* put any formula if desired */ @@ -275,7 +279,7 @@ complete_add_item(grn_ctx *ctx, grn_id id, grn_obj *res, int frequency_threshold grn_obj_get_value(ctx, items_freq, id, item_freq); grn_obj_get_value(ctx, items_boost, id, item_boost); if (GRN_INT32_VALUE(item_boost) >= 0) { - int32_t score; + double score; score = 1 + GRN_INT32_VALUE(item_freq) + GRN_INT32_VALUE(item_boost); @@ -380,12 +384,12 @@ correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, if ((res = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, items, NULL))) { grn_id tid = grn_table_get(ctx, items, TEXT_VALUE_LEN(query)); - int32_t max_score; + double max_score; max_score = cooccurrence_search(ctx, items, items_boost, tid, res, CORRECT, frequency_threshold, conditional_probability_threshold); GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SCORE, - ":", "cooccur(%d)", max_score); + ":", "cooccur(%f)", max_score); if (GRN_TEXT_LEN(query) && ((similar_search_mode == GRN_SUGGEST_SEARCH_YES) || (similar_search_mode == GRN_SUGGEST_SEARCH_AUTO && @@ -419,7 +423,7 @@ correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_obj_get_value(ctx, items_freq2, *rp, &item_freq2); grn_obj_get_value(ctx, items_boost, *rp, &item_boost); if (GRN_INT32_VALUE(&item_boost) >= 0) { - int32_t score; + double score; grn_rset_recinfo *ri; score = 1 + (GRN_INT32_VALUE(&item_freq2) >> 4) + @@ -467,13 +471,13 @@ correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, if ((tc = grn_table_cursor_open(ctx, res, NULL, 0, NULL, 0, 0, -1, 0))) { grn_id id; grn_obj score_value; - GRN_INT32_INIT(&score_value, 0); + GRN_FLOAT_INIT(&score_value, 0); while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { GRN_RECORD_SET(ctx, var, id); grn_expr_exec(ctx, expr, 0); GRN_BULK_REWIND(&score_value); grn_obj_get_value(ctx, score, id, &score_value); - if (GRN_INT32_VALUE(&score_value) < frequency_threshold) { + if (GRN_FLOAT_VALUE(&score_value) < frequency_threshold) { grn_table_cursor_delete(ctx, tc); } } @@ -573,7 +577,18 @@ command_suggest(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat if ((items = grn_ctx_get(ctx, TEXT_VALUE_LEN(VAR(1))))) { if ((items_boost = grn_obj_column(ctx, items, CONST_STR_LEN("boost")))) { - GRN_OUTPUT_MAP_OPEN("RESULT_SET", -1); + int n_outputs = 0; + if (types & COMPLETE) { + n_outputs++; + } + if (types & CORRECT) { + n_outputs++; + } + if (types & SUGGEST) { + n_outputs++; + } + GRN_OUTPUT_MAP_OPEN("RESULT_SET", n_outputs); + if (types & COMPLETE) { if ((col = grn_obj_column(ctx, items, TEXT_VALUE_LEN(VAR(2))))) { GRN_OUTPUT_CSTR("complete"); diff --git a/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt index cba4697f042..eada0395080 100644 --- a/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/table/CMakeLists.txt @@ -24,6 +24,4 @@ set_source_files_properties(${TABLE_SOURCES} COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") set_target_properties(table PROPERTIES PREFIX "") target_link_libraries(table libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS table DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/table") -endif() +install(TARGETS table DESTINATION "${GRN_RELATIVE_PLUGINS_DIR}/table") diff --git a/storage/mroonga/vendor/groonga/plugins/table/table.c b/storage/mroonga/vendor/groonga/plugins/table/table.c index a4fcd17bf90..3b0c09d9a91 100644 --- a/storage/mroonga/vendor/groonga/plugins/table/table.c +++ b/storage/mroonga/vendor/groonga/plugins/table/table.c @@ -17,10 +17,10 @@ #include <string.h> -#include "ctx.h" -#include "db.h" -#include "output.h" -#include "util.h" +#include "grn_ctx.h" +#include "grn_db.h" +#include "grn_output.h" +#include "grn_util.h" #include <groonga/plugin.h> #define VAR GRN_PROC_GET_VAR_BY_OFFSET diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt index 9ffe53d2e8d..a0b964fb659 100644 --- a/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/token_filters/CMakeLists.txt @@ -29,6 +29,19 @@ set_target_properties(stop_word_token_filter PROPERTIES PREFIX "" OUTPUT_NAME "stop_word") target_link_libraries(stop_word_token_filter libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS stop_word_token_filter DESTINATION "${TOKEN_FILTERS_DIR}") +install(TARGETS stop_word_token_filter DESTINATION "${TOKEN_FILTERS_DIR}") + +if(GRN_WITH_LIBSTEMMER) + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/stem_sources.am STEM_SOURCES) + include_directories(${LIBSTEMMER_INCLUDE_DIRS}) + link_directories(${LIBSTEMMER_LIBRARY_DIRS}) + add_library(stem_token_filter MODULE ${STEM_SOURCES}) + set_source_files_properties(${STEM_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") + set_target_properties(stem_token_filter PROPERTIES + PREFIX "" + OUTPUT_NAME "stem") + target_link_libraries(stem_token_filter libgroonga ${LIBSTEMMER_LIBRARIES}) + install(TARGETS stem_token_filter DESTINATION "${TOKEN_FILTERS_DIR}") endif() diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am b/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am index 8d77466f053..c63bef7ac56 100644 --- a/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am +++ b/storage/mroonga/vendor/groonga/plugins/token_filters/Makefile.am @@ -16,5 +16,13 @@ LIBS = \ token_filter_plugins_LTLIBRARIES = token_filter_plugins_LTLIBRARIES += stop_word.la +if WITH_LIBSTEMMER +token_filter_plugins_LTLIBRARIES += stem.la +endif include stop_word_sources.am + +include stem_sources.am +stem_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBSTEMMER_CFLAGS) +stem_la_LIBADD = $(LIBS) $(LIBSTEMMER_LIBS) +stem_la_LDFLAGS = $(AM_LDFLAGS) $(LIBSTEMMER_LDFLAGS) diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/stem.c b/storage/mroonga/vendor/groonga/plugins/token_filters/stem.c new file mode 100644 index 00000000000..010b8c91867 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/token_filters/stem.c @@ -0,0 +1,275 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <grn_str.h> + +#include <groonga.h> +#include <groonga/token_filter.h> + +#include <ctype.h> +#include <string.h> + +#include <libstemmer.h> + +typedef struct { + struct sb_stemmer *stemmer; + grn_tokenizer_token token; + grn_obj buffer; +} grn_stem_token_filter; + +static void * +stem_init(grn_ctx *ctx, grn_obj *table, grn_token_mode mode) +{ + grn_stem_token_filter *token_filter; + + token_filter = GRN_PLUGIN_MALLOC(ctx, sizeof(grn_stem_token_filter)); + if (!token_filter) { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "[token-filter][stem] " + "failed to allocate grn_stem_token_filter"); + return NULL; + } + + { + /* TODO: Support other languages. */ + const char *algorithm = "english"; + const char *encoding = "UTF_8"; + token_filter->stemmer = sb_stemmer_new(algorithm, encoding); + if (!token_filter->stemmer) { + GRN_PLUGIN_FREE(ctx, token_filter); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[token-filter][stem] " + "failed to create stemmer: " + "algorithm=<%s>, encoding=<%s>", + algorithm, encoding); + return NULL; + } + } + grn_tokenizer_token_init(ctx, &(token_filter->token)); + GRN_TEXT_INIT(&(token_filter->buffer), 0); + + return token_filter; +} + +static grn_bool +is_stemmable(grn_obj *data, grn_bool *is_all_upper) +{ + const char *current, *end; + grn_bool have_lower = GRN_FALSE; + grn_bool have_upper = GRN_FALSE; + + *is_all_upper = GRN_FALSE; + + switch (data->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + break; + default : + return GRN_FALSE; + } + + current = GRN_TEXT_VALUE(data); + end = current + GRN_TEXT_LEN(data); + + for (; current < end; current++) { + if (islower(*current)) { + have_lower = GRN_TRUE; + continue; + } + if (isupper(*current)) { + have_upper = GRN_TRUE; + continue; + } + if (isdigit(*current)) { + continue; + } + switch (*current) { + case '-' : + case '\'' : + break; + default : + return GRN_FALSE; + } + } + + if (!have_lower && have_upper) { + *is_all_upper = GRN_TRUE; + } + + return GRN_TRUE; +} + +static void +normalize(grn_ctx *ctx, + const char *string, unsigned int length, + grn_obj *normalized) +{ + const char *current, *end; + const char *unwritten; + + current = unwritten = string; + end = current + length; + + for (; current < end; current++) { + if (isupper(*current)) { + if (current > unwritten) { + GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten); + } + GRN_TEXT_PUTC(ctx, normalized, tolower(*current)); + unwritten = current + 1; + } + } + + if (current != unwritten) { + GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten); + } +} + +static void +unnormalize(grn_ctx *ctx, + const char *string, unsigned int length, + grn_obj *normalized) +{ + const char *current, *end; + const char *unwritten; + + current = unwritten = string; + end = current + length; + + for (; current < end; current++) { + if (islower(*current)) { + if (current > unwritten) { + GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten); + } + GRN_TEXT_PUTC(ctx, normalized, toupper(*current)); + unwritten = current + 1; + } + } + + if (current != unwritten) { + GRN_TEXT_PUT(ctx, normalized, unwritten, current - unwritten); + } +} + +static void +stem_filter(grn_ctx *ctx, + grn_token *current_token, + grn_token *next_token, + void *user_data) +{ + grn_stem_token_filter *token_filter = user_data; + grn_obj *data; + grn_bool is_all_upper = GRN_FALSE; + + if (GRN_CTX_GET_ENCODING(ctx) != GRN_ENC_UTF8) { + return; + } + + data = grn_token_get_data(ctx, current_token); + if (!is_stemmable(data, &is_all_upper)) { + return; + } + + { + const sb_symbol *stemmed; + + if (is_all_upper) { + grn_obj *buffer; + buffer = &(token_filter->buffer); + GRN_BULK_REWIND(buffer); + normalize(ctx, + GRN_TEXT_VALUE(data), + GRN_TEXT_LEN(data), + buffer); + stemmed = sb_stemmer_stem(token_filter->stemmer, + GRN_TEXT_VALUE(buffer), GRN_TEXT_LEN(buffer)); + if (stemmed) { + GRN_BULK_REWIND(buffer); + unnormalize(ctx, + stemmed, + sb_stemmer_length(token_filter->stemmer), + buffer); + grn_token_set_data(ctx, next_token, + GRN_TEXT_VALUE(buffer), GRN_TEXT_LEN(buffer)); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "[token-filter][stem] " + "failed to allocate memory for stemmed word: <%.*s> " + "(normalized: <%.*s>)", + (int)GRN_TEXT_LEN(data), GRN_TEXT_VALUE(data), + (int)GRN_TEXT_LEN(buffer), GRN_TEXT_VALUE(buffer)); + } + } else { + stemmed = sb_stemmer_stem(token_filter->stemmer, + GRN_TEXT_VALUE(data), GRN_TEXT_LEN(data)); + if (stemmed) { + grn_token_set_data(ctx, next_token, + stemmed, + sb_stemmer_length(token_filter->stemmer)); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "[token-filter][stem] " + "failed to allocate memory for stemmed word: <%.*s>", + (int)GRN_TEXT_LEN(data), GRN_TEXT_VALUE(data)); + } + } + } +} + +static void +stem_fin(grn_ctx *ctx, void *user_data) +{ + grn_stem_token_filter *token_filter = user_data; + if (!token_filter) { + return; + } + + grn_tokenizer_token_fin(ctx, &(token_filter->token)); + if (token_filter->stemmer) { + sb_stemmer_delete(token_filter->stemmer); + } + GRN_OBJ_FIN(ctx, &(token_filter->buffer)); + GRN_PLUGIN_FREE(ctx, token_filter); +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_rc rc; + + rc = grn_token_filter_register(ctx, + "TokenFilterStem", -1, + stem_init, + stem_filter, + stem_fin); + + return rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am b/storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am new file mode 100644 index 00000000000..d02a39526e2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/token_filters/stem_sources.am @@ -0,0 +1,2 @@ +stem_la_SOURCES = \ + stem.c diff --git a/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c b/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c index 21451f00b25..9b8cc68200a 100644 --- a/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c +++ b/storage/mroonga/vendor/groonga/plugins/token_filters/stop_word.c @@ -16,7 +16,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <str.h> +#include <grn_str.h> #include <groonga.h> #include <groonga/token_filter.h> @@ -102,7 +102,7 @@ stop_word_filter(grn_ctx *ctx, if (GRN_BOOL_VALUE(&(token_filter->value))) { grn_tokenizer_status status; status = grn_token_get_status(ctx, current_token); - status |= GRN_TOKENIZER_TOKEN_SKIP; + status |= GRN_TOKEN_SKIP; grn_token_set_status(ctx, next_token, status); } } diff --git a/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt index e044c1fbb93..5871e982211 100644 --- a/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/plugins/tokenizers/CMakeLists.txt @@ -30,9 +30,7 @@ if(GRN_WITH_MECAB) PREFIX "" OUTPUT_NAME "mecab") target_link_libraries(mecab_tokenizer libgroonga ${MECAB_LIBRARIES}) - if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS mecab_tokenizer DESTINATION "${TOKENIZERS_DIR}") - endif() + install(TARGETS mecab_tokenizer DESTINATION "${TOKENIZERS_DIR}") endif() if(GRN_WITH_KYTEA) @@ -47,7 +45,5 @@ if(GRN_WITH_KYTEA) PREFIX "" OUTPUT_NAME "kytea") target_link_libraries(kytea_tokenizer libgroonga ${KYTEA_LIBRARIES}) - if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS kytea_tokenizer DESTINATION "${TOKENIZERS_DIR}") - endif() + install(TARGETS kytea_tokenizer DESTINATION "${TOKENIZERS_DIR}") endif() diff --git a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c index 4ac99f9a9e8..49e4b5c877e 100644 --- a/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c +++ b/storage/mroonga/vendor/groonga/plugins/tokenizers/mecab.c @@ -1,5 +1,5 @@ /* -*- c-basic-offset: 2 -*- */ -/* Copyright(C) 2009-2012 Brazil +/* Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,13 +15,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <str.h> +#include <grn_str.h> #include <groonga.h> #include <groonga/tokenizer.h> #include <mecab.h> +#include <stdlib.h> #include <string.h> #include <ctype.h> @@ -38,6 +39,21 @@ typedef struct { grn_tokenizer_token token; } grn_mecab_tokenizer; +static const char * +mecab_global_error_message(void) +{ + double version; + + version = atof(mecab_version()); + /* MeCab <= 0.993 doesn't support mecab_strerror(NULL). */ + if (version <= 0.993) { + return "Unknown"; + } + + return mecab_strerror(NULL); +} + + static grn_encoding translate_mecab_charset_to_grn_encoding(const char *charset) { @@ -96,7 +112,7 @@ mecab_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR, "[tokenizer][mecab] " "mecab_new2() failed on mecab_init(): %s", - mecab_strerror(NULL)); + mecab_global_error_message()); } else { sole_mecab_encoding = get_mecab_encoding(sole_mecab); } @@ -273,7 +289,7 @@ check_mecab_dictionary_encoding(grn_ctx *ctx) GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR, "[tokenizer][mecab] " "mecab_new2 failed in check_mecab_dictionary_encoding: %s", - mecab_strerror(NULL)); + mecab_global_error_message()); } #endif } diff --git a/storage/mroonga/vendor/groonga/src/CMakeLists.txt b/storage/mroonga/vendor/groonga/src/CMakeLists.txt index 4d02109dae5..258d1866c2b 100644 --- a/storage/mroonga/vendor/groonga/src/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/src/CMakeLists.txt @@ -25,9 +25,7 @@ set_source_files_properties(${GROONGA_SOURCES} PROPERTIES COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") target_link_libraries(groonga libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS groonga DESTINATION ${BIN_DIR}) -endif() +install(TARGETS groonga DESTINATION ${BIN_DIR}) if(NOT WIN32) read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/grnslap_sources.am GRNSLAP_SOURCES) @@ -36,9 +34,7 @@ if(NOT WIN32) PROPERTIES COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") target_link_libraries(grnslap libgroonga) - if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS grnslap DESTINATION ${BIN_DIR}) - endif() + install(TARGETS grnslap DESTINATION ${BIN_DIR}) endif() read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/groonga_benchmark_sources.am @@ -48,7 +44,5 @@ set_source_files_properties(${GROONGA_BENCHMARK_SOURCES} PROPERTIES COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") target_link_libraries(groonga-benchmark libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install(TARGETS groonga-benchmark DESTINATION ${BIN_DIR}) -endif() +install(TARGETS groonga-benchmark DESTINATION ${BIN_DIR}) diff --git a/storage/mroonga/vendor/groonga/src/Makefile.am b/storage/mroonga/vendor/groonga/src/Makefile.am index b125db54c3d..a4d57e85c44 100644 --- a/storage/mroonga/vendor/groonga/src/Makefile.am +++ b/storage/mroonga/vendor/groonga/src/Makefile.am @@ -6,6 +6,10 @@ NONEXISTENT_CXX_SOURCE = nonexistent.cpp bin_PROGRAMS = groonga groonga-benchmark noinst_PROGRAMS = grnslap +if WITH_MRUBY +bin_PROGRAMS += grndb +noinst_PROGRAMS += groonga-mruby +endif EXTRA_DIST = \ CMakeLists.txt @@ -22,9 +26,8 @@ AM_LDFLAGS = -no-undefined DEFAULT_INCLUDES = \ -I$(top_builddir) \ - -I$(srcdir) \ - -I$(top_srcdir) \ -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ $(GROONGA_INCLUDEDIR) include groonga_sources.am @@ -46,3 +49,15 @@ nodist_EXTRA_groonga_benchmark_SOURCES = $(NONEXISTENT_CXX_SOURCE) groonga_benchmark_LDADD = \ $(top_builddir)/lib/libgroonga.la \ $(MESSAGE_PACK_LIBS) + +include grndb_sources.am +nodist_EXTRA_grndb_SOURCES = $(NONEXISTENT_CXX_SOURCE) +grndb_LDADD = \ + $(top_builddir)/lib/libgroonga.la \ + $(MESSAGE_PACK_LIBS) + +include groonga_mruby_sources.am +nodist_EXTRA_groonga_mruby_SOURCES = $(NONEXISTENT_CXX_SOURCE) +groonga_mruby_LDADD = \ + $(top_builddir)/lib/libgroonga.la \ + $(MESSAGE_PACK_LIBS) diff --git a/storage/mroonga/vendor/groonga/src/grndb.c b/storage/mroonga/vendor/groonga/src/grndb.c new file mode 100644 index 00000000000..d493338f57e --- /dev/null +++ b/storage/mroonga/vendor/groonga/src/grndb.c @@ -0,0 +1,137 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef WIN32 +# define GROONGA_MAIN +#endif /* WIN32 */ + +#include <grn_mrb.h> +#include <grn_ctx_impl.h> + +#include <mruby/variable.h> +#include <mruby/array.h> + +static int +run_command(grn_ctx *ctx, int argc, char **argv) +{ + int exit_code = EXIT_SUCCESS; + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + mrb_value mrb_command_line_module; + mrb_value mrb_grndb_class; + + mrb_command_line_module = mrb_const_get(mrb, + mrb_obj_value(data->module), + mrb_intern_cstr(mrb, "CommandLine")); + if (mrb->exc) { + goto exit; + } + + mrb_grndb_class = mrb_const_get(mrb, + mrb_command_line_module, + mrb_intern_cstr(mrb, "Grndb")); + if (mrb->exc) { + goto exit; + } + + { + int i; + mrb_value mrb_argv; + mrb_value mrb_grndb; + mrb_value mrb_result; + + mrb_argv = mrb_ary_new_capa(mrb, argc); + for (i = 0; i < argc; i++) { + mrb_ary_push(mrb, mrb_argv, mrb_str_new_cstr(mrb, argv[i])); + } + mrb_grndb = mrb_funcall(mrb, mrb_grndb_class, "new", 1, mrb_argv); + if (mrb->exc) { + goto exit; + } + + mrb_result = mrb_funcall(mrb, mrb_grndb, "run", 0); + if (mrb->exc) { + goto exit; + } + + if (!mrb_bool(mrb_result)) { + exit_code = EXIT_FAILURE; + } + } + +exit : + if (mrb->exc) { + mrb_print_error(mrb); + exit_code = EXIT_FAILURE; + } + + return exit_code; +} + +static int +run(grn_ctx *ctx, int argc, char **argv) +{ + int exit_code = EXIT_SUCCESS; + const char *grndb_rb = "command_line/grndb.rb"; + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + + mrb_gv_set(mrb, mrb_intern_lit(mrb, "$0"), mrb_str_new_cstr(mrb, argv[0])); + + grn_mrb_load(ctx, grndb_rb); + if (ctx->rc != GRN_SUCCESS) { + fprintf(stderr, "Failed to load Ruby script: <%s>: %s", + grndb_rb, ctx->errbuf); + goto exit; + } + + { + int arena_index; + + arena_index = mrb_gc_arena_save(mrb); + exit_code = run_command(ctx, argc, argv); + mrb_gc_arena_restore(mrb, arena_index); + } + +exit : + if (ctx->rc != GRN_SUCCESS) { + exit_code = EXIT_FAILURE; + } + return exit_code; +} + +int +main(int argc, char **argv) +{ + int exit_code = EXIT_SUCCESS; + + if (grn_init() != GRN_SUCCESS) { + return EXIT_FAILURE; + } + + { + grn_ctx ctx; + grn_ctx_init(&ctx, 0); + exit_code = run(&ctx, argc, argv); + grn_ctx_fin(&ctx); + } + + grn_fin(); + + return exit_code; +} diff --git a/storage/mroonga/vendor/groonga/src/grndb_sources.am b/storage/mroonga/vendor/groonga/src/grndb_sources.am new file mode 100644 index 00000000000..ce2e2bb3466 --- /dev/null +++ b/storage/mroonga/vendor/groonga/src/grndb_sources.am @@ -0,0 +1,2 @@ +grndb_SOURCES = \ + grndb.c diff --git a/storage/mroonga/vendor/groonga/src/grnslap.c b/storage/mroonga/vendor/groonga/src/grnslap.c index 5400fbb23e0..be2f181f3e7 100644 --- a/storage/mroonga/vendor/groonga/src/grnslap.c +++ b/storage/mroonga/vendor/groonga/src/grnslap.c @@ -16,8 +16,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "lib/com.h" -#include "lib/ctx_impl.h" +#include <grn_com.h> +#include <grn_ctx_impl.h> #include <string.h> #include <stdio.h> #ifdef HAVE_SYS_WAIT_H @@ -196,7 +196,7 @@ msg_handler(grn_ctx *ctx, grn_obj *msg) grn_msg_close(ctx, msg); } -static void * CALLBACK +static grn_thread_func_result CALLBACK receiver(void *arg) { grn_ctx ctx_, *ctx = &ctx_; @@ -213,7 +213,7 @@ receiver(void *arg) */ } grn_ctx_fin(ctx); - return NULL; + return GRN_THREAD_FUNC_RETURN_VALUE; } static int diff --git a/storage/mroonga/vendor/groonga/src/groonga.c b/storage/mroonga/vendor/groonga/src/groonga.c index 9d1009d72da..b03e70e0258 100644 --- a/storage/mroonga/vendor/groonga/src/groonga.c +++ b/storage/mroonga/vendor/groonga/src/groonga.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2009-2014 Brazil + Copyright(C) 2009-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,20 +16,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifdef WIN32 -# define GROONGA_MAIN -#endif /* WIN32 */ -#include "lib/groonga_in.h" - -#include "lib/com.h" -#include "lib/ctx_impl.h" -#include "lib/proc.h" -#include "lib/db.h" -#include "lib/util.h" #include <string.h> #include <stdio.h> #include <ctype.h> #include <fcntl.h> + +#ifdef WIN32 +# define GROONGA_MAIN +#endif /* WIN32 */ +#include <grn.h> + +#include <grn_com.h> +#include <grn_ctx_impl.h> +#include <grn_proc.h> +#include <grn_db.h> +#include <grn_util.h> + #ifdef HAVE_SYS_WAIT_H # include <sys/wait.h> #endif /* HAVE_SYS_WAIT_H */ @@ -48,7 +50,14 @@ # include <sys/sysctl.h> #endif /* HAVE_SYS_SYSCTL_H */ +#ifdef HAVE_IO_H +# include <io.h> +#endif /* HAVE_IO_H */ + #ifdef HAVE__STRNICMP +# ifdef strncasecmp +# undef strncasecmp +# endif /* strcasecmp */ # define strncasecmp(s1,s2,n) _strnicmp(s1,s2,n) #endif /* HAVE__STRNICMP */ @@ -210,6 +219,7 @@ read_next_line(grn_ctx *ctx, grn_obj *buf) rc = line_editor_fgets(ctx, buf); #else fprintf(stderr, "> "); + fflush(stderr); rc = grn_text_fgets(ctx, buf, stdin); #endif } else { @@ -271,31 +281,73 @@ output_envelope(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj * } static void -s_output(grn_ctx *ctx, int flags, void *arg) +s_output_raw(grn_ctx *ctx, int flags, FILE *stream) +{ + char *chunk = NULL; + unsigned int chunk_size = 0; + int recv_flags; + + grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags); + if (chunk_size > 0) { + fwrite(chunk, 1, chunk_size, stream); + } + + if (flags & GRN_CTX_TAIL) { + grn_obj *command; + + fflush(stream); + + command = GRN_CTX_USER_DATA(ctx)->ptr; + GRN_BULK_REWIND(command); + } +} + +static void +s_output_typed(grn_ctx *ctx, int flags, FILE *stream) { if (ctx && ctx->impl && (flags & GRN_CTX_TAIL)) { - grn_obj *buf = ctx->impl->outbuf; + char *chunk = NULL; + unsigned int chunk_size = 0; + int recv_flags; + grn_obj body; grn_obj *command; - if (GRN_TEXT_LEN(buf) || ctx->rc) { - FILE * stream = (FILE *) arg; + + GRN_TEXT_INIT(&body, 0); + grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags); + GRN_TEXT_SET(ctx, &body, chunk, chunk_size); + + if (GRN_TEXT_LEN(&body) || ctx->rc) { grn_obj head, foot; GRN_TEXT_INIT(&head, 0); GRN_TEXT_INIT(&foot, 0); - output_envelope(ctx, ctx->rc, &head, buf, &foot); + output_envelope(ctx, ctx->rc, &head, &body, &foot); fwrite(GRN_TEXT_VALUE(&head), 1, GRN_TEXT_LEN(&head), stream); - fwrite(GRN_TEXT_VALUE(buf), 1, GRN_TEXT_LEN(buf), stream); + fwrite(GRN_TEXT_VALUE(&body), 1, GRN_TEXT_LEN(&body), stream); fwrite(GRN_TEXT_VALUE(&foot), 1, GRN_TEXT_LEN(&foot), stream); fputc('\n', stream); fflush(stream); - GRN_BULK_REWIND(buf); GRN_OBJ_FIN(ctx, &head); GRN_OBJ_FIN(ctx, &foot); } + GRN_OBJ_FIN(ctx, &body); + command = GRN_CTX_USER_DATA(ctx)->ptr; GRN_BULK_REWIND(command); } } +static void +s_output(grn_ctx *ctx, int flags, void *arg) +{ + FILE *stream = (FILE *)arg; + + if (grn_ctx_get_output_type(ctx) == GRN_CONTENT_NONE) { + s_output_raw(ctx, flags, stream); + } else { + s_output_typed(ctx, flags, stream); + } +} + static int do_alone(int argc, char **argv) { @@ -584,7 +636,7 @@ run_server(grn_ctx *ctx, grn_obj *db, grn_com_event *ev, struct hostent *he; if (!(he = gethostbyname(hostname))) { send_ready_notify(); - SERR("gethostbyname"); + SOERR("gethostbyname"); } else { ev->opaque = db; grn_edges_init(ctx, dispatcher); @@ -643,94 +695,255 @@ start_service(grn_ctx *ctx, const char *db_path, typedef struct { grn_msg *msg; + grn_bool in_body; + grn_bool is_chunked; } ht_context; static void -h_output(grn_ctx *ctx, int flags, void *arg) +h_output_set_header(grn_ctx *ctx, grn_obj *header, + grn_rc rc, long long int content_length) { - grn_rc expr_rc = ctx->rc; - ht_context *hc = (ht_context *)arg; - grn_sock fd = hc->msg->u.fd; - grn_obj header, head, foot, *outbuf = ctx->impl->outbuf; - if (!(flags & GRN_CTX_TAIL)) { return; } - GRN_TEXT_INIT(&header, 0); - GRN_TEXT_INIT(&head, 0); - GRN_TEXT_INIT(&foot, 0); - output_envelope(ctx, expr_rc, &head, outbuf, &foot); - switch (expr_rc) { + switch (rc) { case GRN_SUCCESS : - GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 200 OK\r\n"); + GRN_TEXT_SETS(ctx, header, "HTTP/1.1 200 OK\r\n"); break; case GRN_INVALID_ARGUMENT : case GRN_SYNTAX_ERROR : - GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 400 Bad Request\r\n"); + GRN_TEXT_SETS(ctx, header, "HTTP/1.1 400 Bad Request\r\n"); break; case GRN_NO_SUCH_FILE_OR_DIRECTORY : - GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 404 Not Found\r\n"); + GRN_TEXT_SETS(ctx, header, "HTTP/1.1 404 Not Found\r\n"); break; default : - GRN_TEXT_SETS(ctx, &header, "HTTP/1.1 500 Internal Server Error\r\n"); + GRN_TEXT_SETS(ctx, header, "HTTP/1.1 500 Internal Server Error\r\n"); break; } - GRN_TEXT_PUTS(ctx, &header, "Connection: close\r\n"); - GRN_TEXT_PUTS(ctx, &header, "Content-Type: "); - GRN_TEXT_PUTS(ctx, &header, grn_ctx_get_mime_type(ctx)); - GRN_TEXT_PUTS(ctx, &header, "\r\nContent-Length: "); - grn_text_lltoa(ctx, &header, - GRN_TEXT_LEN(&head) + GRN_TEXT_LEN(outbuf) + GRN_TEXT_LEN(&foot)); - GRN_TEXT_PUTS(ctx, &header, "\r\n\r\n"); - { - ssize_t ret, len; + GRN_TEXT_PUTS(ctx, header, "Content-Type: "); + GRN_TEXT_PUTS(ctx, header, grn_ctx_get_mime_type(ctx)); + GRN_TEXT_PUTS(ctx, header, "\r\n"); + if (content_length >= 0) { + GRN_TEXT_PUTS(ctx, header, "Connection: close\r\n"); + GRN_TEXT_PUTS(ctx, header, "Content-Length: "); + grn_text_lltoa(ctx, header, content_length); + GRN_TEXT_PUTS(ctx, header, "\r\n"); + } else { + GRN_TEXT_PUTS(ctx, header, "Transfer-Encoding: chunked\r\n"); + } + GRN_TEXT_PUTS(ctx, header, "\r\n"); +} + +static void +h_output_send(grn_ctx *ctx, grn_sock fd, + grn_obj *header, grn_obj *head, grn_obj *body, grn_obj *foot) +{ + ssize_t ret; + ssize_t len = 0; #ifdef WIN32 - WSABUF wsabufs[4]; - wsabufs[0].buf = GRN_TEXT_VALUE(&header); - wsabufs[0].len = GRN_TEXT_LEN(&header); - wsabufs[1].buf = GRN_TEXT_VALUE(&head); - wsabufs[1].len = GRN_TEXT_LEN(&head); - wsabufs[2].buf = GRN_TEXT_VALUE(outbuf); - wsabufs[2].len = GRN_TEXT_LEN(outbuf); - wsabufs[3].buf = GRN_TEXT_VALUE(&foot); - wsabufs[3].len = GRN_TEXT_LEN(&foot); - if (WSASend(fd, wsabufs, 4, &ret, 0, NULL, NULL) == SOCKET_ERROR) { - SERR("WSASend"); + int n_buffers = 0; + WSABUF wsabufs[4]; + if (header) { + wsabufs[n_buffers].buf = GRN_TEXT_VALUE(header); + wsabufs[n_buffers].len = GRN_TEXT_LEN(header); + len += GRN_TEXT_LEN(header); + n_buffers++; + } + if (head) { + wsabufs[n_buffers].buf = GRN_TEXT_VALUE(head); + wsabufs[n_buffers].len = GRN_TEXT_LEN(head); + len += GRN_TEXT_LEN(head); + n_buffers++; + } + if (body) { + wsabufs[n_buffers].buf = GRN_TEXT_VALUE(body); + wsabufs[n_buffers].len = GRN_TEXT_LEN(body); + len += GRN_TEXT_LEN(body); + n_buffers++; + } + if (foot) { + wsabufs[n_buffers].buf = GRN_TEXT_VALUE(foot); + wsabufs[n_buffers].len = GRN_TEXT_LEN(foot); + len += GRN_TEXT_LEN(foot); + n_buffers++; + } + { + DWORD sent; + if (WSASend(fd, wsabufs, n_buffers, &sent, 0, NULL, NULL) == SOCKET_ERROR) { + SOERR("WSASend"); } + ret = sent; + } #else /* WIN32 */ - struct iovec msg_iov[4]; - struct msghdr msg; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = msg_iov; - msg.msg_iovlen = 4; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - msg_iov[0].iov_base = GRN_TEXT_VALUE(&header); - msg_iov[0].iov_len = GRN_TEXT_LEN(&header); - msg_iov[1].iov_base = GRN_TEXT_VALUE(&head); - msg_iov[1].iov_len = GRN_TEXT_LEN(&head); - msg_iov[2].iov_base = GRN_TEXT_VALUE(outbuf); - msg_iov[2].iov_len = GRN_TEXT_LEN(outbuf); - msg_iov[3].iov_base = GRN_TEXT_VALUE(&foot); - msg_iov[3].iov_len = GRN_TEXT_LEN(&foot); - if ((ret = sendmsg(fd, &msg, MSG_NOSIGNAL)) == -1) { - SERR("sendmsg"); - } + struct iovec msg_iov[4]; + struct msghdr msg; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = msg_iov; + msg.msg_iovlen = 0; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + if (header) { + msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(header); + msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(header); + len += GRN_TEXT_LEN(header); + msg.msg_iovlen++; + } + if (head) { + msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(head); + msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(head); + len += GRN_TEXT_LEN(head); + msg.msg_iovlen++; + } + if (body) { + msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(body); + msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(body); + len += GRN_TEXT_LEN(body); + msg.msg_iovlen++; + } + if (foot) { + msg_iov[msg.msg_iovlen].iov_base = GRN_TEXT_VALUE(foot); + msg_iov[msg.msg_iovlen].iov_len = GRN_TEXT_LEN(foot); + len += GRN_TEXT_LEN(foot); + msg.msg_iovlen++; + } + if ((ret = sendmsg(fd, &msg, MSG_NOSIGNAL)) == -1) { + SOERR("sendmsg"); + } #endif /* WIN32 */ - len = GRN_TEXT_LEN(&header) + GRN_TEXT_LEN(&head) + - GRN_TEXT_LEN(outbuf) + GRN_TEXT_LEN(&foot); - if (ret != len) { - GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, - "couldn't send all data (%" GRN_FMT_LLD "/%" GRN_FMT_LLD ")", - (long long int)ret, (long long int)len); + if (ret != len) { + GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, + "couldn't send all data (%" GRN_FMT_LLD "/%" GRN_FMT_LLD ")", + (long long int)ret, (long long int)len); + } +} + +static void +h_output_raw(grn_ctx *ctx, int flags, ht_context *hc) +{ + grn_rc expr_rc = ctx->rc; + grn_sock fd = hc->msg->u.fd; + grn_obj header_; + grn_obj head_; + grn_obj body_; + grn_obj foot_; + grn_obj *header = NULL; + grn_obj *head = NULL; + grn_obj *body = NULL; + grn_obj *foot = NULL; + char *chunk = NULL; + unsigned int chunk_size = 0; + int recv_flags; + grn_bool is_last_message = (flags & GRN_CTX_TAIL); + + GRN_TEXT_INIT(&header_, 0); + GRN_TEXT_INIT(&head_, 0); + GRN_TEXT_INIT(&body_, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_INIT(&foot_, 0); + + grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags); + GRN_TEXT_SET(ctx, &body_, chunk, chunk_size); + + if (!hc->in_body) { + if (is_last_message) { + h_output_set_header(ctx, &header_, expr_rc, GRN_TEXT_LEN(&body_)); + hc->is_chunked = GRN_FALSE; + } else { + h_output_set_header(ctx, &header_, expr_rc, -1); + hc->is_chunked = GRN_TRUE; + } + header = &header_; + hc->in_body = GRN_TRUE; + } + + if (GRN_TEXT_LEN(&body_) > 0) { + if (hc->is_chunked) { + grn_text_printf(ctx, &head_, + "%x\r\n", (unsigned int)GRN_TEXT_LEN(&body_)); + head = &head_; + GRN_TEXT_PUTS(ctx, &foot_, "\r\n"); + foot = &foot_; } + body = &body_; + } + + if (is_last_message) { + if (hc->is_chunked) { + GRN_TEXT_PUTS(ctx, &foot_, "0\r\n"); + GRN_TEXT_PUTS(ctx, &foot_, "Connection: close\r\n"); + GRN_TEXT_PUTS(ctx, &foot_, "\r\n"); + foot = &foot_; + } + } + + h_output_send(ctx, fd, header, head, body, foot); + + GRN_OBJ_FIN(ctx, &foot_); + GRN_OBJ_FIN(ctx, &body_); + GRN_OBJ_FIN(ctx, &head_); + GRN_OBJ_FIN(ctx, &header_); +} + +static void +h_output_typed(grn_ctx *ctx, int flags, ht_context *hc) +{ + grn_rc expr_rc = ctx->rc; + grn_sock fd = hc->msg->u.fd; + grn_obj header, head, body, foot; + char *chunk = NULL; + unsigned int chunk_size = 0; + int recv_flags; + grn_bool should_return_body; + + if (!(flags & GRN_CTX_TAIL)) { return; } + + switch (hc->msg->header.qtype) { + case 'G' : + case 'P' : + should_return_body = GRN_TRUE; + break; + default : + should_return_body = GRN_FALSE; + break; + } + + GRN_TEXT_INIT(&header, 0); + GRN_TEXT_INIT(&head, 0); + GRN_TEXT_INIT(&body, 0); + GRN_TEXT_INIT(&foot, 0); + + grn_ctx_recv(ctx, &chunk, &chunk_size, &recv_flags); + GRN_TEXT_SET(ctx, &body, chunk, chunk_size); + + output_envelope(ctx, expr_rc, &head, &body, &foot); + h_output_set_header(ctx, &header, expr_rc, + GRN_TEXT_LEN(&head) + + GRN_TEXT_LEN(&body) + + GRN_TEXT_LEN(&foot)); + if (should_return_body) { + h_output_send(ctx, fd, &header, &head, &body, &foot); + } else { + h_output_send(ctx, fd, &header, NULL, NULL, NULL); } - GRN_BULK_REWIND(outbuf); GRN_OBJ_FIN(ctx, &foot); + GRN_OBJ_FIN(ctx, &body); GRN_OBJ_FIN(ctx, &head); GRN_OBJ_FIN(ctx, &header); } static void +h_output(grn_ctx *ctx, int flags, void *arg) +{ + ht_context *hc = (ht_context *)arg; + + if (grn_ctx_get_output_type(ctx) == GRN_CONTENT_NONE) { + h_output_raw(ctx, flags, hc); + } else { + h_output_typed(ctx, flags, hc); + } +} + +static void do_htreq_get(grn_ctx *ctx, grn_msg *msg) { char *path = NULL; @@ -923,10 +1136,6 @@ do_htreq_post_parse_header(grn_ctx *ctx, return GRN_FALSE; } - if (!header->have_100_continue && current == end) { - return GRN_FALSE; - } - if (current == end) { header->body_start = NULL; } else { @@ -961,6 +1170,8 @@ do_htreq_post(grn_ctx *ctx, grn_msg *msg) if (ctx->rc != GRN_SUCCESS) { ht_context context; context.msg = msg; + context.in_body = GRN_FALSE; + context.is_chunked = GRN_FALSE; h_output(ctx, GRN_CTX_TAIL, &context); return; } @@ -971,7 +1182,7 @@ do_htreq_post(grn_ctx *ctx, grn_msg *msg) int send_flags = MSG_NOSIGNAL; send_size = send(fd, continue_message, strlen(continue_message), send_flags); if (send_size == -1) { - SERR("send"); + SOERR("send"); return; } } @@ -999,7 +1210,7 @@ do_htreq_post(grn_ctx *ctx, grn_msg *msg) break; } if (recv_length == -1) { - SERR("recv"); + SOERR("recv"); break; } buffer_start = buffer; @@ -1052,15 +1263,13 @@ do_htreq(grn_ctx *ctx, grn_msg *msg) grn_com_header *header = &msg->header; switch (header->qtype) { case 'G' : /* GET */ + case 'H' : /* HEAD */ do_htreq_get(ctx, msg); break; case 'P' : /* POST */ do_htreq_post(ctx, msg); break; } - /* TODO: support "Connection: keep-alive" */ - ctx->stat = GRN_CTX_QUIT; - /* TODO: support a command in multi requests. e.g.: load command */ grn_ctx_set_next_expr(ctx, NULL); /* if (ctx->rc != GRN_OPERATION_WOULD_BLOCK) {...} */ grn_msg_close(ctx, (grn_obj *)msg); @@ -1653,7 +1862,7 @@ check_rlimit_nofile(grn_ctx *ctx) #endif /* WIN32 */ } -static void * CALLBACK +static grn_thread_func_result CALLBACK h_worker(void *arg) { ht_context hc; @@ -1676,6 +1885,8 @@ h_worker(void *arg) nfthreads--; MUTEX_UNLOCK(q_mutex); hc.msg = (grn_msg *)msg; + hc.in_body = GRN_FALSE; + hc.is_chunked = GRN_FALSE; do_htreq(ctx, (grn_msg *)msg); MUTEX_LOCK(q_mutex); } while (nfthreads < max_nfthreads && grn_gctx.stat != GRN_CTX_QUIT); @@ -1684,7 +1895,7 @@ exit : MUTEX_UNLOCK(q_mutex); GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, "thread end (%d/%d)", nfthreads, nthreads); grn_ctx_fin(ctx); - return NULL; + return GRN_THREAD_FUNC_RETURN_VALUE; } static void @@ -1729,7 +1940,7 @@ h_server(char *path) return exit_code; } -static void * CALLBACK +static grn_thread_func_result CALLBACK g_worker(void *arg) { GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, "thread start (%d/%d)", nfthreads, nthreads + 1); @@ -1790,7 +2001,7 @@ exit : nthreads--; MUTEX_UNLOCK(q_mutex); GRN_LOG(&grn_gctx, GRN_LOG_NOTICE, "thread end (%d/%d)", nfthreads, nthreads); - return NULL; + return GRN_THREAD_FUNC_RETURN_VALUE; } static void @@ -1891,18 +2102,18 @@ g_server(char *path) } enum { - mode_alone = 0, - mode_client, - mode_daemon, - mode_server, - mode_usage, - mode_version, - mode_config, - mode_error + ACTION_USAGE = 1, + ACTION_VERSION, + ACTION_SHOW_CONFIG, + ACTION_ERROR }; -#define MODE_MASK 0x007f -#define MODE_NEW_DB 0x0100 +#define ACTION_MASK (0x0f) +#define FLAG_MODE_ALONE (1 << 4) +#define FLAG_MODE_CLIENT (1 << 5) +#define FLAG_MODE_DAEMON (1 << 6) +#define FLAG_MODE_SERVER (1 << 7) +#define FLAG_NEW_DB (1 << 8) static uint32_t get_core_number(void) @@ -2123,7 +2334,6 @@ static const int default_http_port = DEFAULT_HTTP_PORT; static const int default_gqtp_port = DEFAULT_GQTP_PORT; static grn_encoding default_encoding = GRN_ENC_DEFAULT; static uint32_t default_max_num_threads = DEFAULT_MAX_NFTHREADS; -static const int default_mode = mode_alone; static const int default_log_level = GRN_LOG_DEFAULT_LEVEL; static const char * const default_protocol = "gqtp"; static const char *default_hostname = "localhost"; @@ -2277,8 +2487,8 @@ show_version(void) #ifdef GRN_WITH_ZLIB printf(",zlib"); #endif -#ifdef GRN_WITH_LZO - printf(",lzo"); +#ifdef GRN_WITH_LZ4 + printf(",lz4"); #endif #ifdef USE_KQUEUE printf(",kqueue"); @@ -2397,26 +2607,27 @@ main(int argc, char **argv) *working_directory_arg = NULL; const char *config_path = NULL; int exit_code = EXIT_SUCCESS; - int i, mode = mode_alone; + int i; + int flags = 0; uint32_t cache_limit = 0; static grn_str_getopt_opt opts[] = { {'p', "port", NULL, 0, GETOPT_OP_NONE}, {'e', "encoding", NULL, 0, GETOPT_OP_NONE}, {'t', "max-threads", NULL, 0, GETOPT_OP_NONE}, - {'h', "help", NULL, mode_usage, GETOPT_OP_UPDATE}, - {'c', NULL, NULL, mode_client, GETOPT_OP_UPDATE}, - {'d', NULL, NULL, mode_daemon, GETOPT_OP_UPDATE}, - {'s', NULL, NULL, mode_server, GETOPT_OP_UPDATE}, + {'h', "help", NULL, ACTION_USAGE, GETOPT_OP_UPDATE}, + {'c', NULL, NULL, FLAG_MODE_CLIENT, GETOPT_OP_ON}, + {'d', NULL, NULL, FLAG_MODE_DAEMON, GETOPT_OP_ON}, + {'s', NULL, NULL, FLAG_MODE_SERVER, GETOPT_OP_ON}, {'l', "log-level", NULL, 0, GETOPT_OP_NONE}, {'i', "server-id", NULL, 0, GETOPT_OP_NONE}, - {'n', NULL, NULL, MODE_NEW_DB, GETOPT_OP_ON}, + {'n', NULL, NULL, FLAG_NEW_DB, GETOPT_OP_ON}, {'\0', "protocol", NULL, 0, GETOPT_OP_NONE}, - {'\0', "version", NULL, mode_version, GETOPT_OP_UPDATE}, + {'\0', "version", NULL, ACTION_VERSION, GETOPT_OP_UPDATE}, {'\0', "log-path", NULL, 0, GETOPT_OP_NONE}, {'\0', "query-log-path", NULL, 0, GETOPT_OP_NONE}, {'\0', "pid-path", NULL, 0, GETOPT_OP_NONE}, {'\0', "config-path", NULL, 0, GETOPT_OP_NONE}, - {'\0', "show-config", NULL, mode_config, GETOPT_OP_UPDATE}, + {'\0', "show-config", NULL, ACTION_SHOW_CONFIG, GETOPT_OP_UPDATE}, {'\0', "cache-limit", NULL, 0, GETOPT_OP_NONE}, {'\0', "file", NULL, 0, GETOPT_OP_NONE}, {'\0', "document-root", NULL, 0, GETOPT_OP_NONE}, @@ -2453,14 +2664,14 @@ main(int argc, char **argv) init_default_settings(); /* only for parsing --config-path. */ - i = grn_str_getopt(argc, argv, opts, &mode); + i = grn_str_getopt(argc, argv, opts, &flags); if (i < 0) { show_usage(stderr); return EXIT_FAILURE; } if (config_path) { - const config_file_status status = config_file_load(config_path, opts, &mode); + const config_file_status status = config_file_load(config_path, opts, &flags); if (status == CONFIG_FILE_FOPEN_ERROR) { fprintf(stderr, "%s: can't open config file: %s (%s)\n", argv[0], config_path, strerror(errno)); @@ -2473,7 +2684,7 @@ main(int argc, char **argv) } } else if (*default_config_path) { const config_file_status status = - config_file_load(default_config_path, opts, &mode); + config_file_load(default_config_path, opts, &flags); if (status != CONFIG_FILE_SUCCESS && status != CONFIG_FILE_FOPEN_ERROR) { fprintf(stderr, "%s: failed to parse config file: %s (%s)\n", argv[0], default_config_path, @@ -2491,22 +2702,21 @@ main(int argc, char **argv) } /* ignore mode option in config file */ - mode = (mode == mode_error) ? default_mode : - ((mode & ~MODE_MASK) | default_mode); + flags = (flags == ACTION_ERROR) ? 0 : (flags & ~ACTION_MASK); - i = grn_str_getopt(argc, argv, opts, &mode); - if (i < 0) { mode = mode_error; } - switch (mode & MODE_MASK) { - case mode_version : + i = grn_str_getopt(argc, argv, opts, &flags); + if (i < 0) { flags = ACTION_ERROR; } + switch (flags & ACTION_MASK) { + case ACTION_VERSION : show_version(); return EXIT_SUCCESS; - case mode_usage : + case ACTION_USAGE : show_usage(output); return EXIT_SUCCESS; - case mode_config : - show_config(output, opts, mode & ~MODE_MASK); + case ACTION_SHOW_CONFIG : + show_config(output, opts, flags & ~ACTION_MASK); return EXIT_SUCCESS; - case mode_error : + case ACTION_ERROR : show_usage(stderr); return EXIT_FAILURE; } @@ -2787,23 +2997,14 @@ main(int argc, char **argv) grn_cache_set_max_n_entries(&grn_gctx, cache, cache_limit); } - newdb = (mode & MODE_NEW_DB); - switch (mode & MODE_MASK) { - case mode_alone : - exit_code = do_alone(argc - i, argv + i); - break; - case mode_client : + newdb = (flags & FLAG_NEW_DB); + is_daemon_mode = (flags & FLAG_MODE_DAEMON); + if (flags & FLAG_MODE_CLIENT) { exit_code = do_client(argc - i, argv + i); - break; - case mode_daemon : - is_daemon_mode = GRN_TRUE; - /* fallthru */ - case mode_server : + } else if (is_daemon_mode || (flags & FLAG_MODE_SERVER)) { exit_code = do_server(argc > i ? argv[i] : NULL); - break; - default: - exit_code = EXIT_FAILURE; - break; + } else { + exit_code = do_alone(argc - i, argv + i); } #ifdef GRN_WITH_LIBEDIT diff --git a/storage/mroonga/vendor/groonga/src/groonga_benchmark.c b/storage/mroonga/vendor/groonga/src/groonga_benchmark.c index 61575174950..e7e426e748f 100644 --- a/storage/mroonga/vendor/groonga/src/groonga_benchmark.c +++ b/storage/mroonga/vendor/groonga/src/groonga_benchmark.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2010-2012 Brazil + Copyright(C) 2010-2014 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -17,7 +17,7 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" +#include <config.h> #endif /* HAVE_CONFIG_H */ #include <stdio.h> @@ -37,9 +37,9 @@ #include <netinet/in.h> #endif /* HAVE_NETINET_IN_H */ -#include "lib/str.h" -#include "lib/com.h" -#include "lib/db.h" +#include <grn_str.h> +#include <grn_com.h> +#include <grn_db.h> #ifdef WIN32 #include <windows.h> @@ -598,7 +598,7 @@ command_send_http(grn_ctx *ctx, const char *command, int type, int task_id) fprintf(stderr, "failed to connect to groonga at %s:%d via HTTP: ", grntest_serverhost, grntest_serverport); #ifdef WIN32 - fprintf(stderr, "%d\n", GetLastError()); + fprintf(stderr, "%lu\n", GetLastError()); #else fprintf(stderr, "%s\n", strerror(errno)); #endif @@ -1149,7 +1149,7 @@ typedef struct _grntest_worker { } grntest_worker; #ifdef WIN32 -static int +static unsigned int __stdcall worker(void *val) { @@ -1252,7 +1252,6 @@ get_sysinfo(const char *path, char *result, int olen) char tmpbuf[256]; #ifdef WIN32 - int cinfo[4]; ULARGE_INTEGER dinfo; char cpustring[64]; SYSTEM_INFO sinfo; @@ -1279,12 +1278,15 @@ get_sysinfo(const char *path, char *result, int olen) memset(cpustring, 0, 64); #ifndef __GNUC__ - __cpuid(cinfo, 0x80000002); - memcpy(cpustring, cinfo, 16); - __cpuid(cinfo, 0x80000003); - memcpy(cpustring+16, cinfo, 16); - __cpuid(cinfo, 0x80000004); - memcpy(cpustring+32, cinfo, 16); + { + int cinfo[4]; + __cpuid(cinfo, 0x80000002); + memcpy(cpustring, cinfo, 16); + __cpuid(cinfo, 0x80000003); + memcpy(cpustring+16, cinfo, 16); + __cpuid(cinfo, 0x80000004); + memcpy(cpustring+32, cinfo, 16); + } #endif if (grntest_outtype == OUT_TSV) { @@ -1313,9 +1315,9 @@ get_sysinfo(const char *path, char *result, int olen) GetSystemInfo(&sinfo); if (grntest_outtype == OUT_TSV) { - sprintf(tmpbuf, "CORE\t%d\n", sinfo.dwNumberOfProcessors); + sprintf(tmpbuf, "CORE\t%lu\n", sinfo.dwNumberOfProcessors); } else { - sprintf(tmpbuf, " \"CORE\": %d,\n", sinfo.dwNumberOfProcessors); + sprintf(tmpbuf, " \"CORE\": %lu,\n", sinfo.dwNumberOfProcessors); } strcat(result, tmpbuf); @@ -1338,9 +1340,10 @@ get_sysinfo(const char *path, char *result, int olen) osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osinfo); if (grntest_outtype == OUT_TSV) { - sprintf(tmpbuf, "Windows %d.%d\n", osinfo.dwMajorVersion, osinfo.dwMinorVersion); + sprintf(tmpbuf, "Windows %ld.%ld\n", + osinfo.dwMajorVersion, osinfo.dwMinorVersion); } else { - sprintf(tmpbuf, " \"OS\": \"Windows %d.%d\",\n", osinfo.dwMajorVersion, + sprintf(tmpbuf, " \"OS\": \"Windows %lu.%lu\",\n", osinfo.dwMajorVersion, osinfo.dwMinorVersion); } strcat(result, tmpbuf); @@ -1561,7 +1564,7 @@ start_server(const char *dbpath, int r) 0, NULL, NULL, &si, &grntest_pi); if (ret == 0) { - fprintf(stderr, "Cannot start groonga server: <%s>: error=%d\n", + fprintf(stderr, "Cannot start groonga server: <%s>: error=%lu\n", groonga_path, GetLastError()); exit(1); } diff --git a/storage/mroonga/vendor/groonga/src/groonga_mruby.c b/storage/mroonga/vendor/groonga/src/groonga_mruby.c new file mode 100644 index 00000000000..9978a002f18 --- /dev/null +++ b/storage/mroonga/vendor/groonga/src/groonga_mruby.c @@ -0,0 +1,84 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <grn_mrb.h> + +#include <stdio.h> +#include <stdlib.h> + +static int +run(grn_ctx *ctx, const char *db_path, const char *ruby_script_path) +{ + grn_obj *db; + + db = grn_db_open(ctx, db_path); + if (!db) { + if (ctx->rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) { + db = grn_db_create(ctx, db_path, NULL); + if (!db) { + fprintf(stderr, "Failed to create database: <%s>: %s", + db_path, ctx->errbuf); + return EXIT_FAILURE; + } + } else { + fprintf(stderr, "Failed to open database: <%s>: %s", + db_path, ctx->errbuf); + return EXIT_FAILURE; + } + } + + grn_mrb_load(ctx, ruby_script_path); + if (ctx->rc != GRN_SUCCESS) { + fprintf(stderr, "Failed to load Ruby script: <%s>: %s", + ruby_script_path, ctx->errbuf); + } + + grn_obj_close(ctx, db); + + if (ctx->rc == GRN_SUCCESS) { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } +} + +int +main(int argc, char **argv) +{ + int exit_code = EXIT_SUCCESS; + + if (argc != 3) { + fprintf(stderr, "Usage: %s DB_PATH RUBY_SCRIPT_PATH\n", argv[0]); + return EXIT_FAILURE; + } + + if (grn_init() != GRN_SUCCESS) { + return EXIT_FAILURE; + } + + { + grn_ctx ctx; + grn_ctx_init(&ctx, 0); + exit_code = run(&ctx, argv[1], argv[2]); + grn_ctx_fin(&ctx); + } + + grn_fin(); + + return exit_code; +} diff --git a/storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am b/storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am new file mode 100644 index 00000000000..c9006755c97 --- /dev/null +++ b/storage/mroonga/vendor/groonga/src/groonga_mruby_sources.am @@ -0,0 +1,2 @@ +groonga_mruby_SOURCES = \ + groonga_mruby.c diff --git a/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c b/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c index 26be6be7d0a..115de1338a4 100644 --- a/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c +++ b/storage/mroonga/vendor/groonga/src/httpd/nginx-module/ngx_http_groonga_module.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2012-2014 Brazil + Copyright(C) 2012-2015 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -16,9 +16,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> +#ifndef WIN32 +# define NGX_GRN_SUPPORT_STOP_BY_COMMAND +#endif #include <ngx_config.h> #include <ngx_core.h> @@ -26,6 +26,13 @@ #include <groonga.h> +#include <sys/stat.h> + +#ifdef NGX_GRN_SUPPORT_STOP_BY_COMMAND +# include <sys/types.h> +# include <unistd.h> +#endif + #define GRN_NO_FLAGS 0 typedef struct { @@ -56,9 +63,19 @@ typedef struct { typedef struct { grn_bool initialized; grn_ctx context; - grn_obj head; - grn_obj body; - grn_obj foot; + struct { + grn_bool processed; + grn_bool header_sent; + ngx_http_request_t *r; + ngx_int_t rc; + ngx_chain_t *free_chain; + ngx_chain_t *busy_chain; + } raw; + struct { + grn_obj head; + grn_obj body; + grn_obj foot; + } typed; } ngx_http_groonga_handler_data_t; typedef struct { @@ -126,18 +143,54 @@ ngx_http_groonga_logger_log(grn_ctx *ctx, grn_log_level level, const char level_marks[] = " EACewnid-"; u_char buffer[NGX_MAX_ERROR_STR]; u_char *last; - + size_t prefix_size; + size_t message_size; + size_t location_size; + size_t postfix_size; + size_t log_message_size; + +#define LOG_PREFIX_FORMAT "%s|%c|%s " + prefix_size = + strlen(timestamp) + + 1 /* | */ + + 1 /* %c */ + + 1 /* | */ + + strlen(title) + + 1 /* a space */; + message_size = strlen(message); if (location && *location) { - last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, - "%s|%c|%s %s %s\n", - timestamp, *(level_marks + level), title, message, - location); + location_size = 1 /* a space */ + strlen(location); } else { + location_size = 0; + } + postfix_size = 1 /* \n */; + log_message_size = prefix_size + message_size + location_size + postfix_size; + + if (log_message_size > NGX_MAX_ERROR_STR) { last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, - "%s|%c|%s %s\n", - timestamp, *(level_marks + level), title, message); + LOG_PREFIX_FORMAT, + timestamp, *(level_marks + level), title); + ngx_write_fd(logger_data->file->fd, buffer, last - buffer); + ngx_write_fd(logger_data->file->fd, (void *)message, message_size); + if (location_size > 0) { + ngx_write_fd(logger_data->file->fd, " ", 1); + ngx_write_fd(logger_data->file->fd, (void *)location, location_size); + } + ngx_write_fd(logger_data->file->fd, "\n", 1); + } else { + if (location && *location) { + last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, + LOG_PREFIX_FORMAT " %s %s\n", + timestamp, *(level_marks + level), title, message, + location); + } else { + last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR, + LOG_PREFIX_FORMAT " %s\n", + timestamp, *(level_marks + level), title, message); + } + ngx_write_fd(logger_data->file->fd, buffer, last - buffer); } - ngx_write_fd(logger_data->file->fd, buffer, last - buffer); +#undef LOG_PREFIX_FORMAT } static void @@ -336,6 +389,7 @@ ngx_http_groonga_grn_obj_to_ngx_buf(ngx_pool_t *pool, grn_obj *object) buffer->pos = (u_char *)GRN_TEXT_VALUE(object); buffer->last = (u_char *)GRN_TEXT_VALUE(object) + GRN_TEXT_LEN(object); buffer->memory = 1; /* this buffer is in memory */ + buffer->in_file = 0; return buffer; } @@ -351,20 +405,109 @@ ngx_http_groonga_handler_cleanup(void *user_data) } context = &(data->context); - GRN_OBJ_FIN(context, &(data->head)); - GRN_OBJ_FIN(context, &(data->body)); - GRN_OBJ_FIN(context, &(data->foot)); + GRN_OBJ_FIN(context, &(data->typed.head)); + GRN_OBJ_FIN(context, &(data->typed.body)); + GRN_OBJ_FIN(context, &(data->typed.foot)); grn_logger_set(context, NULL); grn_query_logger_set(context, NULL); grn_ctx_fin(context); } static void -ngx_http_groonga_context_receive_handler(grn_ctx *context, - int flags, - void *callback_data) +ngx_http_groonga_handler_set_content_type(ngx_http_request_t *r, + const char *content_type) +{ + r->headers_out.content_type.len = strlen(content_type); + r->headers_out.content_type.data = (u_char *)content_type; + r->headers_out.content_type_len = r->headers_out.content_type.len; +} + +static void +ngx_http_groonga_context_receive_handler_raw(grn_ctx *context, + int flags, + ngx_http_groonga_handler_data_t *data) +{ + char *chunk = NULL; + unsigned int chunk_size = 0; + int recv_flags; + ngx_http_request_t *r; + ngx_log_t *log; + grn_bool is_last_chunk; + + grn_ctx_recv(context, &chunk, &chunk_size, &recv_flags); + data->raw.processed = GRN_TRUE; + + if (data->raw.rc != NGX_OK) { + return; + } + + r = data->raw.r; + log = r->connection->log; + is_last_chunk = (flags & GRN_CTX_TAIL); + + if (!data->raw.header_sent) { + ngx_http_groonga_handler_set_content_type(r, grn_ctx_get_mime_type(context)); + r->headers_out.status = NGX_HTTP_OK; + if (is_last_chunk) { + r->headers_out.content_length_n = chunk_size; + if (chunk_size == 0) { + r->header_only = 1; + } + } else { + r->headers_out.content_length_n = -1; + } + data->raw.rc = ngx_http_send_header(r); + data->raw.header_sent = GRN_TRUE; + + if (data->raw.rc != NGX_OK) { + return; + } + } + + if (chunk_size > 0 || is_last_chunk) { + ngx_chain_t *chain; + + chain = ngx_chain_get_free_buf(r->pool, &(data->raw.free_chain)); + if (!chain) { + ngx_log_error(NGX_LOG_ERR, log, 0, + "http_groonga: failed to allocate memory for chunked body"); + data->raw.rc = NGX_ERROR; + return; + } + if (chunk_size == 0) { + chain->buf->pos = NULL; + chain->buf->last = NULL; + chain->buf->memory = 0; + } else { + chain->buf->pos = (u_char *)chunk; + chain->buf->last = (u_char *)chunk + chunk_size; + chain->buf->memory = 1; + } + chain->buf->tag = (ngx_buf_tag_t)&ngx_http_groonga_module; + chain->buf->flush = 1; + chain->buf->temporary = 0; + chain->buf->in_file = 0; + if (is_last_chunk) { + chain->buf->last_buf = 1; + } else { + chain->buf->last_buf = 0; + } + chain->next = NULL; + + data->raw.rc = ngx_http_output_filter(r, chain); + ngx_chain_update_chains(r->pool, + &(data->raw.free_chain), + &(data->raw.busy_chain), + &chain, + (ngx_buf_tag_t)&ngx_http_groonga_module); + } +} + +static void +ngx_http_groonga_context_receive_handler_typed(grn_ctx *context, + int flags, + ngx_http_groonga_handler_data_t *data) { - ngx_http_groonga_handler_data_t *data = callback_data; char *result = NULL; unsigned int result_size = 0; int recv_flags; @@ -375,6 +518,7 @@ ngx_http_groonga_context_receive_handler(grn_ctx *context, grn_ctx_recv(context, &result, &result_size, &recv_flags); +#ifdef NGX_GRN_SUPPORT_STOP_BY_COMMAND if (recv_flags == GRN_CTX_QUIT) { ngx_int_t ngx_rc; ngx_int_t ngx_pid; @@ -394,28 +538,43 @@ ngx_http_groonga_context_receive_handler(grn_ctx *context, context->stat |= GRN_CTX_QUIT; } else { context->rc = GRN_OPERATION_NOT_PERMITTED; - GRN_TEXT_PUTS(context, &(data->body), "false"); + GRN_TEXT_PUTS(context, &(data->typed.body), "false"); context->stat &= ~GRN_CTX_QUIT; } } +#endif if (result_size > 0 || - GRN_TEXT_LEN(&(data->body)) > 0 || + GRN_TEXT_LEN(&(data->typed.body)) > 0 || context->rc != GRN_SUCCESS) { if (result_size > 0) { - GRN_TEXT_PUT(context, &(data->body), result, result_size); + GRN_TEXT_PUT(context, &(data->typed.body), result, result_size); } grn_output_envelope(context, context->rc, - &(data->head), - &(data->body), - &(data->foot), + &(data->typed.head), + &(data->typed.body), + &(data->typed.foot), NULL, 0); } } +static void +ngx_http_groonga_context_receive_handler(grn_ctx *context, + int flags, + void *callback_data) +{ + ngx_http_groonga_handler_data_t *data = callback_data; + + if (grn_ctx_get_output_type(context) == GRN_CONTENT_NONE) { + ngx_http_groonga_context_receive_handler_raw(context, flags, data); + } else { + ngx_http_groonga_context_receive_handler_typed(context, flags, data); + } +} + static ngx_int_t ngx_http_groonga_extract_command_path(ngx_http_request_t *r, ngx_str_t *command_path) @@ -461,15 +620,6 @@ ngx_http_groonga_extract_command_path(ngx_http_request_t *r, return NGX_OK; } -static void -ngx_http_groonga_handler_set_content_type(ngx_http_request_t *r, - const char *content_type) -{ - r->headers_out.content_type.len = strlen(content_type); - r->headers_out.content_type.data = (u_char *)content_type; - r->headers_out.content_type_len = r->headers_out.content_type.len; -} - static ngx_int_t ngx_http_groonga_handler_create_data(ngx_http_request_t *r, ngx_http_groonga_handler_data_t **data_return) @@ -496,10 +646,20 @@ ngx_http_groonga_handler_create_data(ngx_http_request_t *r, if (rc != NGX_OK) { return rc; } + data->initialized = GRN_TRUE; - GRN_TEXT_INIT(&(data->head), GRN_NO_FLAGS); - GRN_TEXT_INIT(&(data->body), GRN_NO_FLAGS); - GRN_TEXT_INIT(&(data->foot), GRN_NO_FLAGS); + + data->raw.processed = GRN_FALSE; + data->raw.header_sent = GRN_FALSE; + data->raw.r = r; + data->raw.rc = NGX_OK; + data->raw.free_chain = NULL; + data->raw.busy_chain = NULL; + + GRN_TEXT_INIT(&(data->typed.head), GRN_NO_FLAGS); + GRN_TEXT_INIT(&(data->typed.body), GRN_NO_FLAGS); + GRN_TEXT_INIT(&(data->typed.foot), GRN_NO_FLAGS); + grn_ctx_use(context, grn_ctx_db(&(location_conf->context))); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { @@ -553,9 +713,10 @@ ngx_http_groonga_handler_validate_post_command(ngx_http_request_t *r, context = &(data->context); ngx_http_groonga_handler_set_content_type(r, "text/plain"); - GRN_TEXT_PUTS(context, &(data->body), "command for POST must be <load>: <"); - GRN_TEXT_PUT(context, &(data->body), command.data, command.len); - GRN_TEXT_PUTS(context, &(data->body), ">"); + GRN_TEXT_PUTS(context, &(data->typed.body), + "command for POST must be <load>: <"); + GRN_TEXT_PUT(context, &(data->typed.body), command.data, command.len); + GRN_TEXT_PUTS(context, &(data->typed.body), ">"); return NGX_HTTP_BAD_REQUEST; } @@ -665,7 +826,7 @@ ngx_http_groonga_handler_process_body(ngx_http_request_t *r, body = r->request_body->bufs->buf; if (!body) { ngx_http_groonga_handler_set_content_type(r, "text/plain"); - GRN_TEXT_PUTS(context, &(data->body), "must send load data as body"); + GRN_TEXT_PUTS(context, &(data->typed.body), "must send load data as body"); return NGX_HTTP_BAD_REQUEST; } @@ -744,6 +905,10 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r, ngx_chain_t head_chain, body_chain, foot_chain; ngx_chain_t *output_chain = NULL; + if (data->raw.processed) { + return data->raw.rc; + } + context = &(data->context); /* set the 'Content-type' header */ @@ -753,17 +918,17 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r, } /* allocate buffers for a response body */ - head_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->head)); + head_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->typed.head)); if (!head_buf) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } - body_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->body)); + body_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->typed.body)); if (!body_buf) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } - foot_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->foot)); + foot_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->typed.foot)); if (!foot_buf) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -778,9 +943,9 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r, /* set the status line */ r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_length_n = GRN_TEXT_LEN(&(data->head)) + - GRN_TEXT_LEN(&(data->body)) + - GRN_TEXT_LEN(&(data->foot)); + r->headers_out.content_length_n = GRN_TEXT_LEN(&(data->typed.head)) + + GRN_TEXT_LEN(&(data->typed.body)) + + GRN_TEXT_LEN(&(data->typed.foot)); if (r->headers_out.content_length_n == 0) { r->header_only = 1; } @@ -1072,7 +1237,7 @@ ngx_http_groonga_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) GRN_CACHE_DEFAULT_MAX_N_ENTRIES); #ifdef NGX_HTTP_GROONGA_LOG_PATH - { + if (!conf->log_file) { ngx_str_t default_log_path; default_log_path.data = (u_char *)NGX_HTTP_GROONGA_LOG_PATH; default_log_path.len = strlen(NGX_HTTP_GROONGA_LOG_PATH); @@ -1085,8 +1250,6 @@ ngx_http_groonga_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } } -#else - conf->log_file = NULL; #endif ngx_conf_merge_str_value(conf->query_log_path, prev->query_log_path, diff --git a/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt b/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt index 0773026a618..c0c7a9c9964 100644 --- a/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/src/suggest/CMakeLists.txt @@ -25,11 +25,9 @@ set_source_files_properties(${GROONGA_SUGGEST_CREATE_DATASET_SOURCES} PROPERTIES COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") target_link_libraries(groonga-suggest-create-dataset libgroonga) -if(NOT MRN_GROONGA_BUNDLED) - install( - TARGETS groonga-suggest-create-dataset - DESTINATION ${BIN_DIR}) -endif() +install( + TARGETS groonga-suggest-create-dataset + DESTINATION ${BIN_DIR}) if(GRN_WITH_LIBEVENT AND GRN_WITH_ZEROMQ AND GRN_WITH_MESSAGE_PACK) set(GRN_WITH_SUGGEST_LEARNER TRUE) @@ -82,9 +80,7 @@ if(GRN_WITH_SUGGEST_LEARNER) ${ZEROMQ_LIBRARIES} ${MESSAGE_PACK_LIBRARIES}) - if(NOT MRN_GROONGA_BUNDLED) - install( - TARGETS groonga-suggest-learner groonga-suggest-httpd - DESTINATION ${BIN_DIR}) - endif() + install( + TARGETS groonga-suggest-learner groonga-suggest-httpd + DESTINATION ${BIN_DIR}) endif() diff --git a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c index 35f2cd09fc0..d566d24b96a 100644 --- a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c +++ b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_create_dataset.c @@ -21,7 +21,7 @@ #include <groonga.h> /* For grn_str_getopt() */ -#include <str.h> +#include <grn_str.h> typedef enum { MODE_NONE, diff --git a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c index 6d94be87a8a..98ae0958908 100644 --- a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c +++ b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_httpd.c @@ -16,7 +16,7 @@ */ /* groonga origin headers */ -#include <str.h> +#include <grn_str.h> #include <stdio.h> #include <signal.h> diff --git a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c index 060d238565a..18b91d438e2 100644 --- a/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c +++ b/storage/mroonga/vendor/groonga/src/suggest/groonga_suggest_learner.c @@ -16,7 +16,7 @@ */ /* for grn_str_getopt() */ -#include <str.h> +#include <grn_str.h> #include "zmq_compatible.h" #include <stdio.h> diff --git a/storage/mroonga/vendor/groonga/tools/travis-before-script.sh b/storage/mroonga/vendor/groonga/tools/travis-before-script.sh index 943f41b0013..71d5a816b87 100755 --- a/storage/mroonga/vendor/groonga/tools/travis-before-script.sh +++ b/storage/mroonga/vendor/groonga/tools/travis-before-script.sh @@ -4,30 +4,46 @@ set -e git submodule update --init --depth 1 +prefix=/tmp/local + case "${BUILD_TOOL}" in - autotools) - ./autogen.sh - - configure_args="" - #if [ "$CC" = "clang" ]; then - configure_args="${configure_args} --enable-debug" - #fi - if [ "$ENABLE_MRUBY" = "yes" ]; then - configure_args="${configure_args} --with-ruby --enable-mruby" - fi - - ./configure --with-ruby ${configure_args} - ;; - cmake) - cmake_args="" - cmake_args="${cmake_args} -DGRN_WITH_DEBUG=yes" - if [ "$ENABLE_MRUBY" = "yes" ]; then - cmake_args="${cmake_args} -DGRN_WITH_MRUBY=yes" - fi - - cmake . ${cmake_args} - ;; + autotools) + ./autogen.sh + + configure_args="" + #if [ "$CC" = "clang" ]; then + configure_args="${configure_args} --enable-debug" + #fi + if [ "$ENABLE_MRUBY" = "yes" ]; then + configure_args="${configure_args} --with-ruby --enable-mruby" + fi + if [ "$ENABLE_JEMALLOC" = "yes" ]; then + configure_args="${configure_args} --with-jemalloc" + fi + + ./configure --prefix=${prefix} --with-ruby ${configure_args} + ;; + cmake) + cmake_args="" + cmake_args="${cmake_args} -DGRN_WITH_DEBUG=yes" + if [ "$ENABLE_MRUBY" = "yes" ]; then + cmake_args="${cmake_args} -DGRN_WITH_MRUBY=yes" + fi + + cmake . ${cmake_args} + ;; +esac + +case "$(uname)" in + Linux) + n_processors="$(grep '^processor' /proc/cpuinfo | wc -l)" + ;; + Darwin) + n_processors="$(/usr/sbin/sysctl -n hw.ncpu)" + ;; + *) + n_processors="1" + ;; esac -n_processors="$(grep '^processor' /proc/cpuinfo | wc -l)" make -j${n_processors} > /dev/null diff --git a/storage/mroonga/vendor/groonga/tools/travis-install.sh b/storage/mroonga/vendor/groonga/tools/travis-install.sh new file mode 100755 index 00000000000..e64e17b9872 --- /dev/null +++ b/storage/mroonga/vendor/groonga/tools/travis-install.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +set -e + +case "${TRAVIS_OS_NAME}" in + linux) + curl --silent --location https://raw.github.com/clear-code/cutter/master/data/travis/setup.sh | sh + sudo apt-get install -qq -y \ + autotools-dev \ + zlib1g-dev \ + libmsgpack-dev \ + libevent-dev \ + libmecab-dev \ + mecab-naist-jdic \ + cmake + if [ "${ENABLE_JEMALLOC}" = "yes" ]; then + sudo apt-get install -qq -y libjemalloc-dev + fi + ;; + osx) + brew install \ + msgpack \ + libevent \ + mecab \ + mecab-ipadic + ;; +esac + +if [ "${ENABLE_MRUBY}" = "yes" ]; then + gem install pkg-config groonga-client +fi diff --git a/storage/mroonga/vendor/groonga/tools/travis-script.sh b/storage/mroonga/vendor/groonga/tools/travis-script.sh index 7931903d419..35bf0bd1c9e 100755 --- a/storage/mroonga/vendor/groonga/tools/travis-script.sh +++ b/storage/mroonga/vendor/groonga/tools/travis-script.sh @@ -2,14 +2,20 @@ set -e +prefix=/tmp/local + case "${BUILD_TOOL}" in - autotools) - test/unit/run-test.sh - test/command/run-test.sh - # test/command/run-test.sh --interface http - # test/command/run-test.sh --interface http --testee groonga-httpd - ;; - cmake) - test/command/run-test.sh - ;; + autotools) + test/unit/run-test.sh + test/command/run-test.sh + if [ "${ENABLE_MRUBY}" = "yes" ]; then + test/query_optimizer/run-test.rb + fi + test/command/run-test.sh --interface http + mkdir -p ${prefix}/var/log/groonga/httpd + test/command/run-test.sh --testee groonga-httpd + ;; + cmake) + test/command/run-test.sh + ;; esac diff --git a/storage/mroonga/vendor/groonga/vendor/Makefile.am b/storage/mroonga/vendor/groonga/vendor/Makefile.am index 334b6fd8917..0b766191a08 100644 --- a/storage/mroonga/vendor/groonga/vendor/Makefile.am +++ b/storage/mroonga/vendor/groonga/vendor/Makefile.am @@ -11,6 +11,7 @@ EXTRA_DIST = \ mruby/CMakeLists.txt dist-hook: + rm -rf $(distdir)/$(NGINX_DIR)/objs/ GIT_DIR=$(srcdir)/mruby-source/.git git archive --format=tar HEAD | \ tar xf - -C $(distdir)/mruby-source $(MKDIR_P) $(distdir)/onigmo-source diff --git a/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt index 9f4aad4c32b..994ad5e0e6c 100644 --- a/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/vendor/mruby/CMakeLists.txt @@ -24,6 +24,8 @@ include_directories( if(GRN_WITH_MRUBY) read_file_list("${CMAKE_CURRENT_SOURCE_DIR}/sources.am" MRUBY_SOURCES) + string(REGEX REPLACE "\\.\\./" "${CMAKE_CURRENT_SOURCE_DIR}/../" + MRUBY_SOURCES "${MRUBY_SOURCES}") add_library(mruby OBJECT ${MRUBY_SOURCES}) set_source_files_properties(${MRUBY_SOURCES} PROPERTIES diff --git a/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am b/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am index 41385bcd589..dff8a235b49 100644 --- a/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am +++ b/storage/mroonga/vendor/groonga/vendor/mruby/Makefile.am @@ -1,9 +1,12 @@ EXTRA_DIST = \ - build_config.rb + build_config.rb \ + mruby-build.timestamp DEFAULT_INCLUDES = \ -I$(srcdir)/../mruby-source/include \ - -I$(srcdir)/../mruby-source/src + -I$(srcdir)/../mruby-source/src \ + -Imruby-io/include \ + -I$(srcdir)/mruby-io/include if WITH_MRUBY noinst_LTLIBRARIES = libmruby.la @@ -22,18 +25,31 @@ include sources.am BUILT_SOURCES = \ parse.c \ mrblib.c \ - mrbgems_init.c \ - mruby_onig_regexp.c + mrbgems_init.c +BUILT_SOURCES += \ + mruby-onig-regexp/src/mruby_onig_regexp.c +BUILT_SOURCES += \ + mruby-io/include/mruby/ext/io.h \ + mruby-io/src/file.c \ + mruby-io/src/file_test.c \ + mruby-io/src/io.c \ + mruby-io/src/mruby_io_gem.c libmruby_la_SOURCES += $(BUILT_SOURCES) parse.c: mruby-build.timestamp mrblib.c: mruby-build.timestamp mrbgems_init.c: mruby-build.timestamp -mruby_onig_regexp.c: mruby-build.timestamp +mruby-onig-regexp/src/mruby_onig_regexp.c: mruby-build.timestamp +mruby-io/include/mruby/ext/io.h: mruby-build.timestamp +mruby-io/src/file.c: mruby-build.timestamp +mruby-io/src/file_test.c: mruby-build.timestamp +mruby-io/src/io.c: mruby-build.timestamp +mruby-io/src/mruby_io_gem.c: mruby-build.timestamp MRUBY_CONFIG = $(abs_srcdir)/build_config.rb MRUBY_BUILD_DIR = $(abs_top_builddir)/vendor/mruby-build MRUBY_ONIG_REGEXP_DIR = $(MRUBY_BUILD_DIR)/mrbgems/mruby-onig-regexp +MRUBY_IO_DIR = $(MRUBY_BUILD_DIR)/mrbgems/mruby-io mruby-build.timestamp: build_config.rb rm -rf $(MRUBY_BUILD_DIR) cd $(srcdir)/../mruby-source && \ @@ -47,7 +63,11 @@ mruby-build.timestamp: build_config.rb cat $(MRUBY_BUILD_DIR)/host/mrbgems/gem_init.c; \ cat $(MRUBY_BUILD_DIR)/host/mrbgems/*/gem_init.c; \ ) > mrbgems_init.c - cp $(MRUBY_ONIG_REGEXP_DIR)/src/mruby_onig_regexp.c ./ + $(MKDIR_P) mruby-onig-regexp/ + cp -r $(MRUBY_ONIG_REGEXP_DIR)/src/ mruby-onig-regexp/ + $(MKDIR_P) mruby-io/ + cp -r $(MRUBY_IO_DIR)/include/ mruby-io/ + cp -r $(MRUBY_IO_DIR)/src/ mruby-io/ EXTRA_DIST += \ mruby-build.timestamp diff --git a/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb b/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb index 2380c04789d..65992c20340 100644 --- a/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb +++ b/storage/mroonga/vendor/groonga/vendor/mruby/build_config.rb @@ -30,4 +30,7 @@ MRuby::Build.new do |conf| conf.gem :core => "mruby-kernel-ext" conf.gem :github => "mattn/mruby-onig-regexp" + conf.gem :github => "iij/mruby-io" + conf.gem :github => "kou/mruby-pp" + conf.gem :github => "kou/mruby-slop" end diff --git a/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am b/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am index 772bfb420c6..9219783bbd7 100644 --- a/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am +++ b/storage/mroonga/vendor/groonga/vendor/onigmo/Makefile.am @@ -4,16 +4,13 @@ EXTRA_DIST = \ CONFIGURE_DEPENDENCIES = \ configure -ALL_DEPEND_TARGETS = -INSTALL_DEPEND_TARGETS = -CLEAN_DEPEND_TARGETS = -if WITH_MRUBY -ALL_DEPEND_TARGETS += onigmo-all +ALL_DEPEND_TARGETS = onigmo-all +CLEAN_DEPEND_TARGETS = onigmo-clean + +INSTALL_DEPEND_TARGETS = onigmo-all if WITH_SHARED_ONIGMO INSTALL_DEPEND_TARGETS += onigmo-install endif -CLEAN_DEPEND_TARGETS += onigmo-clean -endif onigmo-all: cd ../onigmo-source && $(MAKE) all diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS deleted file mode 100644 index 95053dbcb47..00000000000 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -See README.md. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt index 484a7d63bfd..3577572a9f1 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> +# Copyright(C) 2013-2015 Kouhei Sutou <kou@clear-code.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -18,6 +18,16 @@ cmake_minimum_required(VERSION 2.6) project(groonga-normalizer-mysql) +if(DEFINED GROONGA_NORMALIZER_MYSQL_EMBED) + set(GROONGA_NORMALIZER_MYSQL_EMBED_DEFAULT + ${GROONGA_NORMALIZER_MYSQL_EMBED}) +else() + set(GROONGA_NORMALIZER_MYSQL_EMBED_DEFAULT OFF) +endif() +option(GROONGA_NORMALIZER_MYSQL_EMBED + "Build as a static library to embed into an application" + ${GROONGA_NORMALIZER_MYSQL_EMBED_DEFAULT}) + file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version" VERSION) if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") @@ -53,12 +63,11 @@ link_directories( add_subdirectory(normalizers) -configure_file( - groonga-normalizer-mysql.pc.in - "${CMAKE_CURRENT_BINARY_DIR}/groonga-normalizer-mysql.pc" - @ONLY) - -if(NOT GROONGA_NORMALIZER_MYSQL_FOUND) +if(NOT GROONGA_NORMALIZER_MYSQL_EMBED) + configure_file( + groonga-normalizer-mysql.pc.in + "${CMAKE_CURRENT_BINARY_DIR}/groonga-normalizer-mysql.pc" + @ONLY) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/groonga-normalizer-mysql.pc" DESTINATION "lib/pkgconfig/") diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog deleted file mode 100644 index e69de29bb2d..00000000000 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/ChangeLog +++ /dev/null diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL deleted file mode 100644 index 95053dbcb47..00000000000 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/INSTALL +++ /dev/null @@ -1 +0,0 @@ -See README.md. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS deleted file mode 100644 index a4685347e88..00000000000 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/NEWS +++ /dev/null @@ -1 +0,0 @@ -See doc/text/news.md. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README deleted file mode 100644 index 95053dbcb47..00000000000 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README +++ /dev/null @@ -1 +0,0 @@ -See README.md. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md index 866aba84d40..a2fcf4c9f84 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/README.md @@ -6,8 +6,8 @@ groonga-normalizer-mysql ## Description -Groonga-normalizer-mysql is a groonga plugin. It provides MySQL -compatible normalizers and a custom normalizer to groonga. +Groonga-normalizer-mysql is a Groonga plugin. It provides MySQL +compatible normalizers and a custom normalizer to Groonga. MySQL compatible normalizers are `NormalizerMySQLGeneralCI` and `NormalizerMySQLUnicodeCI`. `NormalizerMySQLGeneralCI` corresponds to @@ -62,14 +62,14 @@ doesn't identify them. ### Debian GNU/Linux -[Add apt-line for the groonga deb package repository](http://groonga.org/docs/install/debian.html) +[Add apt-line for the Groonga deb package repository](http://groonga.org/docs/install/debian.html) and install `groonga-normalizer-mysql` package: % sudo aptitude -V -D -y install groonga-normalizer-mysql ### Ubuntu -[Add apt-line for the groonga deb package repository](http://groonga.org/docs/install/ubuntu.html) +[Add apt-line for the Groonga deb package repository](http://groonga.org/docs/install/ubuntu.html) and install `groonga-normalizer-mysql` package: % sudo aptitude -V -D -y install groonga-normalizer-mysql @@ -114,16 +114,16 @@ Install the following build tools: * [Microsoft Visual Studio 2010 Express](http://www.microsoft.com/japan/msdn/vstudio/express/): 2012 isn't tested yet. * [CMake](http://www.cmake.org/) -#### Build groonga +#### Build Groonga -Download the latest groonga source from [packages.groonga.org](http://packages.groonga.org/source/groonga/). Source file name is formatted as `groonga-X.Y.Z.zip`. +Download the latest Groonga source from [packages.groonga.org](http://packages.groonga.org/source/groonga/). Source file name is formatted as `groonga-X.Y.Z.zip`. Extract the source and move to the source folder: > cd ...\groonga-X.Y.Z groonga-X.Y.Z> -Run CMake. Here is a command line to install groonga to `C:\groonga` folder: +Run CMake. Here is a command line to install Groonga to `C:\groonga` folder: groonga-X.Y.Z> cmake . -G "Visual Studio 10 Win64" -DCMAKE_INSTALL_PREFIX=C:\groonga @@ -148,7 +148,7 @@ IMPORTANT!!!: Set `PKG_CONFIG_PATH` environment variable: groonga-normalizer-mysql-X.Y.Z> set PKG_CONFIG_PATH=C:\groongalocal\lib\pkgconfig -Run CMake. Here is a command line to install groonga to `C:\groonga` folder: +Run CMake. Here is a command line to install Groonga to `C:\groonga` folder: groonga-normalizer-mysql-X.Y.Z> cmake . -G "Visual Studio 10 Win64" -DCMAKE_INSTALL_PREFIX=C:\groonga @@ -173,7 +173,7 @@ Then, you can use `NormalizerMySQLGeneralCI` and ## Dependencies -* groonga >= 3.0.3 +* Groonga >= 3.0.3 ## Mailing list diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac index effb5884f93..1ef007bb6df 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/configure.ac @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com> +# Copyright (C) 2013-2015 Kouhei Sutou <kou@clear-code.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -24,7 +24,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([normalizers/mysql.c]) AM_CONFIG_HEADER([config.h]) -AM_INIT_AUTOMAKE([1.9 tar-pax]) +AM_INIT_AUTOMAKE([1.9 foreign tar-pax]) AC_PROG_LIBTOOL @@ -49,11 +49,23 @@ AC_SUBST(GROONGA) normalizers_pluginsdir="\${GROONGA_PLUGINS_DIR}/normalizers" AC_SUBST(normalizers_pluginsdir) +AC_ARG_ENABLE([embed], + AS_HELP_STRING([--enable-embed], + [Build as a static library to embed into an application (default: no)]), + [GROONGA_NORMALIZER_MYSQL_EMBED="$enableval"], + [GROONGA_NORMALIZER_MYSQL_EMBED="no"]) + +if test "x$GROONGA_NORMALIZER_MYSQL_EMBED" = "xyes"; then + AC_DEFINE_UNQUOTED(GROONGA_NORMALIZER_MYSQL_EMBED, + [1], + [Define to 1 if groonga-normalizer-mysql is built for embedding.]) +fi + # check Ruby for test ac_cv_ruby_available="no" -AC_ARG_WITH([ruby19], - AS_HELP_STRING([--with-ruby19=PATH], - [Ruby 1.9 interpreter path (default: auto)]), +AC_ARG_WITH([ruby], + AS_HELP_STRING([--with-ruby=PATH], + [Ruby interpreter path (default: auto)]), [RUBY="$withval"], [RUBY="auto"]) @@ -61,17 +73,19 @@ if test "x$RUBY" = "xno"; then RUBY= else if test "x$RUBY" = "xauto"; then - AC_PATH_PROGS(RUBY, [ruby1.9 ruby19 ruby1.9.1 ruby], ruby19-not-found) - if test "$RUBY" != "ruby19-not-found"; then + AC_PATH_PROGS(RUBY, + [ruby2.1 ruby21 ruby2.0 ruby20 ruby1.9 ruby19 ruby1.9.1 ruby], + ruby-not-found) + if test "$RUBY" != "ruby-not-found"; then ruby_version="`$RUBY --version`" - if echo "$ruby_version" | grep -q -- 'ruby 1\.9'; then + if echo "$ruby_version" | grep -q -- 'ruby \(1\.9\|2\.\)'; then ac_cv_ruby_available="yes" else - AC_MSG_WARN([$RUBY isn't Ruby 1.9 ($ruby_version)]) + AC_MSG_WARN([$RUBY isn't Ruby 1.9 or later ($ruby_version)]) fi fi else - ruby_not_found_warning_message="$RUBY is not found. Disable HTTP test." + ruby_not_found_warning_message="$RUBY is not found. Disable test." case "$RUBY" in /*) AC_CHECK_FILE([$RUBY], diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am index 52dbe4a8f0d..6adf4f103e9 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/Makefile.am @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com> +# Copyright (C) 2013-2015 Kouhei Sutou <kou@clear-code.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -16,4 +16,5 @@ docdir = $(datadir)/doc/$(PACKAGE) dist_doc_DATA = \ - lgpl-2.0.txt + lgpl-2.0.txt \ + news.md diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md new file mode 100644 index 00000000000..9f367a56671 --- /dev/null +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/doc/text/news.md @@ -0,0 +1,12 @@ +# News + +## 1.0.8: 2015-02-10 + +### Fixes + + * Fix registering error when you build with configure. + [GitHub#3][Reported by Kazuhiko] + +### Thanks + + * Kazuhiko diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt index ae290b66347..81b2b963abb 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright(C) 2013 Kouhei Sutou <kou@clear-code.com> +# Copyright(C) 2013-2015 Kouhei Sutou <kou@clear-code.com> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public @@ -17,11 +17,15 @@ set(NORMALIZERS_DIR "${GROONGA_PLUGINS_DIR}/normalizers") read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mysql_sources.am MYSQL_SOURCES) -add_library(mysql_normalizer MODULE ${MYSQL_SOURCES}) -set_target_properties(mysql_normalizer PROPERTIES - PREFIX "" - OUTPUT_NAME "mysql") -target_link_libraries(mysql_normalizer ${GROONGA_LIBRARIES}) -if(NOT MRN_GROONGA_BUNDLED) +if(GROONGA_NORMALIZER_MYSQL_EMBED) + add_library(mysql_normalizer STATIC ${MYSQL_SOURCES}) + set_property(TARGET mysql_normalizer APPEND PROPERTY + COMPILE_DEFINITIONS "GROONGA_NORMALIZER_MYSQL_EMBED") +else() + add_library(mysql_normalizer MODULE ${MYSQL_SOURCES}) + set_target_properties(mysql_normalizer PROPERTIES + PREFIX "" + OUTPUT_NAME "mysql") install(TARGETS mysql_normalizer DESTINATION "${NORMALIZERS_DIR}") endif() +target_link_libraries(mysql_normalizer ${GROONGA_LIBRARIES}) diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c index 94acfb16389..d9e8de4d4a0 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/normalizers/mysql.c @@ -1,6 +1,6 @@ /* -*- c-basic-offset: 2 -*- */ /* - Copyright(C) 2013-2014 Kouhei Sutou <kou@clear-code.com> + Copyright(C) 2013-2015 Kouhei Sutou <kou@clear-code.com> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -18,6 +18,14 @@ MA 02110-1301, USA */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef GROONGA_NORMALIZER_MYSQL_EMBED +# define GRN_PLUGIN_FUNCTION_TAG normalizers_mysql +#endif + #include <groonga/normalizer.h> #include <groonga/nfkc.h> diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile index 97ba2496071..a7e11791feb 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/Vagrantfile @@ -8,12 +8,11 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| vms = [ { :id => "debian-wheezy-i386", - :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.6-i386_chef-provisionerless.box -", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8-i386_chef-provisionerless.box", }, { :id => "debian-wheezy-amd64", - :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.6_chef-provisionerless.box", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_debian-7.8_chef-provisionerless.box", }, ] diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh index fdfc8f52f03..21bf8af6b35 100755 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/apt/build-deb.sh @@ -54,4 +54,4 @@ run cd - package_initial=$(echo "${PACKAGE}" | sed -e 's/\(.\).*/\1/') pool_dir="/vagrant/repositories/${distribution}/pool/${code_name}/${component}/${package_initial}/${PACKAGE}" run mkdir -p "${pool_dir}/" -run cp *.tar.gz *.dsc *.deb "${pool_dir}/" +run cp *.tar.gz *.diff.gz *.dsc *.deb "${pool_dir}/" diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog index 245c138a35a..a02be693955 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/changelog @@ -1,3 +1,15 @@ +groonga-normalizer-mysql (1.0.8-1) unstable; urgency=low + + * New upstream release. + + -- Kouhei Sutou <kou@clear-code.com> Tue, 10 Feb 2015 00:00:00 +0900 + +groonga-normalizer-mysql (1.0.7-1) unstable; urgency=low + + * New upstream release. + + -- <hayashi@clear-code.com> Mon, 09 Feb 2015 00:00:00 +0900 + groonga-normalizer-mysql (1.0.6-1) unstable; urgency=low * New upstream release. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control index 20c456b0a76..37a3805d966 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/control @@ -1,25 +1,31 @@ Source: groonga-normalizer-mysql Section: libs Priority: optional -Maintainer: Kouhei Sutou <kou@clear-code.com> +Maintainer: Groonga Project <packages@groonga.org> Build-Depends: debhelper (>= 9), autotools-dev, pkg-config, libgroonga-dev (>= 3.0.0) Standards-Version: 3.9.3 -Homepage: http://groonga.org/ +Homepage: https://github.com/groonga/groonga-normalizer-mysql Package: groonga-normalizer-mysql -Section: libs Architecture: any Depends: ${misc:Depends}, ${shlibs:Depends}, libgroonga0 -Description: MySQL derived normalizer for groonga. +Description: MySQL derived normalizer for Groonga Groonga is an open-source fulltext search engine and column store. - It lets you write high-performance applications that requires fulltext search. + It lets you write high-performance applications that requires fulltext + search. . - This package provides a normalizer which normalizes text as same as MySQL does. - + This package provides a normalizer which normalizes text as same as + MySQL does. + . + Groonga has its own normalizers by default, but that behavior is a bit + defferent from MySQL does, so as a result, it affects search results. + These normalizers are useful if you regards it important for keeping + normalizer compatibility with MySQL in Mroonga which uses Groonga as + storage engine. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright index cd3295a134c..79b0d9c4e1f 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/copyright @@ -1,29 +1,85 @@ -This package was debianized by Kouhei Sutou <kou@clear-code.com> on -Tue, 29 Jan 2013 14:52:04 +0000. +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Contact: Kouhei Sutou <kou at clear-code.com> +Source: http://packages.groonga.org/source/groonga-normalizer-mysql/ -It was downloaded from <http://groonga.org/> +Files: * +Copyright: 2013 Kouhei Sutou <kou@clear-code.com> +License: LGPL-2 -Upstream Author(s): +Files: debian/* +Copyright: 2013 Kouhei Sutou <kou@clear-code.com> + 2013 HAYASHI Kentaro <hayashi@clear-code.com> +License: LGPL-2 - Kouhei Sutou <kou at clear-code.com> +Files: test/run-test.sh +Copyright: 2013 Kouhei Sutou <kou@clear-code.com> +License: LGPL-2+ -Copyright: +Files: normalizers/mysql_general_ci_table.h +Copyright: 2013 Kouhei Sutou <kou@clear-code.com> + 2000, 2012, Oracle and/or its affiliates +License: LGPL-2 - Copyright(C) 2013 Brazil +Files: normalizers/mysql_unicode_ci_*.h +Copyright: 2013 Kouhei Sutou <kou@clear-code.com> + 2004, 2011, Oracle and/or its affiliates +License: LGPL-2 -License: +Files: ltmain.sh +Copyright: 1996, Gordon Matzigkeit <gord@gnu.ai.mit.edu> + 1996-2011, Free Software Foundation, Inc. +License: GPL-2+ with Libtool exception + GNU Libtool is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + As a special exception to the GNU General Public License, + if you distribute this file as part of a program or library that + is built using GNU Libtool, you may include this file under the + same distribution terms that you use for the rest of that program. + . + GNU Libtool 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 + General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with GNU Libtool; see the file COPYING. If not, a copy + can be downloaded from http://www.gnu.org/licenses/gpl.html, + or obtained by writing to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - This library 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 2 of the License. +License: LGPL-2 + This library 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, version 2 of the License. + . + 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 program. If not, see <http://www.gnu.org/licenses/>. + . + The Debian packaging is (C) 2013, Kouhei Sutou <kou@clear-code.com> and + is licensed under the LGPL-2, see `/usr/share/common-licenses/LGPL-2'. - 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 program. If not, see <http://www.gnu.org/licenses/>. - -The Debian packaging is (C) 2013, Kouhei Sutou <kou@clear-code.com> and -is licensed under the LGPL-2, see `/usr/share/common-licenses/LGPL-2'. +License: LGPL-2+ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 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 + Library General Public License for more details. + . + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU Library General Public + License version 2 can be found in the file `/usr/share/common-licenses/LGPL-2'. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules index 811e09274c0..753d4484cf8 100755 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/rules @@ -13,3 +13,5 @@ export DH_OPTIONS override_dh_auto_test: override_dh_install: + find $(CURDIR) -name '*.la' -delete + find $(CURDIR) -name 'lgpl-2.0.txt' -delete diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch new file mode 100644 index 00000000000..ab451e4c004 --- /dev/null +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/debian/watch @@ -0,0 +1,2 @@ +version=3 +http://packages.groonga.org/source/groonga-normalizer-mysql/groonga-normalizer-mysql-(.+).tar.gz diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in index e51bae6990d..b4751c43762 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/centos/groonga-normalizer-mysql.spec.in @@ -42,7 +42,6 @@ make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la %files -%doc README AUTHORS COPYING %dir %{_libdir}/groonga %dir %{_libdir}/groonga/plugins %dir %{_libdir}/groonga/plugins/normalizers @@ -53,6 +52,12 @@ rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la %{_libdir}/pkgconfig/groonga-normalizer-mysql.pc %changelog +* Tue Feb 10 2015 Kouhei Sutou <kou@clear-code.com> - 1.0.8-1 +- new upstream release. + +* Mon Feb 09 2015 HAYASHI Kentaro <hayashi@clear-code.com> - 1.0.7-1 +- new upstream release. + * Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 1.0.6-1 - new upstream release. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in index 3be5e0797db..fbde53c117f 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/rpm/fedora/groonga-normalizer-mysql.spec.in @@ -41,7 +41,6 @@ make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la %files -%doc README AUTHORS COPYING %dir %{_libdir}/groonga %dir %{_libdir}/groonga/plugins %dir %{_libdir}/groonga/plugins/normalizers @@ -52,6 +51,12 @@ rm $RPM_BUILD_ROOT%{_libdir}/groonga/plugins/*/*.la %{_libdir}/pkgconfig/groonga-normalizer-mysql.pc %changelog +* Tue Feb 10 2015 Kouhei Sutou <kou@clear-code.com> - 1.0.8-1 +- new upstream release. + +* Mon Feb 09 2015 <hayashi@clear-code.com> - 1.0.7-1 +- new upstream release. + * Sun Feb 09 2014 HAYASHI Kentaro <hayashi@clear-code.com> - 1.0.6-1 - new upstream release. diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am index 3b616910900..4afc4a982f0 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/ubuntu/Makefile.am @@ -1,4 +1,4 @@ -CODE_NAMES = precise,trusty +CODE_NAMES = precise,trusty,utopic SOURCE = ../$(PACKAGE)-$(VERSION).tar.gz all: diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am index ea62f6e427e..edd546fbae1 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Makefile.am @@ -1,7 +1,6 @@ REPOSITORIES_PATH = repositories DISTRIBUTIONS = centos ARCHITECTURES = i386 x86_64 -HAVE_DEVELOPMENT_BRANCH = no release: download build sign-packages update-repository upload diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile index 4238d678721..87866a3a0ac 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/packages/yum/Vagrantfile @@ -8,19 +8,19 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| vms = [ { :id => "centos-5-i386", - :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.10-i386_chef-provisionerless.box", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11-i386_chef-provisionerless.box", }, { :id => "centos-5-x86_64", - :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.10_chef-provisionerless.box", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-5.11_chef-provisionerless.box", }, { :id => "centos-6-i386", - :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5-i386_chef-provisionerless.box", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6-i386_chef-provisionerless.box", }, { :id => "centos-6-x86_64", - :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box", + :box_url => "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.6_chef-provisionerless.box", }, { :id => "centos-7-x86_64", diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version index ece61c60124..337a6a8f189 100644 --- a/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version +++ b/storage/mroonga/vendor/groonga/vendor/plugins/groonga-normalizer-mysql/version @@ -1 +1 @@ -1.0.6
\ No newline at end of file +1.0.8
\ No newline at end of file diff --git a/storage/mroonga/version b/storage/mroonga/version index b0372476047..2defa1a3bb8 100644 --- a/storage/mroonga/version +++ b/storage/mroonga/version @@ -1 +1 @@ -4.06
\ No newline at end of file +5.00
\ No newline at end of file diff --git a/storage/mroonga/version_in_hex b/storage/mroonga/version_in_hex index 6f503be55dd..960c1688afd 100644 --- a/storage/mroonga/version_in_hex +++ b/storage/mroonga/version_in_hex @@ -1 +1 @@ -0x0406
\ No newline at end of file +0x0500
\ No newline at end of file diff --git a/storage/mroonga/version_major b/storage/mroonga/version_major index bf0d87ab1b2..7813681f5b4 100644 --- a/storage/mroonga/version_major +++ b/storage/mroonga/version_major @@ -1 +1 @@ -4
\ No newline at end of file +5
\ No newline at end of file diff --git a/storage/mroonga/version_micro b/storage/mroonga/version_micro index 62f9457511f..c227083464f 100644 --- a/storage/mroonga/version_micro +++ b/storage/mroonga/version_micro @@ -1 +1 @@ -6
\ No newline at end of file +0
\ No newline at end of file |