[Groonga-commit] groonga/groonga [master] support geo point in degree.

Back to archive index

null+****@clear***** null+****@clear*****
2010年 7月 6日 (火) 17:03:17 JST


Kouhei Sutou	2010-07-06 08:03:17 +0000 (Tue, 06 Jul 2010)

  New Revision: cb9d35b82c190a607e9c74189f7aa366cfd8daab

  Log:
    support geo point in degree.

  Modified files:
    lib/db.c
    test/unit/core/test-cast-basic.c

  Modified: lib/db.c (+43 -3)
===================================================================
--- lib/db.c    2010-07-06 07:53:39 +0000 (52985cb)
+++ lib/db.c    2010-07-06 08:03:17 +0000 (8030a77)
@@ -3651,6 +3651,11 @@ grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj)
     GRN_BOOL_SET(ctx, dest, value_ < -DBL_EPSILON || DBL_EPSILON < value_);\
   }
 
+#define DEGREE2MSEC(degree)\
+  (((int)degree * 60 * 60 * 1000) +\
+   (((int)(degree * 100) % 100) * 60 * 1000) +\
+   (((int)(degree * 10000) % 100) * 1000) +\
+   ((int)(degree * 10000000) % 1000))
 
 grn_rc
 grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, int addp)
@@ -3770,12 +3775,46 @@ grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, int addp)
     case GRN_DB_WGS84_GEO_POINT :
       {
         int latitude, longitude;
+        double degree;
         const char *cur, *str = GRN_TEXT_VALUE(src);
         const char *str_end = GRN_BULK_CURR(src);
+        char *end;
+        grn_obj buf, *buf_p = NULL;
         latitude = grn_atoi(str, str_end, &cur);
-        if (cur + 1 < str_end) {
-          longitude = grn_atoi(cur + 1, str_end, &cur);
-          if (cur == str_end) {
+        if (cur[0] == '.') {
+          GRN_TEXT_INIT(&buf, 0);
+          GRN_TEXT_PUT(ctx, &buf, str, GRN_TEXT_LEN(src));
+          GRN_TEXT_PUTC(ctx, &buf, '\0');
+          buf_p = &buf;
+          errno = 0;
+          degree = strtod(GRN_TEXT_VALUE(buf_p), &end);
+          if (errno) {
+            rc = GRN_INVALID_ARGUMENT;
+          } else {
+            latitude = DEGREE2MSEC(degree);
+            cur = str + (end - GRN_TEXT_VALUE(buf_p));
+          }
+        }
+        if (!rc && (cur[0] == 'x' || cur[0] == ',') && cur + 1 < str_end) {
+          const char *c = cur + 1;
+          longitude = grn_atoi(c, str_end, &cur);
+          if (cur[0] == '.') {
+            if (!buf_p) {
+              GRN_TEXT_INIT(&buf, 0);
+              GRN_TEXT_PUT(ctx, &buf, str, GRN_TEXT_LEN(src));
+              GRN_TEXT_PUTC(ctx, &buf, '\0');
+              buf_p = &buf;
+            }
+            errno = 0;
+            degree = strtod(GRN_TEXT_VALUE(buf_p) + (c - str), &end);
+            if (errno) {
+              rc = GRN_INVALID_ARGUMENT;
+            } else {
+              longitude = DEGREE2MSEC(degree);
+              cur = str + (end - GRN_TEXT_VALUE(buf_p));
+            }
+          }
+          if (!rc && cur == str_end) {
             GRN_GEO_POINT_SET(ctx, dest, latitude, longitude);
           } else {
             rc = GRN_INVALID_ARGUMENT;
@@ -3783,6 +3822,7 @@ grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, int addp)
         } else {
           rc = GRN_INVALID_ARGUMENT;
         }
+        if (buf_p) { GRN_OBJ_FIN(ctx, buf_p); }
       }
       break;
     default :

  Modified: test/unit/core/test-cast-basic.c (+59 -1)
===================================================================
--- test/unit/core/test-cast-basic.c    2010-07-06 07:53:39 +0000 (4cffaa6)
+++ test/unit/core/test-cast-basic.c    2010-07-06 08:03:17 +0000 (294184b)
@@ -36,7 +36,12 @@ void test_text_to_uint64(void);
 void test_text_to_float(void);
 void test_text_to_time(void);
 void test_text_to_geo_point(void);
+void test_text_to_geo_point_comma(void);
 void test_text_to_geo_point_invalid(void);
+void test_text_to_geo_point_in_degree(void);
+void test_text_to_geo_point_in_degree_invalid(void);
+void test_text_to_geo_point_mixed(void);
+void test_text_to_geo_point_mixed_invalid(void);
 
 void data_text_error(void);
 void test_text_error(gconstpointer data);
@@ -256,9 +261,20 @@ test_text_to_geo_point(void)
 }
 
 void
+test_text_to_geo_point_comma(void)
+{
+  gint takane_latitude, takane_longitude;
+
+  grn_obj_reinit(&context, &dest, GRN_DB_WGS84_GEO_POINT, 0);
+  cast_text("130194581,503802073");
+  GRN_GEO_POINT_VALUE(&dest, takane_latitude, takane_longitude);
+  cut_assert_equal_int(130194581, takane_latitude);
+  cut_assert_equal_int(503802073, takane_longitude);
+}
+
+void
 test_text_to_geo_point_invalid(void)
 {
-  cut_omit("any character is accepted as separator.");
   grn_obj_reinit(&context, &dest, GRN_DB_WGS84_GEO_POINT, 0);
   set_text("130194581?503802073");
   grn_test_assert_equal_rc(GRN_INVALID_ARGUMENT,
@@ -266,6 +282,48 @@ test_text_to_geo_point_invalid(void)
 }
 
 void
+test_text_to_geo_point_in_degree(void)
+{
+  gint takane_latitude, takane_longitude;
+
+  grn_obj_reinit(&context, &dest, GRN_DB_WGS84_GEO_POINT, 0);
+  cast_text("35.6954581363924x139.564207350021");
+  GRN_GEO_POINT_VALUE(&dest, takane_latitude, takane_longitude);
+  cut_assert_equal_int(130194581, takane_latitude);
+  cut_assert_equal_int(503802073, takane_longitude);
+}
+
+void
+test_text_to_geo_point_in_degree_invalid(void)
+{
+  grn_obj_reinit(&context, &dest, GRN_DB_WGS84_GEO_POINT, 0);
+  set_text("35.6954581363924?139.564207350021");
+  grn_test_assert_equal_rc(GRN_INVALID_ARGUMENT,
+                           grn_obj_cast(&context, &src, &dest, FALSE));
+}
+
+void
+test_text_to_geo_point_mixed(void)
+{
+  gint takane_latitude, takane_longitude;
+
+  grn_obj_reinit(&context, &dest, GRN_DB_WGS84_GEO_POINT, 0);
+  cast_text("35.6954581363924x503802073");
+  GRN_GEO_POINT_VALUE(&dest, takane_latitude, takane_longitude);
+  cut_assert_equal_int(130194581, takane_latitude);
+  cut_assert_equal_int(503802073, takane_longitude);
+}
+
+void
+test_text_to_geo_point_mixed_invalid(void)
+{
+  grn_obj_reinit(&context, &dest, GRN_DB_WGS84_GEO_POINT, 0);
+  set_text("35.6954581363924x503802073garbage");
+  grn_test_assert_equal_rc(GRN_INVALID_ARGUMENT,
+                           grn_obj_cast(&context, &src, &dest, FALSE));
+}
+
+void
 data_text_error(void)
 {
 #define ADD_DATA(label, expected, type, text)           \




Groonga-commit メーリングリストの案内
Back to archive index