commit 5e2d537
shrub
·
2026-08-03 18:50:13 +0000 UTC
parent 4fc8077
texture things
15 files changed,
+5301,
-137
+2,
-2
1@@ -6,14 +6,14 @@ BraceWrapping:
2 AfterControlStatement: Never
3 AfterFunction: true
4 BeforeElse: false
5-ColumnLimit: 100
6+ColumnLimit: 120
7 Cpp11BracedListStyle: false
8 AllowAllParametersOfDeclarationOnNextLine: false
9 AllowShortIfStatementsOnASingleLine: Never
10 AllowShortLoopsOnASingleLine: false
11 BinPackParameters: true
12 IndentCaseLabels: false
13-IndentPPDirectives: None
14+IndentPPDirectives: BeforeHash
15 IndentWidth: 8
16 PenaltyReturnTypeOnItsOwnLine: 1000
17 PointerAlignment: Left
+1190,
-0
1@@ -0,0 +1,1190 @@
2+[
3+ {
4+ "name": "air",
5+ "blockState": "air",
6+ "model": null,
7+ "texture": null
8+ },
9+ {
10+ "name": "stone",
11+ "blockState": "stone",
12+ "model": "stone",
13+ "texture": "blocks/stone"
14+ },
15+ {
16+ "name": "grass",
17+ "blockState": "grass",
18+ "model": "grass_normal",
19+ "texture": "blocks/dirt"
20+ },
21+ {
22+ "name": "dirt",
23+ "blockState": "dirt",
24+ "model": "dirt",
25+ "texture": "blocks/dirt"
26+ },
27+ {
28+ "name": "cobblestone",
29+ "blockState": "cobblestone",
30+ "model": "cobblestone",
31+ "texture": "blocks/cobblestone"
32+ },
33+ {
34+ "name": "planks",
35+ "blockState": "oak_planks",
36+ "model": "oak_planks",
37+ "texture": "blocks/planks_oak"
38+ },
39+ {
40+ "name": "sapling",
41+ "blockState": "oak_sapling",
42+ "model": "oak_sapling",
43+ "texture": "blocks/sapling_oak"
44+ },
45+ {
46+ "name": "bedrock",
47+ "blockState": "bedrock",
48+ "model": "bedrock",
49+ "texture": "blocks/bedrock"
50+ },
51+ {
52+ "name": "flowing_water",
53+ "blockState": "flowing_water",
54+ "model": null,
55+ "texture": "blocks/water_flow"
56+ },
57+ {
58+ "name": "water",
59+ "blockState": "water",
60+ "model": null,
61+ "texture": "blocks/water_still"
62+ },
63+ {
64+ "name": "flowing_lava",
65+ "blockState": "flowing_lava",
66+ "model": null,
67+ "texture": "blocks/lava_flow"
68+ },
69+ {
70+ "name": "lava",
71+ "blockState": "lava",
72+ "model": null,
73+ "texture": "blocks/lava_still"
74+ },
75+ {
76+ "name": "sand",
77+ "blockState": "sand",
78+ "model": "sand",
79+ "texture": "blocks/sand"
80+ },
81+ {
82+ "name": "gravel",
83+ "blockState": "gravel",
84+ "model": "gravel",
85+ "texture": "blocks/gravel"
86+ },
87+ {
88+ "name": "gold_ore",
89+ "blockState": "gold_ore",
90+ "model": "gold_ore",
91+ "texture": "blocks/gold_ore"
92+ },
93+ {
94+ "name": "iron_ore",
95+ "blockState": "iron_ore",
96+ "model": "iron_ore",
97+ "texture": "blocks/iron_ore"
98+ },
99+ {
100+ "name": "coal_ore",
101+ "blockState": "coal_ore",
102+ "model": "coal_ore",
103+ "texture": "blocks/coal_ore"
104+ },
105+ {
106+ "name": "log",
107+ "blockState": "oak_log",
108+ "model": "oak_log",
109+ "texture": "blocks/log_oak_top"
110+ },
111+ {
112+ "name": "leaves",
113+ "blockState": "oak_leaves",
114+ "model": "oak_leaves",
115+ "texture": "blocks/leaves_oak"
116+ },
117+ {
118+ "name": "sponge",
119+ "blockState": "sponge",
120+ "model": "sponge",
121+ "texture": "blocks/sponge"
122+ },
123+ {
124+ "name": "glass",
125+ "blockState": "glass",
126+ "model": "glass",
127+ "texture": "blocks/glass"
128+ },
129+ {
130+ "name": "lapis_ore",
131+ "blockState": "lapis_ore",
132+ "model": "lapis_ore",
133+ "texture": "blocks/lapis_ore"
134+ },
135+ {
136+ "name": "lapis_block",
137+ "blockState": "lapis_block",
138+ "model": "lapis_block",
139+ "texture": "blocks/lapis_block"
140+ },
141+ {
142+ "name": "dispenser",
143+ "blockState": "dispenser",
144+ "model": "dispenser_vertical",
145+ "texture": "blocks/dispenser_front_vertical"
146+ },
147+ {
148+ "name": "sandstone",
149+ "blockState": "sandstone",
150+ "model": "sandstone_normal",
151+ "texture": "blocks/sandstone_bottom"
152+ },
153+ {
154+ "name": "noteblock",
155+ "blockState": "noteblock",
156+ "model": "noteblock",
157+ "texture": "blocks/noteblock"
158+ },
159+ {
160+ "name": "bed",
161+ "blockState": "bed",
162+ "model": "bed_foot",
163+ "texture": "blocks/bed_feet_top"
164+ },
165+ {
166+ "name": "golden_rail",
167+ "blockState": "golden_rail",
168+ "model": "golden_rail_flat",
169+ "texture": "blocks/rail_golden"
170+ },
171+ {
172+ "name": "detector_rail",
173+ "blockState": "detector_rail",
174+ "model": "detector_rail_flat",
175+ "texture": "blocks/rail_detector"
176+ },
177+ {
178+ "name": "sticky_piston",
179+ "blockState": "sticky_piston",
180+ "model": "sticky_piston",
181+ "texture": "blocks/piston_bottom"
182+ },
183+ {
184+ "name": "web",
185+ "blockState": "web",
186+ "model": "web",
187+ "texture": "blocks/web"
188+ },
189+ {
190+ "name": "tallgrass",
191+ "blockState": "tall_grass",
192+ "model": "tall_grass",
193+ "texture": "blocks/tallgrass"
194+ },
195+ {
196+ "name": "deadbush",
197+ "blockState": "dead_bush",
198+ "model": "dead_bush",
199+ "texture": "blocks/deadbush"
200+ },
201+ {
202+ "name": "piston",
203+ "blockState": "piston",
204+ "model": "piston_normal",
205+ "texture": "blocks/piston_bottom"
206+ },
207+ {
208+ "name": "piston_head",
209+ "blockState": "piston_head",
210+ "model": "piston_head_normal",
211+ "texture": "blocks/piston_top_normal"
212+ },
213+ {
214+ "name": "wool",
215+ "blockState": "white_wool",
216+ "model": "white_wool",
217+ "texture": "blocks/wool_colored_white"
218+ },
219+ {
220+ "name": "piston_extension",
221+ "blockState": "piston",
222+ "model": "piston_normal",
223+ "texture": "blocks/piston_bottom"
224+ },
225+ {
226+ "name": "yellow_flower",
227+ "blockState": "dandelion",
228+ "model": "dandelion",
229+ "texture": "blocks/flower_dandelion"
230+ },
231+ {
232+ "name": "red_flower",
233+ "blockState": "poppy",
234+ "model": "poppy",
235+ "texture": "blocks/flower_rose"
236+ },
237+ {
238+ "name": "brown_mushroom",
239+ "blockState": "brown_mushroom",
240+ "model": "brown_mushroom",
241+ "texture": "blocks/mushroom_brown"
242+ },
243+ {
244+ "name": "red_mushroom",
245+ "blockState": "red_mushroom",
246+ "model": "red_mushroom",
247+ "texture": "blocks/mushroom_red"
248+ },
249+ {
250+ "name": "gold_block",
251+ "blockState": "gold_block",
252+ "model": "gold_block",
253+ "texture": "blocks/gold_block"
254+ },
255+ {
256+ "name": "iron_block",
257+ "blockState": "iron_block",
258+ "model": "iron_block",
259+ "texture": "blocks/iron_block"
260+ },
261+ {
262+ "name": "double_stone_slab",
263+ "blockState": "stone_double_slab",
264+ "model": "double_stone",
265+ "texture": "blocks/stone_slab_top"
266+ },
267+ {
268+ "name": "stone_slab",
269+ "blockState": "stone_slab",
270+ "model": "half_slab_stone",
271+ "texture": "blocks/stone_slab_top"
272+ },
273+ {
274+ "name": "brick_block",
275+ "blockState": "brick_block",
276+ "model": "brick",
277+ "texture": "blocks/brick"
278+ },
279+ {
280+ "name": "tnt",
281+ "blockState": "tnt",
282+ "model": "tnt",
283+ "texture": "blocks/tnt_bottom"
284+ },
285+ {
286+ "name": "bookshelf",
287+ "blockState": "bookshelf",
288+ "model": "bookshelf",
289+ "texture": "blocks/planks_oak"
290+ },
291+ {
292+ "name": "mossy_cobblestone",
293+ "blockState": "mossy_cobblestone",
294+ "model": "mossy_cobblestone",
295+ "texture": "blocks/cobblestone_mossy"
296+ },
297+ {
298+ "name": "obsidian",
299+ "blockState": "obsidian",
300+ "model": "obsidian",
301+ "texture": "blocks/obsidian"
302+ },
303+ {
304+ "name": "torch",
305+ "blockState": "torch",
306+ "model": "normal_torch",
307+ "texture": "blocks/torch_on"
308+ },
309+ {
310+ "name": "fire",
311+ "blockState": "fire",
312+ "model": "fire_floor_main",
313+ "texture": "blocks/fire_layer_0"
314+ },
315+ {
316+ "name": "mob_spawner",
317+ "blockState": "mob_spawner",
318+ "model": "mob_spawner_cage",
319+ "texture": "blocks/mob_spawner"
320+ },
321+ {
322+ "name": "oak_stairs",
323+ "blockState": "oak_stairs",
324+ "model": "oak_stairs",
325+ "texture": "blocks/planks_oak"
326+ },
327+ {
328+ "name": "chest",
329+ "blockState": "chest",
330+ "model": null,
331+ "texture": null
332+ },
333+ {
334+ "name": "redstone_wire",
335+ "blockState": "redstone_wire",
336+ "model": "redstone_none",
337+ "texture": "blocks/redstone_dust_cross"
338+ },
339+ {
340+ "name": "diamond_ore",
341+ "blockState": "diamond_ore",
342+ "model": "diamond_ore",
343+ "texture": "blocks/diamond_ore"
344+ },
345+ {
346+ "name": "diamond_block",
347+ "blockState": "diamond_block",
348+ "model": "diamond_block",
349+ "texture": "blocks/diamond_block"
350+ },
351+ {
352+ "name": "crafting_table",
353+ "blockState": "crafting_table",
354+ "model": "crafting_table",
355+ "texture": "blocks/crafting_table_front"
356+ },
357+ {
358+ "name": "wheat",
359+ "blockState": "wheat",
360+ "model": "wheat_stage0",
361+ "texture": "blocks/wheat_stage_0"
362+ },
363+ {
364+ "name": "farmland",
365+ "blockState": "farmland",
366+ "model": "farmland_dry",
367+ "texture": "blocks/dirt"
368+ },
369+ {
370+ "name": "furnace",
371+ "blockState": "furnace",
372+ "model": "furnace",
373+ "texture": "blocks/furnace_top"
374+ },
375+ {
376+ "name": "lit_furnace",
377+ "blockState": "lit_furnace",
378+ "model": "lit_furnace",
379+ "texture": "blocks/furnace_top"
380+ },
381+ {
382+ "name": "standing_sign",
383+ "blockState": "standing_sign",
384+ "model": null,
385+ "texture": null
386+ },
387+ {
388+ "name": "wooden_door",
389+ "blockState": "wooden_door",
390+ "model": "wooden_door_bottom",
391+ "texture": "blocks/door_wood_lower"
392+ },
393+ {
394+ "name": "ladder",
395+ "blockState": "ladder",
396+ "model": "ladder",
397+ "texture": "blocks/ladder"
398+ },
399+ {
400+ "name": "rail",
401+ "blockState": "rail",
402+ "model": "normal_rail_flat",
403+ "texture": "blocks/rail_normal"
404+ },
405+ {
406+ "name": "stone_stairs",
407+ "blockState": "stone_stairs",
408+ "model": "stone_stairs",
409+ "texture": "blocks/cobblestone"
410+ },
411+ {
412+ "name": "wall_sign",
413+ "blockState": "wall_sign",
414+ "model": null,
415+ "texture": null
416+ },
417+ {
418+ "name": "lever",
419+ "blockState": "lever",
420+ "model": "lever_off",
421+ "texture": "blocks/cobblestone"
422+ },
423+ {
424+ "name": "stone_pressure_plate",
425+ "blockState": "stone_pressure_plate",
426+ "model": "stone_pressure_plate_up",
427+ "texture": "blocks/stone"
428+ },
429+ {
430+ "name": "iron_door",
431+ "blockState": "iron_door",
432+ "model": "iron_door_bottom",
433+ "texture": "blocks/door_iron_lower"
434+ },
435+ {
436+ "name": "wooden_pressure_plate",
437+ "blockState": "wooden_pressure_plate",
438+ "model": "wooden_pressure_plate_up",
439+ "texture": "blocks/planks_oak"
440+ },
441+ {
442+ "name": "redstone_ore",
443+ "blockState": "redstone_ore",
444+ "model": "redstone_ore",
445+ "texture": "blocks/redstone_ore"
446+ },
447+ {
448+ "name": "lit_redstone_ore",
449+ "blockState": "lit_redstone_ore",
450+ "model": "lit_redstone_ore",
451+ "texture": "blocks/redstone_ore"
452+ },
453+ {
454+ "name": "unlit_redstone_torch",
455+ "blockState": "unlit_redstone_torch",
456+ "model": "unlit_redstone_torch",
457+ "texture": "blocks/redstone_torch_off"
458+ },
459+ {
460+ "name": "redstone_torch",
461+ "blockState": "redstone_torch",
462+ "model": "lit_redstone_torch",
463+ "texture": "blocks/redstone_torch_on"
464+ },
465+ {
466+ "name": "stone_button",
467+ "blockState": "stone_button",
468+ "model": "stone_button",
469+ "texture": "blocks/stone"
470+ },
471+ {
472+ "name": "snow_layer",
473+ "blockState": "snow_layer",
474+ "model": "snow_height2",
475+ "texture": "blocks/snow"
476+ },
477+ {
478+ "name": "ice",
479+ "blockState": "ice",
480+ "model": "ice",
481+ "texture": "blocks/ice"
482+ },
483+ {
484+ "name": "snow",
485+ "blockState": "snow",
486+ "model": "snow",
487+ "texture": "blocks/snow"
488+ },
489+ {
490+ "name": "cactus",
491+ "blockState": "cactus",
492+ "model": "cactus",
493+ "texture": "blocks/cactus_side"
494+ },
495+ {
496+ "name": "clay",
497+ "blockState": "clay",
498+ "model": "clay",
499+ "texture": "blocks/clay"
500+ },
501+ {
502+ "name": "reeds",
503+ "blockState": "reeds",
504+ "model": "reeds",
505+ "texture": "blocks/reeds"
506+ },
507+ {
508+ "name": "jukebox",
509+ "blockState": "jukebox",
510+ "model": "jukebox",
511+ "texture": "blocks/jukebox_top"
512+ },
513+ {
514+ "name": "fence",
515+ "blockState": "fence",
516+ "model": "oak_fence_post",
517+ "texture": "blocks/planks_oak"
518+ },
519+ {
520+ "name": "pumpkin",
521+ "blockState": "pumpkin",
522+ "model": "pumpkin",
523+ "texture": "blocks/pumpkin_top"
524+ },
525+ {
526+ "name": "netherrack",
527+ "blockState": "netherrack",
528+ "model": "netherrack",
529+ "texture": "blocks/netherrack"
530+ },
531+ {
532+ "name": "soul_sand",
533+ "blockState": "soul_sand",
534+ "model": "soul_sand",
535+ "texture": "blocks/soul_sand"
536+ },
537+ {
538+ "name": "glowstone",
539+ "blockState": "glowstone",
540+ "model": "glowstone",
541+ "texture": "blocks/glowstone"
542+ },
543+ {
544+ "name": "portal",
545+ "blockState": "portal",
546+ "model": "portal_ew",
547+ "texture": "blocks/portal"
548+ },
549+ {
550+ "name": "lit_pumpkin",
551+ "blockState": "lit_pumpkin",
552+ "model": "lit_pumpkin",
553+ "texture": "blocks/pumpkin_top"
554+ },
555+ {
556+ "name": "cake",
557+ "blockState": "cake",
558+ "model": "cake_uneaten",
559+ "texture": "blocks/cake_side"
560+ },
561+ {
562+ "name": "unpowered_repeater",
563+ "blockState": "unpowered_repeater",
564+ "model": "repeater_1tick",
565+ "texture": "blocks/repeater_off"
566+ },
567+ {
568+ "name": "powered_repeater",
569+ "blockState": "powered_repeater",
570+ "model": "repeater_on_1tick",
571+ "texture": "blocks/repeater_on"
572+ },
573+ {
574+ "name": "stained_glass",
575+ "blockState": "white_stained_glass",
576+ "model": "glass_white",
577+ "texture": "blocks/glass_white"
578+ },
579+ {
580+ "name": "trapdoor",
581+ "blockState": "trapdoor",
582+ "model": "wooden_trapdoor_bottom",
583+ "texture": "blocks/trapdoor"
584+ },
585+ {
586+ "name": "monster_egg",
587+ "blockState": "monster_egg",
588+ "model": null,
589+ "texture": null
590+ },
591+ {
592+ "name": "stonebrick",
593+ "blockState": "stonebrick",
594+ "model": "stonebrick_normal",
595+ "texture": "blocks/stonebrick"
596+ },
597+ {
598+ "name": "brown_mushroom_block",
599+ "blockState": "brown_mushroom_block",
600+ "model": "brown_mushroom_block_nw",
601+ "texture": "blocks/mushroom_block_inside"
602+ },
603+ {
604+ "name": "red_mushroom_block",
605+ "blockState": "red_mushroom_block",
606+ "model": "red_mushroom_block_nw",
607+ "texture": "blocks/mushroom_block_inside"
608+ },
609+ {
610+ "name": "iron_bars",
611+ "blockState": "iron_bars",
612+ "model": "bars_nsew",
613+ "texture": "blocks/iron_bars"
614+ },
615+ {
616+ "name": "glass_pane",
617+ "blockState": "glass_pane",
618+ "model": "glass_pane_nsew",
619+ "texture": "blocks/glass_pane_top"
620+ },
621+ {
622+ "name": "melon_block",
623+ "blockState": "melon_block",
624+ "model": "melon",
625+ "texture": "blocks/melon_top"
626+ },
627+ {
628+ "name": "pumpkin_stem",
629+ "blockState": "pumpkin_stem",
630+ "model": "pumpkin_stem_growth0",
631+ "texture": "blocks/pumpkin_stem_disconnected"
632+ },
633+ {
634+ "name": "melon_stem",
635+ "blockState": "melon_stem",
636+ "model": "melon_stem_growth0",
637+ "texture": "blocks/melon_stem_disconnected"
638+ },
639+ {
640+ "name": "vine",
641+ "blockState": "vine",
642+ "model": "vine_1",
643+ "texture": "blocks/vine"
644+ },
645+ {
646+ "name": "fence_gate",
647+ "blockState": "fence_gate",
648+ "model": "oak_fence_gate_closed",
649+ "texture": "blocks/planks_oak"
650+ },
651+ {
652+ "name": "brick_stairs",
653+ "blockState": "brick_stairs",
654+ "model": "brick_stairs",
655+ "texture": "blocks/brick"
656+ },
657+ {
658+ "name": "stone_brick_stairs",
659+ "blockState": "stone_brick_stairs",
660+ "model": "stone_brick_stairs",
661+ "texture": "blocks/stonebrick"
662+ },
663+ {
664+ "name": "mycelium",
665+ "blockState": "mycelium",
666+ "model": "mycelium",
667+ "texture": "blocks/dirt"
668+ },
669+ {
670+ "name": "waterlily",
671+ "blockState": "waterlily",
672+ "model": "waterlily",
673+ "texture": "blocks/waterlily"
674+ },
675+ {
676+ "name": "nether_brick",
677+ "blockState": "nether_brick",
678+ "model": "nether_brick",
679+ "texture": "blocks/nether_brick"
680+ },
681+ {
682+ "name": "nether_brick_fence",
683+ "blockState": "nether_brick_fence",
684+ "model": "nether_brick_fence_post",
685+ "texture": "blocks/nether_brick"
686+ },
687+ {
688+ "name": "nether_brick_stairs",
689+ "blockState": "nether_brick_stairs",
690+ "model": "nether_brick_stairs",
691+ "texture": "blocks/nether_brick"
692+ },
693+ {
694+ "name": "nether_wart",
695+ "blockState": "nether_wart",
696+ "model": "nether_wart_stage0",
697+ "texture": "blocks/nether_wart_stage_0"
698+ },
699+ {
700+ "name": "enchanting_table",
701+ "blockState": "enchanting_table",
702+ "model": "enchanting_table_base",
703+ "texture": "blocks/enchanting_table_bottom"
704+ },
705+ {
706+ "name": "brewing_stand",
707+ "blockState": "brewing_stand",
708+ "model": "brewing_stand_empty",
709+ "texture": "blocks/brewing_stand"
710+ },
711+ {
712+ "name": "cauldron",
713+ "blockState": "cauldron",
714+ "model": "cauldron_empty",
715+ "texture": "blocks/cauldron_side"
716+ },
717+ {
718+ "name": "end_portal",
719+ "blockState": "end_portal",
720+ "model": null,
721+ "texture": null
722+ },
723+ {
724+ "name": "end_portal_frame",
725+ "blockState": "end_portal_frame",
726+ "model": "end_portal_frame_empty",
727+ "texture": "blocks/endframe_side"
728+ },
729+ {
730+ "name": "end_stone",
731+ "blockState": "end_stone",
732+ "model": "end_stone",
733+ "texture": "blocks/end_stone"
734+ },
735+ {
736+ "name": "dragon_egg",
737+ "blockState": "dragon_egg",
738+ "model": "dragon_egg",
739+ "texture": "blocks/dragon_egg"
740+ },
741+ {
742+ "name": "redstone_lamp",
743+ "blockState": "redstone_lamp",
744+ "model": "unlit_redstone_lamp",
745+ "texture": "blocks/redstone_lamp_off"
746+ },
747+ {
748+ "name": "lit_redstone_lamp",
749+ "blockState": "lit_redstone_lamp",
750+ "model": "lit_redstone_lamp",
751+ "texture": "blocks/redstone_lamp_on"
752+ },
753+ {
754+ "name": "double_wooden_slab",
755+ "blockState": "oak_double_slab",
756+ "model": "oak_planks",
757+ "texture": "blocks/planks_oak"
758+ },
759+ {
760+ "name": "wooden_slab",
761+ "blockState": "oak_slab",
762+ "model": "half_slab_oak",
763+ "texture": "blocks/planks_oak"
764+ },
765+ {
766+ "name": "cocoa",
767+ "blockState": "cocoa",
768+ "model": "cocoa_age0_s",
769+ "texture": "blocks/cocoa_stage_0"
770+ },
771+ {
772+ "name": "sandstone_stairs",
773+ "blockState": "sandstone_stairs",
774+ "model": "sandstone_stairs",
775+ "texture": "blocks/sandstone_bottom"
776+ },
777+ {
778+ "name": "emerald_ore",
779+ "blockState": "emerald_ore",
780+ "model": "emerald_ore",
781+ "texture": "blocks/emerald_ore"
782+ },
783+ {
784+ "name": "ender_chest",
785+ "blockState": "ender_chest",
786+ "model": null,
787+ "texture": null
788+ },
789+ {
790+ "name": "tripwire_hook",
791+ "blockState": "tripwire_hook",
792+ "model": "tripwire_hook",
793+ "texture": "blocks/planks_oak"
794+ },
795+ {
796+ "name": "tripwire",
797+ "blockState": "tripwire",
798+ "model": "tripwire_ns",
799+ "texture": "blocks/trip_wire"
800+ },
801+ {
802+ "name": "emerald_block",
803+ "blockState": "emerald_block",
804+ "model": "emerald_block",
805+ "texture": "blocks/emerald_block"
806+ },
807+ {
808+ "name": "spruce_stairs",
809+ "blockState": "spruce_stairs",
810+ "model": "spruce_stairs",
811+ "texture": "blocks/planks_spruce"
812+ },
813+ {
814+ "name": "birch_stairs",
815+ "blockState": "birch_stairs",
816+ "model": "birch_stairs",
817+ "texture": "blocks/planks_birch"
818+ },
819+ {
820+ "name": "jungle_stairs",
821+ "blockState": "jungle_stairs",
822+ "model": "jungle_stairs",
823+ "texture": "blocks/planks_jungle"
824+ },
825+ {
826+ "name": "command_block",
827+ "blockState": "command_block",
828+ "model": "command_block",
829+ "texture": "blocks/command_block"
830+ },
831+ {
832+ "name": "beacon",
833+ "blockState": "beacon",
834+ "model": "beacon",
835+ "texture": "blocks/glass"
836+ },
837+ {
838+ "name": "cobblestone_wall",
839+ "blockState": "cobblestone_wall",
840+ "model": "cobblestone_wall_post",
841+ "texture": "blocks/cobblestone"
842+ },
843+ {
844+ "name": "flower_pot",
845+ "blockState": "flower_pot",
846+ "model": "flower_pot",
847+ "texture": "blocks/flower_pot"
848+ },
849+ {
850+ "name": "carrots",
851+ "blockState": "carrots",
852+ "model": "carrots_stage0",
853+ "texture": "blocks/carrots_stage_0"
854+ },
855+ {
856+ "name": "potatoes",
857+ "blockState": "potatoes",
858+ "model": "potatoes_stage0",
859+ "texture": "blocks/potatoes_stage_0"
860+ },
861+ {
862+ "name": "wooden_button",
863+ "blockState": "wooden_button",
864+ "model": "wooden_button",
865+ "texture": "blocks/planks_oak"
866+ },
867+ {
868+ "name": "skull",
869+ "blockState": "skull",
870+ "model": null,
871+ "texture": null
872+ },
873+ {
874+ "name": "anvil",
875+ "blockState": "anvil",
876+ "model": "anvil_undamaged",
877+ "texture": "blocks/anvil_base"
878+ },
879+ {
880+ "name": "trapped_chest",
881+ "blockState": "trapped_chest",
882+ "model": null,
883+ "texture": null
884+ },
885+ {
886+ "name": "light_weighted_pressure_plate",
887+ "blockState": "light_weighted_pressure_plate",
888+ "model": "light_pressure_plate_up",
889+ "texture": "blocks/gold_block"
890+ },
891+ {
892+ "name": "heavy_weighted_pressure_plate",
893+ "blockState": "heavy_weighted_pressure_plate",
894+ "model": "heavy_pressure_plate_up",
895+ "texture": "blocks/iron_block"
896+ },
897+ {
898+ "name": "unpowered_comparator",
899+ "blockState": "unpowered_comparator",
900+ "model": "comparator_unlit",
901+ "texture": "blocks/comparator_off"
902+ },
903+ {
904+ "name": "powered_comparator",
905+ "blockState": "powered_comparator",
906+ "model": "comparator_unlit",
907+ "texture": "blocks/comparator_off"
908+ },
909+ {
910+ "name": "daylight_detector",
911+ "blockState": "daylight_detector",
912+ "model": "daylight_detector",
913+ "texture": "blocks/daylight_detector_top"
914+ },
915+ {
916+ "name": "redstone_block",
917+ "blockState": "redstone_block",
918+ "model": "redstone_block",
919+ "texture": "blocks/redstone_block"
920+ },
921+ {
922+ "name": "quartz_ore",
923+ "blockState": "quartz_ore",
924+ "model": "quartz_ore",
925+ "texture": "blocks/quartz_ore"
926+ },
927+ {
928+ "name": "hopper",
929+ "blockState": "hopper",
930+ "model": "hopper_down",
931+ "texture": "blocks/hopper_outside"
932+ },
933+ {
934+ "name": "quartz_block",
935+ "blockState": "quartz_block",
936+ "model": "quartz_normal",
937+ "texture": "blocks/quartz_block_bottom"
938+ },
939+ {
940+ "name": "quartz_stairs",
941+ "blockState": "quartz_stairs",
942+ "model": "quartz_stairs",
943+ "texture": "blocks/quartz_block_bottom"
944+ },
945+ {
946+ "name": "activator_rail",
947+ "blockState": "activator_rail",
948+ "model": "activator_rail_flat",
949+ "texture": "blocks/rail_activator"
950+ },
951+ {
952+ "name": "dropper",
953+ "blockState": "dropper",
954+ "model": "dropper_vertical",
955+ "texture": "blocks/dropper_front_vertical"
956+ },
957+ {
958+ "name": "stained_hardened_clay",
959+ "blockState": "white_stained_hardened_clay",
960+ "model": "hardened_clay_white",
961+ "texture": "blocks/hardened_clay_stained_white"
962+ },
963+ {
964+ "name": "stained_glass_pane",
965+ "blockState": "white_stained_glass_pane",
966+ "model": "white_pane_nsew",
967+ "texture": "blocks/glass_pane_top_white"
968+ },
969+ {
970+ "name": "leaves2",
971+ "blockState": "acacia_leaves",
972+ "model": "acacia_leaves",
973+ "texture": "blocks/leaves_acacia"
974+ },
975+ {
976+ "name": "log2",
977+ "blockState": "acacia_log",
978+ "model": "acacia_log",
979+ "texture": "blocks/log_acacia_top"
980+ },
981+ {
982+ "name": "acacia_stairs",
983+ "blockState": "acacia_stairs",
984+ "model": "acacia_stairs",
985+ "texture": "blocks/planks_acacia"
986+ },
987+ {
988+ "name": "dark_oak_stairs",
989+ "blockState": "dark_oak_stairs",
990+ "model": "dark_oak_stairs",
991+ "texture": "blocks/planks_big_oak"
992+ },
993+ {
994+ "name": "slime",
995+ "blockState": "slime",
996+ "model": "slime",
997+ "texture": "blocks/slime"
998+ },
999+ {
1000+ "name": "barrier",
1001+ "blockState": "barrier",
1002+ "model": null,
1003+ "texture": null
1004+ },
1005+ {
1006+ "name": "iron_trapdoor",
1007+ "blockState": "iron_trapdoor",
1008+ "model": "iron_trapdoor_bottom",
1009+ "texture": "blocks/iron_trapdoor"
1010+ },
1011+ {
1012+ "name": "prismarine",
1013+ "blockState": "prismarine",
1014+ "model": "prismarine_rough",
1015+ "texture": "blocks/prismarine_rough"
1016+ },
1017+ {
1018+ "name": "sea_lantern",
1019+ "blockState": "sea_lantern",
1020+ "model": "sea_lantern",
1021+ "texture": "blocks/sea_lantern"
1022+ },
1023+ {
1024+ "name": "hay_block",
1025+ "blockState": "hay_block",
1026+ "model": "hay",
1027+ "texture": "blocks/hay_block_top"
1028+ },
1029+ {
1030+ "name": "carpet",
1031+ "blockState": "white_carpet",
1032+ "model": "carpet_white",
1033+ "texture": "blocks/wool_colored_white"
1034+ },
1035+ {
1036+ "name": "hardened_clay",
1037+ "blockState": "hardened_clay",
1038+ "model": "hardened_clay",
1039+ "texture": "blocks/hardened_clay"
1040+ },
1041+ {
1042+ "name": "coal_block",
1043+ "blockState": "coal_block",
1044+ "model": "coal_block",
1045+ "texture": "blocks/coal_block"
1046+ },
1047+ {
1048+ "name": "packed_ice",
1049+ "blockState": "packed_ice",
1050+ "model": "packed_ice",
1051+ "texture": "blocks/ice_packed"
1052+ },
1053+ {
1054+ "name": "double_plant",
1055+ "blockState": "sunflower",
1056+ "model": "double_sunflower_bottom",
1057+ "texture": "blocks/double_plant_sunflower_bottom"
1058+ },
1059+ {
1060+ "name": "standing_banner",
1061+ "blockState": "standing_banner",
1062+ "model": null,
1063+ "texture": null
1064+ },
1065+ {
1066+ "name": "wall_banner",
1067+ "blockState": "wall_banner",
1068+ "model": null,
1069+ "texture": null
1070+ },
1071+ {
1072+ "name": "daylight_detector_inverted",
1073+ "blockState": "daylight_detector_inverted",
1074+ "model": "daylight_detector_inverted",
1075+ "texture": "blocks/daylight_detector_inverted_top"
1076+ },
1077+ {
1078+ "name": "red_sandstone",
1079+ "blockState": "red_sandstone",
1080+ "model": "red_sandstone_normal",
1081+ "texture": "blocks/red_sandstone_bottom"
1082+ },
1083+ {
1084+ "name": "red_sandstone_stairs",
1085+ "blockState": "red_sandstone_stairs",
1086+ "model": "red_sandstone_stairs",
1087+ "texture": "blocks/red_sandstone_bottom"
1088+ },
1089+ {
1090+ "name": "double_stone_slab2",
1091+ "blockState": "red_sandstone_double_slab",
1092+ "model": "red_sandstone_normal",
1093+ "texture": "blocks/red_sandstone_bottom"
1094+ },
1095+ {
1096+ "name": "stone_slab2",
1097+ "blockState": "red_sandstone_slab",
1098+ "model": "half_slab_red_sandstone",
1099+ "texture": "blocks/red_sandstone_bottom"
1100+ },
1101+ {
1102+ "name": "spruce_fence_gate",
1103+ "blockState": "spruce_fence_gate",
1104+ "model": "spruce_fence_gate_closed",
1105+ "texture": "blocks/planks_spruce"
1106+ },
1107+ {
1108+ "name": "birch_fence_gate",
1109+ "blockState": "birch_fence_gate",
1110+ "model": "birch_fence_gate_closed",
1111+ "texture": "blocks/planks_birch"
1112+ },
1113+ {
1114+ "name": "jungle_fence_gate",
1115+ "blockState": "jungle_fence_gate",
1116+ "model": "jungle_fence_gate_closed",
1117+ "texture": "blocks/planks_jungle"
1118+ },
1119+ {
1120+ "name": "dark_oak_fence_gate",
1121+ "blockState": "dark_oak_fence_gate",
1122+ "model": "dark_oak_fence_gate_closed",
1123+ "texture": "blocks/planks_big_oak"
1124+ },
1125+ {
1126+ "name": "acacia_fence_gate",
1127+ "blockState": "acacia_fence_gate",
1128+ "model": "acacia_fence_gate_closed",
1129+ "texture": "blocks/planks_acacia"
1130+ },
1131+ {
1132+ "name": "spruce_fence",
1133+ "blockState": "spruce_fence",
1134+ "model": "spruce_fence_post",
1135+ "texture": "blocks/planks_spruce"
1136+ },
1137+ {
1138+ "name": "birch_fence",
1139+ "blockState": "birch_fence",
1140+ "model": "birch_fence_post",
1141+ "texture": "blocks/planks_birch"
1142+ },
1143+ {
1144+ "name": "jungle_fence",
1145+ "blockState": "jungle_fence",
1146+ "model": "jungle_fence_post",
1147+ "texture": "blocks/planks_jungle"
1148+ },
1149+ {
1150+ "name": "dark_oak_fence",
1151+ "blockState": "dark_oak_fence",
1152+ "model": "dark_oak_fence_post",
1153+ "texture": "blocks/planks_big_oak"
1154+ },
1155+ {
1156+ "name": "acacia_fence",
1157+ "blockState": "acacia_fence",
1158+ "model": "acacia_fence_post",
1159+ "texture": "blocks/planks_acacia"
1160+ },
1161+ {
1162+ "name": "spruce_door",
1163+ "blockState": "spruce_door",
1164+ "model": "spruce_door_bottom",
1165+ "texture": "blocks/door_spruce_lower"
1166+ },
1167+ {
1168+ "name": "birch_door",
1169+ "blockState": "birch_door",
1170+ "model": "birch_door_bottom",
1171+ "texture": "blocks/door_birch_lower"
1172+ },
1173+ {
1174+ "name": "jungle_door",
1175+ "blockState": "jungle_door",
1176+ "model": "jungle_door_bottom",
1177+ "texture": "blocks/door_jungle_lower"
1178+ },
1179+ {
1180+ "name": "acacia_door",
1181+ "blockState": "acacia_door",
1182+ "model": "acacia_door_bottom",
1183+ "texture": "blocks/door_acacia_lower"
1184+ },
1185+ {
1186+ "name": "dark_oak_door",
1187+ "blockState": "dark_oak_door",
1188+ "model": "dark_oak_door_bottom",
1189+ "texture": "blocks/door_dark_oak_lower"
1190+ }
1191+]
+2,
-0
1@@ -3,6 +3,7 @@
2
3 #define MG_KEYS_DOWN_MAX 64
4
5+/* clang-format off */
6 #ifdef MG_PLATFORM_SDL
7 #include <SDL2/SDL_keycode.h>
8 typedef SDL_Keycode MGKey;
9@@ -93,5 +94,6 @@ enum {
10
11 #else /* libmaus */
12 #endif
13+/* clang-format on */
14
15 #endif /* KEYS_H */
+2,
-0
1@@ -4,11 +4,13 @@
2 #include "types.h"
3 #include "platform/keys.h"
4
5+/* clang-format off */
6 #ifdef MG_PLATFORM_SDL
7 #include "platform/platform_sdl.h"
8 #elif MG_PLATFORM_MAUS
9 /* TODO */
10 #endif
11+/* clang-format on */
12
13 typedef struct {
14 MGWindow* win;
+14,
-33
1@@ -29,7 +29,6 @@ typedef struct {
2 u16 mask;
3 } BulkChunkMeta;
4
5-static MGTexture block_textures[BLOCK_LAST];
6 static MGCamera cam;
7 static Chunk chunks[WORLD_WIDTH][WORLD_DEPTH];
8
9@@ -141,8 +140,7 @@ i8 load_server_section(Chunk* section, const u8* data, size_t size)
10 z = (index >> 4) & 15;
11 y = (index >> 8) & 15;
12
13- if (state != 0)
14- chunk_set(section, x, y, z, BLOCK_BRICK);
15+ chunk_set(section, x, y, z, state);
16 }
17
18 if (!chunk_mesh_create(section)) {
19@@ -311,17 +309,8 @@ void test_scene_create(Player* player, i8 server)
20 i32 x;
21 i32 z;
22
23- block_textures[BLOCK_BRICK] = renderer_texture_load("assets/resourcepacks/default/blocks/bedrock.png");
24- if (block_textures[BLOCK_BRICK] == MGTEXTURE_INVALID)
25- mg_die(MG_ERR_TEXTURE_LOAD, "Failed to load brick texture");
26-
27- block_textures[BLOCK_DIRT] = renderer_texture_load("assets/resourcepacks/default/blocks/dirt.png");
28- if (block_textures[BLOCK_DIRT] == MGTEXTURE_INVALID)
29- mg_die(MG_ERR_TEXTURE_LOAD, "Failed to load dirt texture");
30-
31- block_textures[BLOCK_STONE] = renderer_texture_load("assets/resourcepacks/default/blocks/stone.png");
32- if (block_textures[BLOCK_STONE] == MGTEXTURE_INVALID)
33- mg_die(MG_ERR_TEXTURE_LOAD, "Failed to load stone texture");
34+ if (!block_textures_create("assets/resourcepacks/default"))
35+ mg_die(MG_ERR_TEXTURE_LOAD, "Failed to load block textures");
36
37 camera_init(&cam, MG_V3(8.0f, 38.0f, 24.0f));
38 cam.yaw = MG_AngleDeg(-180.0f);
39@@ -362,7 +351,7 @@ void test_scene_draw(MGContext* ctx)
40 i32 width;
41 i32 height;
42 float aspect;
43- BlockType block;
44+ i32 texture;
45
46 ServerChunk* column;
47 Chunk* section_chunk;
48@@ -391,19 +380,17 @@ void test_scene_draw(MGContext* ctx)
49 continue;
50
51 section_chunk = &column->sections[section];
52- if (section_chunk->meshes[BLOCK_BRICK] == MGMESH_INVALID)
53- continue;
54-
55 model = MG_Translate(MG_V3(
56 column->x * CHUNK_WIDTH,
57 section * CHUNK_HEIGHT,
58 column->z * CHUNK_DEPTH
59 ));
60 mvp = MG_MulM4(proj, MG_MulM4(view, model));
61- renderer_mesh_draw(
62- section_chunk ->meshes[BLOCK_BRICK],
63- block_textures[BLOCK_BRICK], &mvp
64- );
65+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
66+ if (section_chunk->meshes[texture] != MGMESH_INVALID)
67+ renderer_mesh_draw(section_chunk->meshes[texture],
68+ block_texture_get(texture), &mvp);
69+ }
70 }
71 }
72 }
73@@ -413,11 +400,11 @@ void test_scene_draw(MGContext* ctx)
74 model = MG_Translate(MG_V3(x * CHUNK_WIDTH, 0.0f, z * CHUNK_DEPTH));
75 mvp = MG_MulM4(proj, MG_MulM4(view, model));
76
77- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++) {
78- if (chunks[x][z].meshes[block] == MGMESH_INVALID)
79+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
80+ if (chunks[x][z].meshes[texture] == MGMESH_INVALID)
81 continue;
82- renderer_mesh_draw(chunks[x][z].meshes[block],
83- block_textures[block], &mvp);
84+ renderer_mesh_draw(chunks[x][z].meshes[texture],
85+ block_texture_get(texture), &mvp);
86 }
87 }
88 }
89@@ -448,13 +435,7 @@ void test_scene_destroy(void)
90 }
91 }
92
93- renderer_texture_destroy(block_textures[BLOCK_BRICK]);
94- renderer_texture_destroy(block_textures[BLOCK_DIRT]);
95- renderer_texture_destroy(block_textures[BLOCK_STONE]);
96-
97- block_textures[BLOCK_BRICK] = MGTEXTURE_INVALID;
98- block_textures[BLOCK_DIRT] = MGTEXTURE_INVALID;
99- block_textures[BLOCK_STONE] = MGTEXTURE_INVALID;
100+ block_textures_destroy();
101 }
102
103 #endif /* TEST_SCENE_H */
+24,
-8
1@@ -1,13 +1,29 @@
2 #ifndef WORLD_BLOCK_H
3 #define WORLD_BLOCK_H
4
5-typedef enum {
6- BLOCK_AIR,
7- BLOCK_BRICK,
8- BLOCK_DIRT,
9- BLOCK_STONE,
10-
11- BLOCK_LAST
12-} BlockType;
13+#include "types.h"
14+#include "renderer/renderer.h"
15+
16+typedef u16 BlockType;
17+
18+#define BLOCK_AIR ((BlockType)0)
19+#define BLOCK_STONE ((BlockType)(1 << 4))
20+#define BLOCK_DIRT ((BlockType)(3 << 4))
21+#define BLOCK_BRICK ((BlockType)(45 << 4))
22+
23+#define BLOCK_FACE_COUNT 6
24+#define BLOCK_TEXTURE_COUNT 512
25+
26+typedef struct {
27+ MGVertex vertices[4];
28+ i32 texture;
29+ i32 cullface;
30+} BlockFace;
31+
32+i8 block_textures_create(const char* path);
33+void block_textures_destroy(void);
34+const BlockFace* block_model_faces(BlockType block, i32* count);
35+i8 block_model_occludes(BlockType block);
36+MGTexture block_texture_get(i32 index);
37
38 #endif /* WORLD_BLOCK_H */
+1,
-1
1@@ -14,7 +14,7 @@
2
3 typedef struct {
4 BlockType blocks[CHUNK_WIDTH][CHUNK_HEIGHT][CHUNK_DEPTH];
5- MGMesh meshes[BLOCK_LAST];
6+ MGMesh meshes[BLOCK_TEXTURE_COUNT];
7 } Chunk;
8
9 /* create a new chunk
+3,
-1
1@@ -25,6 +25,7 @@ sources = [
2 'source/mg_random.c',
3 'source/config.c',
4 'source/util.c',
5+ 'source/world/block.c',
6 'source/world/chunk.c',
7 'source/client/camera.c',
8 'source/client/player.c',
9@@ -34,6 +35,7 @@ sources = [
10 'source/mcproto/crypto.c',
11 'source/mcproto/packet.c',
12 'vendor/stb_image_c89.c',
13+ 'vendor/json.c',
14 ]
15
16 include_dirs = [
17@@ -141,7 +143,7 @@ endif
18 executable(
19 'magnolia',
20 sources,
21- include_directories: include_dirs,
22+ include_directories: include_dirs + vendor_inc,
23 dependencies: deps,
24 c_args: platform_c_args + renderer_c_args,
25 link_args: extra_libs,
+2,
-1
1@@ -64,6 +64,7 @@ int main(int argc, char** argv)
2 MCPacket packet;
3 char error[1024];
4 int poll_result;
5+ int packets;
6
7 Player player;
8
9@@ -91,7 +92,7 @@ int main(int argc, char** argv)
10
11 while (platform_poll(&ctx)) {
12 if (client) {
13- for (;;) {
14+ for (packets = 0; packets < 64; packets++) {
15 poll_result = mc_client_poll(client, &packet, error, sizeof(error));
16 if (poll_result <= 0)
17 break;
+13,
-3
1@@ -9,7 +9,7 @@
2 #include "renderer/renderer.h"
3 #include "renderer_backend.h"
4
5-#define MAX_MESHES (1024)
6+#define MAX_MESHES (16384)
7 #define MAX_TEXTURES (512)
8 #define S3L_MAX_WIDTH (4096)
9 #define S3L_MAX_HEIGHT (4096)
10@@ -239,6 +239,11 @@ static S3L_Vec4 clip_to_screen(const ClipVertex* v)
11 static u32 sample_texture(const RendererMesh* mesh, const RendererTexture* texture,
12 const S3L_PixelInfo* pixel)
13 {
14+ u32 sampled;
15+ u32 colour;
16+ u32 r;
17+ u32 g;
18+ u32 b;
19 u32 tri;
20 const MGVertex* v[3];
21 i32 x;
22@@ -282,7 +287,12 @@ static u32 sample_texture(const RendererMesh* mesh, const RendererTexture* textu
23 } else if (y >= texture->height) {
24 y = texture->height - 1;
25 }
26- return texture->pixels[y * texture->width + x];
27+ sampled = texture->pixels[y * texture->width + x];
28+ colour = mesh->vtc[mesh->idc[(u32)pixel->triangleIndex * 3]].col;
29+ r = (((sampled >> 11) & 31) * (colour & 0xff) / 255) << 11;
30+ g = (((sampled >> 5) & 63) * ((colour >> 8) & 0xff) / 255) << 5;
31+ b = (sampled & 31) * ((colour >> 16) & 0xff) / 255;
32+ return (sampled & 0xff000000) | r | g | b;
33 }
34
35 static u16 rgba_to_rgb565(u32 rgba)
36@@ -523,7 +533,7 @@ MGTexture renderer_backend_texture_load(const char* path)
37 }
38 desc.pixels = pixels;
39 desc.width = width;
40- desc.height = height;
41+ desc.height = height > width && height % width == 0 ? width : height;
42 texture = renderer_backend_texture_create(&desc);
43 stbi_image_free(pixels);
44 return texture;
+4,
-4
1@@ -8,7 +8,7 @@
2 #include "renderer/renderer.h"
3 #include "renderer_backend.h"
4
5-#define MAX_MESHES (2048) /* TODO; random value ig */
6+#define MAX_MESHES (16384)
7 #define MAX_TEXTURES (512) /* TODO; random value ig */
8
9 typedef struct {
10@@ -75,7 +75,8 @@ static const char* fsdr = "#version 330\n"
11 "\n"
12 "void main(void)\n"
13 "{\n"
14- " frag_colour = texture(tex, uv);\n"
15+ " frag_colour = texture(tex, uv) * colour;\n"
16+ " if (frag_colour.a < 0.5) discard;\n"
17 "}\n";
18
19 static void create_pipelines(void)
20@@ -371,7 +372,7 @@ MGTexture renderer_backend_texture_load(const char* path)
21
22 desc.pixels = pixels;
23 desc.width = width;
24- desc.height = height;
25+ desc.height = height > width && height % width == 0 ? width : height;
26 texture = renderer_backend_texture_create(&desc);
27 stbi_image_free(pixels);
28 return texture;
29@@ -449,4 +450,3 @@ void renderer_debug_wireframe(i8 enabled)
30 glPolygonMode(GL_FRONT_AND_BACK, enabled ? GL_LINE : GL_FILL);
31 sg_reset_state_cache();
32 }
33-
+465,
-0
1@@ -0,0 +1,465 @@
2+#include <math.h>
3+#include <stdio.h>
4+#include <stdlib.h>
5+#include <string.h>
6+
7+#include "json.h"
8+#include "util.h"
9+#include "world/block.h"
10+
11+#define NAME_SIZE 128
12+#define PACK_SIZE 256
13+#define PATH_SIZE 512
14+#define VARIABLE_COUNT 16
15+#define MODEL_FACE_COUNT 64
16+#define BLOCK_STATE_COUNT 4096
17+
18+typedef struct {
19+ char name[NAME_SIZE];
20+ char value[NAME_SIZE];
21+} TextureVariable;
22+
23+typedef struct {
24+ MGVertex vertices[4];
25+ char texture[NAME_SIZE];
26+ i32 cullface;
27+} ModelFace;
28+
29+typedef struct {
30+ TextureVariable variables[VARIABLE_COUNT];
31+ i32 variable_count;
32+ ModelFace faces[MODEL_FACE_COUNT];
33+ i32 face_count;
34+} BlockModel;
35+
36+typedef struct {
37+ BlockFace* faces;
38+ i32 face_count;
39+ i8 loaded;
40+ i8 occludes;
41+} LoadedBlock;
42+
43+static const char* face_names[BLOCK_FACE_COUNT] = { "north", "south", "west", "east", "down", "up" };
44+
45+/*its a cube... what more do you want*/
46+/* clang-format off */
47+static const MGVertex face_vertices[BLOCK_FACE_COUNT][4] = {
48+ { { 0, 0, 0, 0, 1, 0xffffffff }, { 0, 1, 0, 0, 0, 0xffffffff },
49+ { 1, 1, 0, 1, 0, 0xffffffff }, { 1, 0, 0, 1, 1, 0xffffffff } },
50+ { { 1, 0, 1, 0, 1, 0xffffffff }, { 1, 1, 1, 0, 0, 0xffffffff },
51+ { 0, 1, 1, 1, 0, 0xffffffff }, { 0, 0, 1, 1, 1, 0xffffffff } },
52+ { { 0, 0, 1, 0, 1, 0xffffffff }, { 0, 1, 1, 0, 0, 0xffffffff },
53+ { 0, 1, 0, 1, 0, 0xffffffff }, { 0, 0, 0, 1, 1, 0xffffffff } },
54+ { { 1, 0, 0, 0, 1, 0xffffffff }, { 1, 1, 0, 0, 0, 0xffffffff },
55+ { 1, 1, 1, 1, 0, 0xffffffff }, { 1, 0, 1, 1, 1, 0xffffffff } },
56+ { { 0, 0, 1, 0, 1, 0xffffffff }, { 0, 0, 0, 0, 0, 0xffffffff },
57+ { 1, 0, 0, 1, 0, 0xffffffff }, { 1, 0, 1, 1, 1, 0xffffffff } },
58+ { { 0, 1, 0, 0, 1, 0xffffffff }, { 0, 1, 1, 0, 0, 0xffffffff },
59+ { 1, 1, 1, 1, 0, 0xffffffff }, { 1, 1, 0, 1, 1, 0xffffffff } }
60+};
61+/* clang-format on */
62+
63+static MGTexture textures[BLOCK_TEXTURE_COUNT];
64+static char texture_names[BLOCK_TEXTURE_COUNT][NAME_SIZE];
65+static LoadedBlock blocks[BLOCK_STATE_COUNT];
66+static char pack_path[PACK_SIZE];
67+static i32 texture_count;
68+static cJSON* block_registry;
69+
70+static cJSON* json_load(const char* path)
71+{
72+ FILE* file;
73+ char* data;
74+ long size;
75+ cJSON* json;
76+
77+ file = fopen(path, "rb");
78+ if (!file)
79+ return NULL;
80+ fseek(file, 0, SEEK_END);
81+ size = ftell(file);
82+ rewind(file);
83+ data = malloc((size_t)size + 1);
84+ if (!data || fread(data, 1, (size_t)size, file) != (size_t)size) {
85+ free(data);
86+ fclose(file);
87+ return NULL;
88+ }
89+ data[size] = '\0';
90+ fclose(file);
91+ json = cJSON_Parse(data);
92+ free(data);
93+ return json;
94+}
95+
96+/* add or override model texture */
97+static void model_texture(BlockModel* model, const char* name, const char* value)
98+{
99+ i32 i;
100+
101+ for (i = 0; i < model->variable_count; i++) {
102+ if (strcmp(model->variables[i].name, name) == 0)
103+ break;
104+ }
105+ if (i == VARIABLE_COUNT)
106+ return;
107+ if (i == model->variable_count)
108+ model->variable_count++;
109+ snprintf(model->variables[i].name, NAME_SIZE, "%s", name);
110+ snprintf(model->variables[i].value, NAME_SIZE, "%s", value);
111+}
112+
113+static float json_number(cJSON* array, i32 index)
114+{
115+ cJSON* item = cJSON_GetArrayItem(array, index);
116+ return cJSON_IsNumber(item) ? (float)item->valuedouble / 16.0f : 0.0f;
117+}
118+
119+/*convert json face element into verticies*/
120+static void model_face(BlockModel* model, cJSON* from, cJSON* to, cJSON* faces, i32 face)
121+{
122+ ModelFace* out;
123+ cJSON* item;
124+ cJSON* uv;
125+ float low[3];
126+ float high[3];
127+ i32 vertex;
128+ i32 axis;
129+
130+ item = cJSON_GetObjectItemCaseSensitive(faces, face_names[face]);
131+ if (!cJSON_IsObject(item) || model->face_count == MODEL_FACE_COUNT)
132+ return;
133+ out = &model->faces[model->face_count++];
134+ memset(out, 0, sizeof(*out));
135+ out->cullface = -1;
136+ for (axis = 0; axis < 3; axis++) {
137+ low[axis] = json_number(from, axis);
138+ high[axis] = json_number(to, axis);
139+ }
140+ for (vertex = 0; vertex < 4; vertex++) {
141+ out->vertices[vertex] = face_vertices[face][vertex];
142+ out->vertices[vertex].x = out->vertices[vertex].x ? high[0] : low[0];
143+ out->vertices[vertex].y = out->vertices[vertex].y ? high[1] : low[1];
144+ out->vertices[vertex].z = out->vertices[vertex].z ? high[2] : low[2];
145+ }
146+ uv = cJSON_GetObjectItemCaseSensitive(item, "uv");
147+ if (cJSON_IsArray(uv) && cJSON_GetArraySize(uv) == 4) {
148+ out->vertices[0].u = out->vertices[1].u = json_number(uv, 0);
149+ out->vertices[2].u = out->vertices[3].u = json_number(uv, 2);
150+ out->vertices[0].v = out->vertices[3].v = json_number(uv, 3);
151+ out->vertices[1].v = out->vertices[2].v = json_number(uv, 1);
152+ }
153+ uv = cJSON_GetObjectItemCaseSensitive(item, "texture");
154+ if (cJSON_IsString(uv))
155+ snprintf(out->texture, NAME_SIZE, "%s", uv->valuestring);
156+ uv = cJSON_GetObjectItemCaseSensitive(item, "tintindex");
157+ if (cJSON_IsNumber(uv)) {
158+ /* TODO for now we just tint everything the same green */
159+ for (vertex = 0; vertex < 4; vertex++)
160+ out->vertices[vertex].col = 0xff59bd91;
161+ }
162+ uv = cJSON_GetObjectItemCaseSensitive(item, "cullface");
163+ if (cJSON_IsString(uv)) {
164+ for (axis = 0; axis < BLOCK_FACE_COUNT; axis++) {
165+ if (strcmp(uv->valuestring, face_names[axis]) == 0)
166+ out->cullface = axis;
167+ }
168+ }
169+}
170+
171+/*rotate stuff that whats to be rotated the amount it wants to be rotated by*/
172+static void model_rotate(BlockModel* model, i32 first, cJSON* rotation)
173+{
174+ cJSON* origin;
175+ cJSON* item;
176+ const char* axis;
177+ float center[3];
178+ float value[3];
179+ float angle;
180+ float sine;
181+ float cosine;
182+ float a;
183+ float b;
184+ i32 face;
185+ i32 vertex;
186+
187+ if (!cJSON_IsObject(rotation))
188+ return;
189+ origin = cJSON_GetObjectItemCaseSensitive(rotation, "origin");
190+ item = cJSON_GetObjectItemCaseSensitive(rotation, "axis");
191+ axis = cJSON_IsString(item) ? item->valuestring : NULL;
192+ item = cJSON_GetObjectItemCaseSensitive(rotation, "angle");
193+ if (!axis || !cJSON_IsNumber(item))
194+ return;
195+ center[0] = json_number(origin, 0);
196+ center[1] = json_number(origin, 1);
197+ center[2] = json_number(origin, 2);
198+ angle = (float)(item->valuedouble * 3.14159265358979323846 / 180.0);
199+ sine = sinf(angle);
200+ cosine = cosf(angle);
201+ for (face = first; face < model->face_count; face++) {
202+ for (vertex = 0; vertex < 4; vertex++) {
203+ value[0] = model->faces[face].vertices[vertex].x - center[0];
204+ value[1] = model->faces[face].vertices[vertex].y - center[1];
205+ value[2] = model->faces[face].vertices[vertex].z - center[2];
206+ if (axis[0] == 'x') {
207+ a = value[1];
208+ b = value[2];
209+ value[1] = a * cosine - b * sine;
210+ value[2] = a * sine + b * cosine;
211+ } else if (axis[0] == 'y') {
212+ a = value[2];
213+ b = value[0];
214+ value[2] = a * cosine - b * sine;
215+ value[0] = a * sine + b * cosine;
216+ } else {
217+ a = value[0];
218+ b = value[1];
219+ value[0] = a * cosine - b * sine;
220+ value[1] = a * sine + b * cosine;
221+ }
222+ model->faces[face].vertices[vertex].x = value[0] + center[0];
223+ model->faces[face].vertices[vertex].y = value[1] + center[1];
224+ model->faces[face].vertices[vertex].z = value[2] + center[2];
225+ }
226+ }
227+}
228+
229+/* load inhereted model data from the parent feild and then apply per model overrides*/
230+static i8 model_load(const char* name, BlockModel* model, i32 depth)
231+{
232+ char path[PATH_SIZE];
233+ cJSON* json;
234+ cJSON* item;
235+ cJSON* element;
236+ cJSON* from;
237+ cJSON* to;
238+ cJSON* faces;
239+ i32 face;
240+ i32 first;
241+
242+ if (depth == 16)
243+ return 0;
244+ if (strchr(name, ':'))
245+ name = strchr(name, ':') + 1;
246+ snprintf(path, sizeof(path), "%s/models/%s%s.json", pack_path, strchr(name, '/') ? "" : "block/", name);
247+ json = json_load(path);
248+ if (!json)
249+ return 0;
250+ /* load the parent first... */
251+ item = cJSON_GetObjectItemCaseSensitive(json, "parent");
252+ if (cJSON_IsString(item) && !model_load(item->valuestring, model, depth + 1)) {
253+ cJSON_Delete(json);
254+ return 0;
255+ }
256+ item = cJSON_GetObjectItemCaseSensitive(json, "textures");
257+ cJSON_ArrayForEach(faces, item)
258+ {
259+ if (cJSON_IsString(faces))
260+ model_texture(model, faces->string, faces->valuestring);
261+ }
262+ item = cJSON_GetObjectItemCaseSensitive(json, "elements");
263+ if (cJSON_IsArray(item)) {
264+ /* ... then let the child override*/
265+ model->face_count = 0;
266+ /* get the from and to values and then turn them into verticies*/
267+ /*TODO we dont rotate stairs*/
268+ cJSON_ArrayForEach(element, item)
269+ {
270+ first = model->face_count;
271+ from = cJSON_GetObjectItemCaseSensitive(element, "from");
272+ to = cJSON_GetObjectItemCaseSensitive(element, "to");
273+ faces = cJSON_GetObjectItemCaseSensitive(element, "faces");
274+ for (face = 0; face < BLOCK_FACE_COUNT; face++)
275+ model_face(model, from, to, faces, face);
276+ model_rotate(model, first, cJSON_GetObjectItemCaseSensitive(element, "rotation"));
277+ }
278+ }
279+ cJSON_Delete(json);
280+ return 1;
281+}
282+
283+static const char* model_resolve(const BlockModel* model, const char* name)
284+{
285+ i32 depth;
286+ i32 i;
287+
288+ for (depth = 0; name && name[0] == '#' && depth < VARIABLE_COUNT; depth++) {
289+ for (i = 0; i < model->variable_count; i++) {
290+ if (strcmp(model->variables[i].name, name + 1) == 0)
291+ break;
292+ }
293+ name = i == model->variable_count ? NULL : model->variables[i].value;
294+ }
295+ return name;
296+}
297+
298+static i32 texture_load(const char* name)
299+{
300+ char path[PATH_SIZE];
301+ const char* colon;
302+ i32 index;
303+
304+ colon = strchr(name, ':');
305+ if (colon)
306+ name = colon + 1;
307+ for (index = 0; index < texture_count; index++) {
308+ if (strcmp(texture_names[index], name) == 0)
309+ return index;
310+ }
311+ if (texture_count == BLOCK_TEXTURE_COUNT)
312+ return -1;
313+ snprintf(path, sizeof(path), "%s/%s.png", pack_path, name);
314+ textures[texture_count] = renderer_texture_load(path);
315+ if (textures[texture_count] == MGTEXTURE_INVALID)
316+ return -1;
317+ snprintf(texture_names[texture_count], NAME_SIZE, "%s", name);
318+ return texture_count++;
319+}
320+
321+static void model_cube(BlockModel* model, const char* texture)
322+{
323+ i32 face;
324+
325+ for (face = 0; face < BLOCK_FACE_COUNT; face++) {
326+ model->faces[face].cullface = face;
327+ memcpy(model->faces[face].vertices, face_vertices[face], sizeof(face_vertices[face]));
328+ snprintf(model->faces[face].texture, NAME_SIZE, "%s", texture);
329+ }
330+ model->face_count = BLOCK_FACE_COUNT;
331+}
332+
333+static i8 face_covers_cube(const ModelFace* face)
334+{
335+ /* only faces spanning their entire boundary plane can occlude neighbours */
336+ static const i32 face_axes[BLOCK_FACE_COUNT] = { 2, 2, 0, 0, 1, 1 };
337+ float low[3] = { 1, 1, 1 };
338+ float high[3] = { 0, 0, 0 };
339+ float value[3];
340+ i32 vertex;
341+ i32 axis;
342+ i32 plane;
343+
344+ for (vertex = 0; vertex < 4; vertex++) {
345+ value[0] = face->vertices[vertex].x;
346+ value[1] = face->vertices[vertex].y;
347+ value[2] = face->vertices[vertex].z;
348+ for (axis = 0; axis < 3; axis++) {
349+ if (value[axis] < low[axis])
350+ low[axis] = value[axis];
351+ if (value[axis] > high[axis])
352+ high[axis] = value[axis];
353+ }
354+ }
355+ plane = face_axes[face->cullface];
356+ for (axis = 0; axis < 3; axis++) {
357+ if (axis != plane && (low[axis] != 0 || high[axis] != 1))
358+ return 0;
359+ }
360+ return face->cullface & 1 ? high[plane] == 1 : low[plane] == 0;
361+}
362+
363+static void block_load(BlockType block)
364+{
365+ LoadedBlock* loaded;
366+ BlockModel model;
367+ cJSON* entry;
368+ cJSON* item;
369+ const char* name;
370+ const char* fallback;
371+ i32 face;
372+ i32 mask;
373+ char path[PATH_SIZE];
374+
375+ loaded = &blocks[block];
376+ loaded->loaded = 1;
377+ entry = cJSON_GetArrayItem(block_registry, block >> 4);
378+ item = cJSON_GetObjectItemCaseSensitive(entry, "blockState");
379+ name = cJSON_IsString(item) ? item->valuestring : NULL;
380+ item = cJSON_GetObjectItemCaseSensitive(entry, "texture");
381+ fallback = cJSON_IsString(item) ? item->valuestring : NULL;
382+ memset(&model, 0, sizeof(model));
383+ if (name) {
384+ snprintf(path, sizeof(path), "%s/blockstates/%s.json", pack_path, name);
385+ item = json_load(path);
386+ if (item) {
387+ entry = cJSON_GetObjectItemCaseSensitive(item, "variants");
388+ if (cJSON_GetArraySize(entry) > (block & 15))
389+ entry = cJSON_GetArrayItem(entry, block & 15);
390+ else
391+ entry = entry ? entry->child : NULL;
392+ if (cJSON_IsArray(entry))
393+ entry = cJSON_GetArrayItem(entry, 0);
394+ entry = cJSON_GetObjectItemCaseSensitive(entry, "model");
395+ if (cJSON_IsString(entry))
396+ model_load(entry->valuestring, &model, 0);
397+ cJSON_Delete(item);
398+ }
399+ }
400+ if (!model.face_count && fallback)
401+ model_cube(&model, fallback);
402+ if (!model.face_count)
403+ return;
404+ loaded->faces = malloc(model.face_count * sizeof(*loaded->faces));
405+ if (!loaded->faces)
406+ return;
407+ loaded->face_count = model.face_count;
408+ mask = 0;
409+ for (face = 0; face < model.face_count; face++) {
410+ name = model_resolve(&model, model.faces[face].texture);
411+ if (!name)
412+ name = fallback;
413+ loaded->faces[face].texture = name ? texture_load(name) : -1;
414+ loaded->faces[face].cullface = model.faces[face].cullface;
415+ memcpy(loaded->faces[face].vertices, model.faces[face].vertices, sizeof(model.faces[face].vertices));
416+ if (model.faces[face].cullface >= 0 && face_covers_cube(&model.faces[face]))
417+ mask |= 1 << model.faces[face].cullface;
418+ }
419+ loaded->occludes = mask == (1 << BLOCK_FACE_COUNT) - 1;
420+}
421+
422+i8 block_textures_create(const char* path)
423+{
424+ block_textures_destroy();
425+ snprintf(pack_path, sizeof(pack_path), "%s", path);
426+ block_registry = json_load("assets/resourcepacks/blocks.json");
427+ return cJSON_IsArray(block_registry);
428+}
429+
430+void block_textures_destroy(void)
431+{
432+ i32 index;
433+
434+ for (index = 0; index < BLOCK_STATE_COUNT; index++)
435+ free(blocks[index].faces);
436+ for (index = 0; index < texture_count; index++)
437+ renderer_texture_destroy(textures[index]);
438+ cJSON_Delete(block_registry);
439+ memset(blocks, 0, sizeof(blocks));
440+ memset(textures, 0, sizeof(textures));
441+ memset(texture_names, 0, sizeof(texture_names));
442+ block_registry = NULL;
443+ pack_path[0] = '\0';
444+ texture_count = 0;
445+}
446+
447+const BlockFace* block_model_faces(BlockType block, i32* count)
448+{
449+ if (!blocks[block].loaded)
450+ block_load(block);
451+ *count = blocks[block].face_count;
452+ return blocks[block].faces;
453+}
454+
455+i8 block_model_occludes(BlockType block)
456+{
457+ i32 count;
458+
459+ block_model_faces(block, &count);
460+ return blocks[block].occludes;
461+}
462+
463+MGTexture block_texture_get(i32 index)
464+{
465+ return index >= 0 && index < texture_count ? textures[index] : MGTEXTURE_INVALID;
466+}
+67,
-84
1@@ -7,52 +7,14 @@
2 #define MAX_MESH_VERTICES 65535U
3
4 static void add_face(MGVertex* vertices, u16* indices, u32* vertex_count, u32* index_count,
5- i32 face, i32 x, i32 y, i32 z);
6+ const BlockFace* face, i32 x, i32 y, i32 z);
7
8 /* 6 = number of faces on a cube */
9 static const i32 face_offsets[6][3] = { { 0, 0, -1 }, { 0, 0, 1 }, { -1, 0, 0 },
10 { 1, 0, 0 }, { 0, -1, 0 }, { 0, 1, 0 } };
11
12-static const MGVertex face_vertices[24] = {
13- /* north: -z */
14- { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, RGBA(255, 0, 0, 255) },
15- { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, RGBA(255, 0, 0, 255) },
16- { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, RGBA(255, 0, 0, 255) },
17- { 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, RGBA(255, 0, 0, 255) },
18-
19- /* south: +z */
20- { 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, RGBA(0, 255, 0, 255) },
21- { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, RGBA(0, 255, 0, 255) },
22- { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, RGBA(0, 255, 0, 255) },
23- { 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, RGBA(0, 255, 0, 255) },
24-
25- /* west: -x */
26- { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, RGBA(0, 0, 255, 255) },
27- { 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, RGBA(0, 0, 255, 255) },
28- { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, RGBA(0, 0, 255, 255) },
29- { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, RGBA(0, 0, 255, 255) },
30-
31- /* east: +x */
32- { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, RGBA(255, 255, 0, 255) },
33- { 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, RGBA(255, 255, 0, 255) },
34- { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, RGBA(255, 255, 0, 255) },
35- { 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, RGBA(255, 255, 0, 255) },
36-
37- /* bottom: -y */
38- { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, RGBA(255, 0, 255, 255) },
39- { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, RGBA(255, 0, 255, 255) },
40- { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, RGBA(255, 0, 255, 255) },
41- { 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, RGBA(255, 0, 255, 255) },
42-
43- /* top: +y */
44- { 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, RGBA(0, 255, 255, 255) },
45- { 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, RGBA(0, 255, 255, 255) },
46- { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, RGBA(0, 255, 255, 255) },
47- { 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, RGBA(0, 255, 255, 255) }
48-};
49-
50 static void add_face(MGVertex* vertices, u16* indices, u32* vertex_count, u32* index_count,
51- i32 face, i32 x, i32 y, i32 z)
52+ const BlockFace* face, i32 x, i32 y, i32 z)
53 {
54 MGVertex vtx;
55 u32 base;
56@@ -61,7 +23,7 @@ static void add_face(MGVertex* vertices, u16* indices, u32* vertex_count, u32* i
57 base = *vertex_count;
58
59 for (i = 0; i < 4; i++) {
60- vtx = face_vertices[face * 4 + i];
61+ vtx = face->vertices[i];
62
63 vtx.x += x;
64 vtx.y += y;
65@@ -140,13 +102,17 @@ void chunk_set(Chunk* chunk, i32 x, i32 y, i32 z, BlockType block)
66
67 i8 chunk_mesh_create(Chunk* chunk)
68 {
69- MGVertex* vertices[BLOCK_LAST];
70- u16* indices[BLOCK_LAST];
71- u32 face_counts[BLOCK_LAST];
72- u32 vertex_counts[BLOCK_LAST];
73- u32 index_counts[BLOCK_LAST];
74+ MGVertex* vertices[BLOCK_TEXTURE_COUNT];
75+ u16* indices[BLOCK_TEXTURE_COUNT];
76+ u32 face_counts[BLOCK_TEXTURE_COUNT];
77+ u32 vertex_counts[BLOCK_TEXTURE_COUNT];
78+ u32 index_counts[BLOCK_TEXTURE_COUNT];
79 MGMeshDesc desc;
80 BlockType block;
81+ BlockType neighbour;
82+ const BlockFace* faces;
83+ i32 face_count;
84+ i32 texture;
85 i32 face;
86 i32 x;
87 i32 y;
88@@ -161,8 +127,8 @@ i8 chunk_mesh_create(Chunk* chunk)
89 memset(vertex_counts, 0, sizeof(vertex_counts));
90 memset(index_counts, 0, sizeof(index_counts));
91
92- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++)
93- chunk->meshes[block] = MGMESH_INVALID;
94+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++)
95+ chunk->meshes[texture] = MGMESH_INVALID;
96
97 /* count visible faces belonging to each block type */
98 for (z = 0; z < CHUNK_DEPTH; z++) {
99@@ -173,35 +139,43 @@ i8 chunk_mesh_create(Chunk* chunk)
100 if (block == BLOCK_AIR)
101 continue;
102
103- for (face = 0; face < 6; face++) {
104- if (chunk_get(chunk, x + face_offsets[face][0],
105- y + face_offsets[face][1],
106- z + face_offsets[face][2]) == BLOCK_AIR)
107- face_counts[block]++;
108+ faces = block_model_faces(block, &face_count);
109+ for (face = 0; face < face_count; face++) {
110+ if (faces[face].texture < 0)
111+ continue;
112+ if (faces[face].cullface >= 0) {
113+ texture = faces[face].cullface;
114+ neighbour = chunk_get(chunk, x + face_offsets[texture][0],
115+ y + face_offsets[texture][1],
116+ z + face_offsets[texture][2]);
117+ if (neighbour != BLOCK_AIR && block_model_occludes(neighbour))
118+ continue;
119+ }
120+ face_counts[faces[face].texture]++;
121 }
122 }
123 }
124 }
125
126 /* allocate for each block type */
127- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++) {
128- if (face_counts[block] == 0)
129+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
130+ if (face_counts[texture] == 0)
131 continue;
132
133- if (face_counts[block] * 4U > MAX_MESH_VERTICES) {
134+ if (face_counts[texture] * 4U > MAX_MESH_VERTICES) {
135 mg_log(LOG_ERR, "Chunk mesh exceeds u16 vertex limit");
136 goto fail;
137 }
138
139- vertices[block] = malloc(face_counts[block] * 4U * sizeof(*vertices[block]));
140- indices[block] = malloc(face_counts[block] * 6U * sizeof(*indices[block]));
141- if (!vertices[block] || !indices[block]) {
142+ vertices[texture] = malloc(face_counts[texture] * 4U * sizeof(*vertices[texture]));
143+ indices[texture] = malloc(face_counts[texture] * 6U * sizeof(*indices[texture]));
144+ if (!vertices[texture] || !indices[texture]) {
145 mg_log(LOG_ERR, "Failed to allocate chunk mesh");
146 goto fail;
147 }
148 }
149
150- /* omit only faces whose neighbour is air */
151+ /* omit culled model faces hidden by a full cube */
152 for (z = 0; z < CHUNK_DEPTH; z++) {
153 for (y = 0; y < CHUNK_HEIGHT; y++) {
154 for (x = 0; x < CHUNK_WIDTH; x++) {
155@@ -210,14 +184,23 @@ i8 chunk_mesh_create(Chunk* chunk)
156 if (block == BLOCK_AIR)
157 continue;
158
159- for (face = 0; face < 6; face++) {
160- if (chunk_get(chunk, x + face_offsets[face][0],
161- y + face_offsets[face][1],
162- z + face_offsets[face][2]) != BLOCK_AIR)
163+ faces = block_model_faces(block, &face_count);
164+ for (face = 0; face < face_count; face++) {
165+ texture = faces[face].texture;
166+ if (texture < 0)
167 continue;
168+ if (faces[face].cullface >= 0) {
169+ texture = faces[face].cullface;
170+ neighbour = chunk_get(chunk, x + face_offsets[texture][0],
171+ y + face_offsets[texture][1],
172+ z + face_offsets[texture][2]);
173+ if (neighbour != BLOCK_AIR && block_model_occludes(neighbour))
174+ continue;
175+ }
176
177- add_face(vertices[block], indices[block],
178- &vertex_counts[block], &index_counts[block], face,
179+ texture = faces[face].texture;
180+ add_face(vertices[texture], indices[texture],
181+ &vertex_counts[texture], &index_counts[texture], &faces[face],
182 x, y, z);
183 }
184 }
185@@ -225,34 +208,34 @@ i8 chunk_mesh_create(Chunk* chunk)
186 }
187
188 /* upload one mesh for each texture */
189- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++) {
190- if (index_counts[block] == 0)
191+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
192+ if (index_counts[texture] == 0)
193 continue;
194
195- desc.vtc = vertices[block];
196- desc.vtcc = vertex_counts[block];
197- desc.idc = indices[block];
198- desc.idcc = index_counts[block];
199+ desc.vtc = vertices[texture];
200+ desc.vtcc = vertex_counts[texture];
201+ desc.idc = indices[texture];
202+ desc.idcc = index_counts[texture];
203
204- chunk->meshes[block] = renderer_mesh_create(&desc);
205+ chunk->meshes[texture] = renderer_mesh_create(&desc);
206
207- if (chunk->meshes[block] == MGMESH_INVALID) {
208+ if (chunk->meshes[texture] == MGMESH_INVALID) {
209 mg_log(LOG_ERR, "Failed to upload chunk mesh");
210 goto fail;
211 }
212 }
213
214- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++) {
215- free(indices[block]);
216- free(vertices[block]);
217+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
218+ free(indices[texture]);
219+ free(vertices[texture]);
220 }
221
222 return 1;
223
224 fail:
225- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++) {
226- free(indices[block]);
227- free(vertices[block]);
228+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
229+ free(indices[texture]);
230+ free(vertices[texture]);
231 }
232
233 chunk_mesh_destroy(chunk);
234@@ -261,13 +244,13 @@ fail:
235
236 void chunk_mesh_destroy(Chunk* chunk)
237 {
238- BlockType block;
239+ i32 texture;
240
241 if (!chunk)
242 return;
243
244- for (block = BLOCK_BRICK; block < BLOCK_LAST; block++) {
245- renderer_mesh_destroy(chunk->meshes[block]);
246- chunk->meshes[block] = MGMESH_INVALID;
247+ for (texture = 0; texture < BLOCK_TEXTURE_COUNT; texture++) {
248+ renderer_mesh_destroy(chunk->meshes[texture]);
249+ chunk->meshes[texture] = MGMESH_INVALID;
250 }
251 }
+3206,
-0
1@@ -0,0 +1,3206 @@
2+/*
3+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
4+
5+ Permission is hereby granted, free of charge, to any person obtaining a copy
6+ of this software and associated documentation files (the "Software"), to deal
7+ in the Software without restriction, including without limitation the rights
8+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ copies of the Software, and to permit persons to whom the Software is
10+ furnished to do so, subject to the following conditions:
11+
12+ The above copyright notice and this permission notice shall be included in
13+ all copies or substantial portions of the Software.
14+
15+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ THE SOFTWARE.
22+*/
23+
24+/* cJSON */
25+/* JSON parser in C. */
26+
27+/* disable warnings about old C89 functions in MSVC */
28+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
29+#define _CRT_SECURE_NO_DEPRECATE
30+#endif
31+
32+#ifdef __GNUC__
33+#pragma GCC visibility push(default)
34+#endif
35+#if defined(_MSC_VER)
36+#pragma warning (push)
37+/* disable warning about single line comments in system headers */
38+#pragma warning (disable : 4001)
39+#endif
40+
41+#include <string.h>
42+#include <stdio.h>
43+#include <math.h>
44+#include <stdlib.h>
45+#include <limits.h>
46+#include <ctype.h>
47+#include <float.h>
48+
49+#ifdef ENABLE_LOCALES
50+#include <locale.h>
51+#endif
52+
53+#if defined(_MSC_VER)
54+#pragma warning (pop)
55+#endif
56+#ifdef __GNUC__
57+#pragma GCC visibility pop
58+#endif
59+
60+#include "json.h"
61+
62+/* define our own boolean type */
63+#ifdef true
64+#undef true
65+#endif
66+#define true ((cJSON_bool)1)
67+
68+#ifdef false
69+#undef false
70+#endif
71+#define false ((cJSON_bool)0)
72+
73+/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
74+#ifndef isinf
75+#define isinf(d) (isnan((d - d)) && !isnan(d))
76+#endif
77+#ifndef isnan
78+#define isnan(d) (d != d)
79+#endif
80+
81+#ifndef NAN
82+#ifdef _WIN32
83+#define NAN sqrt(-1.0)
84+#else
85+#define NAN 0.0/0.0
86+#endif
87+#endif
88+
89+typedef struct {
90+ const unsigned char *json;
91+ size_t position;
92+} error;
93+static error global_error = { NULL, 0 };
94+
95+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
96+{
97+ return (const char*) (global_error.json + global_error.position);
98+}
99+
100+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
101+{
102+ if (!cJSON_IsString(item))
103+ {
104+ return NULL;
105+ }
106+
107+ return item->valuestring;
108+}
109+
110+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
111+{
112+ if (!cJSON_IsNumber(item))
113+ {
114+ return (double) NAN;
115+ }
116+
117+ return item->valuedouble;
118+}
119+
120+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
121+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 19)
122+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
123+#endif
124+
125+CJSON_PUBLIC(const char*) cJSON_Version(void)
126+{
127+ static char version[15];
128+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
129+
130+ return version;
131+}
132+
133+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
134+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
135+{
136+ if ((string1 == NULL) || (string2 == NULL))
137+ {
138+ return 1;
139+ }
140+
141+ if (string1 == string2)
142+ {
143+ return 0;
144+ }
145+
146+ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
147+ {
148+ if (*string1 == '\0')
149+ {
150+ return 0;
151+ }
152+ }
153+
154+ return tolower(*string1) - tolower(*string2);
155+}
156+
157+typedef struct internal_hooks
158+{
159+ void *(CJSON_CDECL *allocate)(size_t size);
160+ void (CJSON_CDECL *deallocate)(void *pointer);
161+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
162+} internal_hooks;
163+
164+#if defined(_MSC_VER)
165+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
166+static void * CJSON_CDECL internal_malloc(size_t size)
167+{
168+ return malloc(size);
169+}
170+static void CJSON_CDECL internal_free(void *pointer)
171+{
172+ free(pointer);
173+}
174+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
175+{
176+ return realloc(pointer, size);
177+}
178+#else
179+#define internal_malloc malloc
180+#define internal_free free
181+#define internal_realloc realloc
182+#endif
183+
184+/* strlen of character literals resolved at compile time */
185+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
186+
187+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
188+
189+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
190+{
191+ size_t length = 0;
192+ unsigned char *copy = NULL;
193+
194+ if (string == NULL)
195+ {
196+ return NULL;
197+ }
198+
199+ length = strlen((const char*)string) + sizeof("");
200+ copy = (unsigned char*)hooks->allocate(length);
201+ if (copy == NULL)
202+ {
203+ return NULL;
204+ }
205+ memcpy(copy, string, length);
206+
207+ return copy;
208+}
209+
210+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
211+{
212+ if (hooks == NULL)
213+ {
214+ /* Reset hooks */
215+ global_hooks.allocate = malloc;
216+ global_hooks.deallocate = free;
217+ global_hooks.reallocate = realloc;
218+ return;
219+ }
220+
221+ global_hooks.allocate = malloc;
222+ if (hooks->malloc_fn != NULL)
223+ {
224+ global_hooks.allocate = hooks->malloc_fn;
225+ }
226+
227+ global_hooks.deallocate = free;
228+ if (hooks->free_fn != NULL)
229+ {
230+ global_hooks.deallocate = hooks->free_fn;
231+ }
232+
233+ /* use realloc only if both free and malloc are used */
234+ global_hooks.reallocate = NULL;
235+ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
236+ {
237+ global_hooks.reallocate = realloc;
238+ }
239+}
240+
241+/* Internal constructor. */
242+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
243+{
244+ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
245+ if (node)
246+ {
247+ memset(node, '\0', sizeof(cJSON));
248+ }
249+
250+ return node;
251+}
252+
253+/* Delete a cJSON structure. */
254+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
255+{
256+ cJSON *next = NULL;
257+ while (item != NULL)
258+ {
259+ next = item->next;
260+ if (!(item->type & cJSON_IsReference) && (item->child != NULL))
261+ {
262+ cJSON_Delete(item->child);
263+ }
264+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
265+ {
266+ global_hooks.deallocate(item->valuestring);
267+ item->valuestring = NULL;
268+ }
269+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
270+ {
271+ global_hooks.deallocate(item->string);
272+ item->string = NULL;
273+ }
274+ global_hooks.deallocate(item);
275+ item = next;
276+ }
277+}
278+
279+/* get the decimal point character of the current locale */
280+static unsigned char get_decimal_point(void)
281+{
282+#ifdef ENABLE_LOCALES
283+ struct lconv *lconv = localeconv();
284+ return (unsigned char) lconv->decimal_point[0];
285+#else
286+ return '.';
287+#endif
288+}
289+
290+typedef struct
291+{
292+ const unsigned char *content;
293+ size_t length;
294+ size_t offset;
295+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
296+ internal_hooks hooks;
297+} parse_buffer;
298+
299+/* check if the given size is left to read in a given parse buffer (starting with 1) */
300+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
301+/* check if the buffer can be accessed at the given index (starting with 0) */
302+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
303+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
304+/* get a pointer to the buffer at the position */
305+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
306+
307+/* Parse the input text to generate a number, and populate the result into item. */
308+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
309+{
310+ double number = 0;
311+ unsigned char *after_end = NULL;
312+ unsigned char *number_c_string;
313+ unsigned char decimal_point = get_decimal_point();
314+ size_t i = 0;
315+ size_t number_string_length = 0;
316+ cJSON_bool has_decimal_point = false;
317+
318+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
319+ {
320+ return false;
321+ }
322+
323+ /* copy the number into a temporary buffer and replace '.' with the decimal point
324+ * of the current locale (for strtod)
325+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
326+ for (i = 0; can_access_at_index(input_buffer, i); i++)
327+ {
328+ switch (buffer_at_offset(input_buffer)[i])
329+ {
330+ case '0':
331+ case '1':
332+ case '2':
333+ case '3':
334+ case '4':
335+ case '5':
336+ case '6':
337+ case '7':
338+ case '8':
339+ case '9':
340+ case '+':
341+ case '-':
342+ case 'e':
343+ case 'E':
344+ number_string_length++;
345+ break;
346+
347+ case '.':
348+ number_string_length++;
349+ has_decimal_point = true;
350+ break;
351+
352+ default:
353+ goto loop_end;
354+ }
355+ }
356+loop_end:
357+ /* malloc for temporary buffer, add 1 for '\0' */
358+ number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1);
359+ if (number_c_string == NULL)
360+ {
361+ return false; /* allocation failure */
362+ }
363+
364+ memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length);
365+ number_c_string[number_string_length] = '\0';
366+
367+ if (has_decimal_point)
368+ {
369+ for (i = 0; i < number_string_length; i++)
370+ {
371+ if (number_c_string[i] == '.')
372+ {
373+ /* replace '.' with the decimal point of the current locale (for strtod) */
374+ number_c_string[i] = decimal_point;
375+ }
376+ }
377+ }
378+
379+ number = strtod((const char*)number_c_string, (char**)&after_end);
380+ if (number_c_string == after_end)
381+ {
382+ /* free the temporary buffer */
383+ input_buffer->hooks.deallocate(number_c_string);
384+ return false; /* parse_error */
385+ }
386+
387+ item->valuedouble = number;
388+
389+ /* use saturation in case of overflow */
390+ if (number >= INT_MAX)
391+ {
392+ item->valueint = INT_MAX;
393+ }
394+ else if (number <= (double)INT_MIN)
395+ {
396+ item->valueint = INT_MIN;
397+ }
398+ else
399+ {
400+ item->valueint = (int)number;
401+ }
402+
403+ item->type = cJSON_Number;
404+
405+ input_buffer->offset += (size_t)(after_end - number_c_string);
406+ /* free the temporary buffer */
407+ input_buffer->hooks.deallocate(number_c_string);
408+ return true;
409+}
410+
411+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
412+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
413+{
414+ if (object == NULL)
415+ {
416+ return (double)NAN;
417+ }
418+
419+ if (number >= INT_MAX)
420+ {
421+ object->valueint = INT_MAX;
422+ }
423+ else if (number <= (double)INT_MIN)
424+ {
425+ object->valueint = INT_MIN;
426+ }
427+ else
428+ {
429+ object->valueint = (int)number;
430+ }
431+
432+ return object->valuedouble = number;
433+}
434+
435+/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
436+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
437+{
438+ char *copy = NULL;
439+ size_t v1_len;
440+ size_t v2_len;
441+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
442+ if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
443+ {
444+ return NULL;
445+ }
446+ /* return NULL if the object is corrupted or valuestring is NULL */
447+ if (object->valuestring == NULL || valuestring == NULL)
448+ {
449+ return NULL;
450+ }
451+
452+ v1_len = strlen(valuestring);
453+ v2_len = strlen(object->valuestring);
454+
455+ if (v1_len <= v2_len)
456+ {
457+ /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
458+ if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
459+ {
460+ return NULL;
461+ }
462+ strcpy(object->valuestring, valuestring);
463+ return object->valuestring;
464+ }
465+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
466+ if (copy == NULL)
467+ {
468+ return NULL;
469+ }
470+ if (object->valuestring != NULL)
471+ {
472+ cJSON_free(object->valuestring);
473+ }
474+ object->valuestring = copy;
475+
476+ return copy;
477+}
478+
479+typedef struct
480+{
481+ unsigned char *buffer;
482+ size_t length;
483+ size_t offset;
484+ size_t depth; /* current nesting depth (for formatted printing) */
485+ cJSON_bool noalloc;
486+ cJSON_bool format; /* is this print a formatted print */
487+ internal_hooks hooks;
488+} printbuffer;
489+
490+/* realloc printbuffer if necessary to have at least "needed" bytes more */
491+static unsigned char* ensure(printbuffer * const p, size_t needed)
492+{
493+ unsigned char *newbuffer = NULL;
494+ size_t newsize = 0;
495+
496+ if ((p == NULL) || (p->buffer == NULL))
497+ {
498+ return NULL;
499+ }
500+
501+ if ((p->length > 0) && (p->offset >= p->length))
502+ {
503+ /* make sure that offset is valid */
504+ return NULL;
505+ }
506+
507+ if (needed > INT_MAX)
508+ {
509+ /* sizes bigger than INT_MAX are currently not supported */
510+ return NULL;
511+ }
512+
513+ needed += p->offset + 1;
514+ if (needed <= p->length)
515+ {
516+ return p->buffer + p->offset;
517+ }
518+
519+ if (p->noalloc) {
520+ return NULL;
521+ }
522+
523+ /* calculate new buffer size */
524+ if (needed > (INT_MAX / 2))
525+ {
526+ /* overflow of int, use INT_MAX if possible */
527+ if (needed <= INT_MAX)
528+ {
529+ newsize = INT_MAX;
530+ }
531+ else
532+ {
533+ return NULL;
534+ }
535+ }
536+ else
537+ {
538+ newsize = needed * 2;
539+ }
540+
541+ if (p->hooks.reallocate != NULL)
542+ {
543+ /* reallocate with realloc if available */
544+ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
545+ if (newbuffer == NULL)
546+ {
547+ p->hooks.deallocate(p->buffer);
548+ p->length = 0;
549+ p->buffer = NULL;
550+
551+ return NULL;
552+ }
553+ }
554+ else
555+ {
556+ /* otherwise reallocate manually */
557+ newbuffer = (unsigned char*)p->hooks.allocate(newsize);
558+ if (!newbuffer)
559+ {
560+ p->hooks.deallocate(p->buffer);
561+ p->length = 0;
562+ p->buffer = NULL;
563+
564+ return NULL;
565+ }
566+
567+ memcpy(newbuffer, p->buffer, p->offset + 1);
568+ p->hooks.deallocate(p->buffer);
569+ }
570+ p->length = newsize;
571+ p->buffer = newbuffer;
572+
573+ return newbuffer + p->offset;
574+}
575+
576+/* calculate the new length of the string in a printbuffer and update the offset */
577+static void update_offset(printbuffer * const buffer)
578+{
579+ const unsigned char *buffer_pointer = NULL;
580+ if ((buffer == NULL) || (buffer->buffer == NULL))
581+ {
582+ return;
583+ }
584+ buffer_pointer = buffer->buffer + buffer->offset;
585+
586+ buffer->offset += strlen((const char*)buffer_pointer);
587+}
588+
589+/* securely comparison of floating-point variables */
590+static cJSON_bool compare_double(double a, double b)
591+{
592+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
593+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
594+}
595+
596+/* Render the number nicely from the given item into a string. */
597+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
598+{
599+ unsigned char *output_pointer = NULL;
600+ double d = item->valuedouble;
601+ int length = 0;
602+ size_t i = 0;
603+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
604+ unsigned char decimal_point = get_decimal_point();
605+ double test = 0.0;
606+
607+ if (output_buffer == NULL)
608+ {
609+ return false;
610+ }
611+
612+ /* This checks for NaN and Infinity */
613+ if (isnan(d) || isinf(d))
614+ {
615+ length = sprintf((char*)number_buffer, "null");
616+ }
617+ else if(d == (double)item->valueint)
618+ {
619+ length = sprintf((char*)number_buffer, "%d", item->valueint);
620+ }
621+ else
622+ {
623+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
624+ length = sprintf((char*)number_buffer, "%1.15g", d);
625+
626+ /* Check whether the original double can be recovered */
627+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
628+ {
629+ /* If not, print with 17 decimal places of precision */
630+ length = sprintf((char*)number_buffer, "%1.17g", d);
631+ }
632+ }
633+
634+ /* sprintf failed or buffer overrun occurred */
635+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
636+ {
637+ return false;
638+ }
639+
640+ /* reserve appropriate space in the output */
641+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
642+ if (output_pointer == NULL)
643+ {
644+ return false;
645+ }
646+
647+ /* copy the printed number to the output and replace locale
648+ * dependent decimal point with '.' */
649+ for (i = 0; i < ((size_t)length); i++)
650+ {
651+ if (number_buffer[i] == decimal_point)
652+ {
653+ output_pointer[i] = '.';
654+ continue;
655+ }
656+
657+ output_pointer[i] = number_buffer[i];
658+ }
659+ output_pointer[i] = '\0';
660+
661+ output_buffer->offset += (size_t)length;
662+
663+ return true;
664+}
665+
666+/* parse 4 digit hexadecimal number */
667+static unsigned parse_hex4(const unsigned char * const input)
668+{
669+ unsigned int h = 0;
670+ size_t i = 0;
671+
672+ for (i = 0; i < 4; i++)
673+ {
674+ /* parse digit */
675+ if ((input[i] >= '0') && (input[i] <= '9'))
676+ {
677+ h += (unsigned int) input[i] - '0';
678+ }
679+ else if ((input[i] >= 'A') && (input[i] <= 'F'))
680+ {
681+ h += (unsigned int) 10 + input[i] - 'A';
682+ }
683+ else if ((input[i] >= 'a') && (input[i] <= 'f'))
684+ {
685+ h += (unsigned int) 10 + input[i] - 'a';
686+ }
687+ else /* invalid */
688+ {
689+ return 0;
690+ }
691+
692+ if (i < 3)
693+ {
694+ /* shift left to make place for the next nibble */
695+ h = h << 4;
696+ }
697+ }
698+
699+ return h;
700+}
701+
702+/* converts a UTF-16 literal to UTF-8
703+ * A literal can be one or two sequences of the form \uXXXX */
704+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
705+{
706+ long unsigned int codepoint = 0;
707+ unsigned int first_code = 0;
708+ const unsigned char *first_sequence = input_pointer;
709+ unsigned char utf8_length = 0;
710+ unsigned char utf8_position = 0;
711+ unsigned char sequence_length = 0;
712+ unsigned char first_byte_mark = 0;
713+
714+ if ((input_end - first_sequence) < 6)
715+ {
716+ /* input ends unexpectedly */
717+ goto fail;
718+ }
719+
720+ /* get the first utf16 sequence */
721+ first_code = parse_hex4(first_sequence + 2);
722+
723+ /* check that the code is valid */
724+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
725+ {
726+ goto fail;
727+ }
728+
729+ /* UTF16 surrogate pair */
730+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
731+ {
732+ const unsigned char *second_sequence = first_sequence + 6;
733+ unsigned int second_code = 0;
734+ sequence_length = 12; /* \uXXXX\uXXXX */
735+
736+ if ((input_end - second_sequence) < 6)
737+ {
738+ /* input ends unexpectedly */
739+ goto fail;
740+ }
741+
742+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
743+ {
744+ /* missing second half of the surrogate pair */
745+ goto fail;
746+ }
747+
748+ /* get the second utf16 sequence */
749+ second_code = parse_hex4(second_sequence + 2);
750+ /* check that the code is valid */
751+ if ((second_code < 0xDC00) || (second_code > 0xDFFF))
752+ {
753+ /* invalid second half of the surrogate pair */
754+ goto fail;
755+ }
756+
757+
758+ /* calculate the unicode codepoint from the surrogate pair */
759+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
760+ }
761+ else
762+ {
763+ sequence_length = 6; /* \uXXXX */
764+ codepoint = first_code;
765+ }
766+
767+ /* encode as UTF-8
768+ * takes at maximum 4 bytes to encode:
769+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
770+ if (codepoint < 0x80)
771+ {
772+ /* normal ascii, encoding 0xxxxxxx */
773+ utf8_length = 1;
774+ }
775+ else if (codepoint < 0x800)
776+ {
777+ /* two bytes, encoding 110xxxxx 10xxxxxx */
778+ utf8_length = 2;
779+ first_byte_mark = 0xC0; /* 11000000 */
780+ }
781+ else if (codepoint < 0x10000)
782+ {
783+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
784+ utf8_length = 3;
785+ first_byte_mark = 0xE0; /* 11100000 */
786+ }
787+ else if (codepoint <= 0x10FFFF)
788+ {
789+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
790+ utf8_length = 4;
791+ first_byte_mark = 0xF0; /* 11110000 */
792+ }
793+ else
794+ {
795+ /* invalid unicode codepoint */
796+ goto fail;
797+ }
798+
799+ /* encode as utf8 */
800+ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
801+ {
802+ /* 10xxxxxx */
803+ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
804+ codepoint >>= 6;
805+ }
806+ /* encode first byte */
807+ if (utf8_length > 1)
808+ {
809+ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
810+ }
811+ else
812+ {
813+ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
814+ }
815+
816+ *output_pointer += utf8_length;
817+
818+ return sequence_length;
819+
820+fail:
821+ return 0;
822+}
823+
824+/* Parse the input text into an unescaped cinput, and populate item. */
825+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
826+{
827+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
828+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
829+ unsigned char *output_pointer = NULL;
830+ unsigned char *output = NULL;
831+
832+ /* not a string */
833+ if (buffer_at_offset(input_buffer)[0] != '\"')
834+ {
835+ goto fail;
836+ }
837+
838+ {
839+ /* calculate approximate size of the output (overestimate) */
840+ size_t allocation_length = 0;
841+ size_t skipped_bytes = 0;
842+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
843+ {
844+ /* is escape sequence */
845+ if (input_end[0] == '\\')
846+ {
847+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
848+ {
849+ /* prevent buffer overflow when last input character is a backslash */
850+ goto fail;
851+ }
852+ skipped_bytes++;
853+ input_end++;
854+ }
855+ input_end++;
856+ }
857+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
858+ {
859+ goto fail; /* string ended unexpectedly */
860+ }
861+
862+ /* This is at most how much we need for the output */
863+ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
864+ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
865+ if (output == NULL)
866+ {
867+ goto fail; /* allocation failure */
868+ }
869+ }
870+
871+ output_pointer = output;
872+ /* loop through the string literal */
873+ while (input_pointer < input_end)
874+ {
875+ if (*input_pointer != '\\')
876+ {
877+ *output_pointer++ = *input_pointer++;
878+ }
879+ /* escape sequence */
880+ else
881+ {
882+ unsigned char sequence_length = 2;
883+ if ((input_end - input_pointer) < 1)
884+ {
885+ goto fail;
886+ }
887+
888+ switch (input_pointer[1])
889+ {
890+ case 'b':
891+ *output_pointer++ = '\b';
892+ break;
893+ case 'f':
894+ *output_pointer++ = '\f';
895+ break;
896+ case 'n':
897+ *output_pointer++ = '\n';
898+ break;
899+ case 'r':
900+ *output_pointer++ = '\r';
901+ break;
902+ case 't':
903+ *output_pointer++ = '\t';
904+ break;
905+ case '\"':
906+ case '\\':
907+ case '/':
908+ *output_pointer++ = input_pointer[1];
909+ break;
910+
911+ /* UTF-16 literal */
912+ case 'u':
913+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
914+ if (sequence_length == 0)
915+ {
916+ /* failed to convert UTF16-literal to UTF-8 */
917+ goto fail;
918+ }
919+ break;
920+
921+ default:
922+ goto fail;
923+ }
924+ input_pointer += sequence_length;
925+ }
926+ }
927+
928+ /* zero terminate the output */
929+ *output_pointer = '\0';
930+
931+ item->type = cJSON_String;
932+ item->valuestring = (char*)output;
933+
934+ input_buffer->offset = (size_t) (input_end - input_buffer->content);
935+ input_buffer->offset++;
936+
937+ return true;
938+
939+fail:
940+ if (output != NULL)
941+ {
942+ input_buffer->hooks.deallocate(output);
943+ output = NULL;
944+ }
945+
946+ if (input_pointer != NULL)
947+ {
948+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
949+ }
950+
951+ return false;
952+}
953+
954+/* Render the cstring provided to an escaped version that can be printed. */
955+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
956+{
957+ const unsigned char *input_pointer = NULL;
958+ unsigned char *output = NULL;
959+ unsigned char *output_pointer = NULL;
960+ size_t output_length = 0;
961+ /* numbers of additional characters needed for escaping */
962+ size_t escape_characters = 0;
963+
964+ if (output_buffer == NULL)
965+ {
966+ return false;
967+ }
968+
969+ /* empty string */
970+ if (input == NULL)
971+ {
972+ output = ensure(output_buffer, sizeof("\"\""));
973+ if (output == NULL)
974+ {
975+ return false;
976+ }
977+ strcpy((char*)output, "\"\"");
978+
979+ return true;
980+ }
981+
982+ /* set "flag" to 1 if something needs to be escaped */
983+ for (input_pointer = input; *input_pointer; input_pointer++)
984+ {
985+ switch (*input_pointer)
986+ {
987+ case '\"':
988+ case '\\':
989+ case '\b':
990+ case '\f':
991+ case '\n':
992+ case '\r':
993+ case '\t':
994+ /* one character escape sequence */
995+ escape_characters++;
996+ break;
997+ default:
998+ if (*input_pointer < 32)
999+ {
1000+ /* UTF-16 escape sequence uXXXX */
1001+ escape_characters += 5;
1002+ }
1003+ break;
1004+ }
1005+ }
1006+ output_length = (size_t)(input_pointer - input) + escape_characters;
1007+
1008+ output = ensure(output_buffer, output_length + sizeof("\"\""));
1009+ if (output == NULL)
1010+ {
1011+ return false;
1012+ }
1013+
1014+ /* no characters have to be escaped */
1015+ if (escape_characters == 0)
1016+ {
1017+ output[0] = '\"';
1018+ memcpy(output + 1, input, output_length);
1019+ output[output_length + 1] = '\"';
1020+ output[output_length + 2] = '\0';
1021+
1022+ return true;
1023+ }
1024+
1025+ output[0] = '\"';
1026+ output_pointer = output + 1;
1027+ /* copy the string */
1028+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
1029+ {
1030+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
1031+ {
1032+ /* normal character, copy */
1033+ *output_pointer = *input_pointer;
1034+ }
1035+ else
1036+ {
1037+ /* character needs to be escaped */
1038+ *output_pointer++ = '\\';
1039+ switch (*input_pointer)
1040+ {
1041+ case '\\':
1042+ *output_pointer = '\\';
1043+ break;
1044+ case '\"':
1045+ *output_pointer = '\"';
1046+ break;
1047+ case '\b':
1048+ *output_pointer = 'b';
1049+ break;
1050+ case '\f':
1051+ *output_pointer = 'f';
1052+ break;
1053+ case '\n':
1054+ *output_pointer = 'n';
1055+ break;
1056+ case '\r':
1057+ *output_pointer = 'r';
1058+ break;
1059+ case '\t':
1060+ *output_pointer = 't';
1061+ break;
1062+ default:
1063+ /* escape and print as unicode codepoint */
1064+ sprintf((char*)output_pointer, "u%04x", *input_pointer);
1065+ output_pointer += 4;
1066+ break;
1067+ }
1068+ }
1069+ }
1070+ output[output_length + 1] = '\"';
1071+ output[output_length + 2] = '\0';
1072+
1073+ return true;
1074+}
1075+
1076+/* Invoke print_string_ptr (which is useful) on an item. */
1077+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
1078+{
1079+ return print_string_ptr((unsigned char*)item->valuestring, p);
1080+}
1081+
1082+/* Predeclare these prototypes. */
1083+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
1084+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
1085+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
1086+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
1087+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
1088+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
1089+
1090+/* Utility to jump whitespace and cr/lf */
1091+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
1092+{
1093+ if ((buffer == NULL) || (buffer->content == NULL))
1094+ {
1095+ return NULL;
1096+ }
1097+
1098+ if (cannot_access_at_index(buffer, 0))
1099+ {
1100+ return buffer;
1101+ }
1102+
1103+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
1104+ {
1105+ buffer->offset++;
1106+ }
1107+
1108+ if (buffer->offset == buffer->length)
1109+ {
1110+ buffer->offset--;
1111+ }
1112+
1113+ return buffer;
1114+}
1115+
1116+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
1117+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1118+{
1119+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1120+ {
1121+ return NULL;
1122+ }
1123+
1124+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1125+ {
1126+ buffer->offset += 3;
1127+ }
1128+
1129+ return buffer;
1130+}
1131+
1132+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1133+{
1134+ size_t buffer_length;
1135+
1136+ if (NULL == value)
1137+ {
1138+ return NULL;
1139+ }
1140+
1141+ /* Adding null character size due to require_null_terminated. */
1142+ buffer_length = strlen(value) + sizeof("");
1143+
1144+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
1145+}
1146+
1147+/* Parse an object - create a new root, and populate. */
1148+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
1149+{
1150+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1151+ cJSON *item = NULL;
1152+
1153+ /* reset error position */
1154+ global_error.json = NULL;
1155+ global_error.position = 0;
1156+
1157+ if (value == NULL || 0 == buffer_length)
1158+ {
1159+ goto fail;
1160+ }
1161+
1162+ buffer.content = (const unsigned char*)value;
1163+ buffer.length = buffer_length;
1164+ buffer.offset = 0;
1165+ buffer.hooks = global_hooks;
1166+
1167+ item = cJSON_New_Item(&global_hooks);
1168+ if (item == NULL) /* memory fail */
1169+ {
1170+ goto fail;
1171+ }
1172+
1173+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1174+ {
1175+ /* parse failure. ep is set. */
1176+ goto fail;
1177+ }
1178+
1179+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1180+ if (require_null_terminated)
1181+ {
1182+ buffer_skip_whitespace(&buffer);
1183+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1184+ {
1185+ goto fail;
1186+ }
1187+ }
1188+ if (return_parse_end)
1189+ {
1190+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
1191+ }
1192+
1193+ return item;
1194+
1195+fail:
1196+ if (item != NULL)
1197+ {
1198+ cJSON_Delete(item);
1199+ }
1200+
1201+ if (value != NULL)
1202+ {
1203+ error local_error;
1204+ local_error.json = (const unsigned char*)value;
1205+ local_error.position = 0;
1206+
1207+ if (buffer.offset < buffer.length)
1208+ {
1209+ local_error.position = buffer.offset;
1210+ }
1211+ else if (buffer.length > 0)
1212+ {
1213+ local_error.position = buffer.length - 1;
1214+ }
1215+
1216+ if (return_parse_end != NULL)
1217+ {
1218+ *return_parse_end = (const char*)local_error.json + local_error.position;
1219+ }
1220+
1221+ global_error = local_error;
1222+ }
1223+
1224+ return NULL;
1225+}
1226+
1227+/* Default options for cJSON_Parse */
1228+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1229+{
1230+ return cJSON_ParseWithOpts(value, 0, 0);
1231+}
1232+
1233+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
1234+{
1235+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
1236+}
1237+
1238+#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1239+
1240+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1241+{
1242+ static const size_t default_buffer_size = 256;
1243+ printbuffer buffer[1];
1244+ unsigned char *printed = NULL;
1245+
1246+ memset(buffer, 0, sizeof(buffer));
1247+
1248+ /* create buffer */
1249+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1250+ buffer->length = default_buffer_size;
1251+ buffer->format = format;
1252+ buffer->hooks = *hooks;
1253+ if (buffer->buffer == NULL)
1254+ {
1255+ goto fail;
1256+ }
1257+
1258+ /* print the value */
1259+ if (!print_value(item, buffer))
1260+ {
1261+ goto fail;
1262+ }
1263+ update_offset(buffer);
1264+
1265+ /* check if reallocate is available */
1266+ if (hooks->reallocate != NULL)
1267+ {
1268+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1269+ if (printed == NULL) {
1270+ goto fail;
1271+ }
1272+ buffer->buffer = NULL;
1273+ }
1274+ else /* otherwise copy the JSON over to a new buffer */
1275+ {
1276+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1277+ if (printed == NULL)
1278+ {
1279+ goto fail;
1280+ }
1281+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1282+ printed[buffer->offset] = '\0'; /* just to be sure */
1283+
1284+ /* free the buffer */
1285+ hooks->deallocate(buffer->buffer);
1286+ buffer->buffer = NULL;
1287+ }
1288+
1289+ return printed;
1290+
1291+fail:
1292+ if (buffer->buffer != NULL)
1293+ {
1294+ hooks->deallocate(buffer->buffer);
1295+ buffer->buffer = NULL;
1296+ }
1297+
1298+ if (printed != NULL)
1299+ {
1300+ hooks->deallocate(printed);
1301+ printed = NULL;
1302+ }
1303+
1304+ return NULL;
1305+}
1306+
1307+/* Render a cJSON item/entity/structure to text. */
1308+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1309+{
1310+ return (char*)print(item, true, &global_hooks);
1311+}
1312+
1313+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1314+{
1315+ return (char*)print(item, false, &global_hooks);
1316+}
1317+
1318+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1319+{
1320+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1321+
1322+ if (prebuffer < 0)
1323+ {
1324+ return NULL;
1325+ }
1326+
1327+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1328+ if (!p.buffer)
1329+ {
1330+ return NULL;
1331+ }
1332+
1333+ p.length = (size_t)prebuffer;
1334+ p.offset = 0;
1335+ p.noalloc = false;
1336+ p.format = fmt;
1337+ p.hooks = global_hooks;
1338+
1339+ if (!print_value(item, &p))
1340+ {
1341+ global_hooks.deallocate(p.buffer);
1342+ p.buffer = NULL;
1343+ return NULL;
1344+ }
1345+
1346+ return (char*)p.buffer;
1347+}
1348+
1349+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
1350+{
1351+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1352+
1353+ if ((length < 0) || (buffer == NULL))
1354+ {
1355+ return false;
1356+ }
1357+
1358+ p.buffer = (unsigned char*)buffer;
1359+ p.length = (size_t)length;
1360+ p.offset = 0;
1361+ p.noalloc = true;
1362+ p.format = format;
1363+ p.hooks = global_hooks;
1364+
1365+ return print_value(item, &p);
1366+}
1367+
1368+/* Parser core - when encountering text, process appropriately. */
1369+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1370+{
1371+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
1372+ {
1373+ return false; /* no input */
1374+ }
1375+
1376+ /* parse the different types of values */
1377+ /* null */
1378+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1379+ {
1380+ item->type = cJSON_NULL;
1381+ input_buffer->offset += 4;
1382+ return true;
1383+ }
1384+ /* false */
1385+ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1386+ {
1387+ item->type = cJSON_False;
1388+ input_buffer->offset += 5;
1389+ return true;
1390+ }
1391+ /* true */
1392+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1393+ {
1394+ item->type = cJSON_True;
1395+ item->valueint = 1;
1396+ input_buffer->offset += 4;
1397+ return true;
1398+ }
1399+ /* string */
1400+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1401+ {
1402+ return parse_string(item, input_buffer);
1403+ }
1404+ /* number */
1405+ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
1406+ {
1407+ return parse_number(item, input_buffer);
1408+ }
1409+ /* array */
1410+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1411+ {
1412+ return parse_array(item, input_buffer);
1413+ }
1414+ /* object */
1415+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1416+ {
1417+ return parse_object(item, input_buffer);
1418+ }
1419+
1420+ return false;
1421+}
1422+
1423+/* Render a value to text. */
1424+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1425+{
1426+ unsigned char *output = NULL;
1427+
1428+ if ((item == NULL) || (output_buffer == NULL))
1429+ {
1430+ return false;
1431+ }
1432+
1433+ switch ((item->type) & 0xFF)
1434+ {
1435+ case cJSON_NULL:
1436+ output = ensure(output_buffer, 5);
1437+ if (output == NULL)
1438+ {
1439+ return false;
1440+ }
1441+ strcpy((char*)output, "null");
1442+ return true;
1443+
1444+ case cJSON_False:
1445+ output = ensure(output_buffer, 6);
1446+ if (output == NULL)
1447+ {
1448+ return false;
1449+ }
1450+ strcpy((char*)output, "false");
1451+ return true;
1452+
1453+ case cJSON_True:
1454+ output = ensure(output_buffer, 5);
1455+ if (output == NULL)
1456+ {
1457+ return false;
1458+ }
1459+ strcpy((char*)output, "true");
1460+ return true;
1461+
1462+ case cJSON_Number:
1463+ return print_number(item, output_buffer);
1464+
1465+ case cJSON_Raw:
1466+ {
1467+ size_t raw_length = 0;
1468+ if (item->valuestring == NULL)
1469+ {
1470+ return false;
1471+ }
1472+
1473+ raw_length = strlen(item->valuestring) + sizeof("");
1474+ output = ensure(output_buffer, raw_length);
1475+ if (output == NULL)
1476+ {
1477+ return false;
1478+ }
1479+ memcpy(output, item->valuestring, raw_length);
1480+ return true;
1481+ }
1482+
1483+ case cJSON_String:
1484+ return print_string(item, output_buffer);
1485+
1486+ case cJSON_Array:
1487+ return print_array(item, output_buffer);
1488+
1489+ case cJSON_Object:
1490+ return print_object(item, output_buffer);
1491+
1492+ default:
1493+ return false;
1494+ }
1495+}
1496+
1497+/* Build an array from input text. */
1498+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1499+{
1500+ cJSON *head = NULL; /* head of the linked list */
1501+ cJSON *current_item = NULL;
1502+
1503+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1504+ {
1505+ return false; /* to deeply nested */
1506+ }
1507+ input_buffer->depth++;
1508+
1509+ if (buffer_at_offset(input_buffer)[0] != '[')
1510+ {
1511+ /* not an array */
1512+ goto fail;
1513+ }
1514+
1515+ input_buffer->offset++;
1516+ buffer_skip_whitespace(input_buffer);
1517+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1518+ {
1519+ /* empty array */
1520+ goto success;
1521+ }
1522+
1523+ /* check if we skipped to the end of the buffer */
1524+ if (cannot_access_at_index(input_buffer, 0))
1525+ {
1526+ input_buffer->offset--;
1527+ goto fail;
1528+ }
1529+
1530+ /* step back to character in front of the first element */
1531+ input_buffer->offset--;
1532+ /* loop through the comma separated array elements */
1533+ do
1534+ {
1535+ /* allocate next item */
1536+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1537+ if (new_item == NULL)
1538+ {
1539+ goto fail; /* allocation failure */
1540+ }
1541+
1542+ /* attach next item to list */
1543+ if (head == NULL)
1544+ {
1545+ /* start the linked list */
1546+ current_item = head = new_item;
1547+ }
1548+ else
1549+ {
1550+ /* add to the end and advance */
1551+ current_item->next = new_item;
1552+ new_item->prev = current_item;
1553+ current_item = new_item;
1554+ }
1555+
1556+ /* parse next value */
1557+ input_buffer->offset++;
1558+ buffer_skip_whitespace(input_buffer);
1559+ if (!parse_value(current_item, input_buffer))
1560+ {
1561+ goto fail; /* failed to parse value */
1562+ }
1563+ buffer_skip_whitespace(input_buffer);
1564+ }
1565+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1566+
1567+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1568+ {
1569+ goto fail; /* expected end of array */
1570+ }
1571+
1572+success:
1573+ input_buffer->depth--;
1574+
1575+ if (head != NULL) {
1576+ head->prev = current_item;
1577+ }
1578+
1579+ item->type = cJSON_Array;
1580+ item->child = head;
1581+
1582+ input_buffer->offset++;
1583+
1584+ return true;
1585+
1586+fail:
1587+ if (head != NULL)
1588+ {
1589+ cJSON_Delete(head);
1590+ }
1591+
1592+ return false;
1593+}
1594+
1595+/* Render an array to text */
1596+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1597+{
1598+ unsigned char *output_pointer = NULL;
1599+ size_t length = 0;
1600+ cJSON *current_element = item->child;
1601+
1602+ if (output_buffer == NULL)
1603+ {
1604+ return false;
1605+ }
1606+
1607+ if (output_buffer->depth >= CJSON_NESTING_LIMIT)
1608+ {
1609+ return false; /* nesting is too deep */
1610+ }
1611+
1612+ /* Compose the output array. */
1613+ /* opening square bracket */
1614+ output_pointer = ensure(output_buffer, 1);
1615+ if (output_pointer == NULL)
1616+ {
1617+ return false;
1618+ }
1619+
1620+ *output_pointer = '[';
1621+ output_buffer->offset++;
1622+ output_buffer->depth++;
1623+
1624+ while (current_element != NULL)
1625+ {
1626+ if (!print_value(current_element, output_buffer))
1627+ {
1628+ return false;
1629+ }
1630+ update_offset(output_buffer);
1631+ if (current_element->next)
1632+ {
1633+ length = (size_t) (output_buffer->format ? 2 : 1);
1634+ output_pointer = ensure(output_buffer, length + 1);
1635+ if (output_pointer == NULL)
1636+ {
1637+ return false;
1638+ }
1639+ *output_pointer++ = ',';
1640+ if(output_buffer->format)
1641+ {
1642+ *output_pointer++ = ' ';
1643+ }
1644+ *output_pointer = '\0';
1645+ output_buffer->offset += length;
1646+ }
1647+ current_element = current_element->next;
1648+ }
1649+
1650+ output_pointer = ensure(output_buffer, 2);
1651+ if (output_pointer == NULL)
1652+ {
1653+ return false;
1654+ }
1655+ *output_pointer++ = ']';
1656+ *output_pointer = '\0';
1657+ output_buffer->depth--;
1658+
1659+ return true;
1660+}
1661+
1662+/* Build an object from the text. */
1663+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1664+{
1665+ cJSON *head = NULL; /* linked list head */
1666+ cJSON *current_item = NULL;
1667+
1668+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1669+ {
1670+ return false; /* to deeply nested */
1671+ }
1672+ input_buffer->depth++;
1673+
1674+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1675+ {
1676+ goto fail; /* not an object */
1677+ }
1678+
1679+ input_buffer->offset++;
1680+ buffer_skip_whitespace(input_buffer);
1681+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1682+ {
1683+ goto success; /* empty object */
1684+ }
1685+
1686+ /* check if we skipped to the end of the buffer */
1687+ if (cannot_access_at_index(input_buffer, 0))
1688+ {
1689+ input_buffer->offset--;
1690+ goto fail;
1691+ }
1692+
1693+ /* step back to character in front of the first element */
1694+ input_buffer->offset--;
1695+ /* loop through the comma separated array elements */
1696+ do
1697+ {
1698+ /* allocate next item */
1699+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1700+ if (new_item == NULL)
1701+ {
1702+ goto fail; /* allocation failure */
1703+ }
1704+
1705+ /* attach next item to list */
1706+ if (head == NULL)
1707+ {
1708+ /* start the linked list */
1709+ current_item = head = new_item;
1710+ }
1711+ else
1712+ {
1713+ /* add to the end and advance */
1714+ current_item->next = new_item;
1715+ new_item->prev = current_item;
1716+ current_item = new_item;
1717+ }
1718+
1719+ if (cannot_access_at_index(input_buffer, 1))
1720+ {
1721+ goto fail; /* nothing comes after the comma */
1722+ }
1723+
1724+ /* parse the name of the child */
1725+ input_buffer->offset++;
1726+ buffer_skip_whitespace(input_buffer);
1727+ if (!parse_string(current_item, input_buffer))
1728+ {
1729+ goto fail; /* failed to parse name */
1730+ }
1731+ buffer_skip_whitespace(input_buffer);
1732+
1733+ /* swap valuestring and string, because we parsed the name */
1734+ current_item->string = current_item->valuestring;
1735+ current_item->valuestring = NULL;
1736+
1737+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1738+ {
1739+ goto fail; /* invalid object */
1740+ }
1741+
1742+ /* parse the value */
1743+ input_buffer->offset++;
1744+ buffer_skip_whitespace(input_buffer);
1745+ if (!parse_value(current_item, input_buffer))
1746+ {
1747+ goto fail; /* failed to parse value */
1748+ }
1749+ buffer_skip_whitespace(input_buffer);
1750+ }
1751+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1752+
1753+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1754+ {
1755+ goto fail; /* expected end of object */
1756+ }
1757+
1758+success:
1759+ input_buffer->depth--;
1760+
1761+ if (head != NULL) {
1762+ head->prev = current_item;
1763+ }
1764+
1765+ item->type = cJSON_Object;
1766+ item->child = head;
1767+
1768+ input_buffer->offset++;
1769+ return true;
1770+
1771+fail:
1772+ if (head != NULL)
1773+ {
1774+ cJSON_Delete(head);
1775+ }
1776+
1777+ return false;
1778+}
1779+
1780+/* Render an object to text. */
1781+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1782+{
1783+ unsigned char *output_pointer = NULL;
1784+ size_t length = 0;
1785+ cJSON *current_item = item->child;
1786+
1787+ if (output_buffer == NULL)
1788+ {
1789+ return false;
1790+ }
1791+
1792+ if (output_buffer->depth >= CJSON_NESTING_LIMIT)
1793+ {
1794+ return false; /* nesting is too deep */
1795+ }
1796+
1797+ /* Compose the output: */
1798+ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1799+ output_pointer = ensure(output_buffer, length + 1);
1800+ if (output_pointer == NULL)
1801+ {
1802+ return false;
1803+ }
1804+
1805+ *output_pointer++ = '{';
1806+ output_buffer->depth++;
1807+ if (output_buffer->format)
1808+ {
1809+ *output_pointer++ = '\n';
1810+ }
1811+ output_buffer->offset += length;
1812+
1813+ while (current_item)
1814+ {
1815+ if (output_buffer->format)
1816+ {
1817+ size_t i;
1818+ output_pointer = ensure(output_buffer, output_buffer->depth);
1819+ if (output_pointer == NULL)
1820+ {
1821+ return false;
1822+ }
1823+ for (i = 0; i < output_buffer->depth; i++)
1824+ {
1825+ *output_pointer++ = '\t';
1826+ }
1827+ output_buffer->offset += output_buffer->depth;
1828+ }
1829+
1830+ /* print key */
1831+ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1832+ {
1833+ return false;
1834+ }
1835+ update_offset(output_buffer);
1836+
1837+ length = (size_t) (output_buffer->format ? 2 : 1);
1838+ output_pointer = ensure(output_buffer, length);
1839+ if (output_pointer == NULL)
1840+ {
1841+ return false;
1842+ }
1843+ *output_pointer++ = ':';
1844+ if (output_buffer->format)
1845+ {
1846+ *output_pointer++ = '\t';
1847+ }
1848+ output_buffer->offset += length;
1849+
1850+ /* print value */
1851+ if (!print_value(current_item, output_buffer))
1852+ {
1853+ return false;
1854+ }
1855+ update_offset(output_buffer);
1856+
1857+ /* print comma if not last */
1858+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1859+ output_pointer = ensure(output_buffer, length + 1);
1860+ if (output_pointer == NULL)
1861+ {
1862+ return false;
1863+ }
1864+ if (current_item->next)
1865+ {
1866+ *output_pointer++ = ',';
1867+ }
1868+
1869+ if (output_buffer->format)
1870+ {
1871+ *output_pointer++ = '\n';
1872+ }
1873+ *output_pointer = '\0';
1874+ output_buffer->offset += length;
1875+
1876+ current_item = current_item->next;
1877+ }
1878+
1879+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1880+ if (output_pointer == NULL)
1881+ {
1882+ return false;
1883+ }
1884+ if (output_buffer->format)
1885+ {
1886+ size_t i;
1887+ for (i = 0; i < (output_buffer->depth - 1); i++)
1888+ {
1889+ *output_pointer++ = '\t';
1890+ }
1891+ }
1892+ *output_pointer++ = '}';
1893+ *output_pointer = '\0';
1894+ output_buffer->depth--;
1895+
1896+ return true;
1897+}
1898+
1899+/* Get Array size/item / object item. */
1900+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1901+{
1902+ cJSON *child = NULL;
1903+ size_t size = 0;
1904+
1905+ if (array == NULL)
1906+ {
1907+ return 0;
1908+ }
1909+
1910+ child = array->child;
1911+
1912+ while(child != NULL)
1913+ {
1914+ size++;
1915+ child = child->next;
1916+ }
1917+
1918+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1919+
1920+ return (int)size;
1921+}
1922+
1923+static cJSON* get_array_item(const cJSON *array, size_t index)
1924+{
1925+ cJSON *current_child = NULL;
1926+
1927+ if (array == NULL)
1928+ {
1929+ return NULL;
1930+ }
1931+
1932+ current_child = array->child;
1933+ while ((current_child != NULL) && (index > 0))
1934+ {
1935+ index--;
1936+ current_child = current_child->next;
1937+ }
1938+
1939+ return current_child;
1940+}
1941+
1942+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1943+{
1944+ if (index < 0)
1945+ {
1946+ return NULL;
1947+ }
1948+
1949+ return get_array_item(array, (size_t)index);
1950+}
1951+
1952+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1953+{
1954+ cJSON *current_element = NULL;
1955+
1956+ if ((object == NULL) || (name == NULL))
1957+ {
1958+ return NULL;
1959+ }
1960+
1961+ current_element = object->child;
1962+ if (case_sensitive)
1963+ {
1964+ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1965+ {
1966+ current_element = current_element->next;
1967+ }
1968+ }
1969+ else
1970+ {
1971+ while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1972+ {
1973+ current_element = current_element->next;
1974+ }
1975+ }
1976+
1977+ if ((current_element == NULL) || (current_element->string == NULL)) {
1978+ return NULL;
1979+ }
1980+
1981+ return current_element;
1982+}
1983+
1984+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1985+{
1986+ return get_object_item(object, string, false);
1987+}
1988+
1989+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1990+{
1991+ return get_object_item(object, string, true);
1992+}
1993+
1994+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1995+{
1996+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
1997+}
1998+
1999+/* Utility for array list handling. */
2000+static void suffix_object(cJSON *prev, cJSON *item)
2001+{
2002+ prev->next = item;
2003+ item->prev = prev;
2004+}
2005+
2006+/* Utility for handling references. */
2007+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
2008+{
2009+ cJSON *reference = NULL;
2010+ if (item == NULL)
2011+ {
2012+ return NULL;
2013+ }
2014+
2015+ reference = cJSON_New_Item(hooks);
2016+ if (reference == NULL)
2017+ {
2018+ return NULL;
2019+ }
2020+
2021+ memcpy(reference, item, sizeof(cJSON));
2022+ reference->string = NULL;
2023+ reference->type |= cJSON_IsReference;
2024+ reference->next = reference->prev = NULL;
2025+ return reference;
2026+}
2027+
2028+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
2029+{
2030+ cJSON *child = NULL;
2031+
2032+ if ((item == NULL) || (array == NULL) || (array == item))
2033+ {
2034+ return false;
2035+ }
2036+
2037+ child = array->child;
2038+ /*
2039+ * To find the last item in array quickly, we use prev in array
2040+ */
2041+ if (child == NULL)
2042+ {
2043+ /* list is empty, start new one */
2044+ array->child = item;
2045+ item->prev = item;
2046+ item->next = NULL;
2047+ }
2048+ else
2049+ {
2050+ /* append to the end */
2051+ if (child->prev)
2052+ {
2053+ suffix_object(child->prev, item);
2054+ array->child->prev = item;
2055+ }
2056+ }
2057+
2058+ return true;
2059+}
2060+
2061+/* Add item to array/object. */
2062+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
2063+{
2064+ return add_item_to_array(array, item);
2065+}
2066+
2067+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2068+ #pragma GCC diagnostic push
2069+#endif
2070+#ifdef __GNUC__
2071+#pragma GCC diagnostic ignored "-Wcast-qual"
2072+#endif
2073+/* helper function to cast away const */
2074+static void* cast_away_const(const void* string)
2075+{
2076+ return (void*)string;
2077+}
2078+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
2079+ #pragma GCC diagnostic pop
2080+#endif
2081+
2082+
2083+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
2084+{
2085+ char *new_key = NULL;
2086+ int new_type = cJSON_Invalid;
2087+
2088+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
2089+ {
2090+ return false;
2091+ }
2092+
2093+ if (constant_key)
2094+ {
2095+ new_key = (char*)cast_away_const(string);
2096+ new_type = item->type | cJSON_StringIsConst;
2097+ }
2098+ else
2099+ {
2100+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
2101+ if (new_key == NULL)
2102+ {
2103+ return false;
2104+ }
2105+
2106+ new_type = item->type & ~cJSON_StringIsConst;
2107+ }
2108+
2109+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
2110+ {
2111+ hooks->deallocate(item->string);
2112+ }
2113+
2114+ item->string = new_key;
2115+ item->type = new_type;
2116+
2117+ return add_item_to_array(object, item);
2118+}
2119+
2120+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
2121+{
2122+ return add_item_to_object(object, string, item, &global_hooks, false);
2123+}
2124+
2125+/* Add an item to an object with constant string as key */
2126+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
2127+{
2128+ return add_item_to_object(object, string, item, &global_hooks, true);
2129+}
2130+
2131+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
2132+{
2133+ if (array == NULL)
2134+ {
2135+ return false;
2136+ }
2137+
2138+ return add_item_to_array(array, create_reference(item, &global_hooks));
2139+}
2140+
2141+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
2142+{
2143+ if ((object == NULL) || (string == NULL))
2144+ {
2145+ return false;
2146+ }
2147+
2148+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
2149+}
2150+
2151+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
2152+{
2153+ cJSON *null = cJSON_CreateNull();
2154+ if (add_item_to_object(object, name, null, &global_hooks, false))
2155+ {
2156+ return null;
2157+ }
2158+
2159+ cJSON_Delete(null);
2160+ return NULL;
2161+}
2162+
2163+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2164+{
2165+ cJSON *true_item = cJSON_CreateTrue();
2166+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
2167+ {
2168+ return true_item;
2169+ }
2170+
2171+ cJSON_Delete(true_item);
2172+ return NULL;
2173+}
2174+
2175+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2176+{
2177+ cJSON *false_item = cJSON_CreateFalse();
2178+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
2179+ {
2180+ return false_item;
2181+ }
2182+
2183+ cJSON_Delete(false_item);
2184+ return NULL;
2185+}
2186+
2187+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2188+{
2189+ cJSON *bool_item = cJSON_CreateBool(boolean);
2190+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2191+ {
2192+ return bool_item;
2193+ }
2194+
2195+ cJSON_Delete(bool_item);
2196+ return NULL;
2197+}
2198+
2199+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2200+{
2201+ cJSON *number_item = cJSON_CreateNumber(number);
2202+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
2203+ {
2204+ return number_item;
2205+ }
2206+
2207+ cJSON_Delete(number_item);
2208+ return NULL;
2209+}
2210+
2211+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2212+{
2213+ cJSON *string_item = cJSON_CreateString(string);
2214+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
2215+ {
2216+ return string_item;
2217+ }
2218+
2219+ cJSON_Delete(string_item);
2220+ return NULL;
2221+}
2222+
2223+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2224+{
2225+ cJSON *raw_item = cJSON_CreateRaw(raw);
2226+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2227+ {
2228+ return raw_item;
2229+ }
2230+
2231+ cJSON_Delete(raw_item);
2232+ return NULL;
2233+}
2234+
2235+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2236+{
2237+ cJSON *object_item = cJSON_CreateObject();
2238+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
2239+ {
2240+ return object_item;
2241+ }
2242+
2243+ cJSON_Delete(object_item);
2244+ return NULL;
2245+}
2246+
2247+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2248+{
2249+ cJSON *array = cJSON_CreateArray();
2250+ if (add_item_to_object(object, name, array, &global_hooks, false))
2251+ {
2252+ return array;
2253+ }
2254+
2255+ cJSON_Delete(array);
2256+ return NULL;
2257+}
2258+
2259+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2260+{
2261+ if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
2262+ {
2263+ return NULL;
2264+ }
2265+
2266+ if (item != parent->child)
2267+ {
2268+ /* not the first element */
2269+ item->prev->next = item->next;
2270+ }
2271+ if (item->next != NULL)
2272+ {
2273+ /* not the last element */
2274+ item->next->prev = item->prev;
2275+ }
2276+
2277+ if (item == parent->child)
2278+ {
2279+ /* first element */
2280+ parent->child = item->next;
2281+ }
2282+ else if (item->next == NULL)
2283+ {
2284+ /* last element */
2285+ parent->child->prev = item->prev;
2286+ }
2287+
2288+ /* make sure the detached item doesn't point anywhere anymore */
2289+ item->prev = NULL;
2290+ item->next = NULL;
2291+
2292+ return item;
2293+}
2294+
2295+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2296+{
2297+ if (which < 0)
2298+ {
2299+ return NULL;
2300+ }
2301+
2302+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2303+}
2304+
2305+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2306+{
2307+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2308+}
2309+
2310+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2311+{
2312+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
2313+
2314+ return cJSON_DetachItemViaPointer(object, to_detach);
2315+}
2316+
2317+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2318+{
2319+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2320+
2321+ return cJSON_DetachItemViaPointer(object, to_detach);
2322+}
2323+
2324+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2325+{
2326+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2327+}
2328+
2329+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2330+{
2331+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2332+}
2333+
2334+/* Replace array/object items with new ones. */
2335+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2336+{
2337+ cJSON *after_inserted = NULL;
2338+
2339+ if (which < 0 || newitem == NULL)
2340+ {
2341+ return false;
2342+ }
2343+
2344+ after_inserted = get_array_item(array, (size_t)which);
2345+ if (after_inserted == NULL)
2346+ {
2347+ return add_item_to_array(array, newitem);
2348+ }
2349+
2350+ if (after_inserted != array->child && after_inserted->prev == NULL) {
2351+ /* return false if after_inserted is a corrupted array item */
2352+ return false;
2353+ }
2354+
2355+ newitem->next = after_inserted;
2356+ newitem->prev = after_inserted->prev;
2357+ after_inserted->prev = newitem;
2358+ if (after_inserted == array->child)
2359+ {
2360+ array->child = newitem;
2361+ }
2362+ else
2363+ {
2364+ newitem->prev->next = newitem;
2365+ }
2366+ return true;
2367+}
2368+
2369+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2370+{
2371+ if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
2372+ {
2373+ return false;
2374+ }
2375+
2376+ if (replacement == item)
2377+ {
2378+ return true;
2379+ }
2380+
2381+ replacement->next = item->next;
2382+ replacement->prev = item->prev;
2383+
2384+ if (replacement->next != NULL)
2385+ {
2386+ replacement->next->prev = replacement;
2387+ }
2388+ if (parent->child == item)
2389+ {
2390+ if (parent->child->prev == parent->child)
2391+ {
2392+ replacement->prev = replacement;
2393+ }
2394+ parent->child = replacement;
2395+ }
2396+ else
2397+ { /*
2398+ * To find the last item in array quickly, we use prev in array.
2399+ * We can't modify the last item's next pointer where this item was the parent's child
2400+ */
2401+ if (replacement->prev != NULL)
2402+ {
2403+ replacement->prev->next = replacement;
2404+ }
2405+ if (replacement->next == NULL)
2406+ {
2407+ parent->child->prev = replacement;
2408+ }
2409+ }
2410+
2411+ item->next = NULL;
2412+ item->prev = NULL;
2413+ cJSON_Delete(item);
2414+
2415+ return true;
2416+}
2417+
2418+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2419+{
2420+ if (which < 0)
2421+ {
2422+ return false;
2423+ }
2424+
2425+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2426+}
2427+
2428+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2429+{
2430+ if ((replacement == NULL) || (string == NULL))
2431+ {
2432+ return false;
2433+ }
2434+
2435+ /* replace the name in the replacement */
2436+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2437+ {
2438+ cJSON_free(replacement->string);
2439+ }
2440+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2441+ if (replacement->string == NULL)
2442+ {
2443+ return false;
2444+ }
2445+
2446+ replacement->type &= ~cJSON_StringIsConst;
2447+
2448+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2449+}
2450+
2451+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2452+{
2453+ return replace_item_in_object(object, string, newitem, false);
2454+}
2455+
2456+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2457+{
2458+ return replace_item_in_object(object, string, newitem, true);
2459+}
2460+
2461+/* Create basic types: */
2462+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2463+{
2464+ cJSON *item = cJSON_New_Item(&global_hooks);
2465+ if(item)
2466+ {
2467+ item->type = cJSON_NULL;
2468+ }
2469+
2470+ return item;
2471+}
2472+
2473+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2474+{
2475+ cJSON *item = cJSON_New_Item(&global_hooks);
2476+ if(item)
2477+ {
2478+ item->type = cJSON_True;
2479+ }
2480+
2481+ return item;
2482+}
2483+
2484+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2485+{
2486+ cJSON *item = cJSON_New_Item(&global_hooks);
2487+ if(item)
2488+ {
2489+ item->type = cJSON_False;
2490+ }
2491+
2492+ return item;
2493+}
2494+
2495+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
2496+{
2497+ cJSON *item = cJSON_New_Item(&global_hooks);
2498+ if(item)
2499+ {
2500+ item->type = boolean ? cJSON_True : cJSON_False;
2501+ }
2502+
2503+ return item;
2504+}
2505+
2506+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2507+{
2508+ cJSON *item = cJSON_New_Item(&global_hooks);
2509+ if(item)
2510+ {
2511+ item->type = cJSON_Number;
2512+ item->valuedouble = num;
2513+
2514+ /* use saturation in case of overflow */
2515+ if (num >= INT_MAX)
2516+ {
2517+ item->valueint = INT_MAX;
2518+ }
2519+ else if (num <= (double)INT_MIN)
2520+ {
2521+ item->valueint = INT_MIN;
2522+ }
2523+ else
2524+ {
2525+ item->valueint = (int)num;
2526+ }
2527+ }
2528+
2529+ return item;
2530+}
2531+
2532+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2533+{
2534+ cJSON *item = cJSON_New_Item(&global_hooks);
2535+ if(item)
2536+ {
2537+ item->type = cJSON_String;
2538+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2539+ if(!item->valuestring)
2540+ {
2541+ cJSON_Delete(item);
2542+ return NULL;
2543+ }
2544+ }
2545+
2546+ return item;
2547+}
2548+
2549+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2550+{
2551+ cJSON *item = cJSON_New_Item(&global_hooks);
2552+ if (item != NULL)
2553+ {
2554+ item->type = cJSON_String | cJSON_IsReference;
2555+ item->valuestring = (char*)cast_away_const(string);
2556+ }
2557+
2558+ return item;
2559+}
2560+
2561+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2562+{
2563+ cJSON *item = cJSON_New_Item(&global_hooks);
2564+ if (item != NULL) {
2565+ item->type = cJSON_Object | cJSON_IsReference;
2566+ item->child = (cJSON*)cast_away_const(child);
2567+ }
2568+
2569+ return item;
2570+}
2571+
2572+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2573+ cJSON *item = cJSON_New_Item(&global_hooks);
2574+ if (item != NULL) {
2575+ item->type = cJSON_Array | cJSON_IsReference;
2576+ item->child = (cJSON*)cast_away_const(child);
2577+ }
2578+
2579+ return item;
2580+}
2581+
2582+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2583+{
2584+ cJSON *item = cJSON_New_Item(&global_hooks);
2585+ if(item)
2586+ {
2587+ item->type = cJSON_Raw;
2588+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2589+ if(!item->valuestring)
2590+ {
2591+ cJSON_Delete(item);
2592+ return NULL;
2593+ }
2594+ }
2595+
2596+ return item;
2597+}
2598+
2599+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2600+{
2601+ cJSON *item = cJSON_New_Item(&global_hooks);
2602+ if(item)
2603+ {
2604+ item->type=cJSON_Array;
2605+ }
2606+
2607+ return item;
2608+}
2609+
2610+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2611+{
2612+ cJSON *item = cJSON_New_Item(&global_hooks);
2613+ if (item)
2614+ {
2615+ item->type = cJSON_Object;
2616+ }
2617+
2618+ return item;
2619+}
2620+
2621+/* Create Arrays: */
2622+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2623+{
2624+ size_t i = 0;
2625+ cJSON *n = NULL;
2626+ cJSON *p = NULL;
2627+ cJSON *a = NULL;
2628+
2629+ if ((count < 0) || (numbers == NULL))
2630+ {
2631+ return NULL;
2632+ }
2633+
2634+ a = cJSON_CreateArray();
2635+
2636+ for(i = 0; a && (i < (size_t)count); i++)
2637+ {
2638+ n = cJSON_CreateNumber(numbers[i]);
2639+ if (!n)
2640+ {
2641+ cJSON_Delete(a);
2642+ return NULL;
2643+ }
2644+ if(!i)
2645+ {
2646+ a->child = n;
2647+ }
2648+ else
2649+ {
2650+ suffix_object(p, n);
2651+ }
2652+ p = n;
2653+ }
2654+
2655+ if (a && a->child) {
2656+ a->child->prev = n;
2657+ }
2658+
2659+ return a;
2660+}
2661+
2662+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2663+{
2664+ size_t i = 0;
2665+ cJSON *n = NULL;
2666+ cJSON *p = NULL;
2667+ cJSON *a = NULL;
2668+
2669+ if ((count < 0) || (numbers == NULL))
2670+ {
2671+ return NULL;
2672+ }
2673+
2674+ a = cJSON_CreateArray();
2675+
2676+ for(i = 0; a && (i < (size_t)count); i++)
2677+ {
2678+ n = cJSON_CreateNumber((double)numbers[i]);
2679+ if(!n)
2680+ {
2681+ cJSON_Delete(a);
2682+ return NULL;
2683+ }
2684+ if(!i)
2685+ {
2686+ a->child = n;
2687+ }
2688+ else
2689+ {
2690+ suffix_object(p, n);
2691+ }
2692+ p = n;
2693+ }
2694+
2695+ if (a && a->child) {
2696+ a->child->prev = n;
2697+ }
2698+
2699+ return a;
2700+}
2701+
2702+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2703+{
2704+ size_t i = 0;
2705+ cJSON *n = NULL;
2706+ cJSON *p = NULL;
2707+ cJSON *a = NULL;
2708+
2709+ if ((count < 0) || (numbers == NULL))
2710+ {
2711+ return NULL;
2712+ }
2713+
2714+ a = cJSON_CreateArray();
2715+
2716+ for(i = 0; a && (i < (size_t)count); i++)
2717+ {
2718+ n = cJSON_CreateNumber(numbers[i]);
2719+ if(!n)
2720+ {
2721+ cJSON_Delete(a);
2722+ return NULL;
2723+ }
2724+ if(!i)
2725+ {
2726+ a->child = n;
2727+ }
2728+ else
2729+ {
2730+ suffix_object(p, n);
2731+ }
2732+ p = n;
2733+ }
2734+
2735+ if (a && a->child) {
2736+ a->child->prev = n;
2737+ }
2738+
2739+ return a;
2740+}
2741+
2742+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
2743+{
2744+ size_t i = 0;
2745+ cJSON *n = NULL;
2746+ cJSON *p = NULL;
2747+ cJSON *a = NULL;
2748+
2749+ if ((count < 0) || (strings == NULL))
2750+ {
2751+ return NULL;
2752+ }
2753+
2754+ a = cJSON_CreateArray();
2755+
2756+ for (i = 0; a && (i < (size_t)count); i++)
2757+ {
2758+ n = cJSON_CreateString(strings[i]);
2759+ if(!n)
2760+ {
2761+ cJSON_Delete(a);
2762+ return NULL;
2763+ }
2764+ if(!i)
2765+ {
2766+ a->child = n;
2767+ }
2768+ else
2769+ {
2770+ suffix_object(p,n);
2771+ }
2772+ p = n;
2773+ }
2774+
2775+ if (a && a->child) {
2776+ a->child->prev = n;
2777+ }
2778+
2779+ return a;
2780+}
2781+
2782+/* Duplication */
2783+cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);
2784+
2785+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2786+{
2787+ return cJSON_Duplicate_rec(item, 0, recurse );
2788+}
2789+
2790+cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
2791+{
2792+ cJSON *newitem = NULL;
2793+ cJSON *child = NULL;
2794+ cJSON *next = NULL;
2795+ cJSON *newchild = NULL;
2796+
2797+ /* Bail on bad ptr */
2798+ if (!item)
2799+ {
2800+ goto fail;
2801+ }
2802+ /* Create new item */
2803+ newitem = cJSON_New_Item(&global_hooks);
2804+ if (!newitem)
2805+ {
2806+ goto fail;
2807+ }
2808+ /* Copy over all vars */
2809+ newitem->type = item->type & (~cJSON_IsReference);
2810+ newitem->valueint = item->valueint;
2811+ newitem->valuedouble = item->valuedouble;
2812+ if (item->valuestring)
2813+ {
2814+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2815+ if (!newitem->valuestring)
2816+ {
2817+ goto fail;
2818+ }
2819+ }
2820+ if (item->string)
2821+ {
2822+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2823+ if (!newitem->string)
2824+ {
2825+ goto fail;
2826+ }
2827+ }
2828+ /* If non-recursive, then we're done! */
2829+ if (!recurse)
2830+ {
2831+ return newitem;
2832+ }
2833+ /* Walk the ->next chain for the child. */
2834+ child = item->child;
2835+ while (child != NULL)
2836+ {
2837+ if(depth >= CJSON_CIRCULAR_LIMIT) {
2838+ goto fail;
2839+ }
2840+ newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
2841+ if (!newchild)
2842+ {
2843+ goto fail;
2844+ }
2845+ if (next != NULL)
2846+ {
2847+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2848+ next->next = newchild;
2849+ newchild->prev = next;
2850+ next = newchild;
2851+ }
2852+ else
2853+ {
2854+ /* Set newitem->child and move to it */
2855+ newitem->child = newchild;
2856+ next = newchild;
2857+ }
2858+ child = child->next;
2859+ }
2860+ if (newitem && newitem->child)
2861+ {
2862+ newitem->child->prev = newchild;
2863+ }
2864+
2865+ return newitem;
2866+
2867+fail:
2868+ if (newitem != NULL)
2869+ {
2870+ cJSON_Delete(newitem);
2871+ }
2872+
2873+ return NULL;
2874+}
2875+
2876+static void skip_oneline_comment(char **input)
2877+{
2878+ *input += static_strlen("//");
2879+
2880+ for (; (*input)[0] != '\0'; ++(*input))
2881+ {
2882+ if ((*input)[0] == '\n') {
2883+ *input += static_strlen("\n");
2884+ return;
2885+ }
2886+ }
2887+}
2888+
2889+static void skip_multiline_comment(char **input)
2890+{
2891+ *input += static_strlen("/*");
2892+
2893+ for (; (*input)[0] != '\0'; ++(*input))
2894+ {
2895+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
2896+ {
2897+ *input += static_strlen("*/");
2898+ return;
2899+ }
2900+ }
2901+}
2902+
2903+static void minify_string(char **input, char **output) {
2904+ (*output)[0] = (*input)[0];
2905+ *input += static_strlen("\"");
2906+ *output += static_strlen("\"");
2907+
2908+
2909+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2910+ (*output)[0] = (*input)[0];
2911+
2912+ if ((*input)[0] == '\"') {
2913+ (*output)[0] = '\"';
2914+ *input += static_strlen("\"");
2915+ *output += static_strlen("\"");
2916+ return;
2917+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
2918+ (*output)[1] = (*input)[1];
2919+ *input += static_strlen("\"");
2920+ *output += static_strlen("\"");
2921+ }
2922+ }
2923+}
2924+
2925+CJSON_PUBLIC(void) cJSON_Minify(char *json)
2926+{
2927+ char *into = json;
2928+
2929+ if (json == NULL)
2930+ {
2931+ return;
2932+ }
2933+
2934+ while (json[0] != '\0')
2935+ {
2936+ switch (json[0])
2937+ {
2938+ case ' ':
2939+ case '\t':
2940+ case '\r':
2941+ case '\n':
2942+ json++;
2943+ break;
2944+
2945+ case '/':
2946+ if (json[1] == '/')
2947+ {
2948+ skip_oneline_comment(&json);
2949+ }
2950+ else if (json[1] == '*')
2951+ {
2952+ skip_multiline_comment(&json);
2953+ } else {
2954+ json++;
2955+ }
2956+ break;
2957+
2958+ case '\"':
2959+ minify_string(&json, (char**)&into);
2960+ break;
2961+
2962+ default:
2963+ into[0] = json[0];
2964+ json++;
2965+ into++;
2966+ }
2967+ }
2968+
2969+ /* and null-terminate. */
2970+ *into = '\0';
2971+}
2972+
2973+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2974+{
2975+ if (item == NULL)
2976+ {
2977+ return false;
2978+ }
2979+
2980+ return (item->type & 0xFF) == cJSON_Invalid;
2981+}
2982+
2983+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2984+{
2985+ if (item == NULL)
2986+ {
2987+ return false;
2988+ }
2989+
2990+ return (item->type & 0xFF) == cJSON_False;
2991+}
2992+
2993+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2994+{
2995+ if (item == NULL)
2996+ {
2997+ return false;
2998+ }
2999+
3000+ return (item->type & 0xff) == cJSON_True;
3001+}
3002+
3003+
3004+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
3005+{
3006+ if (item == NULL)
3007+ {
3008+ return false;
3009+ }
3010+
3011+ return (item->type & (cJSON_True | cJSON_False)) != 0;
3012+}
3013+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
3014+{
3015+ if (item == NULL)
3016+ {
3017+ return false;
3018+ }
3019+
3020+ return (item->type & 0xFF) == cJSON_NULL;
3021+}
3022+
3023+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
3024+{
3025+ if (item == NULL)
3026+ {
3027+ return false;
3028+ }
3029+
3030+ return (item->type & 0xFF) == cJSON_Number;
3031+}
3032+
3033+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
3034+{
3035+ if (item == NULL)
3036+ {
3037+ return false;
3038+ }
3039+
3040+ return (item->type & 0xFF) == cJSON_String;
3041+}
3042+
3043+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
3044+{
3045+ if (item == NULL)
3046+ {
3047+ return false;
3048+ }
3049+
3050+ return (item->type & 0xFF) == cJSON_Array;
3051+}
3052+
3053+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
3054+{
3055+ if (item == NULL)
3056+ {
3057+ return false;
3058+ }
3059+
3060+ return (item->type & 0xFF) == cJSON_Object;
3061+}
3062+
3063+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
3064+{
3065+ if (item == NULL)
3066+ {
3067+ return false;
3068+ }
3069+
3070+ return (item->type & 0xFF) == cJSON_Raw;
3071+}
3072+
3073+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
3074+{
3075+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
3076+ {
3077+ return false;
3078+ }
3079+
3080+ /* check if type is valid */
3081+ switch (a->type & 0xFF)
3082+ {
3083+ case cJSON_False:
3084+ case cJSON_True:
3085+ case cJSON_NULL:
3086+ case cJSON_Number:
3087+ case cJSON_String:
3088+ case cJSON_Raw:
3089+ case cJSON_Array:
3090+ case cJSON_Object:
3091+ break;
3092+
3093+ default:
3094+ return false;
3095+ }
3096+
3097+ /* identical objects are equal */
3098+ if (a == b)
3099+ {
3100+ return true;
3101+ }
3102+
3103+ switch (a->type & 0xFF)
3104+ {
3105+ /* in these cases and equal type is enough */
3106+ case cJSON_False:
3107+ case cJSON_True:
3108+ case cJSON_NULL:
3109+ return true;
3110+
3111+ case cJSON_Number:
3112+ if (compare_double(a->valuedouble, b->valuedouble))
3113+ {
3114+ return true;
3115+ }
3116+ return false;
3117+
3118+ case cJSON_String:
3119+ case cJSON_Raw:
3120+ if ((a->valuestring == NULL) || (b->valuestring == NULL))
3121+ {
3122+ return false;
3123+ }
3124+ if (strcmp(a->valuestring, b->valuestring) == 0)
3125+ {
3126+ return true;
3127+ }
3128+
3129+ return false;
3130+
3131+ case cJSON_Array:
3132+ {
3133+ cJSON *a_element = a->child;
3134+ cJSON *b_element = b->child;
3135+
3136+ for (; (a_element != NULL) && (b_element != NULL);)
3137+ {
3138+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
3139+ {
3140+ return false;
3141+ }
3142+
3143+ a_element = a_element->next;
3144+ b_element = b_element->next;
3145+ }
3146+
3147+ /* one of the arrays is longer than the other */
3148+ if (a_element != b_element) {
3149+ return false;
3150+ }
3151+
3152+ return true;
3153+ }
3154+
3155+ case cJSON_Object:
3156+ {
3157+ cJSON *a_element = NULL;
3158+ cJSON *b_element = NULL;
3159+ cJSON_ArrayForEach(a_element, a)
3160+ {
3161+ /* TODO This has O(n^2) runtime, which is horrible! */
3162+ b_element = get_object_item(b, a_element->string, case_sensitive);
3163+ if (b_element == NULL)
3164+ {
3165+ return false;
3166+ }
3167+
3168+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
3169+ {
3170+ return false;
3171+ }
3172+ }
3173+
3174+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
3175+ * TODO: Do this the proper way, this is just a fix for now */
3176+ cJSON_ArrayForEach(b_element, b)
3177+ {
3178+ a_element = get_object_item(a, b_element->string, case_sensitive);
3179+ if (a_element == NULL)
3180+ {
3181+ return false;
3182+ }
3183+
3184+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
3185+ {
3186+ return false;
3187+ }
3188+ }
3189+
3190+ return true;
3191+ }
3192+
3193+ default:
3194+ return false;
3195+ }
3196+}
3197+
3198+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
3199+{
3200+ return global_hooks.allocate(size);
3201+}
3202+
3203+CJSON_PUBLIC(void) cJSON_free(void *object)
3204+{
3205+ global_hooks.deallocate(object);
3206+ object = NULL;
3207+}
+306,
-0
1@@ -0,0 +1,306 @@
2+/*
3+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
4+
5+ Permission is hereby granted, free of charge, to any person obtaining a copy
6+ of this software and associated documentation files (the "Software"), to deal
7+ in the Software without restriction, including without limitation the rights
8+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ copies of the Software, and to permit persons to whom the Software is
10+ furnished to do so, subject to the following conditions:
11+
12+ The above copyright notice and this permission notice shall be included in
13+ all copies or substantial portions of the Software.
14+
15+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+ THE SOFTWARE.
22+*/
23+
24+#ifndef cJSON__h
25+#define cJSON__h
26+
27+#ifdef __cplusplus
28+extern "C"
29+{
30+#endif
31+
32+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
33+#define __WINDOWS__
34+#endif
35+
36+#ifdef __WINDOWS__
37+
38+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
39+
40+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
41+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
42+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
43+
44+For *nix builds that support visibility attribute, you can define similar behavior by
45+
46+setting default visibility to hidden by adding
47+-fvisibility=hidden (for gcc)
48+or
49+-xldscope=hidden (for sun cc)
50+to CFLAGS
51+
52+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
53+
54+*/
55+
56+#define CJSON_CDECL __cdecl
57+#define CJSON_STDCALL __stdcall
58+
59+/* export symbols by default, this is necessary for copy pasting the C and header file */
60+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
61+#define CJSON_EXPORT_SYMBOLS
62+#endif
63+
64+#if defined(CJSON_HIDE_SYMBOLS)
65+#define CJSON_PUBLIC(type) type CJSON_STDCALL
66+#elif defined(CJSON_EXPORT_SYMBOLS)
67+#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
68+#elif defined(CJSON_IMPORT_SYMBOLS)
69+#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
70+#endif
71+#else /* !__WINDOWS__ */
72+#define CJSON_CDECL
73+#define CJSON_STDCALL
74+
75+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
76+#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
77+#else
78+#define CJSON_PUBLIC(type) type
79+#endif
80+#endif
81+
82+/* project version */
83+#define CJSON_VERSION_MAJOR 1
84+#define CJSON_VERSION_MINOR 7
85+#define CJSON_VERSION_PATCH 19
86+
87+#include <stddef.h>
88+
89+/* cJSON Types: */
90+#define cJSON_Invalid (0)
91+#define cJSON_False (1 << 0)
92+#define cJSON_True (1 << 1)
93+#define cJSON_NULL (1 << 2)
94+#define cJSON_Number (1 << 3)
95+#define cJSON_String (1 << 4)
96+#define cJSON_Array (1 << 5)
97+#define cJSON_Object (1 << 6)
98+#define cJSON_Raw (1 << 7) /* raw json */
99+
100+#define cJSON_IsReference 256
101+#define cJSON_StringIsConst 512
102+
103+/* The cJSON structure: */
104+typedef struct cJSON
105+{
106+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
107+ struct cJSON *next;
108+ struct cJSON *prev;
109+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
110+ struct cJSON *child;
111+
112+ /* The type of the item, as above. */
113+ int type;
114+
115+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
116+ char *valuestring;
117+ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
118+ int valueint;
119+ /* The item's number, if type==cJSON_Number */
120+ double valuedouble;
121+
122+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
123+ char *string;
124+} cJSON;
125+
126+typedef struct cJSON_Hooks
127+{
128+ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
129+ void *(CJSON_CDECL *malloc_fn)(size_t sz);
130+ void (CJSON_CDECL *free_fn)(void *ptr);
131+} cJSON_Hooks;
132+
133+typedef int cJSON_bool;
134+
135+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
136+ * This is to prevent stack overflows. */
137+#ifndef CJSON_NESTING_LIMIT
138+#define CJSON_NESTING_LIMIT 1000
139+#endif
140+
141+/* Limits the length of circular references can be before cJSON rejects to parse them.
142+ * This is to prevent stack overflows. */
143+#ifndef CJSON_CIRCULAR_LIMIT
144+#define CJSON_CIRCULAR_LIMIT 10000
145+#endif
146+
147+/* returns the version of cJSON as a string */
148+CJSON_PUBLIC(const char*) cJSON_Version(void);
149+
150+/* Supply malloc, realloc and free functions to cJSON */
151+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
152+
153+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
154+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
155+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
156+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
157+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
158+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
159+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
160+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
161+
162+/* Render a cJSON entity to text for transfer/storage. */
163+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
164+/* Render a cJSON entity to text for transfer/storage without any formatting. */
165+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
166+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
167+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
168+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
169+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
170+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
171+/* Delete a cJSON entity and all subentities. */
172+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
173+
174+/* Returns the number of items in an array (or object). */
175+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
176+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
177+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
178+/* Get item "string" from object. Case insensitive. */
179+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
180+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
181+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
182+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
183+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
184+
185+/* Check item type and return its value */
186+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
187+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
188+
189+/* These functions check the type of an item */
190+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
191+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
192+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
193+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
194+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
195+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
196+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
197+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
198+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
199+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
200+
201+/* These calls create a cJSON item of the appropriate type. */
202+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
203+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
204+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
205+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
206+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
207+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
208+/* raw json */
209+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
210+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
211+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
212+
213+/* Create a string where valuestring references a string so
214+ * it will not be freed by cJSON_Delete */
215+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
216+/* Create an object/array that only references it's elements so
217+ * they will not be freed by cJSON_Delete */
218+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
219+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
220+
221+/* These utilities create an Array of count items.
222+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
223+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
224+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
225+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
226+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
227+
228+/* Append item to the specified array/object. */
229+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
230+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
231+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
232+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
233+ * writing to `item->string` */
234+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
235+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
236+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
237+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
238+
239+/* Remove/Detach items from Arrays/Objects. */
240+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
241+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
242+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
243+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
244+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
245+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
246+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
247+
248+/* Update array items. */
249+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
250+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
251+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
252+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
253+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
254+
255+/* Duplicate a cJSON item */
256+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
257+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
258+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
259+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
260+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
261+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
262+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
263+
264+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
265+ * The input pointer json cannot point to a read-only address area, such as a string constant,
266+ * but should point to a readable and writable address area. */
267+CJSON_PUBLIC(void) cJSON_Minify(char *json);
268+
269+/* Helper functions for creating and adding items to an object at the same time.
270+ * They return the added item or NULL on failure. */
271+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
272+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
273+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
274+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
275+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
276+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
277+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
278+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
279+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
280+
281+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
282+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
283+/* helper for the cJSON_SetNumberValue macro */
284+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
285+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
286+/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
287+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
288+
289+/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
290+#define cJSON_SetBoolValue(object, boolValue) ( \
291+ (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
292+ (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
293+ cJSON_Invalid\
294+)
295+
296+/* Macro for iterating over an array or object */
297+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
298+
299+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
300+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
301+CJSON_PUBLIC(void) cJSON_free(void *object);
302+
303+#ifdef __cplusplus
304+}
305+#endif
306+
307+#endif