1if not modules then modules = { } end modules [ ' util-tab ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to luat-lib.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9utilities = utilities or { }
10utilities . tables = utilities . tables or { }
11local tables = utilities . tables
12
13local format , gmatch , gsub , sub = string . format , string . gmatch , string . gsub , string . sub
14local concat , insert , remove , sort = table . concat , table . insert , table . remove , table . sort
15local setmetatable , getmetatable , tonumber , tostring , rawget = setmetatable , getmetatable , tonumber , tostring , rawget
16local type , next , rawset , tonumber , tostring , load , select = type , next , rawset , tonumber , tostring , load , select
17local lpegmatch , P , Cs , Cc = lpeg . match , lpeg . P , lpeg . Cs , lpeg . Cc
18local sortedkeys , sortedpairs = table . sortedkeys , table . sortedpairs
19local formatters = string . formatters
20local utftoeight = utf . toeight
21
22local splitter = lpeg . tsplitat ( " . " )
23
24function utilities . tables . definetable ( target , nofirst , nolast )
25 local composed = nil
26 local t = { }
27 local snippets = lpegmatch ( splitter , target )
28 for i = 1 , # snippets - ( nolast and 1 or 0 ) do
29 local name = snippets [ i ]
30 if composed then
31 composed = composed . . " . " . . name
32 t [ # t + 1 ] = formatters [ " if not %s then %s = { } end " ] ( composed , composed )
33 else
34 composed = name
35 if not nofirst then
36 t [ # t + 1 ] = formatters [ " %s = %s or { } " ] ( composed , composed )
37 end
38 end
39 end
40 if composed then
41 if nolast then
42 composed = composed . . " . " . . snippets [ # snippets ]
43 end
44 return concat ( t , " \n " ) , composed
45 else
46 return " " , target
47 end
48end
49
50
51
52function tables . definedtable ( ... )
53 local t = _G
54 for i = 1 , select ( " # " , ... ) do
55 local li = select ( i , ... )
56 local tl = t [ li ]
57 if not tl then
58 tl = { }
59 t [ li ] = tl
60 end
61 t = tl
62 end
63 return t
64end
65
66function tables . accesstable ( target , root )
67 local t = root or _G
68 for name in gmatch ( target , " ([^%.]+) " ) do
69 t = t [ name ]
70 if not t then
71 return
72 end
73 end
74 return t
75end
76
77function tables . migratetable ( target , v , root )
78 local t = root or _G
79 local names = lpegmatch ( splitter , target )
80 for i = 1 , # names -1 do
81 local name = names [ i ]
82 t [ name ] = t [ name ] or { }
83 t = t [ name ]
84 if not t then
85 return
86 end
87 end
88 t [ names [ # names ] ] = v
89end
90
91function tables . removevalue ( t , value )
92 if value then
93 for i = 1 , # t do
94 if t [ i ] = = value then
95 remove ( t , i )
96
97 end
98 end
99 end
100end
101
102function tables . replacevalue ( t , oldvalue , newvalue )
103 if oldvalue and newvalue then
104 for i = 1 , # t do
105 if t [ i ] = = oldvalue then
106 t [ i ] = newvalue
107
108 end
109 end
110 end
111end
112
113function tables . insertbeforevalue ( t , value , extra )
114 for i = 1 , # t do
115 if t [ i ] = = extra then
116 remove ( t , i )
117 end
118 end
119 for i = 1 , # t do
120 if t [ i ] = = value then
121 insert ( t , i , extra )
122 return
123 end
124 end
125 insert ( t , 1 , extra )
126end
127
128function tables . insertaftervalue ( t , value , extra )
129 for i = 1 , # t do
130 if t [ i ] = = extra then
131 remove ( t , i )
132 end
133 end
134 for i = 1 , # t do
135 if t [ i ] = = value then
136 insert ( t , i + 1 , extra )
137 return
138 end
139 end
140 insert ( t , # t + 1 , extra )
141end
142
143
144
145local escape = Cs ( Cc ( ' " ' ) * ( ( P ( ' " ' ) / ' "" ' + P ( 1 ) ) ^ 0 ) * Cc ( ' " ' ) )
146
147function table . tocsv ( t , specification )
148 if t and # t > 0 then
149 local result = { }
150 local r = { }
151 specification = specification or { }
152 local fields = specification . fields
153 if type ( fields ) ~ = " string " then
154 fields = sortedkeys ( t [ 1 ] )
155 end
156 local separator = specification . separator or " , "
157 local noffields = # fields
158 if specification . preamble = = true then
159 for f = 1 , noffields do
160 r [ f ] = lpegmatch ( escape , tostring ( fields [ f ] ) )
161 end
162 result [ 1 ] = concat ( r , separator )
163 end
164 for i = 1 , # t do
165 local ti = t [ i ]
166 for f = 1 , noffields do
167 local field = ti [ fields [ f ] ]
168 if type ( field ) = = " string " then
169 r [ f ] = lpegmatch ( escape , field )
170 else
171 r [ f ] = tostring ( field )
172 end
173 end
174
175 result [ i + 1 ] = concat ( r , separator )
176 end
177 return concat ( result , " \n " )
178 else
179 return " "
180 end
181end
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217local nspaces = utilities . strings . newrepeater ( " " )
218
219local function toxml ( t , d , result , step )
220 local r = # result
221 for k , v in sortedpairs ( t ) do
222 local s = nspaces [ d ]
223 local tk = type ( k )
224 local tv = type ( v )
225 if tv = = " table " then
226 if tk = = " number " then
227 r = r + 1 result [ r ] = formatters [ " %s<entry n='%s'> " ] ( s , k )
228 toxml ( v , d + step , result , step )
229 r = r + 1 result [ r ] = formatters [ " %s</entry> " ] ( s , k )
230 else
231 r = r + 1 result [ r ] = formatters [ " %s<%s> " ] ( s , k )
232 toxml ( v , d + step , result , step )
233 r = r + 1 result [ r ] = formatters [ " %s</%s> " ] ( s , k )
234 end
235 elseif tv = = " string " then
236 if tk = = " number " then
237 r = r + 1 result [ r ] = formatters [ " %s<entry n='%s'>%!xml!</entry> " ] ( s , k , v , k )
238 else
239 r = r + 1 result [ r ] = formatters [ " %s<%s>%!xml!</%s> " ] ( s , k , v , k )
240 end
241 elseif tk = = " number " then
242 r = r + 1 result [ r ] = formatters [ " %s<entry n='%s'>%S</entry> " ] ( s , k , v , k )
243 else
244 r = r + 1 result [ r ] = formatters [ " %s<%s>%S</%s> " ] ( s , k , v , k )
245 end
246 end
247end
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262function table . toxml ( t , specification )
263 specification = specification or { }
264 local name = specification . name
265 local noroot = name = = false
266 local result = ( specification . nobanner or noroot ) and { } or { " <?xml version='1.0' standalone='yes' ?> " }
267 local indent = specification . indent or 0
268 local spaces = specification . spaces or 1
269 if noroot then
270 toxml ( t , indent , result , spaces )
271 else
272 toxml ( { [ name or " data " ] = t } , indent , result , spaces )
273 end
274 return concat ( result , " \n " )
275end
276
277
278
279
280
281
282
283function tables . encapsulate ( core , capsule , protect )
284 if type ( capsule ) ~ = " table " then
285 protect = true
286 capsule = { }
287 end
288 for key , value in next , core do
289 if capsule [ key ] then
290 print ( formatters [ " \ninvalid %s %a in %a " ] ( " inheritance " , key , core ) )
291 os . exit ( )
292 else
293 capsule [ key ] = value
294 end
295 end
296 if protect then
297 for key , value in next , core do
298 core [ key ] = nil
299 end
300 setmetatable ( core , {
301 __index = capsule ,
302 __newindex = function ( t , key , value )
303 if capsule [ key ] then
304 print ( formatters [ " \ninvalid %s %a' in %a " ] ( " overload " , key , core ) )
305 os . exit ( )
306 else
307 rawset ( t , key , value )
308 end
309 end
310 } )
311 end
312end
313
314
315
316
317if JITSUPPORTED then
318
319 local f_hashed_string = formatters [ " [%Q]=%Q, " ]
320 local f_hashed_number = formatters [ " [%Q]=%s, " ]
321 local f_hashed_boolean = formatters [ " [%Q]=%l, " ]
322 local f_hashed_table = formatters [ " [%Q]= " ]
323
324 local f_indexed_string = formatters [ " [%s]=%Q, " ]
325 local f_indexed_number = formatters [ " [%s]=%s, " ]
326 local f_indexed_boolean = formatters [ " [%s]=%l, " ]
327 local f_indexed_table = formatters [ " [%s]= " ]
328
329 local f_ordered_string = formatters [ " %Q, " ]
330 local f_ordered_number = formatters [ " %s, " ]
331 local f_ordered_boolean = formatters [ " %l, " ]
332
333 function table . fastserialize ( t , prefix )
334
335
336
337
338
339 local r = { type ( prefix ) = = " string " and prefix or " return " }
340 local m = 1
341 local function fastserialize ( t , outer )
342 local n = # t
343 m = m + 1
344 r [ m ] = " { "
345 if n > 0 then
346 local v = t [ 0 ]
347 if v then
348 local tv = type ( v )
349 if tv = = " string " then
350 m = m + 1 r [ m ] = f_indexed_string ( 0 , v )
351 elseif tv = = " number " then
352 m = m + 1 r [ m ] = f_indexed_number ( 0 , v )
353 elseif tv = = " table " then
354 m = m + 1 r [ m ] = f_indexed_table ( 0 )
355 fastserialize ( v )
356 m = m + 1 r [ m ] = f_indexed_table ( 0 )
357 elseif tv = = " boolean " then
358 m = m + 1 r [ m ] = f_indexed_boolean ( 0 , v )
359 end
360 end
361 for i = 1 , n do
362 local v = t [ i ]
363 local tv = type ( v )
364 if tv = = " string " then
365 m = m + 1 r [ m ] = f_ordered_string ( v )
366 elseif tv = = " number " then
367 m = m + 1 r [ m ] = f_ordered_number ( v )
368 elseif tv = = " table " then
369 fastserialize ( v )
370 elseif tv = = " boolean " then
371 m = m + 1 r [ m ] = f_ordered_boolean ( v )
372 end
373 end
374 end
375
376
377 for k , v in next , t do
378 local tk = type ( k )
379 if tk = = " number " then
380 if k > n or k < 0 then
381 local tv = type ( v )
382 if tv = = " string " then
383 m = m + 1 r [ m ] = f_indexed_string ( k , v )
384 elseif tv = = " number " then
385 m = m + 1 r [ m ] = f_indexed_number ( k , v )
386 elseif tv = = " table " then
387 m = m + 1 r [ m ] = f_indexed_table ( k )
388 fastserialize ( v )
389 elseif tv = = " boolean " then
390 m = m + 1 r [ m ] = f_indexed_boolean ( k , v )
391 end
392 end
393 else
394 local tv = type ( v )
395 if tv = = " string " then
396 m = m + 1 r [ m ] = f_hashed_string ( k , v )
397 elseif tv = = " number " then
398 m = m + 1 r [ m ] = f_hashed_number ( k , v )
399 elseif tv = = " table " then
400 m = m + 1 r [ m ] = f_hashed_table ( k )
401 fastserialize ( v )
402 elseif tv = = " boolean " then
403 m = m + 1 r [ m ] = f_hashed_boolean ( k , v )
404 end
405 end
406 end
407 m = m + 1
408 if outer then
409 r [ m ] = " } "
410 else
411 r [ m ] = " }, "
412 end
413 return r
414 end
415 return concat ( fastserialize ( t , true ) )
416 end
417
418else
419
420 local f_v = formatters [ " [%q]=%q, " ]
421 local f_t = formatters [ " [%q]= " ]
422 local f_q = formatters [ " %q, " ]
423
424 function table . fastserialize ( t , prefix )
425 local r = { type ( prefix ) = = " string " and prefix or " return " }
426 local m = 1
427 local function fastserialize ( t , outer )
428 local n = # t
429 m = m + 1
430 r [ m ] = " { "
431 if n > 0 then
432 local v = t [ 0 ]
433 if v then
434 m = m + 1
435 r [ m ] = " [0]=' "
436 if type ( v ) = = " table " then
437 fastserialize ( v )
438 else
439 r [ m ] = format ( " %q, " , v )
440 end
441 end
442 for i = 1 , n do
443 local v = t [ i ]
444 m = m + 1
445 if type ( v ) = = " table " then
446 r [ m ] = format ( " [%i]= " , i )
447 fastserialize ( v )
448 else
449 r [ m ] = format ( " [%i]=%q, " , i , v )
450 end
451 end
452 end
453
454
455 for k , v in next , t do
456 local tk = type ( k )
457 if tk = = " number " then
458 if k > n or k < 0 then
459 m = m + 1
460 if type ( v ) = = " table " then
461 r [ m ] = format ( " [%i]= " , k )
462 fastserialize ( v )
463 else
464 r [ m ] = format ( " [%i]=%q, " , k , v )
465 end
466 end
467 else
468 m = m + 1
469 if type ( v ) = = " table " then
470 r [ m ] = format ( " [%q]= " , k )
471 fastserialize ( v )
472 else
473 r [ m ] = format ( " [%q]=%q, " , k , v )
474 end
475 end
476 end
477 m = m + 1
478 if outer then
479 r [ m ] = " } "
480 else
481 r [ m ] = " }, "
482 end
483 return r
484 end
485 return concat ( fastserialize ( t , true ) )
486 end
487
488end
489
490function table . deserialize ( str )
491 if not str or str = = " " then
492 return
493 end
494 local code = load ( str )
495 if not code then
496 return
497 end
498 code = code ( )
499 if not code then
500 return
501 end
502 return code
503end
504
505
506
507function table . load ( filename , loader )
508 if filename then
509 local t = ( loader or io . loaddata ) ( filename )
510 if t and t ~ = " " then
511 local t = utftoeight ( t )
512 t = load ( t )
513 if type ( t ) = = " function " then
514 t = t ( )
515 if type ( t ) = = " table " then
516 return t
517 end
518 end
519 end
520 end
521end
522
523function table . save ( filename , t , n , ... )
524 io . savedata ( filename , table . serialize ( t , n = = nil and true or n , ... ) )
525end
526
527local f_key_value = formatters [ " %s=%q " ]
528local f_add_table = formatters [ " {%t},\n " ]
529local f_return_table = formatters [ " return {\n%t} " ]
530
531local function slowdrop ( t )
532 local r = { }
533 local l = { }
534 for i = 1 , # t do
535 local ti = t [ i ]
536 local j = 0
537 for k , v in next , ti do
538 j = j + 1
539 l [ j ] = f_key_value ( k , v )
540 end
541 r [ i ] = f_add_table ( l )
542 end
543 return f_return_table ( r )
544end
545
546local function fastdrop ( t )
547 local r = { " return {\n " }
548 local m = 1
549 for i = 1 , # t do
550 local ti = t [ i ]
551 m = m + 1 r [ m ] = " { "
552 for k , v in next , ti do
553 m = m + 1 r [ m ] = f_key_value ( k , v )
554 end
555 m = m + 1 r [ m ] = " },\n "
556 end
557 m = m + 1
558 r [ m ] = " } "
559 return concat ( r )
560end
561
562function table . drop ( t , slow )
563 if # t = = 0 then
564 return " return { } "
565 elseif slow = = true then
566 return slowdrop ( t )
567 else
568 return fastdrop ( t )
569 end
570end
571
572
573
574
575
576
577
578
579
580
581local selfmapper = { __index = function ( t , k ) t [ k ] = k return k end }
582
583function table . twowaymapper ( t )
584 if not t then
585 t = { }
586 else
587 local zero = rawget ( t , 0 )
588 for i = zero and 0 or 1 , # t do
589 local ti = t [ i ]
590 if ti then
591 local i = tostring ( i )
592 t [ i ] = ti
593 t [ ti ] = i
594 end
595 end
596 end
597
598 setmetatable ( t , selfmapper )
599 return t
600end
601
602
603
604
605
606
607
608
609
610local f_start_key_idx = formatters [ " %w{ " ]
611local f_start_key_num = JITSUPPORTED and formatters [ " %w[%s]={ " ] or formatters [ " %w[%q]={ " ]
612local f_start_key_str = formatters [ " %w[%q]={ " ]
613local f_start_key_boo = formatters [ " %w[%l]={ " ]
614local f_start_key_nop = formatters [ " %w{ " ]
615
616local f_stop = formatters [ " %w}, " ]
617
618local f_key_num_value_num = JITSUPPORTED and formatters [ " %w[%s]=%s, " ] or formatters [ " %w[%s]=%q, " ]
619local f_key_str_value_num = JITSUPPORTED and formatters [ " %w[%Q]=%s, " ] or formatters [ " %w[%Q]=%q, " ]
620local f_key_boo_value_num = JITSUPPORTED and formatters [ " %w[%l]=%s, " ] or formatters [ " %w[%l]=%q, " ]
621
622local f_key_num_value_str = JITSUPPORTED and formatters [ " %w[%s]=%Q, " ] or formatters [ " %w[%q]=%Q, " ]
623local f_key_str_value_str = formatters [ " %w[%Q]=%Q, " ]
624local f_key_boo_value_str = formatters [ " %w[%l]=%Q, " ]
625
626local f_key_num_value_boo = JITSUPPORTED and formatters [ " %w[%s]=%l, " ] or formatters [ " %w[%q]=%l, " ]
627local f_key_str_value_boo = formatters [ " %w[%Q]=%l, " ]
628local f_key_boo_value_boo = formatters [ " %w[%l]=%l, " ]
629
630local f_key_num_value_not = JITSUPPORTED and formatters [ " %w[%s]={}, " ] or formatters [ " %w[%q]={}, " ]
631local f_key_str_value_not = formatters [ " %w[%Q]={}, " ]
632local f_key_boo_value_not = formatters [ " %w[%l]={}, " ]
633
634local f_key_num_value_seq = JITSUPPORTED and formatters [ " %w[%s]={ %, t }, " ] or formatters [ " %w[%q]={ %, t }, " ]
635local f_key_str_value_seq = formatters [ " %w[%Q]={ %, t }, " ]
636local f_key_boo_value_seq = formatters [ " %w[%l]={ %, t }, " ]
637
638local f_val_num = JITSUPPORTED and formatters [ " %w%s, " ] or formatters [ " %w%q, " ]
639local f_val_str = formatters [ " %w%Q, " ]
640local f_val_boo = formatters [ " %w%l, " ]
641local f_val_not = formatters [ " %w{}, " ]
642local f_val_seq = formatters [ " %w{ %, t }, " ]
643local f_fin_seq = formatters [ " %, t } " ]
644
645local f_table_return = formatters [ " return { " ]
646local f_table_name = formatters [ " %s={ " ]
647local f_table_direct = formatters [ " { " ]
648local f_table_entry = formatters [ " [%Q]={ " ]
649local f_table_finish = formatters [ " } " ]
650
651local spaces = utilities . strings . newrepeater ( " " )
652
653local original_serialize = table . serialize
654
655
656
657
658
659local is_simple_table = table . is_simple_table
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715local function serialize ( root , name , specification )
716
717 if type ( specification ) = = " table " then
718 return original_serialize ( root , name , specification )
719 end
720
721 local t
722 local n = 1
723 local unknown = false
724
725 local function do_serialize ( root , name , depth , level , indexed )
726 if level > 0 then
727 n = n + 1
728 if indexed then
729 t [ n ] = f_start_key_idx ( depth )
730 else
731 local tn = type ( name )
732 if tn = = " number " then
733 t [ n ] = f_start_key_num ( depth , name )
734 elseif tn = = " string " then
735 t [ n ] = f_start_key_str ( depth , name )
736 elseif tn = = " boolean " then
737 t [ n ] = f_start_key_boo ( depth , name )
738 else
739 t [ n ] = f_start_key_nop ( depth )
740 end
741 end
742 depth = depth + 1
743 end
744
745 if root and next ( root ) ~ = nil then
746 local first = nil
747 local last = # root
748 if last > 0 then
749 for k = 1 , last do
750 if rawget ( root , k ) = = nil then
751
752 last = k - 1
753 break
754 end
755 end
756 if last > 0 then
757 first = 1
758 end
759 end
760 local sk = sortedkeys ( root )
761 for i = 1 , # sk do
762 local k = sk [ i ]
763 local v = root [ k ]
764 local tv = type ( v )
765 local tk = type ( k )
766 if first and tk = = " number " and k < = last and k > = first then
767 if tv = = " number " then
768 n = n + 1 t [ n ] = f_val_num ( depth , v )
769 elseif tv = = " string " then
770 n = n + 1 t [ n ] = f_val_str ( depth , v )
771 elseif tv = = " table " then
772 if next ( v ) = = nil then
773 n = n + 1 t [ n ] = f_val_not ( depth )
774 else
775 local st = is_simple_table ( v )
776 if st then
777 n = n + 1 t [ n ] = f_val_seq ( depth , st )
778 else
779 do_serialize ( v , k , depth , level + 1 , true )
780 end
781 end
782 elseif tv = = " boolean " then
783 n = n + 1 t [ n ] = f_val_boo ( depth , v )
784 elseif unknown then
785 n = n + 1 t [ n ] = f_val_str ( depth , tostring ( v ) )
786 end
787 elseif tv = = " number " then
788 if tk = = " number " then
789 n = n + 1 t [ n ] = f_key_num_value_num ( depth , k , v )
790 elseif tk = = " string " then
791 n = n + 1 t [ n ] = f_key_str_value_num ( depth , k , v )
792 elseif tk = = " boolean " then
793 n = n + 1 t [ n ] = f_key_boo_value_num ( depth , k , v )
794 elseif unknown then
795 n = n + 1 t [ n ] = f_key_str_value_num ( depth , tostring ( k ) , v )
796 end
797 elseif tv = = " string " then
798 if tk = = " number " then
799 n = n + 1 t [ n ] = f_key_num_value_str ( depth , k , v )
800 elseif tk = = " string " then
801 n = n + 1 t [ n ] = f_key_str_value_str ( depth , k , v )
802 elseif tk = = " boolean " then
803 n = n + 1 t [ n ] = f_key_boo_value_str ( depth , k , v )
804 elseif unknown then
805 n = n + 1 t [ n ] = f_key_str_value_str ( depth , tostring ( k ) , v )
806 end
807 elseif tv = = " table " then
808 if next ( v ) = = nil then
809 if tk = = " number " then
810 n = n + 1 t [ n ] = f_key_num_value_not ( depth , k )
811 elseif tk = = " string " then
812 n = n + 1 t [ n ] = f_key_str_value_not ( depth , k )
813 elseif tk = = " boolean " then
814 n = n + 1 t [ n ] = f_key_boo_value_not ( depth , k )
815 elseif unknown then
816 n = n + 1 t [ n ] = f_key_str_value_not ( depth , tostring ( k ) )
817 end
818 else
819 local st = is_simple_table ( v )
820 if not st then
821 do_serialize ( v , k , depth , level + 1 )
822 elseif tk = = " number " then
823 n = n + 1 t [ n ] = f_key_num_value_seq ( depth , k , st )
824 elseif tk = = " string " then
825 n = n + 1 t [ n ] = f_key_str_value_seq ( depth , k , st )
826 elseif tk = = " boolean " then
827 n = n + 1 t [ n ] = f_key_boo_value_seq ( depth , k , st )
828 elseif unknown then
829 n = n + 1 t [ n ] = f_key_str_value_seq ( depth , tostring ( k ) , st )
830 end
831 end
832 elseif tv = = " boolean " then
833 if tk = = " number " then
834 n = n + 1 t [ n ] = f_key_num_value_boo ( depth , k , v )
835 elseif tk = = " string " then
836 n = n + 1 t [ n ] = f_key_str_value_boo ( depth , k , v )
837 elseif tk = = " boolean " then
838 n = n + 1 t [ n ] = f_key_boo_value_boo ( depth , k , v )
839 elseif unknown then
840 n = n + 1 t [ n ] = f_key_str_value_boo ( depth , tostring ( k ) , v )
841 end
842 else
843 if tk = = " number " then
844 n = n + 1 t [ n ] = f_key_num_value_str ( depth , k , tostring ( v ) )
845 elseif tk = = " string " then
846 n = n + 1 t [ n ] = f_key_str_value_str ( depth , k , tostring ( v ) )
847 elseif tk = = " boolean " then
848 n = n + 1 t [ n ] = f_key_boo_value_str ( depth , k , tostring ( v ) )
849 elseif unknown then
850 n = n + 1 t [ n ] = f_key_str_value_str ( depth , tostring ( k ) , tostring ( v ) )
851 end
852 end
853 end
854 end
855 if level > 0 then
856 n = n + 1 t [ n ] = f_stop ( depth -1 )
857 end
858 end
859
860 local tname = type ( name )
861
862 if tname = = " string " then
863 if name = = " return " then
864 t = { f_table_return ( ) }
865 else
866 t = { f_table_name ( name ) }
867 end
868 elseif tname = = " number " then
869 t = { f_table_entry ( name ) }
870 elseif tname = = " boolean " then
871 if name then
872 t = { f_table_return ( ) }
873 else
874 t = { f_table_direct ( ) }
875 end
876 else
877 t = { f_table_name ( " t " ) }
878 end
879
880 if root then
881
882
883
884 if getmetatable ( root ) then
885 local dummy = root . _w_h_a_t_e_v_e_r_
886 root . _w_h_a_t_e_v_e_r_ = nil
887 end
888
889 if next ( root ) ~ = nil then
890 local st = is_simple_table ( root )
891 if st then
892 return t [ 1 ] . . f_fin_seq ( st )
893 else
894 do_serialize ( root , name , 1 , 0 )
895 end
896 end
897 end
898 n = n + 1
899 t [ n ] = f_table_finish ( )
900 return concat ( t , " \n " )
901end
902
903table . serialize = serialize
904
905if setinspector then
906 setinspector ( " table " , function ( v )
907 if type ( v ) = = " table " then
908 print ( serialize ( v , " table " , { metacheck = false } ) )
909 return true
910 end
911 end )
912end
913
914
915
916
917
918
919
920
921
922
923
924
925
926local mt = {
927 __newindex = function ( t , k , v )
928 local n = t . last + 1
929 t . last = n
930 t . list [ n ] = k
931 t . hash [ k ] = v
932 end ,
933 __index = function ( t , k )
934 return t . hash [ k ]
935 end ,
936 __len = function ( t )
937 return t . last
938 end ,
939}
940
941function table . orderedhash ( )
942 return setmetatable ( { list = { } , hash = { } , last = 0 } , mt )
943end
944
945function table . ordered ( t )
946 local n = t . last
947 if n > 0 then
948 local l = t . list
949 local i = 1
950 local h = t . hash
951 local f = function ( )
952 if i < = n then
953 local k = i
954 local v = h [ l [ k ] ]
955 i = i + 1
956 return k , v
957 end
958 end
959 return f , 1 , h [ l [ 1 ] ]
960 else
961 return function ( ) end
962 end
963end
964
965
966
967
968
969
970
971
972
973 |