-
Notifications
You must be signed in to change notification settings - Fork 840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce new JSON parser utility #12531
base: main
Are you sure you want to change the base?
Conversation
cec8408
to
e494d37
Compare
I understand the desire to insulate ourselves from the specific json reader implementation by abstracting out an interface for us to use. However, I am a little uncomfortable inventing a new interface for a json reader. Relevant XKCD. Why not use json-parser's json.c/json.h symbols directly? |
@lrbison For the most part, json-parser only provides an API to parse a string. This PR extended that API to support filename. Another reason is that I modeled the JSON object with a |
It's probably better to add some descriptions on how to use the json parser than pointing the users to some source code. Please also include the new features added and how to convert existing tuning files into the json files. |
That's a good idea. I can add an example later. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, but there are still some questions pending.
- Can you don't use the same name for the two .[ch] files. I know they are in different directories, but the identical name is confusing.
- What is the benefit to have the OPAL_OBJECT support ? Is this benefit worth enough to account for the extra memory and CPU needed (including the refcount) to handle the opal_object_t.
@bosilca Thank you very much for the review. I have renamed the files as suggested.
The primary motivation is memory management. In json-parser, only the root object should be freed after use - the child objects are merely pointers to the root. This can be tricky to use. With the opal object lifecycle hooks we can override the destructor to correctly free the root object only, while the application can safely TBH I am not concerned with resource usage - the parser should only be used to read the file into memory and stored somewhere else, e.g. a schema with efficient query methods. Afterwards the parser should be torn down. |
@juntangc I added an example program in |
If you don't add all the OPAL objectification you only have to free a single object, the initial json object via |
That is also my goal. But my opinion differs in that:
|
ab22d6e
to
6363bf1
Compare
To state this differently instead of trusting to user to release a single object once (aka. the main json object she obtained from the load function), you trust them to release each object resulting from |
I think we can solve our disagreement if instead of |
@bosilca Thinking more about OPAL_OBJECT I have a question about inheritance: In this PR I want to hide
Currently I take advantage of the subclass
This makes the intention clear that the user should not touch the internals beyond I wonder what the alternative is if I don't use OPAL_OBJECT. It is obvious to me that we can still do something similar without subclassing, e.g.
Would this be better in your opinion? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks much better to me.
47d5261
to
00503cb
Compare
opal/util/json/opal_json.c
Outdated
*out = OPAL_JSON_OBJECT; | ||
break; | ||
default: | ||
opal_output_verbose(1, 0, "Invalid JSON value type %d\n", type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be a show_help, not a direct opal_output_verbose? (same goes for all cases of errors emitted via opal_output_verbose)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I switched to show help.
/** | ||
* Free JSON resources | ||
* | ||
* @param[in] json Pointer to JSON object to free |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is json
set to NULL upon return? The param is marked in
, but you pass a **
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope json
is not modified upon return.
The **
is due to the fact of that json
being used(and likely declared) as const *
everywhere - here we need a double pointer to tell the compiler that we are not modifying json
, but rather a pointer to it.
opal/util/json/opal_json.h
Outdated
* @returns OPAL_SUCCESS if successful | ||
* OPAL_ERROR otherwise | ||
*/ | ||
OPAL_DECLSPEC int opal_json_get_object_size(const opal_json_t *json, size_t *size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this returning the number of elements in the json object, or the size of the object in bytes?
The name is a little misleading -- IMHO, size
refers to number of bytes. Could we use opal_json_get_num_keys
or somesuch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An object is untyped, it cannot contain elements, it only contains bytes. The other function you are referring to is opal_json_get_array_len
but it can only apply to arrays.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bosilca Actually this function is also counting object length, not bytes.
I wonder if I should simply keep 1 function for both object and array, i.e. opal_json_get_len
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it, object is a keymapped values storage of json_value_t*
while array is just an array of json_value_t*
. Then a single assessor would be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. I decided to keep a single function opal_json_get_container_size
for both array and object. They are too similar to have different functions.
This patch introduces a utility in OPAL based on the 3rd-party project https://github.com/json-parser/json-parser.git The utility provides APIs to read JSON into memory along with getters to retrieve C values. Signed-off-by: Wenduo Wang <wenduwan@amazon.com>
This patch introduces a utility in OPAL based on the 3rd-party project https://github.com/json-parser/json-parser.git
The utility provides APIs to read JSON into memory along with getters to retrieve C values.
Please see the unit test opal_json.c for example usage.