poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] JSON schema refactoring and adaptive code changes.


From: Mohammad-Reza Nabipoor
Subject: Re: [PATCH] JSON schema refactoring and adaptive code changes.
Date: Fri, 17 Sep 2021 20:58:18 +0430

Hello, Kostas.

On Mon, Sep 06, 2021 at 04:49:03PM +0200, Kostas Chasialis wrote:
> Hello Poke team!
> 
> This is the patch which applies the whole refactoring process we’ve discussed 
> about on previous threads and on IRC.
> 
> I believe its way better than the previous schema.
> 
> Since there are a lot of changes made, something might have slipped my 
> attention. Please feel free to comment!
> 
> Thanks.
> 

Thanks for your work.
In general, the patch is good but there are a few details that I think can be
improved.
Some of them are actually improvements to my previous code, and IMHO they
should be fixed now.


0. As I told you over IRC, the `etc/pk-mi-json-schema.json` patch is broken and
doesn't apply to master.
Just FTR :)


1. Please use "type" and "value" instead of "Type" and "Value" to make fields
more consistent.


2. What about making error handling macros shorter?
Instead of having `RETURN_ON_JERR`, `RETURN_ERR_IF` and `GOTO_ON_JERR`,
we can only have two: `FAIL_IF` and `GOTO_IF`.
And I think putting the error handling on a separate line helps readability.
E.g., instead of

```c
  GOTO_ON_JERR (jexpect (json, "kind", json_type_int, &obj, errmsg), failed,
                errmsg, "invalid message");
  RETURN_ERR_IF ((*j_int = json_object_new_int64 (val)) == NULL, errmsg,
                 "json_object_new_int64 () failed");
```

we can write like this:

```c
  int ret;

  ret = jexpect (json, "kind", json_type_int, &obj, errmsg);
  GOTO_IF (ret == J_NOK, failed, errmsg, "invalid message);

  *j_int = json_object_new_int64 (val);
  FAIL_IF (j_int == NULL, errmsg, "json_object_new_int64 () failed");
```

It's shorter, simpler (because we only have two functions) and IMHO more
readable.


3. `jexpect_*` function names are not clear. You're actually generating JSON
from `pk_val`. Jose would suggest a name like this `pk_val_to_json_*`.
(I hate this long prefix, but he loves it && he's the commander :D)

I think you need to rename the functions and make them more consistent.
We can do it over a Jitsi meeting, too.


4. Inline comments:


diff --git a/testsuite/poke.mi-json/mi-json.c b/testsuite/poke.mi-json/mi-json.c
index 714771ed..8e148315 100644
--- a/testsuite/poke.mi-json/mi-json.c
+++ b/testsuite/poke.mi-json/mi-json.c
[...]
 int
-test_val_to_json (const char *pk_obj_str, pk_val val)
+test_val_to_json (pk_compiler pkc, const char *j_obj_str, pk_val val)
 {
-  const char *pk_test_obj_str;
-  json_object *pk_test_obj, *current;
+  const char *j_obj_str_test;


Names start with `j_` prefix are JSON objects (by our convention).
Maybe `test_obj_str` is better.


+  json_object *j_obj, *j_obj_test;


s/j_obj_test/j_test/
s/j_obj/j_value/


+  char *errmsg;
 
-  if ((pk_test_obj_str = pk_mi_val_to_json (val, NULL)) == NULL)
-    return FAIL;
+  /* Get the JSON object string representation from val_to_json.  */
+  if ((j_obj_str_test = pk_mi_val_to_json (val, &errmsg)) == NULL)
+    {
+      printf ("pk_mi_val_to_json () failed\n");


Please report the `errmsg`.


+      return J_NOK;
+    }
+
+  /* Parse it to get the actual JSON object.  */
+  if (parse_json_str_object (j_obj_str_test, &j_obj_test) == J_NOK)
+    {
+      printf ("failed to parse JSON object\n");
+      return J_NOK;
+    }
 
-  if (parse_json_str_object (pk_test_obj_str, &pk_test_obj) == FAIL)
-    return FAIL;
+  /* Compare this JSON object to the one in the .json file.  */
+  if (parse_json_str_object (j_obj_str, &j_obj) == J_NOK)
+    {
+      printf ("failed to parse JSON object\n");
+      return J_NOK;
+    }
 
-  if (json_object_object_get_ex (pk_test_obj, "PokeValue", &current) == 0)
-    return FAIL;
+  if (!json_object_equal (j_obj, j_obj_test))
+    {
+      printf ("json_object_equal () failed\n");
+      printf ("\n");
+      printf ("test JSON object : %s",
+             json_object_to_json_string_ext (j_obj_test,
+                                             JSON_C_TO_STRING_PRETTY));
+      printf ("\n");
+      printf ("actual JSON object : %s",


Please don't put space before the colon (:) character :)


+             json_object_to_json_string_ext (j_obj, JSON_C_TO_STRING_PRETTY));
 
-  if (test_json_pk_val (current, val) == FAIL)
-    return FAIL;
+      printf ("%s\n", errmsg);


Please remove this line. `errmsg` is not valid here.

 
-  if (json_object_put (pk_test_obj) != 1)
-    return FAIL;
+      return J_NOK;
+    }
 
-  return PASS;
+  return J_OK;
 }
 
 void
@@ -681,5 +340,6 @@ main (int argc, char *argv[])
   test_json_to_msg ();
   test_json_to_val_to_json ();
   totals ();
+


Please add tests for invalid JSONs.

   return 0;
 }


diff --git a/poke/pk-mi-json.c b/poke/pk-mi-json.c
index 297de22b..be8d4a8f 100644
--- a/poke/pk-mi-json.c
+++ b/poke/pk-mi-json.c
@@ -32,20 +32,6 @@
 #define J_OK 1
 #define J_NOK 0 /* Not OK */
 
-#define PK_MI_CHECK(errmsg, A, ...)                                           \
-  do                                                                          \
-    {                                                                         \
-      if (A)                                                                  \
-        break;                                                                \
-      if (errmsg != NULL && asprintf (errmsg, "[ERROR] " __VA_ARGS__) == -1)  \
-        {                                                                     \
-          *errmsg = NULL;                                                     \
-          assert (0 && "asprintf () failed");                                 \
-        }                                                                     \
-      goto error;                                                             \
-    }                                                                         \
-  while (0)
-
 /* Error message handling */
 
 /* Prepend the error message to OUT */
@@ -173,878 +159,1614 @@ jerror (int ok, char **out, const char *fmt, ...)
 
 */
 
-/* Functions to convert pk_val to JSON Poke Value.  */
-static json_object *pk_mi_val_to_json_1 (pk_val val, char **errmsg);
+/* Functions to convert Poke value to JSON object.  */
+static int jvalue (pk_val val, json_object **j_val, char **errmsg);
+static int jtype (pk_val type, json_object **j_type, char **errmsg);
 
-static json_object *
-pk_mi_int_to_json (pk_val pk_int, char **errmsg)
+json_object *
+pk_mi_val_to_json_1 (pk_val val, char **errmsg)


Please mark as `static`.


 {
-  json_object *int_object, *type_object, *value_object, *size_object;
-  const char *type;
-  int size;
-
-  assert (pk_type_code (pk_typeof (pk_int)) == PK_INT);
+  json_object *j_obj = NULL, *j_val, *j_type;
 
-  int_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, int_object != NULL, "json_object_new_object () failed");
+  j_obj = json_object_new_object ();
+  GOTO_ERR_IF (j_obj == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  value_object = json_object_new_int64 (pk_int_value (pk_int));
-  PK_MI_CHECK (errmsg, value_object != NULL,
-              "json_object_new_object () failed");
-  size = pk_int_size (pk_int);
-  type = "Integer";
+  GOTO_ON_JERR (jvalue (val, &j_val, errmsg), error, errmsg,
+                "failed to create JSON object from Poke value");


On error, we're leaking `value_object`.
Please fix other memory leaks in this function like this one.

 
-  size_object = json_object_new_int (size);
-  type_object = json_object_new_string (type);
-  PK_MI_CHECK (errmsg, size_object != NULL, "json_object_new_object () 
failed");
-  PK_MI_CHECK (errmsg, type_object != NULL, "json_object_new_object () 
failed");
+  GOTO_ON_JERR (jtype (pk_typeof (val), &j_type, errmsg), error,
+                errmsg, "failed to create JSON object from Poke type");
 
-  /* OK, fill the properties of our object.  */
-  json_object_object_add (int_object, "type", type_object);
-  json_object_object_add (int_object, "value", value_object);
-  json_object_object_add (int_object, "size", size_object);
+  GOTO_ERR_IF (json_object_object_add (j_obj, "Type", j_type) != 0, error,
+               errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j_obj, "Value", j_val) != 0, error,
+               errmsg, "json_object_object_add () failed");
 
-  return int_object;
+  return j_obj;
 
   error:
+    if (j_obj) assert (json_object_put (j_obj) == 1);
+


Please de-indent the label and if statement.
And don't call functions with side-effects in `assert`; they'll be removed
in release mode compilation (technically with `-DNDEBUG` flag).


     return NULL;
 }
 
-static json_object *
-pk_mi_uint_to_json (pk_val pk_uint, char **errmsg)
+const char *
+pk_mi_val_to_json (pk_val val, char **errmsg)
 {
-  json_object *uint_object, *type_object, *value_object, *size_object;
-  const char *type;
-  int size;
+  return json_object_to_json_string_ext (pk_mi_val_to_json_1 (val, errmsg),
+                                         JSON_C_TO_STRING_PRETTY);


- Why `JSON_C_TO_STRING_PRETTY`?
- We're leaking memeory here. You have to `strdup` the string and release
  the JSON object.


+}
+
+static int jexpect_type_integral (pk_val pk_type_int, json_object **j_type_int,
+                                  char **errmsg);
+static int jexpect_type_string (pk_val pk_type_str, json_object **j_type_str,
+                                char **errmsg);
+static int jexpect_type_offset (pk_val pk_type_off, json_object **j_type_off,
+                                char **errmsg);
+static int jexpect_type_struct (pk_val pk_type_sct, json_object **j_type_sct,
+                                char **errmsg);
+static int jexpect_type_array (pk_val pk_type_arr, json_object **j_type_arr,
+                               char **errmsg);
+static int jexpect_type_null (pk_val pk_type_null, json_object **j_type_null,
+                              char **errmsg);
 
-  assert (pk_type_code (pk_typeof (pk_uint)) == PK_UINT);
+static int
+jtype (pk_val ptype, json_object **j_type, char **errmsg)
+{
+#define JEXPECT_TYPE(type)                                             \
+  RETURN_ON_JERR (jexpect_type_##type (ptype, j_type, errmsg), errmsg, \
+                  "failed to create JSON Type object for " #type)
 
-  uint_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, uint_object != NULL, "json_object_new_object () 
failed");
+   if (ptype == PK_NULL)
+    {
+      JEXPECT_TYPE (null);
+      return J_OK;
+    }
 
-  /* Older versions of libjson-c (0.3.1 & under) do not support
-      json_object_new_uint64.
+  switch (pk_type_code (ptype))
+    {
+      case PK_INT:
+      case PK_UINT:
+        JEXPECT_TYPE (integral);
+        break;
+      case PK_STRING:
+        JEXPECT_TYPE (string);
+        break;
+      case PK_OFFSET:
+        JEXPECT_TYPE (offset);
+        break;
+      case PK_STRUCT:
+        JEXPECT_TYPE (struct);
+        break;
+      case PK_ARRAY:
+        JEXPECT_TYPE (array);
+        break;
+      case PK_CLOSURE:


Please return `J_NOK` here.


+      case PK_ANY:


Please handle ANY. The type is `{"code":"Any"}. And value is a Poke value (
the JSON with "Type" and "Value" fields).


+      default:
+        assert (0);
+    }
 
-      In order to support previous versions, we store unsigned integers
-      as signed integers despite them being too large to represent as
-      signed. (i.e. they are stored as negative).  */
-  value_object = json_object_new_int64 ((int64_t) pk_uint_value (pk_uint));
-  PK_MI_CHECK (errmsg, value_object != NULL,
-              "json_object_new_object () failed");
-  size = pk_uint_size (pk_uint);
-  type = "UnsignedInteger";
+  return J_OK;
 
-  size_object = json_object_new_int (size);
-  type_object = json_object_new_string (type);
-  PK_MI_CHECK (errmsg, size_object != NULL, "json_object_new_object () 
failed");
-  PK_MI_CHECK (errmsg, type_object != NULL, "json_object_new_object () 
failed");
+#undef JEXPECT


Wrong #undef :)
#undef JEXPECT_TYPE


+}
 
-  /* OK, fill the properties of our object.  */
-  json_object_object_add (uint_object, "type", type_object);
-  json_object_object_add (uint_object, "value", value_object);
-  json_object_object_add (uint_object, "size", size_object);
+static int
+jexpect_type_error (json_object *j[], const int LEN)


Please use a better name, like `jfree_all`. This is responsible to free
JSON objects.


+{
+  for (int i = 0; i < LEN; i++)


s/LEN/len/


+    if (j[i])
+      {
+        int free_p = json_object_put (j[i]);
 
-  return uint_object;
+        assert (free_p == 1);
+      }
 
-  error:
-    return NULL;
+  return J_NOK;
 }
 
-static json_object *
-pk_mi_string_to_json (pk_val pk_str, char **errmsg)
+static int
+jexpect_type_integral (pk_val pk_type_int, json_object **j_type_int,
+                       char **errmsg)
 {
-  json_object *string_object, *string_type_object, *string_value_object;
+  enum
+  {
+    type_int,
+    code,
+    info,
+    size,
+    signed_p,
+  };
+  const int LEN = 5;
+  json_object *j[LEN];
+  pk_val tmp;
 
-  assert (pk_type_code (pk_typeof (pk_str)) == PK_STRING);
+  memset (j, 0, sizeof (j));
 
-  string_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, string_object != NULL,
-              "json_object_new_object () failed");
+  j[type_int] = json_object_new_object ();
+  GOTO_ERR_IF (j[type_int] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  string_type_object = json_object_new_string ("String");
-  PK_MI_CHECK (errmsg, string_type_object != NULL,
-              "json_object_new_object () failed");
+  j[code] = json_object_new_string ("Integral");
+  GOTO_ERR_IF (j[code] == NULL, error, errmsg,
+               "json_object_new_string () failed");
 
-  string_value_object = json_object_new_string (pk_string_str (pk_str));
-  PK_MI_CHECK (errmsg, string_value_object != NULL,
-              "json_object_new_object () failed");
+  j[info] = json_object_new_object ();
+  GOTO_ERR_IF (j[info] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  /* OK, fill the properties of our object.  */
-  json_object_object_add (string_object, "type", string_type_object);
-  json_object_object_add (string_object, "value", string_value_object);
+  tmp = pk_integral_type_size (pk_type_int);
+  j[size] = json_object_new_int64 (pk_uint_value (tmp));
+  GOTO_ERR_IF (j[size] == NULL, error, errmsg, "json_object_new_int () 
failed");
 
-  return string_object;
+  tmp = pk_integral_type_signed_p (pk_type_int);
+  j[signed_p] = json_object_new_boolean (pk_int_value (tmp));
+  GOTO_ERR_IF (j[signed_p] == NULL, error, errmsg,
+               "json_object_new_boolean () failed");
 
-  error:
-    return NULL;
-}
+  GOTO_ERR_IF (json_object_object_add (j[info], "size", j[size]) != 0, error,
+               errmsg, "json_object_object_add () failed");


Here, you gave the ownership of `j[size]` to the `j[info]` object, so you
have assign `j[size]` to `NULL`.


+  GOTO_ERR_IF (json_object_object_add (j[info], "signed_p", j[signed_p]) != 0,
+               error, errmsg, "json_object_object_add () failed");


Ditto for `j[signed_p]`.


-static json_object *
-pk_mi_offset_to_json (pk_val pk_offset, char **errmsg)
-{
-  json_object *offset_object, *offset_type_object;
-  json_object *magnitude_object;
-  json_object *unit_object, *unit_type_object, *unit_size_object;
-  json_object *unit_value_object;
-  pk_val off_mag, off_unit;
+  GOTO_ERR_IF (json_object_object_add (j[type_int], "code", j[code]) != 0,
+               error, errmsg, "json_object_object_add () failed");


Ditto for `j[code]`.


+  GOTO_ERR_IF (json_object_object_add (j[type_int], "info", j[info]) != 0,
+               error, errmsg, "json_object_object_add () failed");


Ditto for `j[info]`.

 
-  assert (pk_type_code (pk_typeof (pk_offset)) == PK_OFFSET);
+  *j_type_int = j[type_int];
 
-  offset_type_object = json_object_new_string ("Offset");
-  PK_MI_CHECK (errmsg, offset_type_object != NULL,
-              "json_object_new_object () failed");
+  return J_OK;
 
-  off_mag = pk_offset_magnitude (pk_offset);
-  magnitude_object = pk_type_code (pk_typeof (off_mag)) == PK_INT
-                         ? pk_mi_int_to_json (off_mag, errmsg)
-                         : pk_mi_uint_to_json (off_mag, errmsg);
+error:
+  return jexpect_type_error (j, LEN);
+}
 
-  unit_type_object = json_object_new_string ("UnsignedInteger");
-  PK_MI_CHECK (errmsg, unit_type_object != NULL,
-              "json_object_new_object () failed");
+static int
+jexpect_type_string (pk_val pk_type_str, json_object **j_type_str,
+                     char **errmsg)
+{
+  enum
+  {
+    type_str,
+    code
+  };
+  const int LEN = 2;
+  json_object *j[LEN];
 
-  unit_size_object = json_object_new_int (64);
-  PK_MI_CHECK (errmsg, unit_size_object != NULL,
-              "json_object_new_object () failed");
+  memset (j, 0, sizeof (j));
 
-  off_unit = pk_offset_unit (pk_offset);
-  unit_value_object = json_object_new_int64 ((int64_t) pk_uint_value 
(off_unit));
-  PK_MI_CHECK (errmsg, unit_value_object != NULL,
-              "json_object_new_object () failed");
+  /* Not used explictly.  */


Unnecessary comment.


+  (void) pk_type_str;
 
-  unit_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg,  unit_object != NULL,
-              "json_object_new_object () failed");
+  j[type_str] = json_object_new_object ();
+  GOTO_ERR_IF (j[type_str] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  json_object_object_add (unit_object, "type", unit_type_object);
-  json_object_object_add (unit_object, "value", unit_value_object);
-  json_object_object_add (unit_object, "size", unit_size_object);
+  j[code] = json_object_new_string ("String");
+  GOTO_ERR_IF (j[code] == NULL, error, errmsg,
+               "json_object_new_string () failed");
 
-  offset_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, offset_object != NULL, "json_object_new_object () 
failed");
+  GOTO_ERR_IF (json_object_object_add (j[type_str], "code", j[code]) != 0,
+                error, errmsg, "json_object_object_add () failed");
 
-  /* Built sub-objects, add them to our offset_object.  */
-  json_object_object_add (offset_object, "type", offset_type_object);
-  json_object_object_add (offset_object, "magnitude", magnitude_object);
-  json_object_object_add (offset_object, "unit", unit_object);
+  *j_type_str = j[type_str];
 
-  return offset_object;
+  return J_OK;
 
-  error:
-    return NULL;
+error:
+  return jexpect_type_error (j, LEN);
 }
 
-static json_object *
-pk_mi_mapping_to_json (pk_val val, char **errmsg)
+static int
+jexpect_type_offset (pk_val pk_type_off, json_object **j_type_off,
+                     char **errmsg)
 {
   enum
   {
-    mapping,
-    mapped,
-    strict,
-    ios,
-    offset
+    type_off,
+    code,
+    info,
+    magnitude,
+    unit
   };
   const int LEN = 5;
-  /* Store all JSON objects in an array to make resource management easier */
   json_object *j[LEN];


Please make sure, you're not leaking double-freeing these.


-  int mapped_p;
+  pk_val tmp;
 
   memset (j, 0, sizeof (j));
 
-  j[mapping] = json_object_new_object ();
-  PK_MI_CHECK (errmsg, j[mapping] != NULL, "json_object_new_object () failed");
+  j[type_off] = json_object_new_object ();
+  GOTO_ERR_IF (j[type_off] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  mapped_p = pk_val_mapped_p (val);
-  j[mapped] = json_object_new_boolean (mapped_p);
-  PK_MI_CHECK (errmsg, j[mapped] != NULL, "json_object_new_boolean () failed");
+  j[code] = json_object_new_string ("Offset");
+  GOTO_ERR_IF (j[code] == NULL, error, errmsg,
+               "json_object_new_string () failed");
 
-  if (!mapped_p)
-    {
-      json_object_object_add (j[mapping], "mapped", j[mapped]);
-      return j[mapping];
-    }
+  j[info] = json_object_new_object ();
+  GOTO_ERR_IF (j[info] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  j[strict] = json_object_new_boolean (pk_val_strict_p (val));
-  PK_MI_CHECK (errmsg, j[strict] != NULL, "json_object_new_boolean () failed");
+  tmp = pk_offset_type_base_type (pk_type_off);
+  GOTO_ON_JERR (jexpect_type_integral (tmp, &j[magnitude], errmsg), error,
+                errmsg, "failed to create magnitude value");



s/failed to create magnitude value/failed to create type for magnitude/


 
-  j[offset] = pk_mi_offset_to_json (pk_val_offset (val), errmsg);
-  if (j[offset] == NULL)
-    goto error;
+  tmp = pk_offset_type_unit (pk_type_off);
+  j[unit] = json_object_new_int64 ((int64_t) pk_uint_value (tmp));
+  GOTO_ERR_IF(j[unit] == NULL, error, errmsg,
+              "json_object_new_int64 () failed");
 
-  j[ios] = json_object_new_int64 (pk_int_value (pk_val_ios (val)));
-  PK_MI_CHECK (errmsg, j[ios] != NULL, "json_object_new_object () failed");
+  GOTO_ERR_IF (json_object_object_add (j[info], "magnitude", j[magnitude]) != 
0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[info], "unit", j[unit]) != 0,
+               error, errmsg, "json_object_object_add () failed");
 
-  json_object_object_add (j[mapping], "mapped", j[mapped]);
-  json_object_object_add (j[mapping], "strict", j[strict]);
-  json_object_object_add (j[mapping], "IOS", j[ios]);
-  json_object_object_add (j[mapping], "offset", j[offset]);
+  GOTO_ERR_IF (json_object_object_add (j[type_off], "code", j[code]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[type_off], "info", j[info]) != 0,
+               error, errmsg, "json_object_object_add () failed");
 
-  return j[mapping];
+  *j_type_off = j[type_off];
 
-error:
-  for (int i = 0; i < LEN; i++)
-    if (j[i])
-      {
-        int free_p = json_object_put (j[i]);
+  return J_OK;
 
-        assert (free_p == 1);
-      }
-  return NULL;
+error:
+  return jexpect_type_error (j, LEN);
 }
 
-static json_object *
-pk_mi_sct_to_json (pk_val pk_sct, char **errmsg)
+static int
+jexpect_type_struct (pk_val pk_type_sct, json_object **j_type_sct,
+                     char **errmsg)
 {
-  json_object *pk_sct_object, *pk_sct_type_object;
-  json_object *pk_sct_fields_object, *pk_sct_field_object;
-  json_object *pk_sct_mapping_object, *pk_sct_name_object;
-  json_object *pk_sct_field_value_object;
-  json_object *pk_sct_field_offset_object;
-  json_object *pk_sct_field_name_object;
+  enum
+  {
+    type_sct,
+    code,
+    info,
+    name,
+    fname,
+    ftype,
+    field,
+    fields
+  };
+  const int LEN = 8;
+  json_object *j[LEN];


Ditto.


   pk_val tmp;
-  int err;
+  uint64_t nfields;
 
-  assert (pk_type_code (pk_typeof (pk_sct)) == PK_STRUCT);
+  memset (j, 0, sizeof (j));
 
-  pk_sct_type_object = json_object_new_string ("Struct");
-  PK_MI_CHECK (errmsg, pk_sct_type_object != NULL,
+  j[type_sct] = json_object_new_object ();
+  GOTO_ERR_IF (j[type_sct] == NULL, error, errmsg,
                "json_object_new_object () failed");
 
-  pk_sct_fields_object = json_object_new_array ();
-  PK_MI_CHECK (errmsg, pk_sct_fields_object != NULL,
-               "json_object_new_object () failed");
+  j[code] = json_object_new_string ("Struct");
+  GOTO_ERR_IF (j[code] == NULL, error, errmsg,
+               "json_object_new_string () failed");
 
-  /* Get the name of the struct type and convert it to JSON object.  */
-  tmp = pk_struct_type (pk_sct);
-  pk_sct_name_object = pk_mi_string_to_json (pk_struct_type_name (tmp),
-                                                errmsg);
-  PK_MI_CHECK (errmsg, pk_sct_name_object != NULL,
+  j[info] = json_object_new_object ();
+  GOTO_ERR_IF (j[info] == NULL, error, errmsg,
                "json_object_new_object () failed");
 
-  /* Fill the array of struct fields.  */
-  for (ssize_t i = 0 ; i < pk_uint_value (pk_struct_nfields (pk_sct)) ; i++)
+  tmp = pk_struct_type_name (pk_type_sct);
+  if (tmp != PK_NULL)
     {
-      tmp = pk_struct_field_value (pk_sct, i);
-      pk_sct_field_value_object = pk_mi_val_to_json_1 (tmp, errmsg);
-      tmp = pk_struct_field_boffset (pk_sct, i);
-      pk_sct_field_offset_object = pk_mi_uint_to_json (tmp, errmsg);
-      tmp = pk_struct_field_name (pk_sct, i);
-      pk_sct_field_name_object = pk_mi_string_to_json (tmp, errmsg);
+      j[name] = json_object_new_string (pk_string_str (tmp));
+      GOTO_ERR_IF (j[name] == NULL, error, errmsg,
+                   "json_object_new_string () failed");
+    }
+  else
+    j[name] = NULL;
 
-      if (pk_sct_field_value_object == NULL
-          || pk_sct_field_offset_object == NULL
-          || pk_sct_field_name_object == NULL)
-            goto error;
+  j[fields] = json_object_new_array ();
+  GOTO_ERR_IF (j[fields] == NULL, error, errmsg,
+               "json_object_new_array () failed");
 
-      pk_sct_field_object = json_object_new_object ();
+  tmp = pk_struct_type_nfields (pk_type_sct);
+  nfields = pk_uint_value (tmp);
+  for (size_t i = 0 ; i < nfields; i++)
+    {
+      tmp = pk_struct_type_fname (pk_type_sct, i);
+      if (tmp != PK_NULL)
+        {
+          j[fname] = json_object_new_string (pk_string_str (tmp));
+          GOTO_ERR_IF (j[fname] == NULL, error, errmsg,
+                       "json_object_new_string/null () failed");


Please add the `i` to the `errmsg`.


+        }
+      else
+        j[fname] = NULL;
 
-      json_object_object_add (pk_sct_field_object, "name",
-                                         pk_sct_field_name_object);
+      tmp = pk_struct_type_ftype (pk_type_sct, i);
+      GOTO_ON_JERR (jtype (tmp, &j[ftype], errmsg), error, errmsg,
+                    "failed to create struct field type");


Ditto.

 
-      json_object_object_add (pk_sct_field_object, "value",
-                                         pk_sct_field_value_object);
+      j[field] = json_object_new_object ();
+      GOTO_ERR_IF (j[field] == NULL, error, errmsg,
+                   "json_object_new_object () failed");
 

Ditto.


-      json_object_object_add (pk_sct_field_object, "boffset",
-                                         pk_sct_field_offset_object);
+      GOTO_ERR_IF (json_object_object_add (j[field], "name", j[fname]) != 0,
+                   error, errmsg, "json_object_object_add () failed");
+      GOTO_ERR_IF (json_object_object_add (j[field], "type", j[ftype]) != 0,
+                   error, errmsg, "json_object_object_add () failed");
 
 

Ditto.

-      err = json_object_array_add (pk_sct_fields_object,
-                                        pk_sct_field_object);
-      PK_MI_CHECK (errmsg, err != -1,
-                   "failed to add name object to struct field");
+      GOTO_ERR_IF (json_object_array_add (j[fields], j[field]) != 0, error,
+                   errmsg, "json_object_array_add () failed");
 

Ditto.

     }
 
-  pk_sct_mapping_object = pk_mi_mapping_to_json (pk_sct, errmsg);
-  if (pk_sct_mapping_object == NULL)
-    goto error;
+  GOTO_ERR_IF (json_object_object_add (j[info], "name", j[name]) != 0, error,
+                errmsg, "json_ojbect_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[info], "fields", j[fields]) != 0,
+               error, errmsg, "json_object_object_add () failed");
 
-  pk_sct_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, pk_sct_object != NULL,
-              "json_object_new_object () failed");
+  GOTO_ERR_IF (json_object_object_add (j[type_sct], "code", j[code]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[type_sct], "info", j[info]) != 0,
+               error, errmsg, "json_object_object_add () failed");
 
-  json_object_object_add (pk_sct_object, "type", pk_sct_type_object);
-  json_object_object_add (pk_sct_object, "name", pk_sct_name_object);
-  json_object_object_add (pk_sct_object, "fields", pk_sct_fields_object);
-  json_object_object_add (pk_sct_object, "mapping", pk_sct_mapping_object);
+  *j_type_sct = j[type_sct];
 
-  return pk_sct_object;
+  return J_OK;
 
-  error:
-    return NULL;
+error:
+  return jexpect_type_error (j, LEN);
 }
 
-static json_object *
-pk_mi_array_to_json (pk_val pk_array, char **errmsg)
+static int
+jexpect_type_array (pk_val pk_type_arr, json_object **j_type_arr,
+                    char **errmsg)
 {
-  json_object *pk_array_object, *pk_array_type_object;
-  json_object *pk_array_mapping_object, *pk_array_elements_object;
-  json_object *pk_array_element_object, *pk_array_element_value_object;
-  json_object *pk_array_element_offset_object;
+  enum
+  {
+    type_arr,
+    code,
+    info,
+    bound,
+    b_value,
+    b_sizep,
+    etype
+  };
+  const int LEN = 7;
+  json_object *j[LEN];


Ditto.


   pk_val tmp;
-  int err;
+  int64_t bound_value;
+  int bound_size_p;
 
-  assert (pk_type_code (pk_typeof (pk_array)) == PK_ARRAY);
+  memset (j, 0, sizeof (j));
 
-  pk_array_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, pk_array_object != NULL,
+  j[type_arr] = json_object_new_object ();
+  GOTO_ERR_IF (j[type_arr] == NULL, error, errmsg,
                "json_object_new_object () failed");
 
-  const char *type = "Array";
-  pk_array_type_object = json_object_new_string (type);
-  PK_MI_CHECK (errmsg, pk_array_type_object != NULL,
-               "json_object_new_object () failed");
+  j[code] = json_object_new_string ("Array");
+  GOTO_ERR_IF (j[code] == NULL, error, errmsg,
+               "json_object_new_string () failed");
 
-  /* Initialize our array.  */
-  pk_array_elements_object = json_object_new_array ();
-  PK_MI_CHECK (errmsg, pk_array_elements_object != NULL,
+  j[info] = json_object_new_object ();
+  GOTO_ERR_IF (j[info] == NULL, error, errmsg,
                "json_object_new_object () failed");
 
-  /* Fill elements object.  */
-  for (size_t i = 0 ; i < pk_uint_value (pk_array_nelem (pk_array)) ; i++)
+  tmp = pk_array_type_bound (pk_type_arr);
+  if (tmp == PK_NULL)
+      j[bound] = NULL;
+  else
     {
-      /* For every element on the array, get its value & offset and build
-         the corresponding JSON objects.  */
-      tmp = pk_array_elem_val (pk_array, i);
-      pk_array_element_value_object = pk_mi_val_to_json_1 (tmp, errmsg);
-      tmp = pk_array_elem_boffset (pk_array, i);
-      pk_array_element_offset_object = pk_mi_uint_to_json (tmp, errmsg);
-
-      pk_array_element_object = json_object_new_object ();
+      pk_val p_bound, bound_type;
 
-      json_object_object_add (pk_array_element_object, "value",
-                                         pk_array_element_value_object);
+      p_bound = pk_array_type_bound (pk_type_arr);
+      bound_type = pk_typeof (p_bound);
 
-      json_object_object_add (pk_array_element_object, "boffset",
-                                         pk_array_element_offset_object);
+      switch (pk_type_code (bound_type))
+        {
+          case PK_UINT:
+            bound_value = pk_uint_value (p_bound);
+            bound_size_p = 0;
+            break;
+          case PK_OFFSET:
+            {
+              pk_val b_off_mag = pk_offset_magnitude (p_bound);
+
+              switch (pk_type_code (pk_typeof (b_off_mag)))
+                {
+                  case PK_INT:
+                    bound_value = pk_int_value (b_off_mag);
+                    assert (bound_value > 0);
+                    break;
+                  case PK_UINT:
+                    bound_value = pk_uint_value (b_off_mag);
+                    break;
+                  default:
+                    assert (0);
+                }
+              bound_size_p = 1;
+              /* assert is a bit-offset.  */
+              assert (pk_uint_value (pk_offset_unit (p_bound)) == 1);
+              break;
+            }
+          default:
+            GOTO_ERR_IF (1, error, errmsg, "invalid array bound\n");


Don't use `\n` in error message.


+        }
 
-      err = json_object_array_add (pk_array_elements_object,
-                                        pk_array_element_object);
-      PK_MI_CHECK (errmsg, err != -1, "failed to add element to array");
+      j[bound] = json_object_new_object ();
+      GOTO_ERR_IF (j[bound] == NULL, error, errmsg,
+                   "json_object_new_object () failed");
+      j[b_value] = json_object_new_int64 (bound_value);
+      GOTO_ERR_IF (j[b_value] == NULL, error, errmsg,
+                    "json_object_new_int64 () failed");
+      j[b_sizep] = json_object_new_boolean (bound_size_p);
+      GOTO_ERR_IF (j[b_sizep] == NULL, error, errmsg,
+                  "json_object_new_boolean () failed");
+      GOTO_ERR_IF (json_object_object_add (j[bound], "value", j[b_value]) != 0,
+                   error, errmsg, "json_object_object_add () failed");
+      GOTO_ERR_IF (json_object_object_add (j[bound], "size_p", j[b_sizep]) != 
0,
+                   error, errmsg, "json_object_object_add () failed");
     }
 
-  pk_array_mapping_object = pk_mi_mapping_to_json (pk_array, errmsg);
-  if (pk_array_mapping_object == NULL)
-    goto error;
+  tmp = pk_array_type_etype (pk_type_arr);
+  GOTO_ON_JERR (jtype (tmp, &j[etype], errmsg), error, errmsg,
+                "failed to create array etype");
 
-  /* Everything is built on this point.
-     Fill the properties of the array object.  */
-  json_object_object_add (pk_array_object, "type", pk_array_type_object);
-  json_object_object_add (pk_array_object, "elements", 
pk_array_elements_object);
-  json_object_object_add (pk_array_object, "mapping", pk_array_mapping_object);
+  GOTO_ERR_IF (json_object_object_add (j[info], "bound", j[bound]) != 0, error,
+               errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[info], "etype", j[etype]) != 0, error,
+               errmsg, "json_object_object_add () failed");
 
-  return pk_array_object;
+  GOTO_ERR_IF (json_object_object_add (j[type_arr], "code", j[code]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[type_arr], "info", j[info]) != 0,
+               error, errmsg, "json_object_object_add () failed");
 
-  error:
-    return NULL;
+  *j_type_arr = j[type_arr];
+
+  return J_OK;
+
+error:
+  return jexpect_type_error (j, LEN);
 }
 
-static json_object *
-pk_mi_val_to_json_1 (pk_val val, char **errmsg)
+static int
+jexpect_type_null (pk_val pk_type_null, json_object **j_type_null,
+                   char **errmsg)
 {
-  json_object *pk_val_object = NULL;
+  enum
+  {
+    type_null,
+    code
+  };
+  const int LEN = 2;
+  json_object *j[LEN];
+
+  memset (j, 0, sizeof (j));
+
+  /* Not used explictly.  */
+  (void) pk_type_null;
+
+  j[type_null] = json_object_new_object ();
+  GOTO_ERR_IF (j[type_null] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
+  j[code] = json_object_new_string ("Null");
+  GOTO_ERR_IF (j[code] == NULL, error, errmsg,
+               "json_object_new_string () failed");
+
+  GOTO_ERR_IF (json_object_object_add (j[type_null], "code", j[code]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+
+  *j_type_null = j[type_null];
+
+  return J_OK;
+
+error:
+  return jexpect_type_error (j, LEN);
+}
+
+static int jexpect_int (pk_val pk_int, json_object **j_int, char **errmsg);
+static int jexpect_uint (pk_val pk_uint, json_object **j_uint, char **errmsg);
+static int jexpect_string (pk_val pk_str, json_object **j_str, char **errmsg);
+static int jexpect_offset (pk_val pk_off, json_object **j_off, char **errmsg);
+static int jexpect_struct (pk_val pk_sct, json_object **j_sct, char **errmsg);
+static int jexpect_array (pk_val pk_arr, json_object **j_arr, char **errmsg);
+
+static int
+jvalue (pk_val val, json_object **obj, char **errmsg)
+{
   if (val == PK_NULL)
-    return NULL;
+    {
+      *obj = NULL;
+      return J_OK;
+    }
+
+#define JEXPECT(type)                                         \
+  RETURN_ON_JERR (jexpect_##type (val, obj, errmsg), errmsg,  \
+                  "failed to create JSON Value object for " #type)
+
   switch (pk_type_code (pk_typeof (val)))
     {
       case PK_INT:
-        pk_val_object = pk_mi_int_to_json (val, errmsg);
+        JEXPECT (int);
         break;
       case PK_UINT:
-        pk_val_object = pk_mi_uint_to_json (val, errmsg);
+        JEXPECT (uint);
         break;
       case PK_STRING:
-        pk_val_object = pk_mi_string_to_json (val, errmsg);
+        JEXPECT (string);
         break;
       case PK_OFFSET:
-        pk_val_object = pk_mi_offset_to_json (val, errmsg);
+        JEXPECT (offset);
         break;
       case PK_STRUCT:
-        pk_val_object = pk_mi_sct_to_json (val, errmsg);
+        JEXPECT (struct);
         break;
       case PK_ARRAY:
-        pk_val_object = pk_mi_array_to_json (val, errmsg);
+        JEXPECT (array);
         break;
       case PK_CLOSURE:
       case PK_ANY:


Please handle these too.


       default:
         assert (0);
     }
-  return pk_val_object;
+
+  return J_OK;
+
+#undef JEXPECT
 }
 
-const char *
-pk_mi_val_to_json (pk_val val, char **errmsg)
+static int
+jexpect_int (pk_val pk_int, json_object **j_int, char **errmsg)
 {
-  json_object *pk_val_object, *pk_object;
+  int64_t val = pk_int_value (pk_int);
 
-  pk_val_object = pk_mi_val_to_json_1 (val, errmsg);
+  RETURN_ERR_IF ((*j_int = json_object_new_int64 (val)) == NULL, errmsg,
+                 "json_object_new_int64 () failed");
 
-  pk_object = json_object_new_object ();
-  PK_MI_CHECK (errmsg, pk_object != NULL,
-               "failed to create new json_object");
+  return J_OK;
+}
 
-  json_object_object_add (pk_object, "PokeValue", pk_val_object);
+static int
+jexpect_uint (const pk_val pk_uint, json_object **j_uint, char **errmsg)
+{
+  uint64_t val = pk_uint_value (pk_uint);
 
-  return json_object_to_json_string_ext (pk_object, JSON_C_TO_STRING_PRETTY);
+  RETURN_ERR_IF ((*j_uint = json_object_new_int64 ((int64_t) val)) == NULL,
+                 errmsg, "json_object_new_uint64 () failed");
 
-  error:
-    return NULL;
+  return J_OK;
 }
 
-/* Functions to convert JSON object to Poke value.  */
+static int
+jexpect_string (pk_val pk_str, json_object **j_str, char **errmsg)
+{
+  const char *val = pk_string_str (pk_str);
 
-static int pvalue (json_object *j, pk_val *pval, char **errmsg);
-static int pexpect (json_object *j, int type_code, pk_val *pval,
-                    char **errmsg);
+  RETURN_ERR_IF ((*j_str = json_object_new_string (val)) == NULL, errmsg,
+                 "json_object_new_string () failed");
 
-int
-pk_mi_json_to_val (pk_val *value, const char *json_str, char **errmsg)
+  return J_OK;
+}
+
+static int
+jexpect_offset (pk_val pk_off, json_object **j_off, char **errmsg)
 {
-  json_object *j_obj = NULL, *j_pokevalue;
-  json_tokener *tok = NULL;
-  enum json_tokener_error jerr;
-  char *local_errmsg = NULL;
-  int ret, free_p;
+  pk_val p_mag;
+  int64_t val;
 
-  /* All internal functions assume `errmsg` is either NULL or valid pointer
-     to a memory allocated by `malloc`.  */
-  if (errmsg)
-    *errmsg = NULL; /* success */
+  *j_off = NULL;
+  GOTO_ERR_IF ((*j_off = json_object_new_object ()) == NULL, error, errmsg,
+               "json_object_new_object () failed");


Why do we need a `json_object_new_object()`?
You're assigning a another new JSON object to `j_off`, below.

 
-  tok = json_tokener_new ();
-  PK_MI_CHECK (errmsg, tok != NULL, "json_tokener_new () failed");
+  p_mag = pk_offset_magnitude (pk_off);
 
-  j_obj = json_tokener_parse_ex (tok, json_str, strlen (json_str) + 1);
-  jerr = json_tokener_get_error (tok);
-  PK_MI_CHECK (errmsg, j_obj != NULL, "json_tokener_parse_ex () failed: %s",
-               json_tokener_error_desc (jerr));
-  PK_MI_CHECK (errmsg, jerr == json_tokener_success,
-               "json_tokener_parse_ex () failed: %s",
-               json_tokener_error_desc (jerr));
+  switch (pk_type_code (pk_typeof (p_mag)))
+    {
+      case PK_INT:
+        val = pk_int_value (p_mag);
+        break;
+      case PK_UINT:
+        val = (int64_t) pk_uint_value (p_mag);
+        break;
+      default:
+        assert (0);
+    }
 
-  PK_MI_CHECK (errmsg,
-               json_object_object_get_ex (j_obj, "PokeValue", &j_pokevalue)
-                   == J_OK,
-               "expects \"PokeValue\" field");
-  PK_MI_CHECK (errmsg, pvalue (j_pokevalue, value, &local_errmsg) == J_OK,
-               "Invalid PokeValue object: %s", local_errmsg);
+  GOTO_ERR_IF ((*j_off = json_object_new_int64 (val)) == NULL, error,
+               errmsg, "json_object_new_uint64 () failed");
 
-  ret = 0;
-  goto deinit; /* because of the `goto error` inside the PK_MI_CHECK macro */
+  return J_OK;
 
 error:
-  ret = -1;
-
-deinit:
-  free (local_errmsg);
-  if (j_obj)
+  if (*j_off)
     {
-      free_p = json_object_put (j_obj);
+      int free_p = json_object_put (*j_off);
       assert (free_p == 1);
     }
-  if (tok)
-    json_tokener_free (tok);
-  return ret;
+  return J_NOK;
 }
 
-/* Expects field FIELD of type EXPECTED_TYPE in JSON object.
- *
- * Returns J_OK on success, J_NOK otherwise.
- */
 static int
-jexpect (json_object *obj, const char *field, json_type expected_type,
-         json_object **j_val, char **errmsg)
-{
-  json_object *j_field;
-
-  RETURN_ON_JERR (json_object_object_get_ex (obj, field, &j_field), errmsg,
-                  "expects key \"%s\"", field);
-  RETURN_ON_JERR (json_object_is_type (j_field, expected_type), errmsg,
-                  "expects JSON item of type \"%s\" for field \"%s\"",
-                  json_type_to_name (expected_type), field);
-  *j_val = j_field;
-  return J_OK;
-}
-
-/* Parses JSON object as a Poke value.
- *
- * Returns J_OK on success, J_NOK otherwise.
- */
-static inline int
-pvalue (json_object *obj, pk_val *pval, char **errmsg)
+jexpect_map (pk_val val, json_object **j_map, char **errmsg)
 {
-  static const struct
+  enum
   {
-    int type_code;
-    const char *name;
-  } TYPES[] = {
-    { PK_UNKNOWN, "\"Unknown\"" },
-    { PK_INT, "\"Integer\"" },
-    { PK_UINT, "\"UnsignedInteger\"" },
-    { PK_STRING, "\"String\"" },
-    { PK_OFFSET, "\"Offset\"" },
-    { PK_ARRAY, "\"Array\"" },
-    { PK_STRUCT, "\"Struct\"" },
-    { PK_CLOSURE, "\"Closure\"" },
-    { PK_ANY, "\"Any\"" },
+    mapping,
+    mapped,
+    strict,
+    ios,
+    type,
+    value,
+    offset
   };
-  static const int TYPES_LEN = sizeof (TYPES) / sizeof (TYPES[0]);
-  int type_code;
-  const char *type_str;
-  json_object *j_type;
-
-  if (obj == NULL) {
-    *pval = PK_NULL;
-    return J_OK;
-  }
+  const int LEN = 7;
+  /* Store all JSON objects in an array to make resource management easier */
+  json_object *j[LEN];


Ditto.


+  int mapped_p;
+  pk_val tmp, off_value, off_type;
+
+  memset (j, 0, sizeof (j));
 
-  RETURN_ON_JERR (json_object_object_get_ex (obj, "type", &j_type), errmsg,
-                  "expects \"type\" key");
-  type_str = json_object_to_json_string (j_type);
+  j[mapping] = json_object_new_object ();
+  GOTO_ERR_IF (j[mapping] == NULL, error, errmsg,
+               "json_object_new_object () failed");
 
-  type_code = PK_UNKNOWN;
-  for (int i = 0; i < TYPES_LEN; ++i)
-    if (STREQ (type_str, TYPES[i].name))
-      {
-        type_code = TYPES[i].type_code;
-        break;
-      }
-  return pexpect (obj, type_code, pval, errmsg);
+  mapped_p = pk_val_mapped_p (val);
+  j[mapped] = json_object_new_boolean (mapped_p);
+  GOTO_ERR_IF (j[mapped] == NULL, error, errmsg,
+               "json_object_new_boolean () failed");
+
+  j[strict] = json_object_new_boolean (pk_val_strict_p (val));
+  GOTO_ERR_IF (j[strict] == NULL, error, errmsg,
+               "json_object_new_boolean () failed");
+
+  tmp = pk_val_ios (val);
+  if (tmp == PK_NULL)
+      j[ios] = NULL;


De-indent please.


+  else
+    {
+      j[ios] = json_object_new_int (pk_int_value (tmp));
+      GOTO_ERR_IF (j[ios] == NULL, error, errmsg,
+                   "json_object_new_int () failed");
+    }
+
+  /* NOTE(kostas): pk_val_offset does not return PK_NULL even if mapped_p
+  is 0!  Bug?  */
+  if (!mapped_p)
+      j[offset] = NULL;
+  else
+    {
+      off_value = pk_val_offset (val);
+      off_type = pk_typeof (off_value);
+      GOTO_ON_JERR (jexpect_type_offset (off_type, &j[type], errmsg), error,
+                    errmsg, "jexpect_type_offset () failed");
+      GOTO_ON_JERR (jexpect_offset (off_value, &j[value], errmsg), error,
+                    errmsg, "jexpect offset () failed");
+
+      j[offset] = json_object_new_object ();
+      GOTO_ERR_IF (j[offset] == NULL, error, errmsg,
+                   "json_object_new_object () failed");
+
+      GOTO_ERR_IF (json_object_object_add (j[offset], "type", j[type]) != 0,
+                   error, errmsg, "json_object_object_add () failed");
+      GOTO_ERR_IF (json_object_object_add (j[offset], "value", j[value]) != 0,
+                   error, errmsg, "json_object_object_add () failed");
+    }
+
+  GOTO_ERR_IF (json_object_object_add (j[mapping], "mapped", j[mapped]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[mapping], "strict", j[strict]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[mapping], "IOS", j[ios]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[mapping], "offset", j[offset]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+
+  *j_map = j[mapping];
+
+  return J_OK;
+
+error:
+  return jexpect_type_error (j, LEN);
+}
+
+static int
+jexpect_struct (pk_val pk_sct, json_object **j_sct, char **errmsg)
+{
+  enum
+  {
+    sct,
+    fields,
+    boffsets,
+    mapping
+  };
+  const int LEN = 4;
+  /* Store all JSON objects in an array to make resource management easier */
+  json_object *j[LEN];
+  pk_val nfields;
+
+  memset (j, 0, sizeof (j));
+
+  j[sct] = json_object_new_object ();
+  GOTO_ERR_IF (j[sct] == NULL, error, errmsg,
+               "json_object_new_object () failed");
+
+  j[fields] = json_object_new_array ();
+  GOTO_ERR_IF (j[fields] == NULL, error, errmsg,
+               "json_object_new_array () failed");
+
+  j[boffsets] = json_object_new_array ();
+  GOTO_ERR_IF (j[boffsets] == NULL, error, errmsg,
+               "json_object_new_array () failed");
+
+  nfields = pk_struct_nfields (pk_sct);
+  for (size_t i = 0 ; i < pk_uint_value (nfields) ; i++)


Please don't call `pk_uint_value` on every iteration.


+    {
+      json_object *j_field, *j_boffset;
+      pk_val fvalue, fname, fboffset;
+
+      fname = pk_struct_field_name (pk_sct, i);
+      fvalue = pk_struct_ref_field_value (pk_sct, pk_string_str (fname));
+      GOTO_ON_JERR (jvalue (fvalue, &j_field, errmsg), error, errmsg,
+                    "failed to create JSON value");
+      GOTO_ERR_IF (json_object_array_add (j[fields], j_field) != 0, error,
+                   errmsg, "json_object_array_add () failed");
+
+      fboffset = pk_struct_field_boffset (pk_sct, i);
+      j_boffset = json_object_new_int64 ((int64_t) pk_uint_value (fboffset));
+
+      GOTO_ERR_IF (json_object_array_add (j[boffsets], j_boffset) != 0, error,
+                   errmsg, "json_object_array_add () failed");
+    }
+
+  GOTO_ON_JERR (jexpect_map (pk_sct, &j[mapping], errmsg), error, errmsg,
+                "failed to create JSON mapping");
+
+  GOTO_ERR_IF (json_object_object_add (j[sct], "fields", j[fields]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[sct], "boffsets", j[boffsets]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[sct], "mapping", j[mapping]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+
+  *j_sct = j[sct];
+
+  return J_OK;
+
+error:
+  return jexpect_type_error (j, LEN);
 }
 
-static int pexpect_sct (json_object *j_sct, pk_val *pk_sct, char **errmsg);
-static int pexpect_arr (json_object *j_arr, pk_val *p_array, char **errmsg);
+static int
+jexpect_array (pk_val pk_arr, json_object **j_arr, char **errmsg)
+{
+  enum
+  {
+    arr,
+    elements,
+    boffsets,
+    mapping
+  };
+  const int LEN = 4;
+  /* Store all JSON objects in an array to make resource management easier */
+  json_object *j[LEN];
+  pk_val nelems;
+
+  memset (j, 0, sizeof (j));
+
+  j[arr] = json_object_new_object ();
+  GOTO_ERR_IF (j[arr] == NULL, error, errmsg,
+               "json_object_new_object () failed");
+
+  j[elements] = json_object_new_array ();
+  GOTO_ERR_IF (j[elements] == NULL, error, errmsg,
+               "json_object_new_array () failed");
 
-/* Expects a Poke value of type specified by TYPE_CODE in JSON object.
+  j[boffsets] = json_object_new_array ();
+  GOTO_ERR_IF (j[boffsets] == NULL, error, errmsg,
+               "json_object_new_array () failed");
+
+  nelems = pk_array_nelem (pk_arr);
+  for (size_t i = 0 ; i < pk_uint_value (nelems) ; i++)
+    {
+      json_object *j_elem, *j_boffset;
+      pk_val e_value, e_fboffset;
+
+      e_value = pk_array_elem_val (pk_arr, i);
+      GOTO_ON_JERR (jvalue (e_value, &j_elem, errmsg), error, errmsg,
+                    "failed to create JSON object from Poke value");
+      GOTO_ERR_IF (json_object_array_add (j[elements], j_elem) != 0, error,
+                   errmsg, "json_object_array_add () failed");
+
+      e_fboffset = pk_array_elem_boffset (pk_arr, i);
+      j_boffset = json_object_new_int64 ((int64_t) pk_uint_value (e_fboffset));
+      GOTO_ERR_IF (json_object_array_add (j[boffsets], j_boffset) != 0, error,
+                    errmsg, "json_object_array_add () failed");
+    }
+
+  GOTO_ON_JERR (jexpect_map (pk_arr, &j[mapping], errmsg), error, errmsg,
+                "failed to create JSON mapping");
+
+  GOTO_ERR_IF (json_object_object_add (j[arr], "elements", j[elements]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[arr], "boffsets", j[boffsets]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+  GOTO_ERR_IF (json_object_object_add (j[arr], "mapping", j[mapping]) != 0,
+               error, errmsg, "json_object_object_add () failed");
+
+  *j_arr = j[arr];
+
+  return J_OK;
+
+error:
+  return jexpect_type_error (j, LEN);
+}
+
+/* Functions to convert JSON object to Poke value.  */
+static int pvalue (json_object *obj, pk_val pk_type, pk_val *pk_value,
+                   char **errmsg);
+static int ptype (json_object *j_type, pk_val *pk_type, char **errmsg);
+
+int


Mark this as `static`.


+pk_mi_json_to_val_1 (pk_val *value, json_object *j_obj, char **errmsg)
+{
+  json_object *j_poketype, *j_pokevalue;
+  pk_val type;
+
+  RETURN_ON_JERR (json_object_object_get_ex (j_obj, "Type", &j_poketype),
+                  errmsg, "expects \"Type\" field");


s/Type/type/


+  RETURN_ON_JERR (ptype (j_poketype, &type, errmsg), errmsg,
+               "invalid Type representation");
+
+  RETURN_ON_JERR (json_object_object_get_ex (j_obj, "Value", &j_pokevalue),
+                  errmsg, "expects \"Value\" field");
+  RETURN_ON_JERR (pvalue (j_pokevalue, type, value, errmsg), errmsg,
+                  "invalid Value representation");


s/Value/value/


+
+  return J_OK;
+}
+
+int
+pk_mi_json_to_val (pk_val *value, const char *json_str, char **errmsg)
+{
+  json_object *j_obj = NULL;
+  json_tokener *tok = NULL;
+  enum json_tokener_error jerr;
+  int free_p;
+
+  /* All internal functions assume `errmsg` is either NULL or valid pointer
+     to a memory allocated by `malloc`.  */
+  if (errmsg)
+    *errmsg = NULL; /* success */
+
+  tok = json_tokener_new ();
+  GOTO_ERR_IF (tok == NULL, deinit, errmsg, "json_tokener_new () failed");
+
+  j_obj = json_tokener_parse_ex (tok, json_str, strlen (json_str) + 1);
+  jerr = json_tokener_get_error (tok);
+  GOTO_ERR_IF (j_obj == NULL, deinit, errmsg,
+               "json_tokener_parse_ex () failed: %s",
+               json_tokener_error_desc (jerr));
+  GOTO_ERR_IF (jerr != json_tokener_success, deinit, errmsg,
+               "json_tokener_parse_ex () failed %s",
+               json_tokener_error_desc (jerr));
+
+  return pk_mi_json_to_val_1 (value, j_obj, errmsg);
+
+  deinit:


De-indent.


+  if (j_obj)
+    {
+      free_p = json_object_put (j_obj);
+      assert (free_p == 1);
+    }
+  if (tok)
+    json_tokener_free (tok);
+  return J_NOK;
+}
+
+/* Expects field FIELD of type EXPECTED_TYPE in JSON object.
  *
- * Valid values for TYPE_CODE:
- *   PK_UNKNOWN, PK_INT, PK_UINT, PK_STRING, PK_OFFSET, PK_ARRAY, PK_STRUCT,
- *   PK_CLOSURE, PK_ANY.
+ * Returns J_OK on success, J_NOK otherwise.
+ */
+static int
+jexpect (json_object *obj, const char *field, json_type expected_type,
+         json_object **j_val, char **errmsg)
+{
+  json_object *j_field;
+
+  RETURN_ON_JERR (json_object_object_get_ex (obj, field, &j_field), errmsg,
+                  "expects key \"%s\"", field);
+  RETURN_ON_JERR (json_object_is_type (j_field, expected_type), errmsg,
+                  "expects JSON item of type \"%s\" for field \"%s\"",
+                  json_type_to_name (expected_type), field);
+  *j_val = j_field;
+  return J_OK;
+}
+
+static int pexpect_type_integral (json_object *j_type_int, pk_val *pk_type_int,
+                                  char **errmsg);
+static int pexpect_type_offset (json_object *j_type_off, pk_val *pk_type_off,
+                                char **errmsg);
+static int pexpect_type_struct (json_object *j_type_sct, pk_val *pk_type_sct,
+                                char **errmsg);
+static int pexpect_type_array (json_object *j_type_arr, pk_val *pk_type_arr,
+                               char **errmsg);
+
+/* Parses JSON object as a Poke type.
  *
  * Returns J_OK on success, J_NOK otherwise.
  */
 static int
-pexpect (json_object *j, int type_code, pk_val *pval, char **errmsg)
+ptype (json_object *j_type, pk_val *pk_type, char **errmsg)
 {
-  json_object *j_tmp;
-  const char *str;
+  const char *code;
+  json_object *j_code;
+
+#define STR(X) #X
+#define PEXPECT_TYPE(type)                                               \
+  RETURN_ON_JERR (pexpect_type_##type (j_type, pk_type, errmsg), errmsg, \
+                  "invalid " #type " type");
+
+  RETURN_ON_JERR (jexpect (j_type, "code", json_type_string, &j_code, errmsg),
+                  errmsg, "expects \"code\" field in \"type\"");
+  RETURN_ERR_IF ((code = json_object_get_string (j_code)) == NULL, errmsg,
+                  "invalid \"code\" field");
 
-  switch (type_code)
+  if (STREQ (code, "Integral"))
     {
-    case PK_STRING:
-      RETURN_ON_JERR (jexpect (j, "type", json_type_string, &j_tmp, errmsg),
-                      errmsg, "invalid String");
-      str = json_object_get_string (j_tmp);
-      RETURN_ERR_IF (STRNEQ (str, "String"), errmsg,
-                     "expects \"String\" in field \"type\" but got \"%s\"",
-                     str);
-
-      RETURN_ON_JERR (jexpect (j, "value", json_type_string, &j_tmp, errmsg),
-                      errmsg, "invalid String");
-      str = json_object_get_string (j_tmp);
-      RETURN_ERR_IF ((*pval = pk_make_string (str)) == PK_NULL, errmsg,
-                     "pk_make_string () failed");
+      PEXPECT_TYPE (integral);
+    }
+  else if (STREQ (code, "String"))
+    {
+      *pk_type = pk_make_string_type ();
+    }
+  else if (STREQ (code, "Offset"))
+    {
+      PEXPECT_TYPE (offset);
+    }
+  else if (STREQ (code, "Struct"))
+    {
+      PEXPECT_TYPE (struct);
+    }
+  else if (STREQ (code, "Array"))
+    {
+      PEXPECT_TYPE (array);
+    }
+  else if (STREQ (code, "Closure"))
+    {
+      // NOTE(kostas-to-jemarch&mohammad): Such function does not exist in 
libpoke.h
+      // *pk_type = pk_make_closure_type ();


This will be handled in future, when we add Reference type.
We can return `J_NOK` until then.


+    }
+  else if (STREQ (code, "Any"))
+    {
+      *pk_type = pk_make_any_type ();
+    }
+  else if (STREQ (code, "Void"))
+    {
+      // NOTE(kostas-to-jemarch&mohammad): What to do here?
+      // *pk_type = PK_NULL;


Void is simple. type: `{"code": "Void"}` and value: `null`.
That's it!


+    }
+  else
+   {
+     RETURN_ERR_IF (1, errmsg, "Code has an invalid value");
+   }
 
-      return J_OK;
+  return J_OK;
 
-    case PK_OFFSET:
-      {
-        pk_val mag, unit;
-        int code;
-
-        RETURN_ON_JERR (jexpect (j, "type", json_type_string, &j_tmp, errmsg),
-                        errmsg, "invalid Offset");
-        str = json_object_get_string (j_tmp);
-        RETURN_ERR_IF (STRNEQ (str, "Offset"), errmsg,
-                       "expects \"Offset\" in field \"type\" but got \"%s\"",
-                       str);
-
-        RETURN_ON_JERR (
-            jexpect (j, "magnitude", json_type_object, &j_tmp, errmsg), errmsg,
-            "invalid Offset");
-        RETURN_ON_JERR (pvalue (j_tmp, &mag, errmsg), errmsg,
-                        "invalid Offset");
-        code = pk_type_code (pk_typeof (mag));
-        RETURN_ERR_IF (code != PK_INT && code != PK_UINT, errmsg,
-                       "invalid Offset magnitude");
-
-        RETURN_ON_JERR (jexpect (j, "unit", json_type_object, &j_tmp, errmsg),
-                        errmsg, "invalid Offset");
-        RETURN_ON_JERR (pexpect (j_tmp, PK_UINT, &unit, errmsg), errmsg,
-                        "invalid Offset unit");
-
-        RETURN_ERR_IF ((*pval = pk_make_offset (mag, unit)) == PK_NULL, errmsg,
-                       "pk_make_offset () failed");
-        return J_OK;
-      }
+#undef STR
+#undef GET_INFO
+#undef PEXPECT_TYPE
+}
 
-    case PK_INT:
-      {
-        int64_t value;
-        int size;
-
-        RETURN_ON_JERR (jexpect (j, "type", json_type_string, &j_tmp, errmsg),
-                        errmsg, "invalid Integer");
-        str = json_object_get_string (j_tmp);
-        RETURN_ERR_IF (STRNEQ (str, "Integer"), errmsg,
-                       "expects \"Integer\" in field \"type\" but got \"%s\"",
-                       str);
-
-        RETURN_ON_JERR (jexpect (j, "value", json_type_int, &j_tmp, errmsg),
-                        errmsg, "invalid Integer");
-        value = json_object_get_int64 (j_tmp);
-        RETURN_ON_JERR (jexpect (j, "size", json_type_int, &j_tmp, errmsg),
-                        errmsg, "invalid Integer");
-        size = json_object_get_int (j_tmp);
-
-        RETURN_ERR_IF ((*pval = pk_make_int (value, size)) == PK_NULL, errmsg,
-                       "pk_make_int () failed");
-        return J_OK;
-      }
+/* Parses JSON object as a Poke integral type.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
 
-    case PK_UINT:
-      {
-        uint64_t value;
-        int size;
+static int
+pexpect_type_integral (json_object *j_type_int, pk_val *pk_type_int,
+                       char **errmsg)
+{
+  pk_val size, signed_p;
+  int64_t val;
+  json_object *j_iinfo, *j_size, *j_signed_p;
 
-        RETURN_ON_JERR (jexpect (j, "type", json_type_string, &j_tmp, errmsg),
-                        errmsg, "invalid UnsignedInteger");
-        str = json_object_get_string (j_tmp);
-        RETURN_ERR_IF (
-            STRNEQ (str, "UnsignedInteger"), errmsg,
-            "expects \"UnsignedInteger\" in field \"type\" but got \"%s\"",
-            str);
+  RETURN_ON_JERR (jexpect (j_type_int, "info", json_type_object, &j_iinfo,
+                           errmsg), errmsg, "invalid integral type");
 
-        RETURN_ON_JERR (jexpect (j, "value", json_type_int, &j_tmp, errmsg),
-                        errmsg, "invalid UnsignedInteger");
+  RETURN_ON_JERR (jexpect (j_iinfo, "size", json_type_int, &j_size, errmsg),
+                  errmsg, "invalid \"info\"");
+  val = json_object_get_int64 (j_size);
+  RETURN_ERR_IF (val < 1 || val > 64, errmsg, "invalid size value %ld\n", val);



Please use `PRId64` instead of `%ld`.


 
-        /* Older versions of libjson-c (0.3.1 & older) do not support
-           json_object_get_uint64 (only json_object_get_int64).
+  /* SIZE is a uint<64> value.  */
+  size = pk_make_uint ((uint64_t) val, 64);
 
-           In order to support previous versions, we store unsigned integers
-           as signed integers despite them being too large to represent as
-           signed. (i.e. they are stored as negative).
+  RETURN_ON_JERR (jexpect (j_iinfo, "signed_p", json_type_boolean, &j_signed_p,
+                           errmsg), errmsg, "invalid \"info\"");
+  val = json_object_get_boolean (j_signed_p);
 
-           However, users expect to get the unsigned integer they stored.
+  /* SIGNED_P is a int<32> value.  */
+  signed_p = pk_make_int (val, 32);
 
-           Thus, we have to convert it back to uint64_t.  */
-        value = (uint64_t)json_object_get_int64 (j_tmp);
+  *pk_type_int = pk_make_integral_type (size, signed_p);
 
-        RETURN_ON_JERR (jexpect (j, "size", json_type_int, &j_tmp, errmsg),
-                        errmsg, "invalid UnsignedInteger");
-        size = json_object_get_int (j_tmp);
+  return J_OK;
+}
 
-        RETURN_ERR_IF ((*pval = pk_make_uint (value, size)) == PK_NULL, errmsg,
-                       "pk_make_uint () failed");
-        return J_OK;
-      }
+/* Parses JSON object as a Poke offset type.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
+static int
+pexpect_type_offset (json_object *j_type_off, pk_val *pk_type_off,
+                     char **errmsg)
+{
+  pk_val base_type, unit;
+  int64_t val;
+  const char *code;
+  json_object *j_oinfo, *j_magnitude, *j_code, *j_unit;
 
-    case PK_STRUCT:
-      RETURN_ON_JERR (jexpect (j, "type", json_type_string, &j_tmp, errmsg),
-                      errmsg, "invalid Struct");
-      str = json_object_get_string (j_tmp);
-      RETURN_ERR_IF (STRNEQ (str, "Struct"), errmsg,
-                     "expects \"Struct\" in field \"type\" but got \"%s\"",
-                     str);
-      return pexpect_sct (j, pval, errmsg);
+  RETURN_ON_JERR (jexpect (j_type_off, "info", json_type_object, &j_oinfo,
+                           errmsg), errmsg, "invalid offset type");
 
-    case PK_ARRAY:
-      RETURN_ON_JERR (jexpect (j, "type", json_type_string, &j_tmp, errmsg),
-                      errmsg, "invalid Array");
-      str = json_object_get_string (j_tmp);
-      RETURN_ERR_IF (STRNEQ (str, "Array"), errmsg,
-                     "expects \"Array\" in field \"type\" but got \"%s\"",
-                     str);
-      return pexpect_arr (j, pval, errmsg);
+  RETURN_ON_JERR (jexpect (j_oinfo, "magnitude", json_type_object, 
&j_magnitude,
+                           errmsg), errmsg, "invalid \"info\"");
+  RETURN_ON_JERR (jexpect (j_magnitude, "code", json_type_string, &j_code,
+                           errmsg),
+                  errmsg, "expected \"code\" field in \"magnitude\"");
+
+  RETURN_ERR_IF ((code = json_object_get_string (j_code)) == NULL, errmsg,
+                  "invalid \"code\" field");
+  RETURN_ERR_IF (STRNEQ (code, "Integral"), errmsg,
+                 "\"magnitude\" in \"info\" should be of type integral");
+
+  RETURN_ON_JERR (pexpect_type_integral (j_magnitude, &base_type, errmsg),
+                  errmsg, "invalid integral type");
+
+  RETURN_ON_JERR (jexpect (j_oinfo, "unit", json_type_int, &j_unit, errmsg),
+                  errmsg, "invalid \"info\"");
+  val = json_object_get_int64 (j_unit);
+  RETURN_ERR_IF (val < 0, errmsg, "invalid value for unit %ld\n", val);


Ditto.


+  unit = pk_make_uint ((uint64_t) val, 64);
+
+  *pk_type_off = pk_make_offset_type (base_type, unit);
+
+  return J_OK;
+}
+
+/* Parses JSON object as a Poke struct type.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ *
+ */
+static int
+pexpect_type_struct (json_object *j_type_sct, pk_val *pk_type_sct,
+                     char **errmsg)
+{
+  pk_val name, nfields, *fnames, *ftypes;
+  const char *name_str;
+  json_object *j_sinfo, *j_name, *j_fields;
+
+  RETURN_ON_JERR (jexpect (j_type_sct, "info", json_type_object, &j_sinfo,
+                           errmsg), errmsg, "invalid struct type");
+
+  RETURN_ON_JERR (json_object_object_get_ex (j_sinfo, "name", &j_name), errmsg,
+                  "expects \"name\" in \"info\"");
+  switch (json_object_get_type (j_name))
+    {
+      case json_type_string:
+        name_str = json_object_get_string (j_name);
+        RETURN_ERR_IF (name_str == NULL, errmsg, "invalid \"name\" field");
+        name = pk_make_string (name_str);
+        break;
+      case json_type_null:
+        name = PK_NULL;
+        break;
+      default:
+        RETURN_ERR_IF (1, errmsg, "invalid \"info\"");
+    }
+
+  RETURN_ON_JERR (jexpect (j_sinfo, "fields", json_type_array, &j_fields,
+                           errmsg), errmsg, "invalid \"info\"");
+  nfields = pk_make_uint (json_object_array_length (j_fields), 64);
 
+  pk_allocate_struct_attrs (nfields, &fnames, &ftypes);
+  *pk_type_sct = pk_make_struct_type (nfields, name, fnames, ftypes);
+  for (uint64_t i = 0 ; i < pk_uint_value (nfields) ; i++)


Please don't call `pk_uint_value` on each iteration.


+    {
+      json_object *j_field, *j_fname, *j_ftype;
+      pk_val fname, ftype;
+
+      j_field = json_object_array_get_idx (j_fields, i);
+
+      RETURN_ON_JERR (json_object_object_get_ex (j_field, "name", &j_fname),
+                      errmsg, "expects \"name\" in \"fields\"");
+      switch (json_object_get_type (j_fname))
+        {
+          case json_type_string:
+            name_str = json_object_get_string (j_fname);
+            RETURN_ERR_IF (name_str == NULL, errmsg, "invalid \"name\" field");
+            fname = pk_make_string (name_str);
+            break;
+          case json_type_null:
+            fname = PK_NULL;
+            break;
+          default:
+            RETURN_ERR_IF (1, errmsg, "invalid \"info\"");
+        }
+
+      RETURN_ON_JERR (json_object_object_get_ex (j_field, "type", &j_ftype),
+                      errmsg, "expects \"type\" in \"fields\"");
+      RETURN_ON_JERR (ptype (j_ftype, &ftype, errmsg), errmsg,
+                            "failed to parse Poke type");
+
+      pk_struct_type_set_fname (*pk_type_sct, i, fname);
+      pk_struct_type_set_ftype (*pk_type_sct, i, ftype);
+    }
+
+  return J_OK;
+}
+
+/* Parses JSON object as a Poke array type.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ *
+ */
+static int
+pexpect_type_array (json_object *j_type_arr, pk_val *pk_type_arr,
+                    char **errmsg)
+{
+  pk_val bound, etype;
+  int64_t val;
+  json_object *j_ainfo, *j_bound, *j_bound_val, *j_bound_size_p, *j_etype;
+
+  RETURN_ON_JERR (jexpect (j_type_arr, "info", json_type_object, &j_ainfo,
+                           errmsg), errmsg, "invalid array type");
+
+  RETURN_ON_JERR (json_object_object_get_ex (j_ainfo, "bound", &j_bound),
+                  errmsg, "expects \"bound\" in \"type\"");
+  switch (json_object_get_type (j_bound))
+    {
+      case json_type_object:
+        RETURN_ON_JERR (jexpect (j_bound, "value", json_type_int, &j_bound_val,
+                                 errmsg),
+                        errmsg, "expects \"value\" in \"bound\"");
+        RETURN_ON_JERR (jexpect (j_bound, "size_p", json_type_boolean,
+                                 &j_bound_size_p, errmsg),
+                        errmsg, "expects \"size_p\" in \"bound\"");
+        if (json_object_get_boolean (j_bound_size_p))
+          {
+            /* size_p: "true" means that value is the magnitude of a
+            bit-offset.  */
+            val = json_object_get_int64 (j_bound_val);
+            RETURN_ERR_IF (val < 0, errmsg, "invalid bound value %ld\n", val);
+            bound = pk_make_offset (pk_make_uint (val, 64),
+                                    pk_make_uint (1, 64));
+            RETURN_ERR_IF (bound == PK_NULL, errmsg,
+                           "pk_make_offset () failed");
+          }
+        else
+          {
+            val = json_object_get_int64 (j_bound_val);
+            RETURN_ERR_IF (val < 0, errmsg, "invalid bound value %ld\n", val);
+            bound = pk_make_uint (val, 64);
+          }
+        break;
+      case json_type_null:
+        bound = PK_NULL;
+        break;
+      default:
+        RETURN_ERR_IF (1, errmsg, "invalid \"bound\" in \"info\"");
+    }
+
+  RETURN_ON_JERR (json_object_object_get_ex (j_ainfo, "etype", &j_etype),
+                  errmsg, "expected \"etype\" field in \"info\"");
+  RETURN_ON_JERR (ptype (j_etype, &etype, errmsg), errmsg,
+                         "failed to parse Poke type");
+
+  *pk_type_arr = pk_make_array_type (etype, bound);
+
+  return J_OK;
+}
+
+static int pexpect_int (json_object *j_int, pk_val pk_int_type, pk_val *pk_int,
+                        char **errmsg);
+static int pexpect_uint (json_object *j_uint, pk_val pk_uint_type,
+                         pk_val *pk_uint, char **errmsg);
+static int pexpect_string (json_object *j_str, pk_val pk_str_type,
+                           pk_val *pk_str, char **errmsg);
+static int pexpect_offset (json_object *j_off, pk_val pk_off_type,
+                           pk_val *pk_off, char **errmsg);
+static int pexpect_struct (json_object *j_sct, pk_val pk_sct_type,
+                           pk_val *pk_sct, char **errmsg);
+static int pexpect_array (json_object *j_arr, pk_val pk_arr_type,
+                          pk_val *pk_arr, char **errmsg);
+
+/* Parses JSON object as a Poke value.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
+static int
+pvalue (json_object *obj, pk_val pk_type, pk_val *pk_value, char **errmsg)
+{
+  if (obj == NULL) {
+    *pk_value = PK_NULL;
+    return J_NOK;
+  }


To myself: GNU style please! :)


+
+#define PEXPECT(type)                                                     \
+  RETURN_ON_JERR(pexpect_##type (obj, pk_type, pk_value, errmsg), errmsg, \
+                 "failed to parse Poke value (" #type ")")
+
+  switch (pk_type_code (pk_type))
+    {
+    case PK_INT:
+      PEXPECT (int);
+      return J_OK;
+    case PK_UINT:
+      PEXPECT (uint);
+      return J_OK;
+    case PK_STRING:
+      PEXPECT (string);
+      return J_OK;
+    case PK_OFFSET:
+      PEXPECT (offset);
+      return J_OK;
+    case PK_STRUCT:
+      PEXPECT (struct);
+      return J_OK;
+    case PK_ARRAY:
+      PEXPECT (array);
+      return J_OK;
     case PK_ANY:
     case PK_CLOSURE:
       return jerror (J_NOK, errmsg, "unsupported Poke type (code:%d)",
-                     type_code);
-
+                     pk_type_code (pk_type));
     case PK_UNKNOWN:
     default:
-      return jerror (J_NOK, errmsg, "unknown Poke type (code:%d)", type_code);
+      return jerror (J_NOK, errmsg, "unknown Poke type (code:%d)",
+                     pk_type_code (pk_type));
     }
 

Why switch and macro, that loop was better :)


   return J_NOK;
+
+#undef PEXPECT
 }
 
+/* Expects a Poke int value in JSON object.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
 static int
-pexpect_map (json_object *j_map, pk_val p_val, char **errmsg)
+pexpect_int (json_object *j_int, pk_val pk_int_type, pk_val *pk_int,
+             char **errmsg)
 {
-  json_object *j_tmp;
-  pk_val p_ios, p_off;
-  int strict_p;
+  int64_t value;
+  int size;
 
-#define MAP_JERR(cond) RETURN_ON_JERR ((cond), errmsg, "invalid Mapping")
+  /* libpoke says this number is uint<64>, which means we have to cast.  */
+  size = (int) pk_uint_value (pk_integral_type_size (pk_int_type));
 
-  MAP_JERR (jexpect (j_map, "mapped", json_type_boolean, &j_tmp, errmsg));
-  if (!json_object_get_boolean (j_tmp)) /* The value is not mapped */
-    return J_OK;
+  RETURN_ON_JERR (json_object_is_type (j_int, json_type_int), errmsg,
+                  "expects JSON item of type \"%s\" for field \"Value\"",
+                  json_type_to_name (json_type_int));


Why `json_type_to_name (json_type_int)` instead of a simple `"int"`?!
https://github.com/json-c/json-c/blob/4fc44f32df9d59b3fbc1c09a29ca897318d3e610/json_util.c#L274


+  value = json_object_get_int64 (j_int);
 
-  MAP_JERR (jexpect (j_map, "strict", json_type_boolean, &j_tmp, errmsg));
-  strict_p = json_object_get_boolean (j_tmp);
+  /* pk_make_int () can't fail because size is already checked in ptype ().  */
+  *pk_int = pk_make_int (value, size);
 
-  MAP_JERR (jexpect (j_map, "IOS", json_type_int, &j_tmp, errmsg));
-  RETURN_ERR_IF ((p_ios = pk_make_int (json_object_get_int (j_tmp), 32))
-                     == PK_NULL,
-                 errmsg, "pk_make_int (, 32) failed");
+  return J_OK;
+}
 
-  MAP_JERR (jexpect (j_map, "offset", json_type_object, &j_tmp, errmsg));
-  MAP_JERR (pexpect (j_tmp, PK_OFFSET, &p_off, errmsg));
+/* Expects a Poke uint value in JSON object.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
+static int
+pexpect_uint (json_object *j_uint, pk_val pk_uint_type, pk_val *pk_uint,
+              char **errmsg)
+{
+  uint64_t value;
+  int size;
 
-  pk_val_set_mapped (p_val, 1);
-  pk_val_set_strict (p_val, strict_p);
-  pk_val_set_ios (p_val, p_ios);
-  pk_val_set_offset (p_val, p_off);
+  /* libpoke says this number is uint<64>, which means we have to cast.  */
+  size = (int) pk_uint_value (pk_integral_type_size (pk_uint_type));
+
+  RETURN_ON_JERR (json_object_is_type (j_uint, json_type_int), errmsg,
+                  "expects JSON item of type \"%s\" for field \"Value\"",
+                  json_type_to_name (json_type_int));
+  /* Older versions of libjson-c (0.3.1 & older) do not support
+  json_object_get_uint64 (only json_object_get_int64).
+
+  In order to support previous versions, we store unsigned integers
+  as signed integers despite them being too large to represent as
+  signed. (i.e. they are stored as negative).
+
+  However, users expect to get the unsigned integer they stored.
+
+  Thus, we have to convert it back to uint64_t.  */
+  value = (uint64_t)json_object_get_int64 (j_uint);
+
+  /* pk_make_uint () can't fail because size is already checked in ptype ().  
*/
+  *pk_uint = pk_make_uint (value, size);
 
   return J_OK;
 }
 
-/* Expects a Poke struct value in JSON object.
+/* Expects a Poke string value in JSON object.
  *
  * Returns J_OK on success, J_NOK otherwise.
  */
 static int
-pexpect_sct (json_object *j_sct, pk_val *p_struct, char **errmsg)
+pexpect_string (json_object *j_str, pk_val pk_str_type, pk_val *pk_str,
+                char **errmsg)
 {
-  json_object *j_fields, *j_mapping, *j_name;
-  pk_val p_sct_name, p_nfields, p_sct_type, p_sct;
-  pk_val *p_fnames, *p_ftypes;
-  size_t fields_len;
-
-#define SCT_JERR(cond) RETURN_ON_JERR ((cond), errmsg, "invalid Struct")
+  const char *str_value;
 
-  SCT_JERR (jexpect (j_sct, "name", json_type_object, &j_name, errmsg));
-  SCT_JERR (jexpect (j_sct, "fields", json_type_array, &j_fields, errmsg));
-  SCT_JERR (jexpect (j_sct, "mapping", json_type_object, &j_mapping, errmsg));
+  /* Explicitly unused parameter.  */


Unnecessary comment.


+  (void) pk_str_type;
+  RETURN_ON_JERR (json_object_is_type (j_str, json_type_string), errmsg,
+                  "expects JSON item of type \"%s\" for field \"Value\"",
+                  json_type_to_name (json_type_string));


Just use "string".


+  str_value = json_object_get_string (j_str);
+  RETURN_ERR_IF (str_value == NULL, errmsg, "invalid String value");
 
-  fields_len = json_object_array_length (j_fields);
-  p_nfields = pk_make_uint (fields_len, 64);
+  *pk_str = pk_make_string (str_value);
 
-  SCT_JERR (pexpect (j_name, PK_STRING, &p_sct_name, errmsg));
+  return J_OK;
+}
 
-  pk_allocate_struct_attrs (p_nfields, &p_fnames, &p_ftypes);
-  p_sct_type = pk_make_struct_type (p_nfields, p_sct_name, p_fnames, p_ftypes);
-  p_sct = pk_make_struct (p_nfields, p_sct_type);
+/* Expects a Poke offset value in JSON object.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
+static int
+pexpect_offset (json_object *j_off, pk_val pk_off_type, pk_val *pk_off,
+                char **errmsg)
+{
+  pk_val base_type, magnitude;
+  size_t size;
 
-  for (size_t i = 0; i < fields_len; i++)
+  base_type = pk_offset_type_base_type (pk_off_type);
+  size = pk_uint_value (pk_integral_type_size (base_type));
+  switch (pk_type_code (base_type))
     {
-      json_object *j_elem, *j_name, *j_value, *j_boffset;
-      pk_val p_sct_name, p_sct_value, p_sct_boffset;
+      case PK_INT:
+        magnitude = pk_make_int (json_object_get_int64 (j_off), size);
+        break;
+      case PK_UINT:
+        magnitude = pk_make_uint (json_object_get_int64 (j_off), size);
+        break;
+      default:
+        assert (0);
+    }
 
-      j_elem = json_object_array_get_idx (j_fields, i);
+  *pk_off = pk_make_offset (magnitude, pk_offset_type_unit (pk_off_type));
+  RETURN_ERR_IF (*pk_off == PK_NULL, errmsg, "pk_make_offset () failed");
 
-      SCT_JERR (jexpect (j_elem, "name", json_type_object, &j_name, errmsg));
-      SCT_JERR (jexpect (j_elem, "value", json_type_object, &j_value, errmsg));
-      SCT_JERR (
-          jexpect (j_elem, "boffset", json_type_object, &j_boffset, errmsg));
+  return J_OK;
+}
 
-      SCT_JERR (pexpect (j_name, PK_STRING, &p_sct_name, errmsg));
-      SCT_JERR (pvalue (j_value, &p_sct_value, errmsg));
-      SCT_JERR (pexpect (j_boffset, PK_UINT, &p_sct_boffset, errmsg));
+/* Expects a Poke mapping value in JSON object.
+ *
+ * Returns J_OK on success, J_NOK otherwise.
+ */
+static int
+pexpect_map (json_object *j_map, pk_val p_val, char **errmsg)
+{
+  json_object *j_tmp, *j_ios, *j_off, *j_off_type, *j_off_val;
+  pk_val p_ios, p_off_type, p_off;
+  int strict_p, mapped_p;
 
-      RETURN_ERR_IF (p_sct_value == PK_NULL, errmsg, "invalid Struct");
+#define MAP_JERR(cond) RETURN_ON_JERR ((cond), errmsg, "invalid Mapping")
 
-      pk_struct_type_set_fname (p_sct_type, i, p_sct_name);
-      pk_struct_type_set_ftype (p_sct_type, i, pk_typeof (p_sct_value));
-      pk_struct_set_field_name (p_sct, i, p_sct_name);
-      pk_struct_set_field_value (p_sct, i, p_sct_value);
-      pk_struct_set_field_boffset (p_sct, i, p_sct_boffset);
+  MAP_JERR (jexpect (j_map, "mapped", json_type_boolean, &j_tmp, errmsg));
+  mapped_p = json_object_get_boolean (j_tmp);
+
+  MAP_JERR (jexpect (j_map, "strict", json_type_boolean, &j_tmp, errmsg));
+  strict_p = json_object_get_boolean (j_tmp);
+
+  RETURN_ON_JERR (json_object_object_get_ex (j_map, "IOS", &j_ios), errmsg,
+                  "expects \"offset\" in \"mapping\"");
+  switch (json_object_get_type (j_ios))
+    {
+      case json_type_int:
+        p_ios = pk_make_int (json_object_get_int (j_ios), 32);
+        RETURN_ERR_IF (p_ios == PK_NULL, errmsg, "pk_make_int (, 32) failed");
+        break;
+      case json_type_null:
+        p_ios = PK_NULL;
+        break;
+      default:
+        RETURN_ERR_IF (1, errmsg, "invalid \"IOS\" in \"mapping\"");
     }
 
-  SCT_JERR (pexpect_map (j_mapping, p_sct, errmsg));
-  *p_struct = p_sct;
+  RETURN_ON_JERR (json_object_object_get_ex (j_map, "offset", &j_off), errmsg,
+                  "expects \"offset\" in \"mapping\"");
+  switch (json_object_get_type (j_off))
+    {
+      case json_type_object:
+        RETURN_ON_JERR (json_object_object_get_ex (j_off, "type", &j_off_type),
+                        errmsg, "expects \"type\" in \"offset\"");
+        RETURN_ON_JERR (json_object_object_get_ex (j_off, "value", &j_off_val),
+                        errmsg, "expects \"value\" in \"offset\"");
+        MAP_JERR (pexpect_type_offset (j_off_type, &p_off_type, errmsg));
+        MAP_JERR (pexpect_offset (j_off_val, p_off_type, &p_off, errmsg));
+        break;
+      case json_type_null:
+        p_off = PK_NULL;
+        break;
+      default:
+        RETURN_ERR_IF (1, errmsg, "invalid \"offset\" in \"mapping\"");
+    }
+
+  pk_val_set_mapped (p_val, mapped_p);
+  pk_val_set_strict (p_val, strict_p);
+  pk_val_set_ios (p_val, p_ios);
+  pk_val_set_offset (p_val, p_off);
+
   return J_OK;
 
-#undef SCT_JERR
+#undef MAP_JERR
 }
 
-/* Expects a Poke array elem in JSON object.
+/* Expects a Poke struct value in JSON object.
  *
  * Returns J_OK on success, J_NOK otherwise.
  */
 static int
-pexpect_aelem (json_object *j_elem, pk_val *p_elem_val, pk_val *p_elem_boff,
-               char **errmsg)
+pexpect_struct (json_object *j_sct, pk_val pk_sct_type, pk_val *pk_sct,
+                char **errmsg)
 {
-  json_object *j_val, *j_boff;
+  pk_val pk_sct_tmp;
+  json_object *j_fields, *j_boffsets, *j_mapping;
+  size_t nfields;
 
-#define AELEM_JERR(cond)                                                      \
-  RETURN_ON_JERR ((cond), errmsg, "invalid Array element")
-
-  AELEM_JERR (jexpect (j_elem, "value", json_type_object, &j_val, errmsg));
-  AELEM_JERR (jexpect (j_elem, "boffset", json_type_object, &j_boff, errmsg));
+#define SCT_JERR(cond) RETURN_ON_JERR ((cond), errmsg, "invalid Struct")
 
-  AELEM_JERR (pvalue (j_val, p_elem_val, errmsg));
-  AELEM_JERR (pexpect (j_boff, PK_UINT, p_elem_boff, errmsg));
+  SCT_JERR (jexpect (j_sct, "fields", json_type_array, &j_fields, errmsg));
+  nfields = json_object_array_length (j_fields);
+  RETURN_ERR_IF (nfields !=
+                 pk_uint_value (pk_struct_type_nfields (pk_sct_type)), errmsg,
+                 "invalid Struct (fields array length mismatch with type)");
+
+  SCT_JERR (jexpect (j_sct, "boffsets", json_type_array, &j_boffsets, errmsg));
+  RETURN_ERR_IF (json_object_array_length (j_boffsets) != nfields, errmsg,
+                 "invalid Struct (boffsets array length mismatch with type");
+
+  pk_sct_tmp = pk_make_struct (pk_struct_type_nfields (pk_sct_type),
+                               pk_sct_type);
+  for (size_t i = 0 ; i < nfields ; i++)
+    {
+      pk_val field, boffset;
+      json_object *j_field, *j_boffset;
+      int64_t boffset_val;
+
+      j_field = json_object_array_get_idx (j_fields, i);
+      SCT_JERR (pvalue (j_field, pk_struct_type_ftype (pk_sct_type, i), &field,
+                        errmsg));
+
+      j_boffset = json_object_array_get_idx (j_boffsets, i);
+      RETURN_ON_JERR (json_object_is_type (j_boffset, json_type_int), errmsg,
+                      "expects JSON item of type \"%s\" in \"boffsets\"",
+                      json_type_to_name (json_type_int));
+      boffset_val = json_object_get_int64 (j_boffset);
+      RETURN_ERR_IF (boffset_val < 0, errmsg,
+                     "boffset should be positive value");
+      boffset = pk_make_uint ((uint64_t) boffset_val, 64);
+
+      pk_struct_set_field_name (pk_sct_tmp, i,
+                                pk_struct_type_fname (pk_sct_type, i));
+      pk_struct_set_field_value (pk_sct_tmp, i, field);
+      pk_struct_set_field_boffset (pk_sct_tmp, i, boffset);
+    }
 
-  RETURN_ERR_IF (pk_integral_type_size (pk_typeof (*p_elem_boff)) == 64,
-                 errmsg, "boffset should be an uint<64>");
+  SCT_JERR (jexpect (j_sct, "mapping", json_type_object, &j_mapping, errmsg));
+  SCT_JERR (pexpect_map (j_mapping, pk_sct_tmp, errmsg));
+  *pk_sct = pk_sct_tmp;
 
   return J_OK;
 
-#undef AELEM_JER
+#undef SCT_JERR
 }
 
-/* Expects a Poke array in JSON object.
+/* Expects a Poke array value in JSON object.
  *
  * Returns J_OK on success, J_NOK otherwise.
  */
 static int
-pexpect_arr (json_object *j_arr, pk_val *p_array, char **errmsg)
+pexpect_array (json_object *j_arr, pk_val pk_arr_type, pk_val *pk_arr,
+               char **errmsg)
 {
-  json_object *j_elems, *j_elem, *j_mapping;
-  pk_val p_arr, p_value, p_boffset, p_aelem_type /*array element type*/,
-      p_arr_type;
-  size_t elems_len;
+  pk_val pk_arr_tmp, pk_arr_bound;
+  json_object *j_elems, *j_boffsets, *j_mapping;
+  size_t nelems;
+  int64_t pk_arr_bound_value;


What's the purpose of `pk_arr_bound_value`?
I don't understand!
This function seems a little too complicated :)

 
 #define ARR_JERR(cond) RETURN_ON_JERR ((cond), errmsg, "invalid Array")
 
   ARR_JERR (jexpect (j_arr, "elements", json_type_array, &j_elems, errmsg));
-  ARR_JERR (jexpect (j_arr, "mapping", json_type_object, &j_mapping, errmsg));
+  nelems = json_object_array_length (j_elems);
+  pk_arr_bound = pk_array_type_bound (pk_arr_type);
+
+  ARR_JERR (jexpect (j_arr, "boffsets", json_type_array, &j_boffsets, errmsg));
+  RETURN_ERR_IF (json_object_array_length (j_boffsets) != nelems, errmsg,
+                 "invalid Struct: boffsets array length mismatch with type");
 
-  elems_len = json_object_array_length (j_elems);
+  if (pk_arr_bound != PK_NULL)
+    pk_arr_tmp = pk_make_array (pk_arr_bound, pk_arr_type);


`pk_make_array` expect first argument to be hint of #elems.
It's undefined for offset values.
Use the JSON to find the number of elements.


+  else
+    pk_arr_tmp = pk_make_array (pk_make_uint (0, 64), pk_arr_type);
 
-  /* FIXME no empty array */
-  if (elems_len == 0)
+  for (size_t i = 0 ; i < nelems ; i++)
     {
-      *p_array = PK_NULL;
-      return J_OK;
-    }
+      pk_val elem, boffset;
+      json_object *j_elem, *j_boffset;
+      int64_t boffset_val;
 
-  /* assert (elems_len != 0); */
+      j_elem = json_object_array_get_idx (j_elems, i);
+      ARR_JERR (pvalue (j_elem, pk_array_type_etype (pk_arr_type), &elem,
+                        errmsg));
+      pk_array_insert_elem (pk_arr_tmp, i, elem);
+
+      j_boffset = json_object_array_get_idx (j_boffsets, i);
+      RETURN_ON_JERR (json_object_is_type (j_boffset, json_type_int), errmsg,
+                      "expects JSON item of type \"%s\" in \"boffsets\"",
+                      json_type_to_name (json_type_int));
+      boffset_val = json_object_get_int64 (j_boffset);
+      RETURN_ERR_IF (boffset_val < 0, errmsg,
+                     "boffset should be positive value");
+      boffset = pk_make_uint ((uint64_t) boffset_val, 64);
 
-  /* Type of the array will be the type of first element */
-  j_elem = json_object_array_get_idx (j_elems, 0);
+      RETURN_ERR_IF (
+        !pk_val_equal_p (pk_array_elem_boffset (pk_arr_tmp, i), boffset),
+        errmsg, "invalid Array: boffset mismatch at index %zu", i);
+    }
 
-  /* FIXME no support for null items */
-  assert (j_elem != NULL);
+  if (pk_arr_bound != PK_NULL)
+    {
+      /* Double check the size of the generated array and the bound.  */
+      switch (pk_type_code (pk_typeof (pk_arr_bound)))
+        {
+          case PK_UINT:
+            pk_arr_bound_value = pk_uint_value (pk_arr_bound);
+            break;
+          case PK_OFFSET:
+            {
+              pk_val b_off_mag = pk_offset_magnitude (pk_arr_bound);
+
+              switch (pk_type_code (pk_typeof (b_off_mag)))
+                {
+                  case PK_INT:
+                    pk_arr_bound_value = pk_int_value (b_off_mag);
+                    assert (pk_arr_bound_value > 0);
+                    break;
+                  case PK_UINT:
+                    pk_arr_bound_value = pk_uint_value (b_off_mag);
+                    break;
+                  default:
+                    assert (0);
+                }
+              /* NOTE(kostas): We need to discuss about this because
+              it is possible that some array elements won't be of the same 
size!
+              */
+              if (nelems != 0)
+                pk_arr_bound_value /= pk_sizeof (pk_array_elem_val (pk_arr_tmp,
+                                                                    0));


I don't know the reason, but this clearly is not a good idea :)



+              break;
+            }
+          default:
+            assert (0);
+        }
 
-  ARR_JERR (pexpect_aelem (j_elem, &p_value, &p_boffset, errmsg));
-  p_aelem_type = pk_typeof (p_value);
-  p_arr_type = pk_make_array_type (p_aelem_type, PK_NULL);
-  p_arr = pk_make_array (pk_make_uint (elems_len, 64), p_arr_type);
+      RETURN_ERR_IF (nelems != (uint64_t) pk_arr_bound_value, errmsg,
+                    "invalid Array: elements array length mismatch with type");
+    }
 
-  pk_array_insert_elem (p_arr, 0, p_value);
-  RETURN_ERR_IF (!pk_val_equal_p (pk_array_elem_boffset (p_arr, 0), p_boffset),
-                 errmsg, "invalid Array: boffset mismatch at index 0");
+  ARR_JERR (jexpect (j_arr, "mapping", json_type_object, &j_mapping, errmsg));
 
-  for (size_t i = 1; i < elems_len; ++i)
-    {
-      j_elem = json_object_array_get_idx (j_elems, i);
-      assert (j_elem != NULL);
-      ARR_JERR (pexpect_aelem (j_elem, &p_value, &p_boffset, errmsg));
-      pk_array_insert_elem (p_arr, i, p_value);
-      RETURN_ERR_IF (
-          !pk_val_equal_p (pk_array_elem_boffset (p_arr, i), p_boffset),
-          errmsg, "invalid Array: boffset mismatch at index %zu", i);
-    }
+  ARR_JERR (pexpect_map (j_mapping, pk_arr_tmp, errmsg));
+  *pk_arr = pk_arr_tmp;
 
-  ARR_JERR (pexpect_map (j_mapping, p_arr, errmsg));
-  *p_array = p_arr;
   return J_OK;
 
 #undef ARR_JERR
@@ -1088,7 +1810,7 @@ collect_json_arg (const char *name, pk_val value /* Note 
unused */,
 
   if (!json_object_object_get_ex (args, name, &obj))
     return 0;
-  if (pvalue (obj, &val, NULL /* errmsg */) != J_OK)
+  if (pk_mi_json_to_val_1 (&val, obj, NULL) != J_OK)
     return 0;
 
   pk_mi_set_arg (msg, name, val);



Regards,
Mohammad-Reza



reply via email to

[Prev in Thread] Current Thread [Next in Thread]