Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ perf.data.old
.cproject
.project
.settings
.gse
tests/JSONTestSuite/test_parsing
tests/JSONTestSuite/test_transform
tclobjs_remaining
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Quick Reference
* [json object ?*key* *value* ?*key* *value* ...??] - Return a JSON object with the keys and values specified. *value* is a list of two elements, the first being the type {string, number, boolean, null, object, array, json}, and the second being the value.
* [json object *packed_value*] - An alternate syntax that takes the list of keys and values as a single arg instead of a list of args, but is otherwise the same.
* [json array ?*elem* ...?] - Return a JSON array containing each of the elements given. *elem* is a list of two elements, the first being the type {string, number, boolean, null, object, array, json}, and the second being the value.
* [json autoarray ?*value* ...?] - Return a JSON array with automatic type detection. Values matching "true" or "false" become booleans, valid numbers become JSON numbers, and all other values become strings.
* [json autoobject ?*key* *value* ...?] - Return a JSON object with automatic type detection for values. Keys are always strings, values undergo the same automatic type detection as autoarray (booleans, numbers, or strings).
* [json foreach *varlist1* *json_val1* ?*varlist2* *json_val2* ...? *script*] - Evaluate *script* in a loop in a similar way to the [foreach] command. In each iteration, the values stored in the iterator variables in *varlist* are the JSON fragments from *json_val*. Supports iterating over JSON arrays and JSON objects. In the JSON object case, *varlist* must be a two element list, with the first specifiying the variable to hold the key and the second the value. In the JSON array case, the rules are the same as the [foreach] command.
* [json lmap *varlist1* *json_val1* ?*varlist2* *json_val2* ...? *script*] - As for [json foreach], except that it is collecting - the result from each evaluation of *script* is added to a list and returned as the result of the [json lmap] command. If the *script* results in a TCL_CONTINUE code, that iteration is skipped and no element is added to the result list. If it results in TCL_BREAK the iterations are stopped and the results accumulated so far are returned.
* [json amap *varlist1* *json_val1* ?*varlist2* *json_val2* ...? *script*] - As for [json lmap], but the result is a JSON array rather than a list. If the result of each iteration is a JSON value it is added to the array as-is, otherwise it is converted to a JSON string.
Expand Down
258 changes: 258 additions & 0 deletions TECLABCHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
# TECLAB Changes: master → wip

This document describes all changes made in the `wip` branch compared to `master`.

## Commit History

```
5a1a51b WIP
17b92f7 WIP
9bb174f beautify
a476851 adding autoarray tests
fa88e9d readding libtommath submodule
0776812 fix compile errors
66d3a82 Merge branch 'master' of https://github.com/RubyLane/rl_json into wip
5217388 added nopadding test
9ccf3f8 Merge pull request #3 from teclabat/autoarray
321b159 Merge branch 'wip' into autoarray
a07c3f1 Merge pull request #2 from teclabat/pretty
c3588aa pretty command now accepts the -nopadding switch cleanup the pretty.test
23fc406 enhancements for the pretty command: -compact -indent -arrays
ff30d6f new autoarray method
1b9c8e3 Merge pull request #1 from teclabat/noparseargs
10f2db0 parse_args fails to load during tests, simplify as it seems it's anyhow overkill for this
```

## Summary Statistics

```
16 files changed, 891 insertions(+), 79 deletions(-)
```

## Major Features Added

### 1. New `json autoarray` Command

A new command that creates JSON arrays with automatic type detection, eliminating the need for explicit type specification.

**Syntax:**
```tcl
json autoarray ?value ...?
```

**Features:**
- Automatically detects JSON booleans (exact "true" or "false")
- Automatically detects valid JSON numbers
- Defaults to JSON strings for all other values

**Example:**
```tcl
json autoarray 1 2.5 true false "hello world" 42
# Returns: [1,2.5,true,false,"hello world",42]
```

**Files:**
- `generic/rl_json.c`: Implementation of `jsonAutoArray()` function
- `doc/json.n`: Documentation added
- `tests/autoarray.test`: Comprehensive test suite (322 new lines)

### 2. New `json autoobject` Command

A new command that creates JSON objects from key-value pairs with automatic type detection for values, complementing the `json autoarray` command.

**Syntax:**
```tcl
json autoobject ?key value ...?
```

**Features:**
- Keys are always treated as strings (as required by JSON specification)
- Values undergo automatic type detection:
- Exact "true" or "false" (case-sensitive) → JSON booleans
- Valid JSON numbers → JSON numbers
- All other values → JSON strings
- Requires even number of arguments (key-value pairs)
- Duplicate keys allowed (last value wins)

**Example:**
```tcl
json autoobject name "Alice" age 30 active true score 95.5
# Returns: {"name":"Alice","age":30,"active":true,"score":95.5}
```

**Files:**
- `generic/rl_json.c`: Implementation of `jsonAutoObject()` function
- `doc/json.n`: Documentation added
- `tests/autoobject.test`: Comprehensive test suite (260+ new lines)

### 3. Enhanced `json pretty` Command

Significant enhancements to the pretty-printing functionality with three new options.

**New Options:**

#### `-compact`
Returns a compact, single-line representation with no extra whitespace (equivalent to `json normalize`).

**Example:**
```tcl
json pretty -compact $jsonValue
```

#### `-nopadding`
Removes the automatic padding/alignment of object keys, resulting in more condensed output.

**Example:**
```tcl
json pretty -nopadding $jsonValue
```

#### `-arrays <mode>`
Controls array formatting with two modes:
- `inline`: All arrays formatted on a single line `[1,2,3]`
- `multiline`: All arrays formatted with one element per line

**Default behavior:** Arrays with ≤3 elements are inline, larger arrays are multiline.

**Example:**
```tcl
json pretty -arrays inline $jsonValue
json pretty -arrays multiline $jsonValue
```

**Files Modified:**
- `generic/rl_json.c`: Core implementation
- `generic/api.c`: API updates
- `generic/rl_json.decls`: Declaration updates
- `generic/rl_jsonDecls.h`: Header updates
- `generic/rl_jsonInt.h`: Internal header updates
- `doc/json.n`: Extended documentation
- `tests/pretty.test`: Expanded test coverage (+180 lines)

## Bug Fixes and Improvements

### Parser Error Reporting
**File:** `generic/parser.c`

Fixed format specifiers for cross-platform compatibility:
- Added Tcl version-specific format strings for error messages
- Proper handling of `size_t` values in error reporting
- Fixed warnings on 64-bit systems

### Memory Leak Debugging
**File:** `generic/rl_json.c`

Updated leak detection tools:
- Changed address handling from `unsigned long` to `Tcl_WideInt`
- Proper casting to `uintptr_t` for pointer conversions
- Better cross-platform compatibility

### TIP445 Support
**Files:**
- `generic/tip445.h`: Changed from symlink to regular file
- `generic/tip445.fix.h`: New file with TIP445 compatibility shims

Added compatibility layer for building on Tcl 8.6.

### Submodule Updates
**File:** `teabase`

Updated teabase submodule:
- From: `b58eac68cc3d07c4f3155a3d390e31fc29fb255b`
- To: `b293fee95e97cbe6ce1583807e4d2aed8404e2e3`

### libtommath Integration
**File:** `generic/rl_jsonInt.h`

Added proper configuration header support and reorganized includes for CBOR support.

## Configuration and Build Changes

### .gitignore
Added `.gse` to ignored files.

### Version Update
**File:** `doc/json.n`

Updated package version:
- From: `0.14.0`
- To: `0.15.0`

## Test Improvements

### New Test Files
- `tests/autoarray.test`: Complete test suite for autoarray functionality (322 lines)

### Enhanced Test Files
- `tests/pretty.test`: Added 180+ lines of new tests for enhanced pretty options
- `tests/helpers.tcl`: Minor updates for test infrastructure
- `tests/set.test`: Minor updates
- `tests/unset.test`: Minor updates

## API Changes

### Modified C API Functions

**`JSON_Pretty()`** signature changed:
```c
// Old:
int JSON_Pretty(Tcl_Interp* interp, Tcl_Obj* obj, Tcl_Obj* indent,
Tcl_Obj** prettyString)

// New:
int JSON_Pretty(Tcl_Interp* interp, Tcl_Obj* obj, Tcl_Obj* indent,
int nopadding, int compact, int arrays_inline,
Tcl_Obj** prettyString)
```

**`json_pretty()`** internal function signature changed:
```c
// Old:
int json_pretty(Tcl_Interp* interp, Tcl_Obj* json, Tcl_Obj* indent,
Tcl_Obj* pad, Tcl_DString* ds)

// New:
int json_pretty(Tcl_Interp* interp, Tcl_Obj* json, Tcl_Obj* indent,
int nopadding, Tcl_Obj* pad, int arrays_inline,
Tcl_DString* ds)
```

### New Tcl Commands
- `json autoarray ?value ...?`
- `json autoobject ?key value ...?`

### Enhanced Tcl Commands
- `json pretty ?-indent indent? ?-compact? ?-nopadding? ?-arrays inline|multiline? jsonValue ?key ...?`

## Documentation Updates

**File:** `doc/json.n`

Comprehensive documentation added/updated for:
1. `json autoarray` - Complete new section with examples
2. `json pretty` - Expanded with detailed descriptions of all new options
3. Version number updated throughout

## Backward Compatibility

### Breaking Changes
- The C API function `JSON_Pretty()` has a changed signature
- Code calling this C function directly will need to be updated

### Non-Breaking Changes
- All Tcl-level commands maintain backward compatibility
- New options are optional and default to previous behavior
- Existing scripts will continue to work unchanged

## Statistics by Component

### Code Changes
- **C source files:** 6 files modified, ~180 insertions
- **Header files:** 4 files modified, ~30 insertions
- **Documentation:** 1 file modified, ~70 insertions
- **Tests:** 4 files modified/added, ~500 insertions

### Lines of Code
- **Total additions:** 891 lines
- **Total deletions:** 79 lines
- **Net change:** +812 lines
82 changes: 76 additions & 6 deletions doc/json.n
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
'\" See the file "LICENSE" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
.TH json n 0.14.0 rl_json "RubyLane/JSON Package Commands"
.TH json n 0.15.0 rl_json "RubyLane/JSON Package Commands"
.so man.macros
.BS
'\" Note: do not modify the .SH NAME line immediately below!
.SH NAME
json \- Parse, manipulate and produce JSON documents
json \- Parse, manipulate and produce JSON documents
.SH SYNOPSIS
.nf
\fBpackage require rl_json\fR ?\fB0.14.0\fR?
\fBpackage require rl_json\fR ?\fB0.15.0\fR?

\fBjson get\fR ?\fB-default\fR \fIdefaultValue\fR? \fIjsonValue\fR ?\fIkey ...\fR?
\fBjson extract\fR ?\fB-default\fR \fIdefaultValue\fR? \fIjsonValue\fR ?\fIkey ...\fR?
Expand All @@ -28,6 +28,7 @@ json \- Parse, manipulate and produce JSON documents
\fBjson boolean\fR \fIvalue\fR
\fBjson object\fR \fI?key value ?key value ...??\fR
\fBjson array\fR \fIelem ...\fR
\fBjson autoarray\fR \fIvalue ...\fR
\fBjson bool\fR \fIvalue\fR
\fBjson normalize\fR \fIjsonValue\fR
\fBjson pretty\fR ?\fB-indent\fR \fIindent\fR? \fIjsonValue\fR ?\fIkey ...\fR?
Expand Down Expand Up @@ -170,6 +171,49 @@ Return a JSON array containing each of the elements given. \fIelem\fR is a list
of two elements, the first being the type {string, number, boolean, null, object, array, json},
and the second being the value.
.TP
\fBjson autoarray \fI?value ...?\fR
.
Return a JSON array containing each of the values given, with automatic type detection.
Unlike \fBjson array\fR which requires explicit type specification, \fBjson autoarray\fR
automatically determines the appropriate JSON type for each value:
.RS
.IP \(bu 3
Values exactly matching "true" or "false" (case-sensitive) are converted to JSON booleans.
.IP \(bu 3
Values that can be parsed as valid JSON numbers are converted to JSON numbers.
.IP \(bu 3
All other values are converted to JSON strings.
.RE
.PP
For example:
.CS
json autoarray 1 2.5 true false "hello world" 42
# Returns: [1,2.5,true,false,"hello world",42]
.CE
.TP
\fBjson autoobject \fI?key value ...?\fR
.
Return a JSON object containing the key-value pairs given, with automatic type detection
for values. Keys are always treated as strings (as required by JSON), while values undergo
the same automatic type detection as \fBjson autoarray\fR:
.RS
.IP \(bu 3
Values exactly matching "true" or "false" (case-sensitive) are converted to JSON booleans.
.IP \(bu 3
Values that can be parsed as valid JSON numbers are converted to JSON numbers.
.IP \(bu 3
All other values are converted to JSON strings.
.RE
.PP
The command requires an even number of arguments (key-value pairs). If duplicate keys
are provided, the last value wins.
.PP
For example:
.CS
json autoobject name "Alice" age 30 active true score 95.5
# Returns: {"name":"Alice","age":30,"active":true,"score":95.5}
.CE
.TP
\fBjson foreach \fIvarList1 jsonValue1\fR ?\fIvarList2 jsonValue2 ...\fR? \fIscript\fR
.
Evaluate \fIscript\fR in a loop in a similar way to the \fBforeach\fR command.
Expand Down Expand Up @@ -232,12 +276,38 @@ Return a
version of the input \fIjsonValue\fR, i.e., with all optional whitespace
trimmed.
.TP
\fBjson pretty\fR ?\fB-indent\fR \fIindent\fR? \fIjsonValue\fR ?\fIkey ...\fR?
\fBjson pretty\fR ?\fB-indent\fR \fIindent\fR? ?\fB-compact\fR? ?\fB-arrays\fR \fImode\fR? \fIjsonValue\fR ?\fIkey ...\fR?
.
Returns a pretty-printed string representation of \fIjsonValue\fR, found by
following the path of \fIkey\fRs. Useful for debugging or inspecting the
structure of JSON data. If \fB-indent\fR is supplied, use \fIindent\fR for
each level of indent, otherwise default to four spaces.
structure of JSON data.
.RS
.PP
The following options control the formatting:
.TP
\fB-indent\fR \fIindent\fR
.
Use \fIindent\fR for each level of indent. Defaults to four spaces if not specified.
.TP
\fB-compact\fR
.
Return a compact, single-line representation with no extra whitespace. This is equivalent
to \fBjson normalize\fR but provided for convenience when using other pretty options.
When this option is used, \fB-indent\fR and \fB-arrays\fR are ignored.
.TP
\fB-arrays\fR \fImode\fR
.
Control how arrays are formatted. \fImode\fR must be one of:
.RS
.IP \fBinline\fR 10
All arrays are formatted on a single line: [1,2,3]
.IP \fBmultiline\fR 10
All arrays are formatted with one element per line.
.RE
.PP
If not specified, arrays with 3 or fewer elements are formatted inline, while larger
arrays are formatted with one element per line.
.RE
.TP
\fBjson decode \fIbytes\fR ?\fIencoding\fR?
.
Expand Down
Loading