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 _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_STRn_pretty_js (const char *text)
 Conservatively re-indent JavaScript (newlines at top-level braces and semicolons, two-space indent by brace depth).
 
N_STRn_pretty_json (const char *text)
 Reformat a JSON document with cJSON (parse + print).
 
N_STRn_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 279 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.

◆ 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.

◆ 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.

Function Documentation

◆ _emit_line()

static 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 167 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()

static 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 175 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()

static 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 140 of file n_pretty.c.

Referenced by n_pretty_xml().

+ Here is the caller graph for this function:

◆ _js_lead()

static int _js_lead ( JS_STATE js)
static

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

Definition at line 295 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()

static int _js_newline ( JS_STATE js)
static

terminate the current line unless already at a line start

Definition at line 313 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()

static 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 268 of file n_pretty.c.

Referenced by n_pretty_js().

+ Here is the caller graph for this function:

◆ _js_regex_len()

static 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 364 of file n_pretty.c.

Referenced by n_pretty_js().

+ Here is the caller graph for this function:

◆ _js_regex_possible()

static 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 261 of file n_pretty.c.

Referenced by n_pretty_js().

+ Here is the caller graph for this function:

◆ _js_string_len()

static 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 322 of file n_pretty.c.

Referenced by n_pretty_js().

+ Here is the caller graph for this function:

◆ _js_template_len()

static 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 339 of file n_pretty.c.

Referenced by n_pretty_js().

+ Here is the caller graph for this function:

◆ _js_token()

static 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 307 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:

◆ _name_in_list()

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

whether lowercase element name is in a NULL-terminated list

Definition at line 118 of file n_pretty.c.

Referenced by n_pretty_xml().

+ Here is the caller graph for this function:

◆ _out_ch()

static 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(), and n_pretty_js().

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

◆ _out_finish()

static 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(), and n_pretty_xml().

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

◆ _out_indent()

static 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(), and _js_lead().

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

◆ _out_mem()

static 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(), and _out_indent().

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

◆ _stristr()

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

case-insensitive search for needle in haystack

Definition at line 157 of file n_pretty.c.

Referenced by n_pretty_xml().

+ Here is the caller graph for this function:

◆ _tag_name()

static 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 126 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 115 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 110 of file n_pretty.c.

Referenced by n_pretty_xml().