Pharos 0.7.23
Modern Web Framework & Web App Hosting Service.
Loading...
Searching...
No Matches
native_yyjson_helpers.c
Go to the documentation of this file.
1/**
2 * @file
3 * @brief Implements small reusable yyjson wrappers with explicit ownership and type checks for Pharos native runtime callers.
4 */
5
7
8#include "native_support.h"
9
10#include <limits.h>
11#include <stdlib.h>
12#include <string.h>
13
14/**
15 * @brief Duplicates a JSON string value into owned storage.
16 * @param value JSON string value to duplicate.
17 * @return Newly allocated string, or NULL when the value is invalid.
18 */
19static char *native_json_string_dup(yyjson_val *value) {
20 const char *text = NULL;
21 size_t len = 0;
22 char *copy = NULL;
23 if (!yyjson_is_str(value)) {
24 return NULL;
25 }
26 text = yyjson_get_str(value);
27 len = yyjson_get_len(value);
28 copy = (char *)malloc(len + 1);
29 if (copy == NULL) {
30 return NULL;
31 }
32 memcpy(copy, text, len);
33 copy[len] = '\0';
34 return copy;
35}
36
37/**
38 * @brief Tests whether a numeric JSON value can be converted to long.
39 * @param value Numeric JSON value.
40 * @param out Output location for the converted value.
41 * @return 1 when conversion succeeds, otherwise 0.
42 */
43static int native_json_long_from_value(yyjson_val *value, long *out) {
44 int64_t signed_value = 0;
45 uint64_t unsigned_value = 0;
46 double real_value = 0.0;
47 if (value == NULL || out == NULL || !yyjson_is_num(value)) {
48 return 0;
49 }
50 if (yyjson_is_sint(value)) {
51 signed_value = yyjson_get_sint(value);
52 if (signed_value < LONG_MIN || signed_value > LONG_MAX) {
53 return 0;
54 }
55 *out = (long)signed_value;
56 return 1;
57 }
58 if (yyjson_is_uint(value)) {
59 unsigned_value = yyjson_get_uint(value);
60 if (unsigned_value > (uint64_t)LONG_MAX) {
61 return 0;
62 }
63 *out = (long)unsigned_value;
64 return 1;
65 }
66 if (!yyjson_is_real(value)) {
67 return 0;
68 }
69 real_value = yyjson_get_real(value);
70 if (real_value < (double)LONG_MIN || real_value > (double)LONG_MAX) {
71 return 0;
72 }
73 if ((double)((long)real_value) != real_value) {
74 return 0;
75 }
76 *out = (long)real_value;
77 return 1;
78}
79
80/**
81 * @brief Searches an object array for an element whose named field matches a string.
82 * @param array_value Array to inspect.
83 * @param field_name Object field to compare.
84 * @param expected_value String value to match.
85 * @return Matching object, or NULL when not found.
86 */
88 yyjson_val *array_value,
89 const char *field_name,
90 const char *expected_value) {
91 yyjson_arr_iter iter;
92 yyjson_val *item = NULL;
93 if (array_value == NULL || field_name == NULL || expected_value == NULL) {
94 return NULL;
95 }
96 if (!yyjson_arr_iter_init(array_value, &iter)) {
97 return NULL;
98 }
99 while ((item = yyjson_arr_iter_next(&iter)) != NULL) {
100 yyjson_val *field_value = NULL;
101 if (!yyjson_is_obj(item)) {
102 continue;
103 }
104 field_value = yyjson_obj_get(item, field_name);
105 if (yyjson_is_str(field_value) &&
106 yyjson_equals_str(field_value, expected_value)) {
107 return item;
108 }
109 }
110 return NULL;
111}
112
114 char *text = NULL;
115 yyjson_doc *doc = NULL;
116 if (path == NULL || path[0] == '\0') {
117 return NULL;
118 }
119 text = read_file_text(path);
120 if (text == NULL) {
121 return NULL;
122 }
123 doc = native_json_doc_load_text(text);
124 free(text);
125 return doc;
126}
127
129 size_t len = 0;
130 if (text == NULL) {
131 return NULL;
132 }
133 len = strlen(text);
134 if (len == 0) {
135 return NULL;
136 }
137 return yyjson_read(text, len, YYJSON_READ_NOFLAG);
138}
139
141 if (doc == NULL) {
142 return;
143 }
144 yyjson_doc_free(doc);
145}
146
148 if (obj == NULL || key == NULL || !yyjson_is_obj(obj)) {
149 return NULL;
150 }
151 return yyjson_obj_get(obj, key);
152}
153
155 yyjson_val *value = native_json_obj_get(obj, key);
156 if (!yyjson_is_arr(value)) {
157 return NULL;
158 }
159 return value;
160}
161
162char *native_json_obj_get_string_dup(yyjson_val *obj, const char *key) {
164}
165
167 yyjson_val *obj,
168 const char *key,
169 long default_value,
170 int *found_out) {
171 yyjson_val *value = NULL;
172 long converted = default_value;
173 int found = 0;
174 value = native_json_obj_get(obj, key);
175 if (native_json_long_from_value(value, &converted)) {
176 found = 1;
177 } else {
178 converted = default_value;
179 }
180 if (found_out != NULL) {
181 *found_out = found;
182 }
183 return converted;
184}
185
187 yyjson_val *root,
188 const char *migration_id) {
189 yyjson_val *migrations = native_json_obj_get_array(root, "migrations");
191 migrations,
192 "migration_id",
193 migration_id);
194}
195
197 yyjson_val *root,
198 const char *backend_name) {
199 yyjson_val *backends = native_json_obj_get_array(root, "backends");
201 backends,
202 "backend",
203 backend_name);
204}
205
207 if (value == NULL) {
208 return NULL;
209 }
210 return yyjson_val_write(value, YYJSON_WRITE_NOFLAG, NULL);
211}
212
214 yyjson_arr_iter iter;
215 yyjson_val *item = NULL;
216 Buffer buffer;
217 if (array_value == NULL || !yyjson_is_arr(array_value)) {
218 return NULL;
219 }
220 buffer_init(&buffer);
221 if (!yyjson_arr_iter_init(array_value, &iter)) {
222 return NULL;
223 }
224 while ((item = yyjson_arr_iter_next(&iter)) != NULL) {
225 const char *text = NULL;
226 size_t len = 0;
227 if (!yyjson_is_str(item)) {
228 buffer_free(&buffer);
229 return NULL;
230 }
231 text = yyjson_get_str(item);
232 len = yyjson_get_len(item);
233 if (buffer.len > 0 && buffer_append(&buffer, "\n", 1) != 0) {
234 buffer_free(&buffer);
235 return NULL;
236 }
237 if (buffer_append(&buffer, text, len) != 0) {
238 buffer_free(&buffer);
239 return NULL;
240 }
241 }
242 if (buffer.data == NULL) {
243 return dup_range("", 0);
244 }
245 return buffer.data;
246}
void buffer_init(Buffer *buffer)
Initializes a growable buffer to an empty state.
char * dup_range(const char *start, size_t len)
Duplicates a byte range into a newly allocated NUL-terminated string.
void buffer_free(Buffer *buffer)
Releases memory owned by a growable buffer.
int buffer_append(Buffer *buffer, const void *data, size_t len)
Appends bytes to a growable buffer and maintains a trailing NUL byte.
char * read_file_text(const char *path)
Reads an entire file into a newly allocated text buffer.
Declares shared low-level support helpers used across the Pharos native runtime.
yyjson_doc * native_json_doc_load_file(const char *path)
Parses a JSON file into an owned yyjson document.
yyjson_val * native_json_find_migration_by_id(yyjson_val *root, const char *migration_id)
Finds a migration record by migration_id under a fixture root.
long native_json_obj_get_long_default(yyjson_val *obj, const char *key, long default_value, int *found_out)
Reads a numeric object member or returns a fallback value.
void native_json_doc_free(yyjson_doc *doc)
Releases a document returned by the native yyjson helpers.
static int native_json_long_from_value(yyjson_val *value, long *out)
Tests whether a numeric JSON value can be converted to long.
static char * native_json_string_dup(yyjson_val *value)
Duplicates a JSON string value into owned storage.
yyjson_val * native_json_find_backend_by_name(yyjson_val *root, const char *backend_name)
Finds a backend record by backend name under a fixture root.
yyjson_doc * native_json_doc_load_text(const char *text)
Parses JSON text into an owned yyjson document.
char * native_json_obj_get_string_dup(yyjson_val *obj, const char *key)
Duplicates a string-valued key from a JSON object.
char * native_json_string_array_lines_dup(yyjson_val *array_value)
Converts a JSON string array into newline-delimited text.
static yyjson_val * native_json_find_object_by_string_field(yyjson_val *array_value, const char *field_name, const char *expected_value)
Searches an object array for an element whose named field matches a string.
yyjson_val * native_json_obj_get_array(yyjson_val *obj, const char *key)
Looks up an array-valued key from a JSON object value.
yyjson_val * native_json_obj_get(yyjson_val *obj, const char *key)
Looks up a key from a JSON object value.
char * native_json_serialize_compact_dup(yyjson_val *value)
Serializes a JSON value to compact JSON text.
Declares shared helper wrappers around vendored yyjson parsing and serialization APIs.
Growable byte buffer used by parsing and string assembly helpers.
size_t len
char * data
yyjson_api_inline char * yyjson_val_write(const yyjson_val *val, yyjson_write_flag flg, size_t *len)
Definition yyjson.h:1738
yyjson_api_inline bool yyjson_is_str(const yyjson_val *val)
Definition yyjson.h:5390
yyjson_api_inline bool yyjson_is_obj(const yyjson_val *val)
Definition yyjson.h:5398
yyjson_api_inline bool yyjson_is_sint(const yyjson_val *val)
Definition yyjson.h:5374
yyjson_api_inline uint64_t yyjson_get_uint(const yyjson_val *val)
Definition yyjson.h:5449
yyjson_api_inline int64_t yyjson_get_sint(const yyjson_val *val)
Definition yyjson.h:5453
yyjson_api_inline bool yyjson_is_arr(const yyjson_val *val)
Definition yyjson.h:5394
yyjson_api_inline yyjson_val * yyjson_obj_get(const yyjson_val *obj, const char *key)
Definition yyjson.h:5693
yyjson_api_inline bool yyjson_is_real(const yyjson_val *val)
Definition yyjson.h:5382
static const yyjson_read_flag YYJSON_READ_NOFLAG
Definition yyjson.h:809
yyjson_api_inline bool yyjson_equals_str(const yyjson_val *val, const char *str)
Definition yyjson.h:5477
yyjson_api_inline bool yyjson_is_uint(const yyjson_val *val)
Definition yyjson.h:5370
yyjson_api_inline yyjson_val * yyjson_arr_iter_next(yyjson_arr_iter *iter)
Definition yyjson.h:5672
yyjson_api_inline bool yyjson_is_num(const yyjson_val *val)
Definition yyjson.h:5386
yyjson_api_inline size_t yyjson_get_len(const yyjson_val *val)
Definition yyjson.h:5473
const char size_t len
Definition yyjson.h:8364
yyjson_api_inline void yyjson_doc_free(yyjson_doc *doc)
Definition yyjson.h:5335
static const yyjson_write_flag YYJSON_WRITE_NOFLAG
Definition yyjson.h:1245
yyjson_api_inline const char * yyjson_get_str(const yyjson_val *val)
Definition yyjson.h:5469
yyjson_api_inline double yyjson_get_real(const yyjson_val *val)
Definition yyjson.h:5461
yyjson_api_inline yyjson_doc * yyjson_read(const char *dat, size_t len, yyjson_read_flag flg)
Definition yyjson.h:1066
yyjson_api_inline bool yyjson_arr_iter_init(const yyjson_val *arr, yyjson_arr_iter *iter)
Definition yyjson.h:5650