1*44704f69SBart Van Assche #ifndef SG_PR2SERR_H 2*44704f69SBart Van Assche #define SG_PR2SERR_H 3*44704f69SBart Van Assche 4*44704f69SBart Van Assche /* 5*44704f69SBart Van Assche * Copyright (c) 2004-2022 Douglas Gilbert. 6*44704f69SBart Van Assche * All rights reserved. 7*44704f69SBart Van Assche * Use of this source code is governed by a BSD-style 8*44704f69SBart Van Assche * license that can be found in the BSD_LICENSE file. 9*44704f69SBart Van Assche * 10*44704f69SBart Van Assche * SPDX-License-Identifier: BSD-2-Clause 11*44704f69SBart Van Assche */ 12*44704f69SBart Van Assche 13*44704f69SBart Van Assche #include <inttypes.h> 14*44704f69SBart Van Assche #include <stdio.h> 15*44704f69SBart Van Assche #include <stdbool.h> 16*44704f69SBart Van Assche 17*44704f69SBart Van Assche #ifdef __cplusplus 18*44704f69SBart Van Assche extern "C" { 19*44704f69SBart Van Assche #endif 20*44704f69SBart Van Assche 21*44704f69SBart Van Assche /* pr2serr and pr2ws are convenience functions that replace the somewhat 22*44704f69SBart Van Assche * long-winded fprintf(stderr, ....). The second form (i.e. pr2ws() ) is for 23*44704f69SBart Van Assche * internal library use and may place its output somewhere other than stderr; 24*44704f69SBart Van Assche * it depends on the external variable sg_warnings_strm which can be set 25*44704f69SBart Van Assche * with sg_set_warnings_strm(). By default it uses stderr. */ 26*44704f69SBart Van Assche 27*44704f69SBart Van Assche #if __USE_MINGW_ANSI_STDIO -0 == 1 28*44704f69SBart Van Assche #define __printf(a, b) __attribute__((__format__(gnu_printf, a, b))) 29*44704f69SBart Van Assche #elif defined(__GNUC__) || defined(__clang__) 30*44704f69SBart Van Assche #define __printf(a, b) __attribute__((__format__(printf, a, b))) 31*44704f69SBart Van Assche #else 32*44704f69SBart Van Assche #define __printf(a, b) 33*44704f69SBart Van Assche #endif 34*44704f69SBart Van Assche 35*44704f69SBart Van Assche int pr2serr(const char * fmt, ...) __printf(1, 2); 36*44704f69SBart Van Assche 37*44704f69SBart Van Assche int pr2ws(const char * fmt, ...) __printf(1, 2); 38*44704f69SBart Van Assche 39*44704f69SBart Van Assche /* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of 40*44704f69SBart Van Assche * functions that can be called multiple times. Returns number of chars 41*44704f69SBart Van Assche * placed in cp excluding the trailing null char. So for cp_max_len > 0 the 42*44704f69SBart Van Assche * return value is always < cp_max_len; for cp_max_len <= 1 the return value 43*44704f69SBart Van Assche * is 0 and no chars are written to cp. Note this means that when 44*44704f69SBart Van Assche * cp_max_len = 1, this function assumes that cp[0] is the null character 45*44704f69SBart Van Assche * and does nothing (and returns 0). Linux kernel has a similar function 46*44704f69SBart Van Assche * called scnprintf(). */ 47*44704f69SBart Van Assche int sg_scnpr(char * cp, int cp_max_len, const char * fmt, ...) __printf(3, 4); 48*44704f69SBart Van Assche 49*44704f69SBart Van Assche /* JSON support functions and structures follow. The prefix "sgj_" is used 50*44704f69SBart Van Assche * for sg3_utils JSON functions, types and values. */ 51*44704f69SBart Van Assche 52*44704f69SBart Van Assche enum sgj_separator_t { 53*44704f69SBart Van Assche SGJ_SEP_NONE = 0, 54*44704f69SBart Van Assche SGJ_SEP_SPACE_1, 55*44704f69SBart Van Assche SGJ_SEP_SPACE_2, 56*44704f69SBart Van Assche SGJ_SEP_SPACE_3, 57*44704f69SBart Van Assche SGJ_SEP_SPACE_4, 58*44704f69SBart Van Assche SGJ_SEP_EQUAL_NO_SPACE, 59*44704f69SBart Van Assche SGJ_SEP_EQUAL_1_SPACE, 60*44704f69SBart Van Assche SGJ_SEP_COLON_NO_SPACE, 61*44704f69SBart Van Assche SGJ_SEP_COLON_1_SPACE, 62*44704f69SBart Van Assche }; 63*44704f69SBart Van Assche 64*44704f69SBart Van Assche typedef void * sgj_opaque_p; 65*44704f69SBart Van Assche 66*44704f69SBart Van Assche /* Apart from the state information at the end of this structure, the earlier 67*44704f69SBart Van Assche * fields are initialized from the command line argument given to the 68*44704f69SBart Van Assche * --json= option. If there is no argument then they initialized as shown. */ 69*44704f69SBart Van Assche typedef struct sgj_state_t { 70*44704f69SBart Van Assche /* the following set by default, the SG3_UTILS_JSON_OPTS environment 71*44704f69SBart Van Assche * variable or command line argument to --json option, in that order. */ 72*44704f69SBart Van Assche bool pr_as_json; /* = false (def: is human readable output) */ 73*44704f69SBart Van Assche bool pr_exit_status; /* 'e' (def: true) */ 74*44704f69SBart Van Assche bool pr_hex; /* 'h' (def: false) */ 75*44704f69SBart Van Assche bool pr_leadin; /* 'l' (def: true) */ 76*44704f69SBart Van Assche bool pr_name_ex; /* 'n' name_extra (information) (def: false) */ 77*44704f69SBart Van Assche bool pr_out_hr; /* 'o' (def: false) */ 78*44704f69SBart Van Assche bool pr_packed; /* 'k' (def: false) only when !pr_pretty */ 79*44704f69SBart Van Assche bool pr_pretty; /* 'p' (def: true) */ 80*44704f69SBart Van Assche bool pr_string; /* 's' (def: true) */ 81*44704f69SBart Van Assche char pr_format; /* (def: '\0') */ 82*44704f69SBart Van Assche int pr_indent_size; /* digit (def: 4) */ 83*44704f69SBart Van Assche int verbose; /* 'v' (def: 0) incremented each appearance */ 84*44704f69SBart Van Assche 85*44704f69SBart Van Assche /* the following hold state information */ 86*44704f69SBart Van Assche int first_bad_char; /* = '\0' */ 87*44704f69SBart Van Assche sgj_opaque_p basep; /* base JSON object pointer */ 88*44704f69SBart Van Assche sgj_opaque_p out_hrp; /* JSON array pointer when pr_out_hr set */ 89*44704f69SBart Van Assche sgj_opaque_p userp; /* for temporary usage */ 90*44704f69SBart Van Assche } sgj_state; 91*44704f69SBart Van Assche 92*44704f69SBart Van Assche /* This function tries to convert the in_name C string to the "snake_case" 93*44704f69SBart Van Assche * convention so the output sname only contains lower case ASCII letters, 94*44704f69SBart Van Assche * numerals and "_" as a separator. Any leading or trailing underscores 95*44704f69SBart Van Assche * are removed as are repeated underscores (e.g. "_Snake __ case" becomes 96*44704f69SBart Van Assche * "snake_case"). Parentheses and the characters between them are removed. 97*44704f69SBart Van Assche * Returns sname (i.e. the pointer to the output buffer). 98*44704f69SBart Van Assche * Note: strlen(in_name) should be <= max_sname_len . */ 99*44704f69SBart Van Assche char * sgj_convert_to_snake_name(const char * in_name, char * sname, 100*44704f69SBart Van Assche int max_sname_len); 101*44704f69SBart Van Assche bool sgj_is_snake_name(const char * in_name); 102*44704f69SBart Van Assche 103*44704f69SBart Van Assche /* There are many variants of JSON supporting functions below and some 104*44704f69SBart Van Assche * abbreviations are used to shorten their function names: 105*44704f69SBart Van Assche * sgj_ - prefix of all the functions related to (non-)JSON output 106*44704f69SBart Van Assche * hr - human readable form (as it was before JSON) 107*44704f69SBart Van Assche * js - JSON only output 108*44704f69SBart Van Assche * haj - human readable and JSON output, hr goes in 'output' array 109*44704f69SBart Van Assche * pr - has printf() like variadic arguments 110*44704f69SBart Van Assche * _r - suffix indicating the return value should/must be used 111*44704f69SBart Van Assche * nv - adds a name-value JSON field (or several) 112*44704f69SBart Van Assche * o - value is the provided JSON object (or array) 113*44704f69SBart Van Assche * i - value is a JSON integer object (int64_t or uint64_t) 114*44704f69SBart Van Assche * b - value is a JSON boolean object 115*44704f69SBart Van Assche * s - value is a JSON string object 116*44704f69SBart Van Assche * str - same as s 117*44704f69SBart Van Assche * hex - value is hexadecimal in a JSON string object 118*44704f69SBart Van Assche * _nex - extra 'name_extra' JSON string object about name 119*44704f69SBart Van Assche * new - object that needs sgj_free_unattached() if not attached 120*44704f69SBart Van Assche * 121*44704f69SBart Van Assche * */ 122*44704f69SBart Van Assche 123*44704f69SBart Van Assche /* If jsp in non-NULL and jsp->pr_as_json is true then this call is ignored 124*44704f69SBart Van Assche * unless jsp->pr_out_hrp is true. Otherwise this function prints to stdout 125*44704f69SBart Van Assche * like printf(fmt, ...); note that no LF is added. In the jsp->pr_out_hrp is 126*44704f69SBart Van Assche * true case, nothing is printed to stdout but instead is placed into a JSON 127*44704f69SBart Van Assche * array (jsp->out_hrp) after some preprocessing. That preprocessing involves 128*44704f69SBart Van Assche * removing a leading LF from 'fmt' (if present) and up to two trailing LF 129*44704f69SBart Van Assche * characters. */ 130*44704f69SBart Van Assche void sgj_pr_hr(sgj_state * jsp, const char * fmt, ...) __printf(2, 3); 131*44704f69SBart Van Assche 132*44704f69SBart Van Assche /* Initializes the state object pointed to by jsp based on the argument 133*44704f69SBart Van Assche * given to the right of --json= pointed to by j_optarg. If it is NULL 134*44704f69SBart Van Assche * then state object gets its default values. Returns true if argument 135*44704f69SBart Van Assche * to --json= is decoded properly, else returns false and places the 136*44704f69SBart Van Assche * first "bad" character in jsp->first_bad_char . Note that no JSON 137*44704f69SBart Van Assche * in-core tree needs to exist when this function is called. */ 138*44704f69SBart Van Assche bool sgj_init_state(sgj_state * jsp, const char * j_optarg); 139*44704f69SBart Van Assche 140*44704f69SBart Van Assche /* sgj_start() creates a JSON in-core tree and returns a pointer to it (or 141*44704f69SBart Van Assche * NULL if the associated heap allocation fails). It should be paired with 142*44704f69SBart Van Assche * sgj_finish() to clean up (i.e. remove all heap allocations) all the 143*44704f69SBart Van Assche * elements (i.e. JSON objects and arrays) that have been placed in that 144*44704f69SBart Van Assche * in-core tree. If jsp is NULL nothing further happens. Otherwise the pointer 145*44704f69SBart Van Assche * to be returned is placed in jsp->basep. If jsp->pr_leadin is true and 146*44704f69SBart Van Assche * util_name is non-NULL then a "utility_invoked" JSON object is made with 147*44704f69SBart Van Assche * "name", and "version_date" object fields. If the jsp->pr_out_hr field is 148*44704f69SBart Van Assche * true a named array called "output" is added to the "utility_invoked" object 149*44704f69SBart Van Assche * (creating it in the case when jsp->pr_leadin is false) and a pointer to 150*44704f69SBart Van Assche * that array object is placed in jsp->objectp . The returned pointer is not 151*44704f69SBart Van Assche * usually needed but if it is NULL then a heap allocation has failed. */ 152*44704f69SBart Van Assche sgj_opaque_p sgj_start_r(const char * util_name, const char * ver_str, 153*44704f69SBart Van Assche int argc, char *argv[], sgj_state * jsp); 154*44704f69SBart Van Assche 155*44704f69SBart Van Assche /* These are low level functions returning a pointer to a newly created JSON 156*44704f69SBart Van Assche * object or array. If jsp is NULL or jsp->pr_as_json is false nothing happens 157*44704f69SBart Van Assche * and NULL is returned. Note that this JSON object is _not_ placed in the 158*44704f69SBart Van Assche * in-core tree controlled by jsp (jsp->basep); it may be added later as the 159*44704f69SBart Van Assche * fourth argument to sgj_js_nv_o(), for example. */ 160*44704f69SBart Van Assche sgj_opaque_p sgj_new_unattached_object_r(sgj_state * jsp); 161*44704f69SBart Van Assche sgj_opaque_p sgj_new_unattached_array_r(sgj_state * jsp); 162*44704f69SBart Van Assche 163*44704f69SBart Van Assche /* If jsp is NULL or jsp->pr_as_json is false nothing happens and NULL is 164*44704f69SBart Van Assche * returned. Otherwise it creates a new named object (whose name is what 165*44704f69SBart Van Assche * 'name' points to) at 'jop' with an empty object as its value; a pointer 166*44704f69SBart Van Assche * to that empty object is returned. If 'jop' is NULL then jsp->basep is 167*44704f69SBart Van Assche * used instead. The returned value should always be checked (for NULL) 168*44704f69SBart Van Assche * and if not, used. */ 169*44704f69SBart Van Assche sgj_opaque_p sgj_named_subobject_r(sgj_state * jsp, sgj_opaque_p jop, 170*44704f69SBart Van Assche const char * name); 171*44704f69SBart Van Assche sgj_opaque_p sgj_snake_named_subobject_r(sgj_state * jsp, sgj_opaque_p jop, 172*44704f69SBart Van Assche const char * conv2sname); 173*44704f69SBart Van Assche 174*44704f69SBart Van Assche /* If jsp is NULL or jsp->pr_as_json is false nothing happens and NULL is 175*44704f69SBart Van Assche * returned. Otherwise it creates a new named object (whose name is what 176*44704f69SBart Van Assche * 'name' points to) at 'jop' with an empty array as its value; a pointer 177*44704f69SBart Van Assche * to that empty array is returned. If 'jop' is NULL then jsp->basep is 178*44704f69SBart Van Assche * used instead. The returned value should always * be checked (for NULL) 179*44704f69SBart Van Assche * and if not, used. */ 180*44704f69SBart Van Assche sgj_opaque_p sgj_named_subarray_r(sgj_state * jsp, sgj_opaque_p jop, 181*44704f69SBart Van Assche const char * name); 182*44704f69SBart Van Assche sgj_opaque_p sgj_snake_named_subarray_r(sgj_state * jsp, sgj_opaque_p jop, 183*44704f69SBart Van Assche const char * conv2sname); 184*44704f69SBart Van Assche 185*44704f69SBart Van Assche /* If either jsp or value is NULL or jsp->pr_as_json is false then nothing 186*44704f69SBart Van Assche * happens and NULL is returned. The insertion point is at jop but if it is 187*44704f69SBart Van Assche * NULL jsp->basep is used. If 'name' is non-NULL a new named JSON object is 188*44704f69SBart Van Assche * added using 'name' and the associated value is a JSON string formed from 189*44704f69SBart Van Assche * 'value'. If 'name' is NULL then 'jop' is assumed to be a JSON array and 190*44704f69SBart Van Assche * a JSON string formed from 'value' is added. Note that the jsp->pr_string 191*44704f69SBart Van Assche * setting is ignored by this function. If successful returns a * a pointer 192*44704f69SBart Van Assche * newly formed JSON string. */ 193*44704f69SBart Van Assche sgj_opaque_p sgj_js_nv_s(sgj_state * jsp, sgj_opaque_p jop, 194*44704f69SBart Van Assche const char * name, const char * value); 195*44704f69SBart Van Assche sgj_opaque_p sgj_js_nv_s_len(sgj_state * jsp, sgj_opaque_p jop, 196*44704f69SBart Van Assche const char * name, 197*44704f69SBart Van Assche const char * value, int slen); 198*44704f69SBart Van Assche 199*44704f69SBart Van Assche /* If either jsp is NULL or jsp->pr_as_json is false then nothing happens and 200*44704f69SBart Van Assche * NULL is returned. The insertion point is at jop but if it is NULL 201*44704f69SBart Van Assche * jsp->basep is used. If 'name' is non-NULL a new named JSON object is 202*44704f69SBart Van Assche * added using 'name' and the associated value is a JSON integer formed from 203*44704f69SBart Van Assche * 'value'. If 'name' is NULL then 'jop' is assumed to be a JSON array and 204*44704f69SBart Van Assche * a JSON integer formed from 'value' is added. If successful returns a 205*44704f69SBart Van Assche * a pointer newly formed JSON integer. */ 206*44704f69SBart Van Assche sgj_opaque_p sgj_js_nv_i(sgj_state * jsp, sgj_opaque_p jop, 207*44704f69SBart Van Assche const char * name, int64_t value); 208*44704f69SBart Van Assche 209*44704f69SBart Van Assche /* If either jsp is NULL or jsp->pr_as_json is false then nothing happens and 210*44704f69SBart Van Assche * NULL is returned. The insertion point is at jop but if it is NULL 211*44704f69SBart Van Assche * jsp->basep is used. If 'name' is non-NULL a new named JSON object is 212*44704f69SBart Van Assche * added using 'name' and the associated value is a JSON boolean formed from 213*44704f69SBart Van Assche * 'value'. If 'name' is NULL then 'jop' is assumed to be a JSON array and 214*44704f69SBart Van Assche * a JSON boolean formed from 'value' is added. If successful returns a 215*44704f69SBart Van Assche * a pointer newly formed JSON boolean. */ 216*44704f69SBart Van Assche sgj_opaque_p sgj_js_nv_b(sgj_state * jsp, sgj_opaque_p jop, 217*44704f69SBart Van Assche const char * name, bool value); 218*44704f69SBart Van Assche 219*44704f69SBart Van Assche /* If jsp is NULL, jsp->pr_as_json is false or ua_jop is NULL nothing then 220*44704f69SBart Van Assche * happens and NULL is returned. 'jop' is the insertion point but if it is 221*44704f69SBart Van Assche * NULL jsp->basep is used instead. If 'name' is non-NULL a new named JSON 222*44704f69SBart Van Assche * object is added using 'name' and the associated value is ua_jop. If 'name' 223*44704f69SBart Van Assche * is NULL then 'jop' is assumed to be a JSON array and ua_jop is added to 224*44704f69SBart Van Assche * it. If successful returns ua_jop . The "ua_" prefix stands for unattached. 225*44704f69SBart Van Assche * That should be the case before invocation and it will be attached to jop 226*44704f69SBart Van Assche * after a successful invocation. This means that ua_jop must have been 227*44704f69SBart Van Assche * created by sgj_new_unattached_object_r() or similar. */ 228*44704f69SBart Van Assche sgj_opaque_p sgj_js_nv_o(sgj_state * jsp, sgj_opaque_p jop, 229*44704f69SBart Van Assche const char * name, sgj_opaque_p ua_jop); 230*44704f69SBart Van Assche 231*44704f69SBart Van Assche /* This function only produces JSON output if jsp is non-NULL and 232*44704f69SBart Van Assche * jsp->pr_as_json is true. It adds a named object at 'jop' (or jop->basep 233*44704f69SBart Van Assche * if jop is NULL) along with a value. If jsp->pr_hex is true then that 234*44704f69SBart Van Assche * value is two sub-objects, one named 'i' with a 'value' as a JSON integer, 235*44704f69SBart Van Assche * the other one named 'hex' with 'value' rendered as hex in a JSON string. 236*44704f69SBart Van Assche * If jsp->pr_hex is false then there are no sub-objects and the 'value' is 237*44704f69SBart Van Assche * rendered as JSON integer. */ 238*44704f69SBart Van Assche void sgj_js_nv_ihex(sgj_state * jsp, sgj_opaque_p jop, 239*44704f69SBart Van Assche const char * name, uint64_t value); 240*44704f69SBart Van Assche 241*44704f69SBart Van Assche /* This function only produces JSON output if jsp is non-NULL and 242*44704f69SBart Van Assche * jsp->pr_as_json is true. It adds a named object at 'jop' (or jop->basep 243*44704f69SBart Van Assche * if jop is NULL) along with a value. If jsp->pr_string is true then that 244*44704f69SBart Van Assche * value is two sub-objects, one named 'i' with a 'val_i' as a JSON integer, 245*44704f69SBart Van Assche * the other one named str_name with val_s rendered as a JSON string. If 246*44704f69SBart Van Assche * str_name is NULL then "meaning" will be used. If jsp->pr_string is false 247*44704f69SBart Van Assche * then there are no sub-objects and the 'val_i' is rendered as a JSON 248*44704f69SBart Van Assche * integer. */ 249*44704f69SBart Van Assche void sgj_js_nv_istr(sgj_state * jsp, sgj_opaque_p jop, 250*44704f69SBart Van Assche const char * name, int64_t val_i, 251*44704f69SBart Van Assche const char * str_name, const char * val_s); 252*44704f69SBart Van Assche 253*44704f69SBart Van Assche /* Similar to sgj_js_nv_istr(). The hex output is conditional jsp->pr_hex . */ 254*44704f69SBart Van Assche void sgj_js_nv_ihexstr(sgj_state * jsp, sgj_opaque_p jop, 255*44704f69SBart Van Assche const char * name, int64_t val_i, 256*44704f69SBart Van Assche const char * str_name, const char * val_s); 257*44704f69SBart Van Assche 258*44704f69SBart Van Assche /* This function only produces JSON output if jsp is non-NULL and 259*44704f69SBart Van Assche * jsp->pr_as_json is true. It adds a named object at 'jop' (or jop->basep 260*44704f69SBart Van Assche * if jop is NULL) along with a value. If jsp->pr_name_ex is true then that 261*44704f69SBart Van Assche * value is two sub-objects, one named 'i' with a 'val_i' as a JSON integer, 262*44704f69SBart Van Assche * the other one named "abbreviated_name_expansion" with value nex_s rendered 263*44704f69SBart Van Assche * as a JSON string. If jsp->pr_hex and 'hex_as_well' are true, then a 264*44704f69SBart Van Assche * sub-object named 'hex' with a value rendered as a hex string equal to 265*44704f69SBart Van Assche * val_i. If jsp->pr_name_ex is false and either jsp->pr_hex or hex_as_well are 266*44704f69SBart Van Assche * false then there are no sub-objects and the 'val_i' is rendered as a JSON 267*44704f69SBart Van Assche * integer. */ 268*44704f69SBart Van Assche void sgj_js_nv_ihex_nex(sgj_state * jsp, sgj_opaque_p jop, const char * name, 269*44704f69SBart Van Assche int64_t val_i, bool hex_as_well, const char * nex_s); 270*44704f69SBart Van Assche 271*44704f69SBart Van Assche void sgj_js_nv_ihexstr_nex(sgj_state * jsp, sgj_opaque_p jop, 272*44704f69SBart Van Assche const char * name, int64_t val_i, bool hex_as_well, 273*44704f69SBart Van Assche const char * str_name, const char * val_s, 274*44704f69SBart Van Assche const char * nex_s); 275*44704f69SBart Van Assche 276*44704f69SBart Van Assche /* Add named field whose value is a (large) JSON string made up of num_bytes 277*44704f69SBart Van Assche * ASCII hexadecimal bytes (each two hex digits separated by a space) starting 278*44704f69SBart Van Assche * at byte_arr. The heap is used for intermediate storage so num_bytes can 279*44704f69SBart Van Assche * be arbitrarily large. */ 280*44704f69SBart Van Assche void sgj_js_nv_hex_bytes(sgj_state * jsp, sgj_opaque_p jop, const char * name, 281*44704f69SBart Van Assche const uint8_t * byte_arr, int num_bytes); 282*44704f69SBart Van Assche 283*44704f69SBart Van Assche /* The '_haj_' refers to generating output both for human readable and/or 284*44704f69SBart Van Assche * JSON with a single invocation. If jsp is non-NULL and jsp->pr_out_hr is 285*44704f69SBart Van Assche * true then both JSON and human readable output is formed (and the latter is 286*44704f69SBart Van Assche * placed in the jsp->out_hrp JSON array). The human readable form will have 287*44704f69SBart Van Assche * leadin_sp spaces followed by 'name' then a separator, then 'value' with a 288*44704f69SBart Van Assche * trailing LF. If 'name' is NULL then it and the separator are ignored. If 289*44704f69SBart Van Assche * there is JSON output, then leadin_sp and sep are ignored. If 'jop' is NULL 290*44704f69SBart Van Assche * then basep->basep is used. If 'name' is NULL then a JSON string object, 291*44704f69SBart Van Assche * made from 'value' is added to the JSON array pointed to by 'jop'. 292*44704f69SBart Van Assche * Otherwise a 'name'-d JSON object whose value is a JSON string object made 293*44704f69SBart Van Assche * from 'value' is added at 'jop'. */ 294*44704f69SBart Van Assche void sgj_haj_vs(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 295*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, 296*44704f69SBart Van Assche const char * value); 297*44704f69SBart Van Assche 298*44704f69SBart Van Assche /* Similar to sgj_haj_vs()'s description with 'JSON string object' 299*44704f69SBart Van Assche * replaced by 'JSON integer object'. */ 300*44704f69SBart Van Assche void sgj_haj_vi(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 301*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, 302*44704f69SBart Van Assche int64_t value, bool hex_as_well); 303*44704f69SBart Van Assche void sgj_haj_vistr(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 304*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, 305*44704f69SBart Van Assche int64_t value, bool hex_as_well, const char * val_s); 306*44704f69SBart Van Assche 307*44704f69SBart Van Assche /* The '_nex' refers to a "name_extra" (information) sub-object (a JSON 308*44704f69SBart Van Assche * string) which explains a bit more about the 'name' entry. This is useful 309*44704f69SBart Van Assche * when T10 specifies the name as an abbreviation (e.g. SYSV). Whether this 310*44704f69SBart Van Assche * sub-object is shown in the JSON output is controlled by the 'n' control 311*44704f69SBart Van Assche * character. */ 312*44704f69SBart Van Assche void sgj_haj_vi_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 313*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, 314*44704f69SBart Van Assche int64_t value, bool hex_as_well, const char * nex_s); 315*44704f69SBart Van Assche void sgj_haj_vistr_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 316*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, 317*44704f69SBart Van Assche int64_t value, bool hex_as_well, 318*44704f69SBart Van Assche const char * val_s, const char * nex_s); 319*44704f69SBart Van Assche 320*44704f69SBart Van Assche /* Similar to above '_haj_' calls but a named sub-object is always formed 321*44704f69SBart Van Assche * containing a JSON integer object named "i" whose value is 'value'. The 322*44704f69SBart Van Assche * returned pointer is to that sub-object. */ 323*44704f69SBart Van Assche sgj_opaque_p sgj_haj_subo_r(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 324*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, 325*44704f69SBart Van Assche int64_t value, bool hex_as_well); 326*44704f69SBart Van Assche 327*44704f69SBart Van Assche /* Similar to sgj_haj_vs()'s description with 'JSON string object' replaced 328*44704f69SBart Van Assche * by 'JSON boolean object'. */ 329*44704f69SBart Van Assche void sgj_haj_vb(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp, 330*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, bool value); 331*44704f69SBart Van Assche 332*44704f69SBart Van Assche /* Breaks up the string pointed to by 'sp' into lines and adds them to the 333*44704f69SBart Van Assche * jsp->out_hrp array. Treat '\n' in sp as line breaks. Consumes characters 334*44704f69SBart Van Assche * from sp until either a '\0' is found or slen is exhausted. Add each line 335*44704f69SBart Van Assche * to jsp->out_hrp JSON array (if conditions met). */ 336*44704f69SBart Van Assche void sgj_js_str_out(sgj_state * jsp, const char * sp, int slen); 337*44704f69SBart Van Assche 338*44704f69SBart Van Assche /* This function only produces JSON output if jsp is non-NULL and 339*44704f69SBart Van Assche * jsp->pr_as_json is true. 'sbp' is assumed to point to sense data as 340*44704f69SBart Van Assche * defined by T10 with a length of 'sb_len' bytes. Returns false if an 341*44704f69SBart Van Assche * issue is detected, else it returns true. */ 342*44704f69SBart Van Assche bool sgj_js_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp, 343*44704f69SBart Van Assche int sb_len); 344*44704f69SBart Van Assche 345*44704f69SBart Van Assche bool sgj_js_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop, 346*44704f69SBart Van Assche const uint8_t * ddp, int dd_len); 347*44704f69SBart Van Assche 348*44704f69SBart Van Assche /* Nothing in the in-core JSON tree is actually printed to 'fp' (typically 349*44704f69SBart Van Assche * stdout) until this call is made. If jsp is NULL, jsp->pr_as_json is false 350*44704f69SBart Van Assche * or jsp->basep is NULL then this function does nothing. If jsp->exit_status 351*44704f69SBart Van Assche * is true then a new JSON object named "exit_status" and the 'exit_status' 352*44704f69SBart Van Assche * value rendered as a JSON integer is appended to jsp->basep. The in-core 353*44704f69SBart Van Assche * JSON tree with jsp->basep as its root is streamed to 'fp'. */ 354*44704f69SBart Van Assche void sgj_js2file(sgj_state * jsp, sgj_opaque_p jop, int exit_status, 355*44704f69SBart Van Assche FILE * fp); 356*44704f69SBart Van Assche 357*44704f69SBart Van Assche /* This function is only needed if the pointer returned from either 358*44704f69SBart Van Assche * sgj_new_unattached_object_r() or sgj_new_unattached_array_r() has not 359*44704f69SBart Van Assche * been attached into the in-core JSON tree whose root is jsp->basep . */ 360*44704f69SBart Van Assche void sgj_free_unattached(sgj_opaque_p jop); 361*44704f69SBart Van Assche 362*44704f69SBart Van Assche /* If jsp is NULL or jsp->basep is NULL then this function does nothing. 363*44704f69SBart Van Assche * This function does bottom up, heap freeing of all the in-core JSON 364*44704f69SBart Van Assche * objects and arrays attached to the root JSON object assumed to be 365*44704f69SBart Van Assche * found at jsp->basep . After this call jsp->basep, jsp->out_hrp and 366*44704f69SBart Van Assche * jsp->userp will all be set to NULL. */ 367*44704f69SBart Van Assche void sgj_finish(sgj_state * jsp); 368*44704f69SBart Van Assche 369*44704f69SBart Van Assche char * sg_json_usage(int char_if_not_j, char * b, int blen); 370*44704f69SBart Van Assche 371*44704f69SBart Van Assche 372*44704f69SBart Van Assche #ifdef __cplusplus 373*44704f69SBart Van Assche } 374*44704f69SBart Van Assche #endif 375*44704f69SBart Van Assche 376*44704f69SBart Van Assche #endif 377