[Groonga-commit] groonga/grngo at 84bbf6e [master] Add new cgo structures and fuctions to fix bugs.

アーカイブの一覧に戻る

susumu.yata null+****@clear*****
Tue Jul 21 14:29:40 JST 2015


susumu.yata	2015-07-21 14:29:40 +0900 (Tue, 21 Jul 2015)

  New Revision: 84bbf6e5af7ea2afeb7e3096c18681c840730a8f
  https://github.com/groonga/grngo/commit/84bbf6e5af7ea2afeb7e3096c18681c840730a8f

  Message:
    Add new cgo structures and fuctions to fix bugs.
    
    New implementations are not yet tested and used.
    
    GitHub: #14, #15, #17

  Modified files:
    grngo.c
    grngo.h

  Modified: grngo.c (+980 -0)
===================================================================
--- grngo.c    2015-07-17 19:59:34 +0900 (f47bc29)
+++ grngo.c    2015-07-21 14:29:40 +0900 (4a411a9)
@@ -3,8 +3,988 @@
 #include <math.h>
 #include <string.h>
 
+// -- miscellaneous --
+
 #define GRNGO_MAX_BUILTIN_TYPE_ID GRN_DB_WGS84_GEO_POINT
 
+#define GRNGO_MAX_SHORT_TEXT_LEN 4095
+#define GRNGO_MAX_TEXT_LEN       65535
+#define GRNGO_MAX_LONG_TEXT_LEN  2147484647
+
+#define GRNGO_BOOL_DB_TYPE      grn_bool
+#define GRNGO_INT8_DB_TYPE      int8_t
+#define GRNGO_INT16_DB_TYPE     int16_t
+#define GRNGO_INT32_DB_TYPE     int32_t
+#define GRNGO_INT64_DB_TYPE     int64_t
+#define GRNGO_UINT8_DB_TYPE     uint8_t
+#define GRNGO_UINT16_DB_TYPE    uint16_t
+#define GRNGO_UINT32_DB_TYPE    uint32_t
+#define GRNGO_UINT64_DB_TYPE    uint64_t
+#define GRNGO_FLOAT_DB_TYPE     double
+#define GRNGO_TIME_DB_TYPE      int64_t
+#define GRNGO_TEXT_DB_TYPE      grngo_text
+#define GRNGO_GEO_POINT_DB_TYPE grngo_geo_point
+
+#define GRNGO_DB_TYPE(type) GRNGO_ ## type ## _DB_TYPE
+
+#define GRNGO_BOOL_C_TYPE      grn_bool
+#define GRNGO_INT8_C_TYPE      int64_t
+#define GRNGO_INT16_C_TYPE     int64_t
+#define GRNGO_INT32_C_TYPE     int64_t
+#define GRNGO_INT64_C_TYPE     int64_t
+#define GRNGO_UINT8_C_TYPE     int64_t
+#define GRNGO_UINT16_C_TYPE    int64_t
+#define GRNGO_UINT32_C_TYPE    int64_t
+#define GRNGO_UINT64_C_TYPE    int64_t
+#define GRNGO_FLOAT_C_TYPE     double
+#define GRNGO_TIME_C_TYPE      int64_t
+#define GRNGO_TEXT_C_TYPE      grngo_text
+#define GRNGO_GEO_POINT_C_TYPE grngo_geo_point
+
+#define GRNGO_C_TYPE(type)  GRNGO_ ## type ## _C_TYPE
+
+#define GRNGO_TEST_BOOL(value)       (1)
+#define GRNGO_TEST_INT8(value)       \
+  (((value) >= INT8_MIN) && ((value) <= INT8_MAX))
+#define GRNGO_TEST_INT16(value)      \
+  (((value) >= INT16_MIN) && ((value) <= INT16_MAX))
+#define GRNGO_TEST_INT32(value)      \
+  (((value) >= INT32_MIN) && ((value) <= INT32_MAX))
+#define GRNGO_TEST_INT64(value)      (1)
+#define GRNGO_TEST_UINT8(value)      \
+  (((value) >= 0) && ((value) <= (int64_t)UINT8_MAX))
+#define GRNGO_TEST_UINT16(value)     \
+  (((value) >= 0) && ((value) <= (int64_t)UINT16_MAX))
+#define GRNGO_TEST_UINT32(value)     \
+  (((value) >= 0) && ((value) <= (int64_t)UINT32_MAX))
+#define GRNGO_TEST_UINT64(value)     ((value) >= 0)
+#define GRNGO_TEST_TIME(value)       (1)
+#define GRNGO_TEST_FLOAT(value)      (!isnan(value))
+#define GRNGO_TEST_SHORT_TEXT(value) \
+  (((value).ptr && ((value).size < GRNGO_MAX_SHORT_TEXT_LEN)) ||\
+   (!(value).ptr && !(value).size))
+#define GRNGO_TEST_TEXT(value)       \
+  (((value).ptr && ((value).size < GRNGO_MAX_TEXT_LEN)) ||\
+   (!(value).ptr && !(value).size))
+#define GRNGO_TEST_LONG_TEXT(value)  \
+  (((value).ptr && ((value).size < GRNGO_MAX_LONG_TEXT_LEN)) ||\
+   (!(value).ptr && !(value).size))
+#define GRNGO_TEST_GEO_POINT(value)  \
+  (((value).latitude  >= ( -90 * 60 * 60 * 1000)) &&\
+   ((value).latitude  <= (  90 * 60 * 60 * 1000)) &&\
+   ((value).longitude >= (-180 * 60 * 60 * 1000)) &&\
+   ((value).longitude <= ( 180 * 60 * 60 * 1000)))
+#define GRNGO_TEST_VECTOR(value)     \
+  ((value.ptr) || (!(value).ptr && !(value).size))
+
+static void *
+_grngo_malloc(grngo_db *db, size_t size,
+              const char *file, int line, const char *func) {
+  void *buf = malloc(size);
+  if (!buf && db) {
+    // TODO: Error!
+  }
+  return buf;
+}
+#define GRNGO_MALLOC(db, size)\
+  _grngo_malloc(db, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+static void *
+_grngo_realloc(grngo_db *db, void *ptr, size_t size,
+               const char *file, int line, const char *func) {
+  void *buf = realloc(ptr, size);
+  if (!buf && db) {
+    // TODO: Error!
+  }
+  return buf;
+}
+#define GRNGO_REALLOC(db, ptr, size)\
+  _grngo_realloc(db, ptr, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+static void
+_grngo_free(grngo_db *db, void *buf,
+            const char *file, int line, const char *func) {
+  free(buf);
+}
+#define GRNGO_FREE(db, buf)\
+  _grngo_free(db, buf, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+// -- grngo_db --
+
+static grngo_db *
+_grngo_new_db(void) {
+  grngo_db *db = (grngo_db *)GRNGO_MALLOC(NULL, sizeof(*db));
+  if (!db) {
+    return NULL;
+  }
+  memset(db, 0, sizeof(*db));
+  db->ctx = NULL;
+  db->obj = NULL;
+  db->estr = db->estr_buf;
+  return db;
+}
+
+static void
+_grngo_delete_db(grngo_db *db) {
+  if (db->obj) {
+    grn_obj_close(db->ctx, db->obj);
+  }
+  if (db->ctx) {
+    grn_ctx_close(db->ctx);
+  }
+  GRNGO_FREE(NULL, db);
+}
+
+static grn_rc
+_grngo_create_db(grngo_db *db, const char *path) {
+  db->ctx = grn_ctx_open(0);
+  if (!db->ctx) {
+    return GRN_NO_MEMORY_AVAILABLE;
+  }
+  db->obj = grn_db_create(db->ctx, path, NULL);
+  if (!db->obj) {
+    if (db->ctx->rc != GRN_SUCCESS) {
+      return db->ctx->rc;
+    }
+    return GRN_UNKNOWN_ERROR;
+  }
+  return GRN_SUCCESS;
+}
+
+static grn_rc
+_grngo_open_db(grngo_db *db, const char *path) {
+  db->ctx = grn_ctx_open(0);
+  if (!db->ctx) {
+    return GRN_NO_MEMORY_AVAILABLE;
+  }
+  db->obj = grn_db_open(db->ctx, path);
+  if (!db->obj) {
+    if (db->ctx->rc != GRN_SUCCESS) {
+      return db->ctx->rc;
+    }
+    return GRN_UNKNOWN_ERROR;
+  }
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grngo_create_db(const char *path, size_t path_len, grngo_db **db) {
+  if ((!path && path_len) || !db) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  // Create a zero-terminated path.
+  char *path_cstr = NULL;
+  if (path) {
+    path_cstr = GRNGO_MALLOC(NULL, path_len + 1);
+    if (!path_cstr) {
+      return GRN_NO_MEMORY_AVAILABLE;
+    }
+    memcpy(path_cstr, path, path_len);
+    path_cstr[path_len] = '\0';
+  }
+  // Create a DB.
+  grngo_db *new_db = _grngo_new_db();
+  grn_rc rc = new_db ? GRN_SUCCESS : GRN_NO_MEMORY_AVAILABLE;
+  if (rc == GRN_SUCCESS) {
+    rc = _grngo_create_db(new_db, path_cstr);
+    if (rc == GRN_SUCCESS) {
+      *db = new_db;
+    } else {
+      _grngo_delete_db(new_db);
+    }
+  }
+  GRNGO_FREE(NULL, path_cstr);
+  return rc;
+}
+
+grn_rc
+grngo_open_db(const char *path, size_t path_len, grngo_db **db) {
+  if ((!path && path_len) || !db) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  // Create a zero-terminated path.
+  char *path_cstr = NULL;
+  if (path) {
+    path_cstr = GRNGO_MALLOC(NULL, path_len + 1);
+    if (!path_cstr) {
+      return GRN_NO_MEMORY_AVAILABLE;
+    }
+    memcpy(path_cstr, path, path_len);
+    path_cstr[path_len] = '\0';
+  }
+  // Open a DB.
+  grngo_db *new_db = _grngo_new_db();
+  grn_rc rc = new_db ? GRN_SUCCESS : GRN_NO_MEMORY_AVAILABLE;
+  if (rc == GRN_SUCCESS) {
+    rc = _grngo_open_db(new_db, path_cstr);
+    if (rc == GRN_SUCCESS) {
+      *db = new_db;
+    } else {
+      _grngo_delete_db(new_db);
+    }
+  }
+  GRNGO_FREE(NULL, path_cstr);
+  return rc;
+}
+
+void
+grngo_close_db(grngo_db *db) {
+  if (db) {
+    _grngo_delete_db(db);
+  }
+}
+
+// -- grngo_table --
+
+static grngo_table *
+_grngo_new_table(grngo_db *db) {
+  grngo_table *table = (grngo_table *)GRNGO_MALLOC(db, sizeof(*table));
+  if (!table) {
+    return NULL;
+  }
+  memset(table, 0, sizeof(*table));
+  table->db = db;
+  table->obj = NULL;
+  return table;
+}
+
+static void
+_grngo_delete_table(grngo_table *table) {
+  if (table->obj) {
+    grn_obj_unlink(table->db->ctx, table->obj);
+  }
+  GRNGO_FREE(table->db, table);
+}
+
+static grn_rc
+_grngo_set_key_type(grngo_table *table, grn_obj *obj) {
+  grn_id domain = obj->header.domain;
+  if (domain <= GRNGO_MAX_BUILTIN_TYPE_ID) {
+    table->key_type = domain;
+    return GRN_SUCCESS;
+  }
+  for ( ; ; ) {
+    obj = grn_ctx_at(table->db->ctx, domain);
+    if (!obj) {
+      if (table->db->ctx->rc != GRN_SUCCESS) {
+        return table->db->ctx->rc;
+      }
+      return GRN_UNKNOWN_ERROR;
+    }
+    domain = obj->header.domain;
+    grn_obj_unlink(table->db->ctx, obj);
+    if (domain <= GRNGO_MAX_BUILTIN_TYPE_ID) {
+      table->key_type = domain;
+      break;
+    }
+  }
+  return GRN_SUCCESS;
+}
+
+static grn_rc
+_grngo_open_table(grngo_table *table, const char *name, size_t name_len) {
+  grn_obj *obj = grn_ctx_get(table->db->ctx, name, name_len);
+  if (!obj) {
+    if (table->db->ctx->rc != GRN_SUCCESS) {
+      return table->db->ctx->rc;
+    }
+    return GRN_UNKNOWN_ERROR;
+  }
+  if (!grn_obj_is_table(table->db->ctx, obj)) {
+    grn_obj_unlink(table->db->ctx, obj);
+    return GRN_INVALID_FORMAT;
+  }
+  table->obj = obj;
+  return _grngo_set_key_type(table, obj);
+}
+
+grn_rc
+grngo_open_table(grngo_db *db, const char *name, size_t name_len,
+                 grngo_table **table) {
+  if (!db || !name || (name_len == 0) || !table) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grngo_table *new_table = _grngo_new_table(db);
+  grn_rc rc = new_table ? GRN_SUCCESS : GRN_NO_MEMORY_AVAILABLE;
+  if (rc == GRN_SUCCESS) {
+    rc = _grngo_open_table(new_table, name, name_len);
+    if (rc == GRN_SUCCESS) {
+      *table = new_table;
+    } else {
+      _grngo_delete_table(new_table);
+    }
+  }
+  return rc;
+}
+
+void
+grngo_close_table(grngo_table *table) {
+  if (table) {
+    _grngo_delete_table(table);
+  }
+}
+
+static grn_rc
+_grngo_insert_row(grngo_table *table, const void *key, size_t key_size,
+                  grn_bool *inserted, grn_id *id) {
+  int tmp_inserted;
+  grn_id tmp_id = grn_table_add(table->db->ctx, table->obj, key, key_size,
+                                &tmp_inserted);
+  if (tmp_id == GRN_ID_NIL) {
+    if (table->db->ctx->rc != GRN_SUCCESS) {
+      return table->db->ctx->rc;
+    }
+    return GRN_UNKNOWN_ERROR;
+  }
+  *inserted = (grn_bool)tmp_inserted;
+  *id = tmp_id;
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grngo_insert_void(grngo_table *table, grn_bool *inserted, grn_id *id) {
+  if (!table || !inserted || !id) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if (table->key_type != GRN_DB_VOID) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  return _grngo_insert_row(table, NULL, 0, inserted, id);
+}
+
+grn_rc
+grngo_insert_bool(grngo_table *table, grn_bool key,
+                  grn_bool *inserted, grn_id *id) {
+  if (!table || !inserted || !id) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if ((table->key_type != GRN_DB_BOOL) || !GRNGO_TEST_BOOL(key)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  return _grngo_insert_row(table, &key, sizeof(key), inserted, id);
+}
+
+#define GRNGO_INSERT_INT_CASE_BLOCK(type)\
+  case GRN_DB_ ## type: {\
+    if (!GRNGO_TEST_ ## type(key)) {\
+      return GRN_INVALID_ARGUMENT;\
+    }\
+    GRNGO_DB_TYPE(type) tmp_key = (GRNGO_DB_TYPE(type))key;\
+    return _grngo_insert_row(table, &tmp_key, sizeof(tmp_key), inserted, id);\
+  }
+grn_rc
+grngo_insert_int(grngo_table *table, int64_t key,
+                 grn_bool *inserted, grn_id *id) {
+  if (!table || !inserted || !id) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  switch (table->key_type) {
+    GRNGO_INSERT_INT_CASE_BLOCK(INT8)
+    GRNGO_INSERT_INT_CASE_BLOCK(INT16)
+    GRNGO_INSERT_INT_CASE_BLOCK(INT32)
+    GRNGO_INSERT_INT_CASE_BLOCK(INT64)
+    GRNGO_INSERT_INT_CASE_BLOCK(UINT8)
+    GRNGO_INSERT_INT_CASE_BLOCK(UINT16)
+    GRNGO_INSERT_INT_CASE_BLOCK(UINT32)
+    GRNGO_INSERT_INT_CASE_BLOCK(UINT64)
+    GRNGO_INSERT_INT_CASE_BLOCK(TIME)
+    default: {
+      return GRN_INVALID_ARGUMENT;
+    }
+  }
+}
+#undef GRNGO_INSERT_INT_CASE_BLOCK
+
+grn_rc
+grngo_insert_float(grngo_table *table, double key,
+                   grn_bool *inserted, grn_id *id) {
+  if (!table || !inserted || !id) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if ((table->key_type != GRN_DB_FLOAT) || !GRNGO_TEST_FLOAT(key)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  return _grngo_insert_row(table, &key, sizeof(key), inserted, id);
+}
+
+grn_rc
+grngo_insert_text(grngo_table *table, grngo_text key,
+                  grn_bool *inserted, grn_id *id) {
+  if (!table || !inserted || !id) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  if ((table->key_type != GRN_DB_SHORT_TEXT) || !GRNGO_TEST_SHORT_TEXT(key)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  return _grngo_insert_row(table, key.ptr, key.size, inserted, id);
+}
+
+grn_rc
+grngo_insert_geo_point(grngo_table *table, grn_geo_point key,
+                       grn_bool *inserted, grn_id *id) {
+  if (!table || !inserted || !id) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  switch (table->key_type) {
+    case GRN_DB_TOKYO_GEO_POINT:
+    case GRN_DB_WGS84_GEO_POINT: {
+      if (!GRNGO_TEST_GEO_POINT(key)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      break;
+    }
+    default: {
+      return GRN_INVALID_ARGUMENT;
+    }
+  }
+  return _grngo_insert_row(table, &key, sizeof(key), inserted, id);
+}
+
+// -- grngo_column --
+
+static grngo_column *
+_grngo_new_column(grngo_table *table) {
+  grngo_column *column = (grngo_column *)GRNGO_MALLOC(table->db,
+                                                      sizeof(*column));
+  if (!column) {
+    return NULL;
+  }
+  memset(column, 0, sizeof(*column));
+  column->db = table->db;
+  column->table = table;
+  column->objs = NULL;
+  return column;
+}
+
+static void
+_grngo_delete_column(grngo_column *column) {
+  if (column->objs) {
+    size_t i;
+    for (i = 0; i < column->num_objs; i++) {
+      grn_obj_unlink(column->db->ctx, column->objs[i]);
+    }
+    GRNGO_FREE(column->db, column->objs);
+  }
+  GRNGO_FREE(column->db, column);
+}
+
+static grn_rc
+_grngo_open_column_obj(grngo_db *db, grn_obj *table,
+                       const char *name, size_t name_len, grn_obj **obj) {
+  grn_obj *new_obj;
+  if ((name_len == GRN_COLUMN_NAME_VALUE_LEN) &&
+      !memcmp(name, GRN_COLUMN_NAME_VALUE, name_len)) {
+    new_obj = grn_ctx_at(db->ctx, grn_obj_id(db->ctx, table));
+  } else {
+    new_obj = grn_obj_column(db->ctx, table, name, name_len);
+  }
+  if (!new_obj) {
+    if (db->ctx->rc != GRN_SUCCESS) {
+      return db->ctx->rc;
+    }
+    return GRN_UNKNOWN_ERROR;
+  }
+  *obj = new_obj;
+  return GRN_SUCCESS;
+}
+
+static grn_rc
+_grngo_push_column(grngo_column *column, grn_obj **table,
+                   const char *name, size_t name_len) {
+  grn_obj *obj;
+  grn_rc rc = _grngo_open_column_obj(column->db, *table, name, name_len, &obj);
+  if (rc != GRN_SUCCESS) {
+    return rc;
+  }
+  switch (obj->header.type) {
+    case GRN_COLUMN_VAR_SIZE: {
+      grn_obj_flags type = obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK;
+      if (type == GRN_OBJ_COLUMN_VECTOR) {
+        column->dimension++;
+      }
+    }
+    case GRN_TABLE_HASH_KEY:
+    case GRN_TABLE_PAT_KEY:
+    case GRN_TABLE_NO_KEY:
+    case GRN_ACCESSOR:
+    case GRN_COLUMN_FIX_SIZE: {
+      grn_id range = grn_obj_get_range(column->db->ctx, obj);
+      if (range == GRN_DB_VOID) {
+        grn_obj_unlink(column->db->ctx, obj);
+        return GRN_INVALID_ARGUMENT;
+      } else if (range <= GRNGO_MAX_BUILTIN_TYPE_ID) {
+        column->value_type = range;
+        *table = NULL;
+      } else {
+        grn_obj *range_obj = grn_ctx_at(column->db->ctx, range);
+        if (!grn_obj_is_table(column->db->ctx, range_obj)) {
+          grn_obj_unlink(column->db->ctx, range_obj);
+          return GRN_INVALID_ARGUMENT;
+        }
+        *table = range_obj;
+      }
+      break;
+    }
+    default: {
+      grn_obj_unlink(column->db->ctx, obj);
+      return GRN_INVALID_ARGUMENT;
+    }
+  }
+  size_t new_size = sizeof(grn_obj *) * (column->num_objs + 1);
+  grn_obj **new_objs = (grn_obj **)GRNGO_REALLOC(column->db, column->objs,
+                                                 new_size);
+  if (!new_objs) {
+    return GRN_NO_MEMORY_AVAILABLE;
+  }
+  column->objs = new_objs;
+  column->num_objs++;
+  return GRN_SUCCESS;
+}
+
+static grn_rc
+_grngo_open_column(grngo_table *table, grngo_column *column,
+                   const char *name, size_t name_len) {
+  grn_obj *owner = table->obj;
+  while (name_len) {
+    if (!owner) {
+      return GRN_INVALID_ARGUMENT;
+    }
+    const char *token = name;
+    size_t token_len = 0;
+    while (name_len) {
+      name_len--;
+      if (*name++ == '.') {
+        break;
+      }
+      token_len++;
+    }
+    grn_rc rc = _grngo_push_column(column, &owner, token, token_len);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
+  if (column->num_objs == 1) {
+    switch (column->objs[0]->header.type) {
+      case GRN_TABLE_HASH_KEY:
+      case GRN_TABLE_PAT_KEY:
+      case GRN_TABLE_NO_KEY:
+      case GRN_COLUMN_FIX_SIZE:
+      case GRN_COLUMN_VAR_SIZE: {
+        column->writable = GRN_TRUE;
+        break;
+      }
+      default: {
+        break;
+      }
+    }
+  }
+  while (owner) {
+    grn_rc rc = _grngo_push_column(column, &owner, GRN_COLUMN_NAME_KEY,
+                                   GRN_COLUMN_NAME_KEY_LEN);
+    if (rc != GRN_SUCCESS) {
+      return rc;
+    }
+  }
+  return GRN_SUCCESS;
+}
+
+grn_rc
+grngo_open_column(grngo_table *table, const char *name, size_t name_len,
+                  grngo_column **column) {
+  if (!table || !name || (name_len == 0) || !column) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grngo_column *new_column = _grngo_new_column(table);
+  grn_rc rc = new_column ? GRN_SUCCESS : GRN_NO_MEMORY_AVAILABLE;
+  if (rc == GRN_SUCCESS) {
+    rc = _grngo_open_column(table, new_column, name, name_len);
+    if (rc == GRN_SUCCESS) {
+      *column = new_column;
+    } else {
+      _grngo_delete_column(new_column);
+    }
+  }
+  return rc;
+}
+
+grn_rc
+grngo_close_column(grngo_column *column) {
+  if (column) {
+    _grngo_delete_column(column);
+  }
+}
+
+grn_rc
+grngo_set_bool(grngo_column *column, grn_id id, grn_bool value) {
+  if (!column || !GRNGO_TEST_BOOL(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  GRN_BOOL_INIT(&obj, 0);
+  GRN_BOOL_SET(ctx, &obj, value);
+  grn_rc rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_int(grngo_column *column, grn_id id, int64_t value) {
+  if (!column) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  switch (column->value_type) {
+    case GRN_DB_INT8: {
+      if ((value < INT8_MIN) || (value > INT8_MAX)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_INT8_INIT(&obj, 0);
+      GRN_INT8_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_INT16: {
+      if ((value < INT16_MIN) || (value > INT16_MAX)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_INT16_INIT(&obj, 0);
+      GRN_INT16_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_INT32: {
+      if ((value < INT32_MIN) || (value > INT32_MAX)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_INT32_INIT(&obj, 0);
+      GRN_INT32_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_INT64: {
+      GRN_INT64_INIT(&obj, 0);
+      GRN_INT64_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_UINT8: {
+      if ((value < 0) || (value > (int64_t)UINT8_MAX)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_UINT8_INIT(&obj, 0);
+      GRN_UINT8_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_UINT16: {
+      if ((value < 0) || (value > (int64_t)UINT16_MAX)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_UINT16_INIT(&obj, 0);
+      GRN_UINT16_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_UINT32: {
+      if ((value < 0) || (value > (int64_t)UINT32_MAX)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_UINT32_INIT(&obj, 0);
+      GRN_UINT32_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_UINT64: {
+      if (value < 0) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_UINT64_INIT(&obj, 0);
+      GRN_UINT64_SET(ctx, &obj, value);
+      break;
+    }
+    case GRN_DB_TIME: {
+      GRN_TIME_INIT(&obj, 0);
+      GRN_TIME_SET(ctx, &obj, value);
+      break;
+    }
+    default: {
+      return GRN_INVALID_ARGUMENT;
+    }
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_float(grngo_column *column, grn_id id, double value) {
+  if (!column || !GRNGO_TEST_FLOAT(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  GRN_FLOAT_INIT(&obj, 0);
+  GRN_FLOAT_SET(ctx, &obj, value);
+  grn_rc rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_text(grngo_column *column, grn_id id, grngo_text value) {
+  if (!column) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  switch (column->value_type) {
+    case GRN_DB_SHORT_TEXT: {
+      if (!GRNGO_TEST_SHORT_TEXT(value)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_SHORT_TEXT_INIT(&obj, 0);
+      break;
+    }
+    case GRN_DB_TEXT: {
+      if (!GRNGO_TEST_TEXT(value)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_TEXT_INIT(&obj, 0);
+      break;
+    }
+    case GRN_DB_LONG_TEXT: {
+      if (!GRNGO_TEST_LONG_TEXT(value)) {
+        return GRN_INVALID_ARGUMENT;
+      }
+      GRN_LONG_TEXT_INIT(&obj, 0);
+      break;
+    }
+  }
+  GRN_TEXT_SET(ctx, &obj, value.ptr, value.size);
+  grn_rc rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_geo_point(grngo_column *column, grn_id id, grn_geo_point value) {
+  if (!column || !GRNGO_TEST_GEO_POINT(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  switch (column->value_type) {
+    case GRN_DB_TOKYO_GEO_POINT: {
+      GRN_TOKYO_GEO_POINT_INIT(&obj, 0);
+      break;
+    }
+    case GRN_DB_WGS84_GEO_POINT: {
+      GRN_WGS84_GEO_POINT_INIT(&obj, 0);
+      break;
+    }
+    default: {
+      return GRN_UNKNOWN_ERROR;
+    }
+  }
+  GRN_GEO_POINT_SET(ctx, &obj, value.latitude, value.longitude);
+  grn_rc rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_bool_vector(grngo_column *column, grn_id id, grngo_vector value) {
+  if (!column || !GRNGO_TEST_VECTOR(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  GRN_BOOL_INIT(&obj, GRN_OBJ_VECTOR);
+  grn_rc rc = grn_bulk_write(ctx, &obj, (const char *)value.ptr,
+                             sizeof(grn_bool) * value.size);
+  if (rc == GRN_SUCCESS) {
+    rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+#define GRNGO_SET_INT_VECTOR_CASE_BLOCK(type)\
+  case GRN_DB_ ## type: {\
+    for (i = 0; i < value.size; i++) {\
+      if (!GRNGO_TEST_ ## type(values[i])) {\
+        return GRN_INVALID_ARGUMENT;\
+      }\
+    }\
+    GRN_ ## type ## _INIT(&obj, GRN_OBJ_VECTOR);\
+    rc = grn_bulk_resize(ctx, &obj, sizeof(GRNGO_DB_TYPE(type)) * value.size);\
+    if (rc != GRN_SUCCESS) {\
+      break;\
+    }\
+    GRNGO_DB_TYPE(type) *head = (GRNGO_DB_TYPE(type) *)GRN_BULK_HEAD(&obj);\
+    for (i = 0; i < value.size; i++) {\
+      head[i] = (GRNGO_DB_TYPE(type))values[i];\
+    }\
+    break;\
+  }
+grn_rc
+grngo_set_int_vector(grngo_column *column, grn_id id, grngo_vector value) {
+  if (!column || !GRNGO_TEST_VECTOR(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  size_t i;
+  const int64_t *values = (const int64_t *)value.ptr;
+  grn_rc rc = GRN_SUCCESS;
+  switch (column->value_type) {
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(INT8)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(INT16)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(INT32)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(INT64)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(UINT8)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(UINT16)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(UINT32)
+    GRNGO_SET_INT_VECTOR_CASE_BLOCK(UINT64)
+    default: {
+      return GRN_INVALID_ARGUMENT;
+    }
+  }
+  if (rc == GRN_SUCCESS) {
+    rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+#undef GRNGO_SET_INT_VECTOR_CASE_BLOCK
+
+grn_rc
+grngo_set_float_vector(grngo_column *column, grn_id id, grngo_vector value) {
+  if (!column || !GRNGO_TEST_VECTOR(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  GRN_FLOAT_INIT(&obj, GRN_OBJ_VECTOR);
+  grn_rc rc = grn_bulk_write(ctx, &obj, (const char *)value.ptr,
+                             sizeof(double) * value.size);
+  if (rc == GRN_SUCCESS) {
+    rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_text_vector(grngo_column *column, grn_id id, grngo_vector value) {
+  if (!column || !GRNGO_TEST_VECTOR(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  size_t i;
+  const grngo_text *values = (const grngo_text *)value.ptr;
+  switch (column->value_type) {
+    case GRN_DB_SHORT_TEXT: {
+      for (i = 0; i < value.size; i++) {
+        if (values[i].size > GRNGO_MAX_SHORT_TEXT_LEN) {
+          return GRN_INVALID_ARGUMENT;
+        }
+      }
+      GRN_SHORT_TEXT_INIT(&obj, GRN_OBJ_VECTOR);
+      break;
+    }
+    case GRN_DB_TEXT: {
+      for (i = 0; i < value.size; i++) {
+        if (values[i].size > GRNGO_MAX_TEXT_LEN) {
+          return GRN_INVALID_ARGUMENT;
+        }
+      }
+      GRN_TEXT_INIT(&obj, GRN_OBJ_VECTOR);
+      break;
+    }
+    case GRN_DB_LONG_TEXT: {
+      for (i = 0; i < value.size; i++) {
+        if (values[i].size > GRNGO_MAX_LONG_TEXT_LEN) {
+          return GRN_INVALID_ARGUMENT;
+        }
+      }
+      GRN_LONG_TEXT_INIT(&obj, GRN_OBJ_VECTOR);
+      break;
+    }
+  }
+  grn_rc rc = GRN_SUCCESS;
+  for (i = 0; i < value.size; i++) {
+    rc = grn_vector_add_element(ctx, &obj, (const char *)values[i].ptr,
+                                values[i].size, 0, obj.header.domain);
+    if (rc != GRN_SUCCESS) {
+      break;
+    }
+  }
+  if (rc == GRN_SUCCESS) {
+    rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+grn_rc
+grngo_set_geo_point_vector(grngo_column *column, grn_id id,
+                           grngo_vector value) {
+  if (!column || !GRNGO_TEST_VECTOR(value)) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_ctx *ctx = column->db->ctx;
+  if (grn_table_at(ctx, column->table->obj, id) == GRN_ID_NIL) {
+    return GRN_INVALID_ARGUMENT;
+  }
+  grn_obj obj;
+  switch (column->value_type) {
+    case GRN_DB_TOKYO_GEO_POINT: {
+      GRN_TOKYO_GEO_POINT_INIT(&obj, GRN_OBJ_VECTOR);
+      break;
+    }
+    case GRN_DB_WGS84_GEO_POINT: {
+      GRN_WGS84_GEO_POINT_INIT(&obj, GRN_OBJ_VECTOR);
+      break;
+    }
+    default: {
+      return GRN_UNKNOWN_ERROR;
+    }
+  }
+  grn_rc rc = grn_bulk_write(ctx, &obj, (const char *)value.ptr,
+                             sizeof(grn_geo_point) * value.size);
+  if (rc == GRN_SUCCESS) {
+    rc = grn_obj_set_value(ctx, column->objs[0], id, &obj, GRN_OBJ_SET);
+  }
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc;
+}
+
+// -- old... --
+
 grn_rc grngo_find_table(grn_ctx *ctx, const char *name, size_t name_len,
                         grn_obj **table) {
   if (!ctx || !name || !table) {

  Modified: grngo.h (+86 -2)
===================================================================
--- grngo.h    2015-07-17 19:59:34 +0900 (b8b06be)
+++ grngo.h    2015-07-21 14:29:40 +0900 (95afd98)
@@ -6,16 +6,96 @@
 
 #include <groonga.h>
 
+#define GRNGO_ESTR_BUF_SIZE 256
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+// -- miscellaneous --
+
 typedef struct {
-  char *ptr;
+  char   *ptr;
   size_t size;
 } grngo_text;
 
 typedef struct {
-  void *ptr;
+  void   *ptr;
   size_t size;
 } grngo_vector;
 
+// -- grngo_db --
+
+typedef struct {
+  grn_ctx *ctx;
+  grn_obj *obj;
+  char    *estr;  // TODO: Reserved.
+  char    estr_buf[GRNGO_ESTR_BUF_SIZE];  // TODO: Reserved.
+} grngo_db;
+
+grn_rc grngo_create_db(const char *path, size_t path_len, grngo_db **db);
+grn_rc grngo_open_db(const char *path, size_t path_len, grngo_db **db);
+void grngo_close_db(grngo_db *db);
+
+// -- grngo_table --
+
+typedef struct {
+  grngo_db         *db;
+  grn_obj          *obj;
+  grn_builtin_type key_type;
+} grngo_table;
+
+grn_rc grngo_open_table(grngo_db *db, const char *name, size_t name_len,
+                        grngo_table **tbl);
+void grngo_close_table(grngo_table *tbl);
+
+grn_rc grngo_insert_void(grngo_table *tbl, grn_bool *inserted, grn_id *id);
+grn_rc grngo_insert_bool(grngo_table *tbl, grn_bool key,
+                         grn_bool *inserted, grn_id *id);
+grn_rc grngo_insert_int(grngo_table *tbl, int64_t key,
+                        grn_bool *inserted, grn_id *id);
+grn_rc grngo_insert_float(grngo_table *tbl, double key,
+                          grn_bool *inserted, grn_id *id);
+grn_rc grngo_insert_text(grngo_table *tbl, grngo_text key,
+                         grn_bool *inserted, grn_id *id);
+grn_rc grngo_insert_geo_point(grngo_table *tbl, grn_geo_point key,
+                              grn_bool *inserted, grn_id *id);
+
+// -- grngo_column --
+
+typedef struct {
+  grngo_db         *db;
+  grngo_table      *table;
+  grn_obj          **objs;
+  size_t           num_objs;
+  grn_builtin_type value_type;
+  int              dimension;
+  grn_bool         writable;
+} grngo_column;
+
+grn_rc grngo_open_column(grngo_table *tbl, const char *name, size_t name_len,
+                         grngo_column **column);
+grn_rc grngo_close_column(grngo_column *column);
+
+grn_rc grngo_set_bool(grngo_column *column, grn_id id, grn_bool value);
+grn_rc grngo_set_int(grngo_column *column, grn_id id, int64_t value);
+grn_rc grngo_set_float(grngo_column *column, grn_id id, double value);
+grn_rc grngo_set_text(grngo_column *column, grn_id id, grngo_text value);
+grn_rc grngo_set_geo_point(grngo_column *column, grn_id id,
+                           grn_geo_point value);
+grn_rc grngo_set_bool_vector(grngo_column *column, grn_id id,
+                             grngo_vector value);
+grn_rc grngo_set_int_vector(grngo_column *column, grn_id id,
+                            grngo_vector value);
+grn_rc grngo_set_float_vector(grngo_column *column, grn_id id,
+                              grngo_vector value);
+grn_rc grngo_set_text_vector(grngo_column *column, grn_id id,
+                             grngo_vector value);
+grn_rc grngo_set_geo_point_vector(grngo_column *column, grn_id id,
+                                  grngo_vector value);
+
+// -- old... --
+
 // grngo_find_table finds a table.
 grn_rc grngo_find_table(grn_ctx *ctx, const char *name, size_t name_len,
                         grn_obj **table);
@@ -204,4 +284,8 @@ grn_bool grngo_column_get_text_vector(grn_ctx *ctx, grn_obj *column,
 grn_bool grngo_column_get_geo_point_vector(grn_ctx *ctx, grn_obj *column,
                                            grn_id id, grngo_vector *value);
 
+#ifdef __cplusplus
+}  // extern "C"
+#endif  // __cplusplus
+
 #endif  // GRNGO_H
-------------- next part --------------
HTML����������������������������...
ダウンロード 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る