Merge branch 'ks-10.1-mroonga' into 10.1

This commit is contained in:
Sergei Golubchik 2017-11-10 01:14:55 +01:00
commit d79fd5ba7f
1798 changed files with 171923 additions and 108728 deletions

View file

@ -1,4 +1,4 @@
# Copyright(C) 2015 Brazil
# Copyright(C) 2015-2017 Brazil
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@ -38,3 +38,104 @@ else()
install(TARGETS vector_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}")
endif()
target_link_libraries(vector_functions libgroonga)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/string_sources.am
STRING_SOURCES)
set_source_files_properties(${STRING_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
if(GRN_EMBED)
add_library(string_functions STATIC ${STRING_SOURCES})
set_target_properties(
string_functions
PROPERTIES
POSITION_INDEPENDENT_CODE ON)
else()
add_library(string_functions MODULE ${STRING_SOURCES})
set_target_properties(string_functions PROPERTIES
PREFIX ""
OUTPUT_NAME "string")
install(TARGETS string_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}")
endif()
target_link_libraries(string_functions libgroonga)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/number_sources.am
NUMBER_SOURCES)
set_source_files_properties(${NUMBER_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
if(GRN_EMBED)
add_library(number_functions STATIC ${NUMBER_SOURCES})
set_target_properties(
number_functions
PROPERTIES
POSITION_INDEPENDENT_CODE ON)
else()
add_library(number_functions MODULE ${NUMBER_SOURCES})
set_target_properties(number_functions PROPERTIES
PREFIX ""
OUTPUT_NAME "number")
install(TARGETS number_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}")
endif()
target_link_libraries(number_functions libgroonga "${M_LIBS}")
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/time_sources.am
TIME_SOURCES)
set_source_files_properties(${TIME_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
if(GRN_EMBED)
add_library(time_functions STATIC ${TIME_SOURCES})
set_target_properties(
time_functions
PROPERTIES
POSITION_INDEPENDENT_CODE ON)
else()
add_library(time_functions MODULE ${TIME_SOURCES})
set_target_properties(time_functions PROPERTIES
PREFIX ""
OUTPUT_NAME "time")
install(TARGETS time_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}")
endif()
target_link_libraries(time_functions libgroonga)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/index_column_sources.am
INDEX_COLUMN_SOURCES)
set_source_files_properties(${INDEX_COLUMN_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
if(GRN_EMBED)
add_library(index_column_functions STATIC ${INDEX_COLUMN_SOURCES})
set_target_properties(
index_column_functions
PROPERTIES
POSITION_INDEPENDENT_CODE ON)
else()
add_library(index_column_functions MODULE ${INDEX_COLUMN_SOURCES})
set_target_properties(index_column_functions PROPERTIES
PREFIX ""
OUTPUT_NAME "index_column")
install(TARGETS index_column_functions
DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}")
endif()
target_link_libraries(index_column_functions libgroonga)
read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/math_sources.am
MATH_SOURCES)
set_source_files_properties(${MATH_SOURCES}
PROPERTIES
COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}")
if(GRN_EMBED)
add_library(math_functions STATIC ${MATH_SOURCES})
set_target_properties(
math_functions
PROPERTIES
POSITION_INDEPENDENT_CODE ON)
else()
add_library(math_functions MODULE ${MATH_SOURCES})
set_target_properties(math_functions PROPERTIES
PREFIX ""
OUTPUT_NAME "math")
install(TARGETS math_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}")
endif()
target_link_libraries(math_functions libgroonga)

View file

@ -16,5 +16,18 @@ LIBS = \
function_plugins_LTLIBRARIES =
function_plugins_LTLIBRARIES += vector.la
function_plugins_LTLIBRARIES += string.la
function_plugins_LTLIBRARIES += number.la
function_plugins_LTLIBRARIES += time.la
function_plugins_LTLIBRARIES += index_column.la
function_plugins_LTLIBRARIES += math.la
include vector_sources.am
include string_sources.am
include number_sources.am
include time_sources.am
include index_column_sources.am
include math_sources.am
number_la_LIBADD = -lm
math_la_LIBADD = -lm

View file

@ -0,0 +1,266 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2017 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 GRN_EMBEDDED
# define GRN_PLUGIN_FUNCTION_TAG functions_time
#endif
#include <groonga/plugin.h>
static grn_rc
selector_index_column_df_ratio_between(grn_ctx *ctx,
grn_obj *table,
grn_obj *index,
int n_args,
grn_obj **args,
grn_obj *res,
grn_operator op)
{
grn_rc rc = GRN_SUCCESS;
grn_obj *index_column;
grn_ii *ii;
double min;
double max;
grn_obj *source_table;
unsigned int n_documents;
grn_posting posting;
if ((n_args - 1) != 3) {
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio_between(): "
"wrong number of arguments (%d for 3)", n_args - 1);
rc = ctx->rc;
goto exit;
}
index_column = args[1];
ii = (grn_ii *)index_column;
min = GRN_FLOAT_VALUE(args[2]);
max = GRN_FLOAT_VALUE(args[3]);
source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index_column));
n_documents = grn_table_size(ctx, source_table);
memset(&posting, 0, sizeof(grn_posting));
posting.sid = 1;
if (op == GRN_OP_AND) {
GRN_TABLE_EACH_BEGIN(ctx, res, cursor, record_id) {
void *key;
grn_id term_id;
uint32_t n_match_documents;
double df_ratio;
grn_table_cursor_get_key(ctx, cursor, &key);
term_id = *(grn_id *)key;
n_match_documents = grn_ii_estimate_size(ctx, ii, term_id);
if (n_match_documents > n_documents) {
n_match_documents = n_documents;
}
df_ratio = (double)n_match_documents / (double)n_documents;
if (min <= df_ratio && df_ratio <= max) {
posting.rid = term_id;
grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op);
}
} GRN_TABLE_EACH_END(ctx, cursor);
grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op);
} else {
GRN_TABLE_EACH_BEGIN(ctx, table, cursor, term_id) {
uint32_t n_match_documents;
double df_ratio;
n_match_documents = grn_ii_estimate_size(ctx, ii, term_id);
if (n_match_documents > n_documents) {
n_match_documents = n_documents;
}
df_ratio = (double)n_match_documents / (double)n_documents;
{
void *key;
int key_size;
key_size = grn_table_cursor_get_key(ctx, cursor, &key);
}
if (min <= df_ratio && df_ratio <= max) {
posting.rid = term_id;
grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op);
}
} GRN_TABLE_EACH_END(ctx, cursor);
}
exit :
return rc;
}
static grn_obj *
func_index_column_df_ratio(grn_ctx *ctx,
int n_args,
grn_obj **args,
grn_user_data *user_data)
{
grn_obj *term_table;
grn_obj *index_column_name;
grn_obj *index_column;
grn_ii *ii;
grn_id term_id;
if (n_args != 1) {
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio(): "
"wrong number of arguments (%d for 1)", n_args - 1);
return NULL;
}
{
grn_obj *expr;
grn_obj *variable;
expr = grn_plugin_proc_get_caller(ctx, user_data);
if (!expr) {
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio(): "
"called directly");
return NULL;
}
variable = grn_expr_get_var_by_offset(ctx, expr, 0);
if (!variable) {
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio(): "
"caller expression must have target record information");
return NULL;
}
term_table = grn_ctx_at(ctx, variable->header.domain);
term_id = GRN_RECORD_VALUE(variable);
while (GRN_TRUE) {
grn_obj *key_type;
key_type = grn_ctx_at(ctx, term_table->header.domain);
if (!grn_obj_is_table(ctx, key_type)) {
break;
}
grn_table_get_key(ctx, term_table, term_id, &term_id, sizeof(grn_id));
term_table = key_type;
}
}
index_column_name = args[0];
if (!grn_obj_is_text_family_bulk(ctx, index_column_name)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, index_column_name);
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio(): "
"the first argument must be index column name: %.*s",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
index_column = grn_obj_column(ctx,
term_table,
GRN_TEXT_VALUE(index_column_name),
GRN_TEXT_LEN(index_column_name));
if (!index_column) {
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio(): "
"nonexistent object: <%.*s>",
(int)GRN_TEXT_LEN(index_column_name),
GRN_TEXT_VALUE(index_column_name));
return NULL;
}
if (!grn_obj_is_index_column(ctx, index_column)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, index_column);
GRN_PLUGIN_ERROR(ctx,
GRN_INVALID_ARGUMENT,
"index_column_df_ratio(): "
"the first argument must be index column: %.*s",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
if (grn_obj_is_accessor(ctx, index_column)) {
grn_obj_unlink(ctx, index_column);
}
return NULL;
}
ii = (grn_ii *)index_column;
{
grn_obj *source_table;
unsigned int n_documents;
uint32_t n_match_documents;
double df_ratio;
grn_obj *df_ratio_value;
source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index_column));
n_documents = grn_table_size(ctx, source_table);
n_match_documents = grn_ii_estimate_size(ctx, ii, term_id);
if (n_match_documents > n_documents) {
n_match_documents = n_documents;
}
df_ratio = (double)n_match_documents / (double)n_documents;
df_ratio_value = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_FLOAT, 0);
if (!df_ratio_value) {
return NULL;
}
GRN_FLOAT_SET(ctx, df_ratio_value, df_ratio);
return df_ratio_value;
}
}
grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
return ctx->rc;
}
grn_rc
GRN_PLUGIN_REGISTER(grn_ctx *ctx)
{
grn_obj *selector_proc;
selector_proc = grn_proc_create(ctx, "index_column_df_ratio_between", -1,
GRN_PROC_FUNCTION,
NULL, NULL, NULL, 0, NULL);
grn_proc_set_selector(ctx, selector_proc,
selector_index_column_df_ratio_between);
grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP);
grn_proc_create(ctx, "index_column_df_ratio", -1,
GRN_PROC_FUNCTION,
func_index_column_df_ratio, NULL, NULL, 0, NULL);
return ctx->rc;
}
grn_rc
GRN_PLUGIN_FIN(grn_ctx *ctx)
{
return GRN_SUCCESS;
}

View file

@ -0,0 +1,2 @@
index_column_la_SOURCES = \
index_column.c

View file

@ -0,0 +1,142 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2017 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 GRN_EMBEDDED
# define GRN_PLUGIN_FUNCTION_TAG functions_math
#endif
#include <groonga/plugin.h>
#include <math.h>
#include <stdlib.h>
static grn_obj *
func_math_abs(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
grn_obj *number;
grn_obj *grn_abs_number = NULL;
if (n_args != 1) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"math_abs(): wrong number of arguments (%d for 1)",
n_args);
return NULL;
}
number = args[0];
if (!(number->header.type == GRN_BULK &&
grn_type_id_is_number_family(ctx, number->header.domain))) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, number);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"math_abs(): the first argument must be a number: "
"<%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
#define ABS_AS_IS(return_type, to_type, getter, setter) { \
grn_abs_number = grn_plugin_proc_alloc(ctx, \
user_data, \
(return_type), \
0); \
if (!grn_abs_number) { \
return NULL; \
} \
setter(ctx, grn_abs_number, getter(number)); \
}
#define ABS_CONVERT_TYPE(func, return_type, to_type, getter, setter) { \
grn_abs_number = grn_plugin_proc_alloc(ctx, \
user_data, \
(return_type), \
0); \
if (!grn_abs_number) { \
return NULL; \
} else { \
to_type abs_number_raw = (to_type)(func)(getter(number)); \
setter(ctx, grn_abs_number, abs_number_raw); \
} \
}
switch (number->header.domain) {
case GRN_DB_INT8:
ABS_CONVERT_TYPE(abs, GRN_DB_UINT8, uint8_t, GRN_INT8_VALUE, GRN_UINT8_SET);
break;
case GRN_DB_UINT8:
ABS_AS_IS(GRN_DB_UINT8, uint8_t, GRN_UINT8_VALUE, GRN_UINT8_SET);
break;
case GRN_DB_INT16:
ABS_CONVERT_TYPE(abs, GRN_DB_UINT16, uint16_t, GRN_INT16_VALUE, GRN_UINT16_SET);
break;
case GRN_DB_UINT16:
ABS_AS_IS(GRN_DB_UINT16, uint16_t, GRN_UINT16_VALUE, GRN_UINT16_SET);
break;
case GRN_DB_INT32:
ABS_CONVERT_TYPE(labs, GRN_DB_UINT32, uint32_t, GRN_INT32_VALUE, GRN_UINT32_SET);
break;
case GRN_DB_UINT32:
ABS_AS_IS(GRN_DB_UINT32, uint32_t, GRN_UINT32_VALUE, GRN_UINT32_SET);
break;
case GRN_DB_INT64:
ABS_CONVERT_TYPE(llabs, GRN_DB_UINT64, uint64_t, GRN_INT64_VALUE, GRN_UINT64_SET);
break;
case GRN_DB_UINT64:
ABS_AS_IS(GRN_DB_UINT64, uint64_t, GRN_UINT64_VALUE, GRN_UINT64_SET);
break;
case GRN_DB_FLOAT:
ABS_CONVERT_TYPE(fabs, GRN_DB_FLOAT, double, GRN_FLOAT_VALUE, GRN_FLOAT_SET);
break;
default :
break;
}
#undef ABS_CONVERT_TYPE
#undef ABS_AS_IS
return grn_abs_number;
}
grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
return ctx->rc;
}
grn_rc
GRN_PLUGIN_REGISTER(grn_ctx *ctx)
{
grn_rc rc = GRN_SUCCESS;
grn_proc_create(ctx,
"math_abs", -1,
GRN_PROC_FUNCTION,
func_math_abs,
NULL, NULL, 0, NULL);
return rc;
}
grn_rc
GRN_PLUGIN_FIN(grn_ctx *ctx)
{
return GRN_SUCCESS;
}

View file

@ -0,0 +1,2 @@
math_la_SOURCES = \
math.c

View file

@ -0,0 +1,187 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2016 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 GRN_EMBEDDED
# define GRN_PLUGIN_FUNCTION_TAG functions_number
#endif
#include <groonga/plugin.h>
#include <math.h>
static grn_obj *
func_number_classify(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
grn_obj *number;
grn_obj *interval;
grn_obj casted_interval;
grn_obj *classed_number;
if (n_args != 2) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"number_classify(): wrong number of arguments (%d for 2)",
n_args);
return NULL;
}
number = args[0];
if (!(number->header.type == GRN_BULK &&
grn_type_id_is_number_family(ctx, number->header.domain))) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, number);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"number_classify(): the first argument must be a number: "
"<%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
interval = args[1];
if (!(interval->header.type == GRN_BULK &&
grn_type_id_is_number_family(ctx, interval->header.domain))) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, interval);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"number_classify(): the second argument must be a number: "
"<%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
classed_number = grn_plugin_proc_alloc(ctx,
user_data,
number->header.domain,
0);
if (!classed_number) {
return NULL;
}
GRN_VALUE_FIX_SIZE_INIT(&casted_interval, 0, number->header.domain);
grn_obj_cast(ctx, interval, &casted_interval, GRN_FALSE);
#define CLASSIFY_RAW(type, getter, setter, classifier) { \
type number_raw; \
type interval_raw; \
type class_raw; \
type classed_number_raw; \
\
number_raw = getter(number); \
interval_raw = getter(&casted_interval); \
class_raw = classifier(number_raw, interval_raw); \
classed_number_raw = class_raw * interval_raw; \
setter(ctx, classed_number, classed_number_raw); \
}
#define CLASSIFIER_INT(number_raw, interval_raw) \
(number_raw) < 0 ? \
((((number_raw) + 1) / (interval_raw)) - 1) : \
(((number_raw) / (interval_raw)))
#define CLASSIFY_INT(type, getter, setter) \
CLASSIFY_RAW(type, getter, setter, CLASSIFIER_INT)
#define CLASSIFIER_UINT(number_raw, interval_raw) \
((number_raw) / (interval_raw))
#define CLASSIFY_UINT(type, getter, setter) \
CLASSIFY_RAW(type, getter, setter, CLASSIFIER_UINT)
#define CLASSIFIER_FLOAT(number_raw, interval_raw) \
floor((number_raw) / (interval_raw))
#define CLASSIFY_FLOAT(getter, setter) \
CLASSIFY_RAW(double, getter, setter, CLASSIFIER_FLOAT)
switch (number->header.domain) {
case GRN_DB_INT8 :
CLASSIFY_INT(int8_t, GRN_INT8_VALUE, GRN_INT8_SET);
break;
case GRN_DB_UINT8 :
CLASSIFY_UINT(uint8_t, GRN_UINT8_VALUE, GRN_UINT8_SET);
break;
case GRN_DB_INT16 :
CLASSIFY_INT(int16_t, GRN_INT16_VALUE, GRN_INT16_SET);
break;
case GRN_DB_UINT16 :
CLASSIFY_UINT(uint16_t, GRN_UINT16_VALUE, GRN_UINT16_SET);
break;
case GRN_DB_INT32 :
CLASSIFY_INT(int32_t, GRN_INT32_VALUE, GRN_INT32_SET);
break;
case GRN_DB_UINT32 :
CLASSIFY_UINT(uint32_t, GRN_UINT32_VALUE, GRN_UINT32_SET);
break;
case GRN_DB_INT64 :
CLASSIFY_INT(int64_t, GRN_INT64_VALUE, GRN_INT64_SET);
break;
case GRN_DB_UINT64 :
CLASSIFY_UINT(uint64_t, GRN_UINT64_VALUE, GRN_UINT64_SET);
break;
case GRN_DB_FLOAT :
CLASSIFY_FLOAT(GRN_FLOAT_VALUE, GRN_FLOAT_SET);
break;
default :
break;
}
#undef CLASSIFY_FLOAT
#undef CLASSIFIER_FLAOT
#undef CLASSIFY_UINT
#undef CLASSIFIER_UINT
#undef CLASSIFY_INT
#undef CLASSIFIER_INT
#undef CLASSIFY_RAW
GRN_OBJ_FIN(ctx, &casted_interval);
return classed_number;
}
grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
return ctx->rc;
}
grn_rc
GRN_PLUGIN_REGISTER(grn_ctx *ctx)
{
grn_rc rc = GRN_SUCCESS;
grn_proc_create(ctx,
"number_classify", -1,
GRN_PROC_FUNCTION,
func_number_classify,
NULL, NULL, 0, NULL);
return rc;
}
grn_rc
GRN_PLUGIN_FIN(grn_ctx *ctx)
{
return GRN_SUCCESS;
}

View file

@ -0,0 +1,2 @@
number_la_SOURCES = \
number.c

View file

@ -0,0 +1,299 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2016 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 GRN_EMBEDDED
# define GRN_PLUGIN_FUNCTION_TAG functions_string
#endif
#include <groonga/plugin.h>
/*
* func_string_length() returns the number of characters in a string.
* If the string contains an invalid byte sequence, this function returns the
* number of characters before the invalid byte sequence.
*/
static grn_obj *
func_string_length(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
grn_obj *target;
unsigned int length = 0;
grn_obj *grn_length;
if (n_args != 1) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"string_length(): wrong number of arguments (%d for 1)",
n_args);
return NULL;
}
target = args[0];
if (!(target->header.type == GRN_BULK &&
((target->header.domain == GRN_DB_SHORT_TEXT) ||
(target->header.domain == GRN_DB_TEXT) ||
(target->header.domain == GRN_DB_LONG_TEXT)))) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, target);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"string_length(): target object must be a text bulk: "
"<%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
{
const char *s = GRN_TEXT_VALUE(target);
const char *e = GRN_TEXT_VALUE(target) + GRN_TEXT_LEN(target);
const char *p;
unsigned int cl = 0;
for (p = s; p < e && (cl = grn_charlen(ctx, p, e)); p += cl) {
length++;
}
}
grn_length = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, 0);
if (!grn_length) {
return NULL;
}
GRN_UINT32_SET(ctx, grn_length, length);
return grn_length;
}
static grn_obj *
func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
grn_obj *target;
grn_obj *from_raw;
grn_obj *length_raw = NULL;
int64_t from = 0;
int64_t length = -1;
const char *start = NULL;
const char *end = NULL;
grn_obj *substring;
if (n_args < 2) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"string_substring(): wrong number of arguments (%d for 2..3)",
n_args);
return NULL;
}
target = args[0];
from_raw = args[1];
if (n_args == 3) {
length_raw = args[2];
}
if (!(target->header.type == GRN_BULK &&
grn_type_id_is_text_family(ctx, target->header.domain))) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, target);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"string_substring(): target object must be a text bulk: "
"<%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
/* TODO: extract as grn_func_arg_int64() */
if (!grn_type_id_is_number_family(ctx, from_raw->header.domain)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, from_raw);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"string_substring(): from must be a number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
if (from_raw->header.domain == GRN_DB_INT32) {
from = GRN_INT32_VALUE(from_raw);
} else if (from_raw->header.domain == GRN_DB_INT64) {
from = GRN_INT64_VALUE(from_raw);
} else {
grn_obj buffer;
grn_rc rc;
GRN_INT64_INIT(&buffer, 0);
rc = grn_obj_cast(ctx, from_raw, &buffer, GRN_FALSE);
if (rc == GRN_SUCCESS) {
from = GRN_INT64_VALUE(&buffer);
}
GRN_OBJ_FIN(ctx, &buffer);
if (rc != GRN_SUCCESS) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, from_raw);
GRN_PLUGIN_ERROR(ctx, rc,
"string_substring(): "
"failed to cast from value to number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
}
if (length_raw) {
/* TODO: extract as grn_func_arg_int64() */
if (!grn_type_id_is_number_family(ctx, length_raw->header.domain)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, length_raw);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"string_substring(): length must be a number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
if (length_raw->header.domain == GRN_DB_INT32) {
length = GRN_INT32_VALUE(length_raw);
} else if (length_raw->header.domain == GRN_DB_INT64) {
length = GRN_INT64_VALUE(length_raw);
} else {
grn_obj buffer;
grn_rc rc;
GRN_INT64_INIT(&buffer, 0);
rc = grn_obj_cast(ctx, length_raw, &buffer, GRN_FALSE);
if (rc == GRN_SUCCESS) {
length = GRN_INT64_VALUE(&buffer);
}
GRN_OBJ_FIN(ctx, &buffer);
if (rc != GRN_SUCCESS) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, length_raw);
GRN_PLUGIN_ERROR(ctx, rc,
"string_substring(): "
"failed to cast length value to number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
}
}
substring = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, 0);
if (!substring) {
return NULL;
}
GRN_BULK_REWIND(substring);
if (GRN_TEXT_LEN(target) == 0) {
return substring;
}
if (length == 0) {
return substring;
}
while (from < 0) {
from += GRN_TEXT_LEN(target);
}
{
const char *p;
start = NULL;
p = GRN_TEXT_VALUE(target);
end = p + GRN_TEXT_LEN(target);
if (from == 0) {
start = p;
} else {
unsigned int char_length = 0;
size_t n_chars = 0;
for (;
p < end && (char_length = grn_charlen(ctx, p, end));
p += char_length, n_chars++) {
if (n_chars == from) {
start = p;
break;
}
}
}
if (start && length > 0) {
unsigned int char_length = 0;
size_t n_chars = 0;
for (;
p < end && (char_length = grn_charlen(ctx, p, end));
p += char_length, n_chars++) {
if (n_chars == length) {
end = p;
break;
}
}
}
}
if (start) {
GRN_TEXT_SET(ctx, substring, start, end - start);
}
return substring;
}
grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
return ctx->rc;
}
grn_rc
GRN_PLUGIN_REGISTER(grn_ctx *ctx)
{
grn_rc rc = GRN_SUCCESS;
grn_proc_create(ctx, "string_length", -1, GRN_PROC_FUNCTION, func_string_length,
NULL, NULL, 0, NULL);
grn_proc_create(ctx, "string_substring", -1, GRN_PROC_FUNCTION, func_string_substring,
NULL, NULL, 0, NULL);
return rc;
}
grn_rc
GRN_PLUGIN_FIN(grn_ctx *ctx)
{
return GRN_SUCCESS;
}

View file

@ -0,0 +1,2 @@
string_la_SOURCES = \
string.c

View file

@ -0,0 +1,376 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2016 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 GRN_EMBEDDED
# define GRN_PLUGIN_FUNCTION_TAG functions_time
#endif
#include <groonga/plugin.h>
#include <math.h>
typedef enum {
GRN_TIME_CLASSIFY_UNIT_SECOND,
GRN_TIME_CLASSIFY_UNIT_MINUTE,
GRN_TIME_CLASSIFY_UNIT_HOUR,
GRN_TIME_CLASSIFY_UNIT_DAY,
GRN_TIME_CLASSIFY_UNIT_WEEK,
GRN_TIME_CLASSIFY_UNIT_MONTH,
GRN_TIME_CLASSIFY_UNIT_YEAR
} grn_time_classify_unit;
static grn_obj *
func_time_classify_raw(grn_ctx *ctx,
int n_args,
grn_obj **args,
grn_user_data *user_data,
const char *function_name,
grn_time_classify_unit unit)
{
grn_obj *time;
uint32_t interval_raw = 1;
grn_obj *classed_time;
grn_bool accept_interval = GRN_TRUE;
switch (unit) {
case GRN_TIME_CLASSIFY_UNIT_SECOND :
case GRN_TIME_CLASSIFY_UNIT_MINUTE :
case GRN_TIME_CLASSIFY_UNIT_HOUR :
accept_interval = GRN_TRUE;
break;
case GRN_TIME_CLASSIFY_UNIT_DAY :
case GRN_TIME_CLASSIFY_UNIT_WEEK :
accept_interval = GRN_FALSE;
break;
case GRN_TIME_CLASSIFY_UNIT_MONTH :
case GRN_TIME_CLASSIFY_UNIT_YEAR :
accept_interval = GRN_TRUE;
break;
}
if (accept_interval) {
if (!(n_args == 1 || n_args == 2)) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"%s(): "
"wrong number of arguments (%d for 1..2)",
function_name,
n_args);
return NULL;
}
} else {
if (n_args != 1) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"%s(): "
"wrong number of arguments (%d for 1)",
function_name,
n_args);
return NULL;
}
}
time = args[0];
if (!(time->header.type == GRN_BULK &&
time->header.domain == GRN_DB_TIME)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, time);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"%s(): "
"the first argument must be a time: "
"<%.*s>",
function_name,
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
if (n_args == 2) {
grn_obj *interval;
grn_obj casted_interval;
interval = args[1];
if (!(interval->header.type == GRN_BULK &&
grn_type_id_is_number_family(ctx, interval->header.domain))) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, interval);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"%s(): "
"the second argument must be a number: "
"<%.*s>",
function_name,
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
GRN_VALUE_FIX_SIZE_INIT(&casted_interval, 0, GRN_DB_UINT32);
grn_obj_cast(ctx, interval, &casted_interval, GRN_FALSE);
interval_raw = GRN_UINT32_VALUE(&casted_interval);
GRN_OBJ_FIN(ctx, &casted_interval);
if (interval_raw == 0) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, interval);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"%s(): "
"the second argument must not be zero: "
"<%.*s>",
function_name,
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
}
{
int64_t time_raw;
struct tm tm;
int64_t classed_time_raw;
time_raw = GRN_TIME_VALUE(time);
if (!grn_time_to_tm(ctx, time_raw, &tm)) {
return NULL;
}
switch (unit) {
case GRN_TIME_CLASSIFY_UNIT_SECOND :
tm.tm_sec = (tm.tm_sec / interval_raw) * interval_raw;
break;
case GRN_TIME_CLASSIFY_UNIT_MINUTE :
tm.tm_min = (tm.tm_min / interval_raw) * interval_raw;
tm.tm_sec = 0;
break;
case GRN_TIME_CLASSIFY_UNIT_HOUR :
tm.tm_hour = (tm.tm_hour / interval_raw) * interval_raw;
tm.tm_min = 0;
tm.tm_sec = 0;
break;
case GRN_TIME_CLASSIFY_UNIT_DAY :
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
break;
case GRN_TIME_CLASSIFY_UNIT_WEEK :
if ((tm.tm_mday - tm.tm_wday) >= 0) {
tm.tm_mday -= tm.tm_wday;
} else {
int n_underflowed_mday = -(tm.tm_mday - tm.tm_wday);
int mday;
int max_mday = 31;
if (tm.tm_mon == 0) {
tm.tm_year--;
tm.tm_mon = 11;
} else {
tm.tm_mon--;
}
for (mday = max_mday; mday > n_underflowed_mday; mday--) {
int64_t unused;
tm.tm_mday = mday;
if (grn_time_from_tm(ctx, &unused, &tm)) {
break;
}
}
tm.tm_mday -= n_underflowed_mday;
}
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
break;
case GRN_TIME_CLASSIFY_UNIT_MONTH :
tm.tm_mon = (tm.tm_mon / interval_raw) * interval_raw;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
break;
case GRN_TIME_CLASSIFY_UNIT_YEAR :
tm.tm_year = (((1900 + tm.tm_year) / interval_raw) * interval_raw) - 1900;
tm.tm_mon = 0;
tm.tm_mday = 1;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
break;
}
if (!grn_time_from_tm(ctx, &classed_time_raw, &tm)) {
return NULL;
}
classed_time = grn_plugin_proc_alloc(ctx,
user_data,
time->header.domain,
0);
if (!classed_time) {
return NULL;
}
GRN_TIME_SET(ctx, classed_time, classed_time_raw);
return classed_time;
}
}
static grn_obj *
func_time_classify_second(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_second",
GRN_TIME_CLASSIFY_UNIT_SECOND);
}
static grn_obj *
func_time_classify_minute(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_minute",
GRN_TIME_CLASSIFY_UNIT_MINUTE);
}
static grn_obj *
func_time_classify_hour(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_hour",
GRN_TIME_CLASSIFY_UNIT_HOUR);
}
static grn_obj *
func_time_classify_day(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_day",
GRN_TIME_CLASSIFY_UNIT_DAY);
}
static grn_obj *
func_time_classify_week(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_week",
GRN_TIME_CLASSIFY_UNIT_WEEK);
}
static grn_obj *
func_time_classify_month(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_month",
GRN_TIME_CLASSIFY_UNIT_MONTH);
}
static grn_obj *
func_time_classify_year(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
return func_time_classify_raw(ctx,
n_args,
args,
user_data,
"time_classify_year",
GRN_TIME_CLASSIFY_UNIT_YEAR);
}
grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
return ctx->rc;
}
grn_rc
GRN_PLUGIN_REGISTER(grn_ctx *ctx)
{
grn_rc rc = GRN_SUCCESS;
grn_proc_create(ctx,
"time_classify_second", -1,
GRN_PROC_FUNCTION,
func_time_classify_second,
NULL, NULL, 0, NULL);
grn_proc_create(ctx,
"time_classify_minute", -1,
GRN_PROC_FUNCTION,
func_time_classify_minute,
NULL, NULL, 0, NULL);
grn_proc_create(ctx,
"time_classify_hour", -1,
GRN_PROC_FUNCTION,
func_time_classify_hour,
NULL, NULL, 0, NULL);
grn_proc_create(ctx,
"time_classify_day", -1,
GRN_PROC_FUNCTION,
func_time_classify_day,
NULL, NULL, 0, NULL);
grn_proc_create(ctx,
"time_classify_week", -1,
GRN_PROC_FUNCTION,
func_time_classify_week,
NULL, NULL, 0, NULL);
grn_proc_create(ctx,
"time_classify_month", -1,
GRN_PROC_FUNCTION,
func_time_classify_month,
NULL, NULL, 0, NULL);
grn_proc_create(ctx,
"time_classify_year", -1,
GRN_PROC_FUNCTION,
func_time_classify_year,
NULL, NULL, 0, NULL);
return rc;
}
grn_rc
GRN_PLUGIN_FIN(grn_ctx *ctx)
{
return GRN_SUCCESS;
}

View file

@ -0,0 +1,2 @@
time_la_SOURCES = \
time.c

View file

@ -1,6 +1,6 @@
/* -*- c-basic-offset: 2 -*- */
/*
Copyright(C) 2015 Brazil
Copyright(C) 2015-2017 Brazil
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@ -70,6 +70,307 @@ func_vector_size(grn_ctx *ctx, int n_args, grn_obj **args,
return grn_size;
}
static grn_obj *
func_vector_slice(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
grn_obj *target;
grn_obj *from_raw = NULL;
grn_obj *length_raw = NULL;
int64_t from = 0;
int64_t length = -1;
uint32_t to = 0;
uint32_t size = 0;
grn_obj *slice;
if (n_args < 2 || n_args > 3) {
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"vector_slice(): wrong number of arguments (%d for 2..3)",
n_args);
return NULL;
}
target = args[0];
from_raw = args[1];
if (n_args == 3) {
length_raw = args[2];
}
switch (target->header.type) {
case GRN_VECTOR :
case GRN_PVECTOR :
case GRN_UVECTOR :
size = grn_vector_size(ctx, target);
break;
default :
{
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, target, &inspected);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"vector_slice(): target object must be vector: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
break;
}
if (!grn_type_id_is_number_family(ctx, from_raw->header.domain)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, from_raw);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"vector_slice(): from must be a number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
if (from_raw->header.domain == GRN_DB_INT32) {
from = GRN_INT32_VALUE(from_raw);
} else if (from_raw->header.domain == GRN_DB_INT64) {
from = GRN_INT64_VALUE(from_raw);
} else {
grn_obj buffer;
grn_rc rc;
GRN_INT64_INIT(&buffer, 0);
rc = grn_obj_cast(ctx, from_raw, &buffer, GRN_FALSE);
if (rc == GRN_SUCCESS) {
from = GRN_INT64_VALUE(&buffer);
}
GRN_OBJ_FIN(ctx, &buffer);
if (rc != GRN_SUCCESS) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, from_raw);
GRN_PLUGIN_ERROR(ctx, rc,
"vector_slice(): "
"failed to cast from value to number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
}
if (length_raw) {
if (!grn_type_id_is_number_family(ctx, length_raw->header.domain)) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, length_raw);
GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
"vector_slice(): length must be a number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
if (length_raw->header.domain == GRN_DB_INT32) {
length = GRN_INT32_VALUE(length_raw);
} else if (length_raw->header.domain == GRN_DB_INT64) {
length = GRN_INT64_VALUE(length_raw);
} else {
grn_obj buffer;
grn_rc rc;
GRN_INT64_INIT(&buffer, 0);
rc = grn_obj_cast(ctx, length_raw, &buffer, GRN_FALSE);
if (rc == GRN_SUCCESS) {
length = GRN_INT64_VALUE(&buffer);
}
GRN_OBJ_FIN(ctx, &buffer);
if (rc != GRN_SUCCESS) {
grn_obj inspected;
GRN_TEXT_INIT(&inspected, 0);
grn_inspect(ctx, &inspected, length_raw);
GRN_PLUGIN_ERROR(ctx, rc,
"vector_slice(): "
"failed to cast length value to number: <%.*s>",
(int)GRN_TEXT_LEN(&inspected),
GRN_TEXT_VALUE(&inspected));
GRN_OBJ_FIN(ctx, &inspected);
return NULL;
}
}
}
slice = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, GRN_OBJ_VECTOR);
if (!slice) {
return NULL;
}
if (target->header.flags & GRN_OBJ_WITH_WEIGHT) {
slice->header.flags |= GRN_OBJ_WITH_WEIGHT;
}
if (length < 0) {
length = size + length + 1;
}
if (length > size) {
length = size;
}
if (length <= 0) {
return slice;
}
while (from < 0) {
from += size;
}
to = from + length;
if (to > size) {
to = size;
}
switch (target->header.type) {
case GRN_VECTOR :
{
unsigned int i;
for (i = from; i < to; i++) {
const char *content;
unsigned int content_length;
unsigned int weight;
grn_id domain;
content_length = grn_vector_get_element(ctx, target, i,
&content, &weight, &domain);
grn_vector_add_element(ctx, slice,
content, content_length, weight, domain);
}
}
break;
case GRN_PVECTOR :
{
unsigned int i;
for (i = from; i < to; i++) {
grn_obj *element = GRN_PTR_VALUE_AT(target, i);
GRN_PTR_PUT(ctx, slice, element);
}
}
break;
case GRN_UVECTOR :
{
grn_obj *domain;
domain = grn_ctx_at(ctx, target->header.domain);
if (grn_obj_is_table(ctx, domain)) {
unsigned int i;
for (i = from; i < to; i++) {
grn_id id;
unsigned int weight;
id = grn_uvector_get_element(ctx, target, i, &weight);
grn_uvector_add_element(ctx, slice, id, weight);
}
} else {
#define PUT_SLICE_VALUES(type) do { \
unsigned int i; \
for (i = from; i < to; i++) { \
GRN_ ## type ## _PUT(ctx, \
slice, \
GRN_ ## type ## _VALUE_AT(target, i)); \
} \
} while (GRN_FALSE)
switch (target->header.domain) {
case GRN_DB_BOOL :
PUT_SLICE_VALUES(BOOL);
break;
case GRN_DB_INT8 :
PUT_SLICE_VALUES(INT8);
break;
case GRN_DB_UINT8 :
PUT_SLICE_VALUES(UINT8);
break;
case GRN_DB_INT16 :
PUT_SLICE_VALUES(INT16);
break;
case GRN_DB_UINT16 :
PUT_SLICE_VALUES(UINT16);
break;
case GRN_DB_INT32 :
PUT_SLICE_VALUES(INT32);
break;
case GRN_DB_UINT32 :
PUT_SLICE_VALUES(UINT32);
break;
case GRN_DB_INT64 :
PUT_SLICE_VALUES(INT64);
break;
case GRN_DB_UINT64 :
PUT_SLICE_VALUES(UINT64);
break;
case GRN_DB_FLOAT :
PUT_SLICE_VALUES(FLOAT);
break;
case GRN_DB_TIME :
PUT_SLICE_VALUES(TIME);
break;
}
}
}
break;
#undef PUT_SLICE_VALUES
}
return slice;
}
static grn_obj *
func_vector_new(grn_ctx *ctx, int n_args, grn_obj **args,
grn_user_data *user_data)
{
grn_obj *vector = NULL;
int i;
if (n_args == 0) {
return grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, GRN_OBJ_VECTOR);
}
vector = grn_plugin_proc_alloc(ctx,
user_data,
args[0]->header.domain,
GRN_OBJ_VECTOR);
if (!vector) {
return NULL;
}
for (i = 0; i < n_args; i++) {
grn_obj *element = args[i];
switch (vector->header.type) {
case GRN_VECTOR :
grn_vector_add_element(ctx,
vector,
GRN_BULK_HEAD(element),
GRN_BULK_VSIZE(element),
0,
element->header.domain);
break;
case GRN_UVECTOR :
grn_bulk_write(ctx,
vector,
GRN_BULK_HEAD(element),
GRN_BULK_VSIZE(element));
break;
case GRN_PVECTOR :
GRN_PTR_PUT(ctx, vector, element);
break;
default :
break;
}
}
return vector;
}
grn_rc
GRN_PLUGIN_INIT(grn_ctx *ctx)
{
@ -84,6 +385,12 @@ GRN_PLUGIN_REGISTER(grn_ctx *ctx)
grn_proc_create(ctx, "vector_size", -1, GRN_PROC_FUNCTION, func_vector_size,
NULL, NULL, 0, NULL);
grn_proc_create(ctx, "vector_slice", -1, GRN_PROC_FUNCTION, func_vector_slice,
NULL, NULL, 0, NULL);
grn_proc_create(ctx, "vector_new", -1, GRN_PROC_FUNCTION, func_vector_new,
NULL, NULL, 0, NULL);
return rc;
}