|  | # This was imported into gdb from: | 
|  | # https://github.com/jorge-leon/ton | 
|  |  | 
|  | # This software is copyrighted by Georg Lehner <jorge@at.anteris.net>. | 
|  | # The following terms apply to all files associated with the software | 
|  | # unless explicitly disclaimed in individual files. | 
|  |  | 
|  | # The authors hereby grant permission to use, copy, modify, distribute, | 
|  | # and license this software and its documentation for any purpose, | 
|  | # provided that existing copyright notices are retained in all copies | 
|  | # and that this notice is included verbatim in any distributions. No | 
|  | # written agreement, license, or royalty fee is required for any of the | 
|  | # authorized uses.  Modifications to this software may be copyrighted by | 
|  | # their authors and need not follow the licensing terms described here, | 
|  | # provided that the new terms are clearly indicated on the first page of | 
|  | # each file where they apply. | 
|  |  | 
|  | # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY | 
|  | # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 
|  | # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY | 
|  | # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE | 
|  | # POSSIBILITY OF SUCH DAMAGE. | 
|  |  | 
|  | # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, | 
|  | # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 
|  | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND | 
|  | # NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND | 
|  | # THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE | 
|  | # MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 
|  |  | 
|  | # GOVERNMENT USE: If you are acquiring this software on behalf of the | 
|  | # U.S. government, the Government shall have only "Restricted Rights" in | 
|  | # the software and related documentation as defined in the Federal | 
|  | # Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2).  If you | 
|  | # are acquiring the software on behalf of the Department of Defense, the | 
|  | # software shall be classified as "Commercial Computer Software" and the | 
|  | # Government shall have only "Restricted Rights" as defined in Clause | 
|  | # 252.227-7013 (c) (1) of DFARs.  Notwithstanding the foregoing, the | 
|  | # authors grant the U.S. Government and others acting in its behalf | 
|  | # permission to use and distribute the software in accordance with the | 
|  | # terms specified in this license. | 
|  |  | 
|  |  | 
|  | # leg20180331: ton / TON - Tcl Object Notation | 
|  | # | 
|  | # This package provides manipulation functionality for TON - a data | 
|  | # serialization format with a direct mapping to JSON. | 
|  | # | 
|  | # In its essence, a JSON parser is provided, which can convert a JSON | 
|  | # string into a Tcllib json style dictionary (dicts and arrays mixed), | 
|  | # into a jimhttp style dictionary (only dicts) or into a nested, typed | 
|  | # Tcl list. | 
|  | # | 
|  | # Finally, TON can be converted into (unformatted) JSON. | 
|  |  | 
|  | namespace eval ton { | 
|  | namespace export json2ton | 
|  |  | 
|  | variable version 0.4 | 
|  |  | 
|  | } | 
|  | proc ton::json2ton json { | 
|  | # Parse JSON string json | 
|  | # | 
|  | # return: TON | 
|  |  | 
|  | set i [trr $json [string length $json]] | 
|  | if {!$i} {return ""} | 
|  | lassign [jscan $json $i] i ton | 
|  | if {[set i [trr $json $i]]} { | 
|  | error "json string invalid:[incr i -1]: left over characters." | 
|  | } | 
|  | return $ton | 
|  | } | 
|  | proc ton::trr {s i} { | 
|  | # Trim righthand whitespace on the first i characters of s. | 
|  | # return: number of remaining characters in s | 
|  |  | 
|  | while {[set j $i] && | 
|  | ([string is space [set c [string index $s [incr i -1]]]] | 
|  | || $c eq "\n")} {} | 
|  | return $j | 
|  | } | 
|  | proc ton::jscan {json i {d :}} { | 
|  | # Scan JSON in first i characters of string json. | 
|  | # d is the default delimiter list for the next token. | 
|  | # | 
|  | # return list of | 
|  | # - remaining characters in json | 
|  | # - TON | 
|  | # | 
|  | # The string must already be whitespace trimmed from the right. | 
|  |  | 
|  | incr i -1 | 
|  |  | 
|  | if {[set c [string index $json $i]] eq "\""} { | 
|  | str $json [incr i -1] | 
|  | } elseif {$c eq "\}"} { | 
|  | obj $json $i | 
|  | } elseif {$c eq "\]"} { | 
|  | arr $json $i | 
|  | } elseif {$c in {e l}} { | 
|  | lit $json $i | 
|  | } elseif {[string match {[0-9.]} $c]} { | 
|  | num $json $i $c $d | 
|  | } else { | 
|  | error "json string end invalid:$i: ..[string range $json $i-10 $i].." | 
|  | } | 
|  | } | 
|  | proc ton::num {json i c d} { | 
|  | # Parse number from position i in string json to the left. | 
|  | # c .. character at position i | 
|  | # d .. delimiter on which to stop | 
|  | # | 
|  | # return list: | 
|  | # - remaining string length | 
|  | # - TON of number | 
|  |  | 
|  | set float [expr {$c eq "."}] | 
|  | for {set j $i} {$i} {incr i -1} { | 
|  | if {[string match $d [set c [string index $json $i-1]]]} break | 
|  | set float [expr {$float || [string match "\[eE.]" $c]}] | 
|  | } | 
|  | set num [string trimleft [string range $json $i $j]] | 
|  | if {!$float && [string is entier $num]} { | 
|  | list $i "i $num" | 
|  | } elseif {$float && [string is double $num]} { | 
|  | list $i "d $num" | 
|  | } else { | 
|  | error "number invalid:$i: $num." | 
|  | } | 
|  | } | 
|  | proc ton::lit {json i} { | 
|  | # Parse literal from position i in string json to the left | 
|  | # return list: | 
|  | # - remaining string length | 
|  | # - TON of literal | 
|  |  | 
|  | if {[set c [string index $json $i-1]] eq "u"} { | 
|  | list [incr i -3] "l true" | 
|  | } elseif {$c eq "s"} { | 
|  | list [incr i -4] "l false" | 
|  | } elseif {$c eq "l"} { | 
|  | list [incr i -3] "l null" | 
|  | } else { | 
|  | set e [string range $json $i-3 $i] | 
|  | error "literal invalid:[incr i -1]: ..$e." | 
|  | } | 
|  | } | 
|  | proc ton::str {json i} { | 
|  | # Parse string from position i in string json to the left | 
|  | # return list: | 
|  | # - remaining string length | 
|  | # - TON of string | 
|  |  | 
|  | for {set j $i} {$i} {incr i -1} { | 
|  | set i [string last \" $json $i] | 
|  | if {[string index $json $i-1] ne "\\"} break | 
|  | } | 
|  | if {$i==-1} { | 
|  | error "json string start invalid:$i: exhausted while parsing string." | 
|  | } | 
|  | list $i "s [list [string range $json $i+1 $j]]" | 
|  | } | 
|  | proc ton::arr {json i} { | 
|  | # Parse array from i characters in string json | 
|  | # return list: | 
|  | # - remaining string length | 
|  | # - TON of array | 
|  |  | 
|  | set i [trr $json $i] | 
|  | if {!$i} { | 
|  | error "json string invalid:0: exhausted while parsing array." | 
|  | } | 
|  | if {[string index $json $i-1] eq "\["} { | 
|  | return [list [incr i -1] a] | 
|  | } | 
|  | set r {} | 
|  | while {$i} { | 
|  | lassign [jscan $json $i "\[,\[]"] i v | 
|  | lappend r \[$v\] | 
|  | set i [trr $json $i] | 
|  | incr i -1 | 
|  | if {[set c [string index $json $i]] eq ","} { | 
|  | set i [trr $json $i] | 
|  | continue | 
|  | } elseif {$c eq "\["} break | 
|  | error "json string invalid:$i: parsing array." | 
|  | } | 
|  | lappend r a | 
|  | return [list $i [join [lreverse $r]]] | 
|  | } | 
|  | proc ton::obj {json i} { | 
|  | # Parse array from i character in string json | 
|  | # return list: | 
|  | # - remaining string length | 
|  | # - TON of object | 
|  |  | 
|  | set i [trr $json $i] | 
|  | if {!$i} { | 
|  | error "json string invalid:0: exhausted while parsing object." | 
|  | } | 
|  | if {[string index $json $i-1] eq "\{"} { | 
|  | return [list [incr i -1] o] | 
|  | } | 
|  | set r {} | 
|  | while {$i} { | 
|  | lassign [jscan $json $i] i v | 
|  | set i [trr $json $i] | 
|  | incr i -1 | 
|  | if {[string index $json $i] ne ":"} { | 
|  | error "json string invalid:$i: parsing key in object." | 
|  | } | 
|  | set i [trr $json $i] | 
|  | lassign [jscan $json $i] i k | 
|  | lassign $k type k | 
|  | if {$type ne "s"} { | 
|  | error "json string invalid:[incr i -1]: key not a string." | 
|  | } | 
|  | lappend r \[$v\] [list $k] | 
|  | set i [trr $json $i] | 
|  | incr i -1 | 
|  | if {[set c [string index $json $i]] eq ","} { | 
|  | set i [trr $json $i] | 
|  | continue | 
|  | } elseif {$c eq "\{"} break | 
|  | error "json string invalid:$i: parsing object." | 
|  | } | 
|  | lappend r o | 
|  | return [list $i [join [lreverse $r]]] | 
|  | } | 
|  | # TON decoders | 
|  | namespace eval ton::2list { | 
|  | proc atom {type v} {list $type $v} | 
|  | foreach type {i d s l} { | 
|  | interp alias {} $type {} [namespace current]::atom $type | 
|  | } | 
|  | proc a args { | 
|  | set r a | 
|  | foreach v $args {lappend r $v} | 
|  | return $r | 
|  | } | 
|  | proc o args { | 
|  | set r o | 
|  | foreach {k v} $args {lappend r $k $v} | 
|  | return $r | 
|  | } | 
|  | # There is plenty of room for validation in get | 
|  | # array index bounds | 
|  | # object key existence | 
|  | proc get {l args} { | 
|  | foreach k $args { | 
|  | switch [lindex $l 0] { | 
|  | o {set l [dict get [lrange $l 1 end] $k]} | 
|  | a {set l [lindex $l [incr k]]} | 
|  | default { | 
|  | error "error: key $k to long, or wrong data: [lindex $l 0]" | 
|  | } | 
|  | } | 
|  | } | 
|  | return $l | 
|  | } | 
|  | } | 
|  | namespace eval ton::2dict { | 
|  | proc atom v {return $v} | 
|  | foreach type {i d l s} { | 
|  | interp alias {} $type {} [namespace current]::atom | 
|  | } | 
|  | proc a args {return $args} | 
|  | proc o args {return $args} | 
|  | } | 
|  | namespace eval ton::a2dict { | 
|  | proc atom v {return $v} | 
|  | foreach type {i d l s} { | 
|  | interp alias {} $type {} [namespace current]::atom | 
|  | } | 
|  | proc a args { | 
|  | set i -1 | 
|  | set r {} | 
|  | foreach v $args { | 
|  | lappend r [incr i] $v | 
|  | } | 
|  | return $r | 
|  | } | 
|  | proc o args {return $args} | 
|  | } | 
|  | namespace eval ton::2json { | 
|  | proc atom v {return $v} | 
|  | foreach type {i d l} { | 
|  | interp alias {} $type {} [namespace current]::atom | 
|  | } | 
|  | proc a args { | 
|  | return "\[[join $args {, }]]" | 
|  | } | 
|  | proc o args { | 
|  | set r {} | 
|  | foreach {k v} $args {lappend r "\"$k\": $v"} | 
|  | return "{[join $r {, }]}" | 
|  | } | 
|  | proc s s {return "\"$s\""} | 
|  | } | 
|  |  | 
|  | package provide ton $ton::version |