[Commits] cc18a5d: MDEV-5313 Improving audit API.

Alexey Botchkov holyfoot at askmonty.org
Fri Jan 18 01:18:49 EET 2019


revision-id: cc18a5db9bce667c9b8722cdf6f51ee83b55a4b0 (mariadb-10.4.1-98-gcc18a5d)
parent(s): dd03cb3776e6d25dc1dd2c3a83473a1b78ae99f9
committer: Alexey Botchkov
timestamp: 2019-01-18 03:18:02 +0400
message:

MDEV-5313 Improving audit API.

json_locate_key() implemented.
get rid of 'key_len' argument in functions.

---
 include/json_lib.h                            |   5 ++
 include/mysql/plugin_audit.h.pp               |   4 +-
 include/mysql/plugin_auth.h.pp                |   4 +-
 include/mysql/plugin_encryption.h.pp          |   4 +-
 include/mysql/plugin_ftparser.h.pp            |   4 +-
 include/mysql/plugin_password_validation.h.pp |   4 +-
 include/mysql/service_json.h                  |   4 +-
 sql/sql_acl.cc                                | 100 +++++++++++++-------------
 strings/json_lib.c                            |  94 +++++++++++++++++++++++-
 unittest/strings/json-t.c                     |  28 +++++++-
 10 files changed, 185 insertions(+), 66 deletions(-)

diff --git a/include/json_lib.h b/include/json_lib.h
index a347538..b6add6d 100644
--- a/include/json_lib.h
+++ b/include/json_lib.h
@@ -425,6 +425,11 @@ int json_path_compare(const json_path_t *a, const json_path_t *b,
 
 int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs);
 
+int json_locate_key(const char *js, const char *js_end,
+                    const char *kname,
+                    const char **key_start, const char **key_end,
+                    int *comma_pos);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 47f07ae..c5ae678 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
                                          int n_item,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key, const char *key_end,
+                                         const char *key,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
                                     const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index f9d01a8..41cb7d07 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
                                          int n_item,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key, const char *key_end,
+                                         const char *key,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
                                     const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index e55a034..6597dec 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
                                          int n_item,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key, const char *key_end,
+                                         const char *key,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
                                     const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index f9d9844..bd1cfc7 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
                                          int n_item,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key, const char *key_end,
+                                         const char *key,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
                                     const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index b672db6..2f9d229 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
                                          int n_item,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key, const char *key_end,
+                                         const char *key,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
                                     const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h
index 734787a..141b762 100644
--- a/include/mysql/service_json.h
+++ b/include/mysql/service_json.h
@@ -66,7 +66,7 @@ extern struct json_service_st {
                                          int n_item,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_key)(const char *js, const char *js_end,
-                                         const char *key, const char *key_end,
+                                         const char *key,
                                          const char **value, int *value_len);
   enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
                              int nkey,
@@ -95,7 +95,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
                                     int n_item,
                                     const char **value, int *value_len);
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len);
 enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
                        const char **keyname, const char **keyname_end,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 61d6812..bb5a397 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1204,16 +1204,16 @@ class User_table_json: public User_table
 
   int get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const
   {
-    *plugin= get_str_value(root, STRING_WITH_LEN("plugin"));
+    *plugin= get_str_value(root, "plugin");
     if (!**plugin)
       *plugin= native_password_plugin_name.str;
-    *authstr= get_str_value(root, STRING_WITH_LEN("authentication_string"));
+    *authstr= get_str_value(root, "authentication_string");
     return *plugin == NULL || *authstr == NULL;
   }
   void set_auth(const char *p, size_t pl, const char *as, size_t asl) const
   {
-    set_str_value(STRING_WITH_LEN("plugin"), p, pl);
-    set_str_value(STRING_WITH_LEN("authentication_string"), as, asl);
+    set_str_value("plugin", p, pl);
+    set_str_value("authentication_string", as, asl);
   }
   ulong get_access() const
   {
@@ -1222,7 +1222,7 @@ class User_table_json: public User_table
       (or, for example, my_count_bits(GLOBAL_ACLS))
       in the json too, and it'll allow us to do privilege upgrades
     */
-    return get_int_value(STRING_WITH_LEN("access")) & GLOBAL_ACLS;
+    return get_int_value("access") & GLOBAL_ACLS;
   }
   void set_access(ulong rights, bool revoke) const
   {
@@ -1231,53 +1231,53 @@ class User_table_json: public User_table
       access&= ~rights;
     else
       access|= rights;
-    set_int_value(STRING_WITH_LEN("access"), access & GLOBAL_ACLS);
+    set_int_value("access", access & GLOBAL_ACLS);
   }
 
   SSL_type get_ssl_type () const
-  { return (SSL_type)get_int_value(STRING_WITH_LEN("ssl_type")); }
+  { return (SSL_type)get_int_value("ssl_type"); }
   int set_ssl_type (SSL_type x) const
-  { return set_int_value(STRING_WITH_LEN("ssl_type"), x); }
+  { return set_int_value("ssl_type", x); }
   const char* get_ssl_cipher (MEM_ROOT *root) const
-  { return get_str_value(root, STRING_WITH_LEN("ssl_cipher")); }
+  { return get_str_value(root, "ssl_cipher"); }
   int set_ssl_cipher (const char *s, size_t l) const
-  { return set_str_value(STRING_WITH_LEN("ssl_cipher"), s, l); }
+  { return set_str_value("ssl_cipher", s, l); }
   const char* get_x509_issuer (MEM_ROOT *root) const
-  { return get_str_value(root, STRING_WITH_LEN("x509_issuer")); }
+  { return get_str_value(root, "x509_issuer"); }
   int set_x509_issuer (const char *s, size_t l) const
-  { return set_str_value(STRING_WITH_LEN("x509_issuer"), s, l); }
+  { return set_str_value("x509_issuer", s, l); }
   const char* get_x509_subject (MEM_ROOT *root) const
-  { return get_str_value(root, STRING_WITH_LEN("x509_subject")); }
+  { return get_str_value(root, "x509_subject"); }
   int set_x509_subject (const char *s, size_t l) const
-  { return set_str_value(STRING_WITH_LEN("x509_subject"), s, l); }
+  { return set_str_value("x509_subject", s, l); }
   longlong get_max_questions () const
-  { return get_int_value(STRING_WITH_LEN("max_questions")); }
+  { return get_int_value("max_questions"); }
   int set_max_questions (longlong x) const
-  { return set_int_value(STRING_WITH_LEN("max_questions"), x); }
+  { return set_int_value("max_questions", x); }
   longlong get_max_updates () const
-  { return get_int_value(STRING_WITH_LEN("max_updates")); }
+  { return get_int_value("max_updates"); }
   int set_max_updates (longlong x) const
-  { return set_int_value(STRING_WITH_LEN("max_updates"), x); }
+  { return set_int_value("max_updates", x); }
   longlong get_max_connections () const
-  { return get_int_value(STRING_WITH_LEN("max_connections")); }
+  { return get_int_value("max_connections"); }
   int set_max_connections (longlong x) const
-  { return set_int_value(STRING_WITH_LEN("max_connections"), x); }
+  { return set_int_value("max_connections", x); }
   longlong get_max_user_connections () const
-  { return get_int_value(STRING_WITH_LEN("max_user_connections")); }
+  { return get_int_value("max_user_connections"); }
   int set_max_user_connections (longlong x) const
-  { return set_int_value(STRING_WITH_LEN("max_user_connections"), x); }
+  { return set_int_value("max_user_connections", x); }
   double get_max_statement_time () const
-  { return get_double_value(STRING_WITH_LEN("max_statement_time")); }
+  { return get_double_value("max_statement_time"); }
   int set_max_statement_time (double x) const
-  { return set_double_value(STRING_WITH_LEN("max_statement_time"), x); }
+  { return set_double_value("max_statement_time", x); }
   bool get_is_role () const
-  { return get_bool_value(STRING_WITH_LEN("is_role")); }
+  { return get_bool_value("is_role"); }
   int set_is_role (bool x) const
-  { return set_bool_value(STRING_WITH_LEN("is_role"), x); }
+  { return set_bool_value("is_role", x); }
   const char* get_default_role (MEM_ROOT *root) const
-  { return get_str_value(root, STRING_WITH_LEN("default_role")); }
+  { return get_str_value(root, "default_role"); }
   int set_default_role (const char *s, size_t l) const
-  { return set_str_value(STRING_WITH_LEN("default_role"), s, l); }
+  { return set_str_value("default_role", s, l); }
 
   ~User_table_json() {}
  private:
@@ -1290,24 +1290,24 @@ class User_table_json: public User_table
                                  USERNAME_CHAR_LENGTH);
     return 0;
   }
-  bool get_value(const char *key, size_t klen,
+  bool get_value(const char *key, 
                  enum json_types vt, const char **v, size_t *vl) const
   {
     enum json_types value_type;
     int int_vl;
     String str, *res= m_table->field[2]->val_str(&str);
     if (!res ||
-        (value_type= json_get_object_key(res->ptr(), res->end(),
-                             key, key+klen, v, &int_vl)) == JSV_BAD_JSON)
+        (value_type= json_get_object_key(res->ptr(), res->end(), key,
+                                             v, &int_vl)) == JSV_BAD_JSON)
       return 1; // invalid
     *vl= int_vl;
     return value_type != vt;
   }
-  const char *get_str_value(MEM_ROOT *root, const char *key, size_t klen) const
+  const char *get_str_value(MEM_ROOT *root, const char *key) const
   {
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSV_STRING, &value_start, &value_len))
+    if (get_value(key, JSV_STRING, &value_start, &value_len))
       return "";
     char *ptr= (char*)alloca(value_len);
     int len= json_unescape(m_table->field[2]->charset(),
@@ -1319,35 +1319,35 @@ class User_table_json: public User_table
       return NULL;
     return strmake_root(root, ptr, len);
   }
-  longlong get_int_value(const char *key, size_t klen) const
+  longlong get_int_value(const char *key) const
   {
     int err;
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSV_NUMBER, &value_start, &value_len))
+    if (get_value(key, JSV_NUMBER, &value_start, &value_len))
       return 0;
     const char *value_end= value_start + value_len;
     return my_strtoll10(value_start, (char**)&value_end, &err);
   }
-  double get_double_value(const char *key, size_t klen) const
+  double get_double_value(const char *key) const
   {
     int err;
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSV_NUMBER, &value_start, &value_len))
+    if (get_value(key, JSV_NUMBER, &value_start, &value_len))
       return 0;
     const char *value_end= value_start + value_len;
     return my_strtod(value_start, (char**)&value_end, &err);
   }
-  bool get_bool_value(const char *key, size_t klen) const
+  bool get_bool_value(const char *key) const
   {
     size_t value_len;
     const char *value_start;
-    if (get_value(key, klen, JSV_TRUE, &value_start, &value_len))
+    if (get_value(key, JSV_TRUE, &value_start, &value_len))
       return false;
     return true;
   }
-  bool set_value(const char *key, size_t klen,
+  bool set_value(const char *key,
                  const char *val, size_t vlen, bool string) const
   {
     int value_len;
@@ -1356,7 +1356,7 @@ class User_table_json: public User_table
     String str, *res= m_table->field[2]->val_str(&str);
     if (!res || !res->length())
       (res= &str)->set(STRING_WITH_LEN("{}"), m_table->field[2]->charset());
-    value_type= json_get_object_key(res->ptr(), res->end(), key, key+klen,
+    value_type= json_get_object_key(res->ptr(), res->end(), key,
                                     &value_start, &value_len);
     if (value_type == JSV_BAD_JSON)
       return 1; // invalid
@@ -1367,7 +1367,7 @@ class User_table_json: public User_table
       if (value_len)
         json.append(',');
       json.append('"');
-      json.append(key, klen);
+      json.append(STRING_WITH_LEN(key));
       json.append(STRING_WITH_LEN("\":"));
       if (string)
         json.append('"');
@@ -1382,7 +1382,7 @@ class User_table_json: public User_table
     m_table->field[2]->store(json.ptr(), json.length(), json.charset());
     return 0;
   }
-  bool set_str_value(const char *key, size_t klen, const char *val, size_t vlen) const
+  bool set_str_value(const char *key, const char *val, size_t vlen) const
   {
     char buf[JSON_SIZE];
     int blen= json_escape(system_charset_info,
@@ -1391,22 +1391,22 @@ class User_table_json: public User_table
                           (uchar*)buf, (uchar*)buf+sizeof(buf));
     if (blen < 0)
       return 1;
-    return set_value(key, klen, buf, blen, true);
+    return set_value(key, buf, blen, true);
   }
-  bool set_int_value(const char *key, size_t klen, longlong val) const
+  bool set_int_value(const char *key, longlong val) const
   {
     char v[MY_INT64_NUM_DECIMAL_DIGITS+1];
     size_t vlen= longlong10_to_str(val, v, -10) - v;
-    return set_value(key, klen, v, vlen, false);
+    return set_value(key, v, vlen, false);
   }
-  bool set_double_value(const char *key, size_t klen, double val) const
+  bool set_double_value(const char *key, double val) const
   {
     char v[FLOATING_POINT_BUFFER+1];
     size_t vlen= my_fcvt(val, TIME_SECOND_PART_DIGITS, v, NULL);
-    return set_value(key, klen, v, vlen, false);
+    return set_value(key, v, vlen, false);
   }
-  bool set_bool_value(const char *key, size_t klen, bool val) const
-  { return set_value(key, klen, val ? "true" : "false", val ? 4 : 5, false); }
+  bool set_bool_value(const char *key, bool val) const
+  { return set_value(key, val ? "true" : "false", val ? 4 : 5, false); }
 };
 
 class Db_table: public Grant_table_base
diff --git a/strings/json_lib.c b/strings/json_lib.c
index e28ec3c..6c94ce2 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -1943,9 +1943,10 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
   @retval JSV_NOTHING - no such key found.
 */
 enum json_types json_get_object_key(const char *js, const char *js_end,
-                                    const char *key, const char *key_end,
+                                    const char *key,
                                     const char **value, int *value_len)
 {
+  const char *key_end= key + strlen(key);
   json_engine_t je;
   json_string_t key_name;
   int n_keys= 0;
@@ -1999,10 +2000,99 @@ enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey
 
   @retval 0 - success, json is well-formed
   @retval 1 - error, json is invalid
-*/int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs)
+*/
+int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs)
 {
   json_engine_t je;
   json_scan_start(&je, cs, (const uchar *) js, (const uchar *) js + js_len);
   while (json_scan_next(&je) == 0) /* no-op */ ;
   return je.s.error == 0;
 }
+
+
+/*
+  Expects the JSON object as an js argument, and the key name.
+  Looks for this key in the object and returns
+  the location of all the text related to it.
+  The text includes the comma, separating this key.
+
+  comma_pos - the hint where the comma is. It is important
+       if you plan to replace the key rather than just cut.
+    1  - comma is on the left
+    2  - comma is on the right.
+    0  - no comma at all (the object has just this single key)
+ 
+  if no such key found *key_start is set to NULL.
+*/
+int json_locate_key(const char *js, const char *js_end,
+                    const char *kname,
+                    const char **key_start, const char **key_end,
+                    int *comma_pos)
+{
+  const char *kname_end= kname + strlen(kname);
+  json_engine_t je;
+  json_string_t key_name;
+  int t_next, c_len, match_result;
+
+  json_string_set_cs(&key_name, &my_charset_utf8mb4_bin);
+
+  json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js,
+                  (const uchar *) js_end);
+
+  if (json_read_value(&je) ||
+      je.value_type != JSON_VALUE_OBJECT)
+    goto err_return;
+
+  *key_start= (const char *) je.s.c_str;
+  *comma_pos= 0;
+
+  while (!json_scan_next(&je))
+  {
+    switch (je.state)
+    {
+    case JST_KEY:
+      json_string_set_str(&key_name, (const uchar *) kname,
+                          (const uchar *) kname_end);
+      match_result= json_key_matches(&je, &key_name);
+      if (json_skip_key(&je))
+        goto err_return;
+      get_first_nonspace(&je.s, &t_next, &c_len);
+      je.s.c_str-= c_len;
+
+      if (match_result)
+      {
+        *key_end= (const char *) je.s.c_str;
+
+        if (*comma_pos == 1)
+          return 0;
+
+        DBUG_ASSERT(*comma_pos == 0);
+
+        if (t_next == C_COMMA)
+        {
+          *key_end+= c_len;
+          *comma_pos= 2;
+        }
+        else if (t_next == C_RCURB)
+          *comma_pos= 0;
+        else
+          goto err_return;
+        return 0;
+      }
+
+      *key_start= (const char *) je.s.c_str;
+      *comma_pos= 1;
+      break;
+
+    case JST_OBJ_END:
+      *key_start= NULL;
+      return 0;
+    }
+  }
+
+err_return:
+  return 1;
+
+}
+
+
diff --git a/unittest/strings/json-t.c b/unittest/strings/json-t.c
index 8af8636..ce0f04d 100644
--- a/unittest/strings/json-t.c
+++ b/unittest/strings/json-t.c
@@ -17,21 +17,29 @@
 #include <my_sys.h>
 #include <json_lib.h>
 
+int json_locate_key(const char *js, const char *js_end, const char *kname,
+                    const char **key_start, const char **key_end,
+                    int *comma_pos);
 int main()
 {
   const char *json="{\"int\":1, \"str\":\"foo bar\", "
                    "\"array\":[10,20,{\"c\":\"d\"}],\"bool\":false}";
   const char *json_ar="[1, \"foo bar\", " "[10,20,{\"c\":\"d\"}], false]";
+  const char *json_w="{\"int\" : 1 , \"str\" : \"foo bar\" , "
+                   "\"array\" : [10,20,{\"c\":\"d\"}]  , \"bool\" : false  }";
+  const char *json_1="{ \"str\" : \"foo bar\"   }";
   enum json_types value_type;
   const char *value_start;
   int value_len;
+  const char *key_start, *key_end;
+  int result, comma_pos;
 
-  plan(10);
+  plan(15);
 
 #define do_json(V)                                                      \
   do {                                                                  \
     value_type= json_get_object_key(json, json+strlen(json),            \
-                  V, V + (sizeof(V) - 1),&value_start, &value_len);     \
+                  V, &value_start, &value_len);                         \
     ok(value_type != JSV_BAD_JSON, V);                                  \
     diag("type=%d, value=\"%.*s\"", value_type, (int)value_len, value_start); \
   } while(0)
@@ -42,6 +50,16 @@ int main()
     ok(value_type != JSV_BAD_JSON, #N);                      \
     diag("type=%d, value=\"%.*s\"", value_type, (int)value_len, value_start); \
   } while(0)
+#define do_json_locate(J, V)                              \
+  do {                                                    \
+    result= json_locate_key(J, J+strlen(J),               \
+                  V, &key_start, &key_end, &comma_pos);   \
+    ok(result == 0, V);                                   \
+    if (key_start)                                        \
+      diag("key_str=\"%.*s\" comma_pos= %d", (int)(key_end - key_start), key_start, comma_pos); \
+    else                                                                                    \
+      diag("no key found"); \
+  } while(0)
 
   do_json("int");
   do_json("str");
@@ -54,5 +72,11 @@ int main()
   do_json_ar(2);
   do_json_ar(3);
   do_json_ar(4);
+
+  do_json_locate(json_w, "bool");
+  do_json_locate(json_w, "int");
+  do_json_locate(json_w, "array");
+  do_json_locate(json_1, "str");
+  do_json_locate(json_w, "c");
   return exit_status();
 }


More information about the commits mailing list