Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_pretty.c File Reference

Lexical pretty-printers for JSON, XML/HTML and JavaScript text. More...

#include "nilorea/n_pretty.h"
#include "nilorea/n_common.h"
#include "nilorea/n_log.h"
#include <ctype.h>
#include <string.h>
#include "cJSON.h"
Include dependency graph for n_pretty.c:

Go to the source code of this file.

Data Structures

struct  JS_STATE
 JS emitter state threaded through the helpers. More...
struct  PRETTY_OUT
 growing output buffer fed by write_and_fit_ex More...

Macros

#define PRETTY_INDENT_STEP   2
 spaces per indentation level
#define PRETTY_OUT_PADDING   256
 growth headroom so consecutive short appends share one realloc
#define PRETTY_TAG_NAME_MAX   31
 longest element name kept for void/raw-text lookups

Functions

static int _emit_line (PRETTY_OUT *o, int depth, const char *s, size_t n)
 emit one indented line holding n raw bytes of s
static int _emit_trimmed (PRETTY_OUT *o, int depth, const char *s, size_t n)
 emit s trimmed of leading/trailing whitespace as one indented line; empty-after-trim runs are skipped
static const char * _find_tag_end (const char *p)
 find the '>' closing a tag starting at p, honoring quoted attribute values; returns NULL when the tag never closes
static int _js_lead (JS_STATE *js)
 emit the indent or the collapsed space before a token, as appropriate
static int _js_newline (JS_STATE *js)
 terminate the current line unless already at a line start
static int _js_regex_keyword (const char *s, size_t n)
 whether the n bytes at s are a keyword after which an expression (and therefore a regex literal) can start, e.g.
static size_t _js_regex_len (const char *s)
 length of the regex literal starting at s (slash to closing slash, escapes and character classes honored, trailing flags included)
static int _js_regex_possible (char c)
 whether a '/' may start a regex literal after last significant char c (start of input, after an operator, an opener, or a separator)
static size_t _js_string_len (const char *s)
 length of the string literal starting at s (quote to closing quote, escapes honored, stops at end of line or input on unterminated ones)
static size_t _js_template_len (const char *s)
 length of the template literal starting at s (backtick to backtick, escapes honored, ${...} interpolations skipped by brace counting)
static int _js_token (JS_STATE *js, const char *s, size_t n)
 emit a raw token of n bytes with leading indent/space handling
static int _jsonl_lead (PRETTY_OUT *o, int depth, int *at_line_start)
 emit the pending indent of a lenient JSON line, TRUE on success
static int _jsonl_newline (PRETTY_OUT *o, int *at_line_start)
 end the current lenient JSON line unless it is still empty, TRUE on success
static int _name_in_list (const char *name, const char **list)
 whether lowercase element name is in a NULL-terminated list
static int _out_ch (PRETTY_OUT *o, char c)
 append a single character to the output, TRUE on success
static N_STR * _out_finish (PRETTY_OUT *o)
 hand the buffer over to a new N_STR (no copy); the PRETTY_OUT is emptied
static int _out_indent (PRETTY_OUT *o, int depth)
 append depth * PRETTY_INDENT_STEP spaces, TRUE on success
static int _out_mem (PRETTY_OUT *o, const char *s, size_t n)
 append n bytes of s to the output, TRUE on success
static const char * _stristr (const char *haystack, const char *needle)
 case-insensitive search for needle in haystack
static void _tag_name (const char *p, char *name, size_t name_size)
 extract the lowercased element name from a tag starting at p ("<name" or "</name")
N_STR * n_pretty_js (const char *text)
 Conservatively re-indent JavaScript (newlines at top-level braces and semicolons, two-space indent by brace depth).
N_STR * n_pretty_json (const char *text)
 Reformat a JSON document with cJSON (parse + print).
N_STR * n_pretty_json_lenient (const char *text)
 Re-indent a JSON document by punctuation alone, without parsing it.
N_STR * n_pretty_xml (const char *text)
 Re-indent an XML or HTML document (one tag or text run per line).

Variables

static const char * PRETTY_RAWTEXT_ELEMENTS [] = {"script", "style", NULL}
 HTML elements whose content is raw text (no nested markup).
static const char * PRETTY_VOID_ELEMENTS []
 HTML elements that never have content or a closing tag.

Detailed Description

Lexical pretty-printers for JSON, XML/HTML and JavaScript text.

Author
Castagnier Mickael
Version
1.0
Date
10/07/2026

Definition in file n_pretty.c.


Data Structure Documentation

◆ JS_STATE

struct JS_STATE

JS emitter state threaded through the helpers.

Definition at line 381 of file n_pretty.c.

Collaboration diagram for JS_STATE:
Data Fields
int at_line_start 1 when nothing has been emitted on the current line yet
int indent current indentation depth
int kw_regex 1 when the last token was a keyword that can precede a regex literal
char last_sig last significant code character emitted (0 = none yet)
PRETTY_OUT o output buffer
int pending_space 1 when collapsed whitespace separates the previous and next token

◆ PRETTY_OUT

struct PRETTY_OUT

growing output buffer fed by write_and_fit_ex

Definition at line 40 of file n_pretty.c.

Collaboration diagram for PRETTY_OUT:
Data Fields
char * buf buffer, reallocated on growth
NSTRBYTE size total allocation in bytes
NSTRBYTE written meaningful bytes, excluding the terminating '\0'

Macro Definition Documentation

◆ PRETTY_INDENT_STEP

#define PRETTY_INDENT_STEP   2

spaces per indentation level

Definition at line 52 of file n_pretty.c.

Referenced by _out_indent().

◆ PRETTY_OUT_PADDING

#define PRETTY_OUT_PADDING   256

growth headroom so consecutive short appends share one realloc

Definition at line 50 of file n_pretty.c.

Referenced by _out_mem().

◆ PRETTY_TAG_NAME_MAX

#define PRETTY_TAG_NAME_MAX   31

longest element name kept for void/raw-text lookups

Definition at line 54 of file n_pretty.c.

Referenced by n_pretty_xml().

Function Documentation

◆ _emit_line()

int _emit_line ( PRETTY_OUT * o,
int depth,
const char * s,
size_t n )
static

emit one indented line holding n raw bytes of s

Definition at line 269 of file n_pretty.c.

References _out_ch(), _out_indent(), and _out_mem().

Referenced by _emit_trimmed(), and n_pretty_xml().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _emit_trimmed()

int _emit_trimmed ( PRETTY_OUT * o,
int depth,
const char * s,
size_t n )
static

emit s trimmed of leading/trailing whitespace as one indented line; empty-after-trim runs are skipped

Definition at line 277 of file n_pretty.c.

References _emit_line().

Referenced by n_pretty_xml().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _find_tag_end()

const char * _find_tag_end ( const char * p)
static

find the '>' closing a tag starting at p, honoring quoted attribute values; returns NULL when the tag never closes

Definition at line 242 of file n_pretty.c.

Referenced by n_pretty_xml().

Here is the caller graph for this function:

◆ _js_lead()

int _js_lead ( JS_STATE * js)
static

emit the indent or the collapsed space before a token, as appropriate

Definition at line 397 of file n_pretty.c.

References _out_ch(), _out_indent(), JS_STATE::at_line_start, JS_STATE::indent, JS_STATE::o, and JS_STATE::pending_space.

Referenced by _js_token().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _js_newline()

int _js_newline ( JS_STATE * js)
static

terminate the current line unless already at a line start

Definition at line 415 of file n_pretty.c.

References _out_ch(), JS_STATE::at_line_start, JS_STATE::o, and JS_STATE::pending_space.

Referenced by n_pretty_js().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _js_regex_keyword()

int _js_regex_keyword ( const char * s,
size_t n )
static

whether the n bytes at s are a keyword after which an expression (and therefore a regex literal) can start, e.g.

return /re/

Definition at line 370 of file n_pretty.c.

Referenced by n_pretty_js().

Here is the caller graph for this function:

◆ _js_regex_len()

size_t _js_regex_len ( const char * s)
static

length of the regex literal starting at s (slash to closing slash, escapes and character classes honored, trailing flags included)

Definition at line 466 of file n_pretty.c.

Referenced by n_pretty_js().

Here is the caller graph for this function:

◆ _js_regex_possible()

int _js_regex_possible ( char c)
static

whether a '/' may start a regex literal after last significant char c (start of input, after an operator, an opener, or a separator)

Definition at line 363 of file n_pretty.c.

Referenced by n_pretty_js().

Here is the caller graph for this function:

◆ _js_string_len()

size_t _js_string_len ( const char * s)
static

length of the string literal starting at s (quote to closing quote, escapes honored, stops at end of line or input on unterminated ones)

Definition at line 424 of file n_pretty.c.

Referenced by n_pretty_js().

Here is the caller graph for this function:

◆ _js_template_len()

size_t _js_template_len ( const char * s)
static

length of the template literal starting at s (backtick to backtick, escapes honored, ${...} interpolations skipped by brace counting)

Definition at line 441 of file n_pretty.c.

Referenced by n_pretty_js().

Here is the caller graph for this function:

◆ _js_token()

int _js_token ( JS_STATE * js,
const char * s,
size_t n )
static

emit a raw token of n bytes with leading indent/space handling

Definition at line 409 of file n_pretty.c.

References _js_lead(), _out_mem(), and JS_STATE::o.

Referenced by n_pretty_js().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _jsonl_lead()

int _jsonl_lead ( PRETTY_OUT * o,
int depth,
int * at_line_start )
static

emit the pending indent of a lenient JSON line, TRUE on success

Definition at line 110 of file n_pretty.c.

References _out_indent().

Referenced by n_pretty_json_lenient().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _jsonl_newline()

int _jsonl_newline ( PRETTY_OUT * o,
int * at_line_start )
static

end the current lenient JSON line unless it is still empty, TRUE on success

Definition at line 117 of file n_pretty.c.

References _out_ch().

Referenced by n_pretty_json_lenient().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _name_in_list()

int _name_in_list ( const char * name,
const char ** list )
static

whether lowercase element name is in a NULL-terminated list

Definition at line 220 of file n_pretty.c.

Referenced by n_pretty_xml().

Here is the caller graph for this function:

◆ _out_ch()

int _out_ch ( PRETTY_OUT * o,
char c )
static

append a single character to the output, TRUE on success

Definition at line 63 of file n_pretty.c.

References _out_mem().

Referenced by _emit_line(), _js_lead(), _js_newline(), _jsonl_newline(), n_pretty_js(), and n_pretty_json_lenient().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _out_finish()

N_STR * _out_finish ( PRETTY_OUT * o)
static

hand the buffer over to a new N_STR (no copy); the PRETTY_OUT is emptied

Definition at line 76 of file n_pretty.c.

References PRETTY_OUT::buf, char_to_nstr_nocopy(), Free, PRETTY_OUT::size, and PRETTY_OUT::written.

Referenced by n_pretty_js(), n_pretty_json_lenient(), and n_pretty_xml().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _out_indent()

int _out_indent ( PRETTY_OUT * o,
int depth )
static

append depth * PRETTY_INDENT_STEP spaces, TRUE on success

Definition at line 68 of file n_pretty.c.

References _out_mem(), and PRETTY_INDENT_STEP.

Referenced by _emit_line(), _js_lead(), and _jsonl_lead().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _out_mem()

int _out_mem ( PRETTY_OUT * o,
const char * s,
size_t n )
static

append n bytes of s to the output, TRUE on success

Definition at line 57 of file n_pretty.c.

References PRETTY_OUT::buf, PRETTY_OUT_PADDING, PRETTY_OUT::size, write_and_fit_ex(), and PRETTY_OUT::written.

Referenced by _emit_line(), _js_token(), _out_ch(), _out_indent(), and n_pretty_json_lenient().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _stristr()

const char * _stristr ( const char * haystack,
const char * needle )
static

case-insensitive search for needle in haystack

Definition at line 259 of file n_pretty.c.

Referenced by n_pretty_xml().

Here is the caller graph for this function:

◆ _tag_name()

void _tag_name ( const char * p,
char * name,
size_t name_size )
static

extract the lowercased element name from a tag starting at p ("<name" or "</name")

Definition at line 228 of file n_pretty.c.

Referenced by n_pretty_xml().

Here is the caller graph for this function:

Variable Documentation

◆ PRETTY_RAWTEXT_ELEMENTS

const char* PRETTY_RAWTEXT_ELEMENTS[] = {"script", "style", NULL}
static

HTML elements whose content is raw text (no nested markup).

Definition at line 217 of file n_pretty.c.

Referenced by n_pretty_xml().

◆ PRETTY_VOID_ELEMENTS

const char* PRETTY_VOID_ELEMENTS[]
static
Initial value:
= {
"area", "base", "br", "col", "embed", "hr", "img", "input",
"link", "meta", "param", "source", "track", "wbr", NULL}

HTML elements that never have content or a closing tag.

Definition at line 212 of file n_pretty.c.

Referenced by n_pretty_xml().