Skip to content

Havoc's single-file CSON (CoffeeScript Object Notation) library for C++.

License

Notifications You must be signed in to change notification settings

Havoc7891/havCSON

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

havCSON

Havoc's single-file CSON (CoffeeScript Object Notation) library for C++.

Table of Contents

Features

  • Single-header, dependency-free (just include havCSON.hpp)
  • Reading and writing CSON files (from strings or UTF-8 file paths)
    • Also supports generating CSON files from scratch
  • Optional throwing parse API (ParseOrThrow) in addition to error-code based parsing
  • Convert parsed data to JSON text via ToJsonString
  • Pretty-print output with controllable indent width and optional key sorting
  • Lossless round-trip mode that keeps comments / blank lines / ordering with matching write helpers
  • Unicode / UTF-8 support with validation

Getting Started

This library requires C++23. The library should be cross-platform, but has only been tested under Windows so far.

Installation

Copy the header file into your project folder and include the file like this:

#include "havCSON.hpp"

Usage

Here are some code examples demonstrating how to use the library. Each snippet is independent; copy the header and drop the snippet you need into your code.

Read CSON file

using namespace havCSON;

Value config;
Error error;

auto code = ParseFile("config.cson", config, &error);
if (code != ErrorCode::OK)
{
  std::cerr << "Failed: line " << error.where.line << " col " << error.where.column
            << " (" << error.message << ")\n";
  return;
}

// Optional: throw on error
Value parsed = ParseOrThrow("foo: 1");

// Convert to JSON string without pretty-printing
std::string json;
if (!ToJsonString(config, json, &error))
{
  std::cerr << "JSON conversion failed: " << error.message << "\n";
}

Write CSON file

using namespace havCSON;

Value root = Object{
  {"name", "Havoc"},
  {"level", 42.0}, // Numbers are double
  {"items", Array{1.0, 2.0, 3.0}},
};

WriteOptions options;
options.indentWidth = 2;
options.sortObjectKeys = true;

Error error;
if (!WriteFile("out.cson", root, options, &error))
{
  std::cerr << "Write failed: " << error.message << "\n";
}

// Get the formatted string without touching disk
std::string text;
if (!ToString(root, text, options, &error))
{
  std::cerr << "Formatting failed: " << error.message << "\n";
}

Parse from a string and mutate the data

using namespace havCSON;

// CoffeeScript-style inline array and object
Value value = ParseOrThrow("user: {name: \"Havoc\", tags: [\"dev\", \"cpp\"]}");

// Add a nested field
Object& obj = value.asObject().at("user").asObject();
obj["active"] = true;

// Push another tag
obj["tags"].asArray().push_back("oss");

Error error;
std::string formatted;
if (!ToString(value, formatted, {}, &error))
{
  std::cerr << "Formatting failed: " << error.message << "\n";
}
else
{
  std::cout << formatted << "\n";
}

Create an array and array entries

using namespace havCSON;

Array inventory;
inventory.emplace_back("Sword");
inventory.emplace_back("Shield");
inventory.emplace_back(3.0);

Value player = Object{
  {"name", "Havoc"},
  {"inventory", inventory},
};

Iterate over an array

const havCSON::Array& items = player.asObject().at("inventory").asArray();
for (const havCSON::Value& item : items)
{
  std::cout << "Item type index: " << item.index() << "\n";
}

Check if value exists

const auto& obj = player.asObject();
if (auto it = obj.find("name"); it != obj.end())
{
  std::cout << "Name: " << std::get<std::string>(it->second) << "\n";
}

Check value type

const havCSON::Value& numberValue = player.asObject().at("inventory").asArray().at(2);
if (numberValue.isNumber())
{
  double level = std::get<double>(numberValue);
  std::cout << "Level: " << level << "\n";
}

Handle multiline strings and comments losslessly

using namespace havCSON;

std::string src = R"(# Header comment
bio: """
  Multiline
  text preserved
"""
)";

LosslessValue lossless;
Error error;
if (ParseLossless(src, lossless, &error) != ErrorCode::OK)
{
  // Handle
}

// Keep comments / spacing when writing back out
std::string roundtrip;
if (!ToStringLossless(lossless, roundtrip, {}, &error))
{
  std::cerr << "Lossless formatting failed: " << error.message << "\n";
}

Contributing

Thank you for your interest! Suggestions for features and bug reports are always welcome via issues.

To maintain a consistent design and quality for this library, changes are implemented by the maintainer rather than via direct pull requests.

License

Copyright © 2025-2026 René Nicolaus

This library is released under the MIT license.

About

Havoc's single-file CSON (CoffeeScript Object Notation) library for C++.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages