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