製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Requires C++23 (e.g.,
-std=c++23for GCC/Clang,/std:c++latestfor MSVC).
API Reference · Usage Guide · Releases
A small framework for generating entities from your own components, with dependencies, validation and replay.
Core — Generate entities composed of user-defined components. Each component produces a typed random value accessible via entity.get<T>(key). Register, remove, and generate with fluent chaining.
Batch Generation. Generate thousands of entities from one seed, on several threads with the same output for any thread count, optionally unique by a key, and stream them as JSON Lines or CSV (see the usage guide).
Generic Components — Ready-made templates for common patterns: constant_component<T>, choice_component<T>, range_component<T>, callback_component, and weighted_choice_component<T>. All accept an optional custom formatter.
Request-First API — entity_request carries component selection, group, batch count, entity validation and per-call inputs (a country, a reference date, ...) for each call. Generation methods accept (request) or (request, seed); setup stays on the instance.
Dependencies & Fields — A component declares depends_on(): a request pulls in what it needs, orders it, and skips a component whose dependency was skipped. field(key, fn) builds a component in one expression, with a label, formatter, JSON mapper, validator and condition.
Recipes — Components that draw from a list or a range are written as rows of a tab-separated file (constant, choice, weighted, int, real, with labels, dependencies and weights) and registered with add_recipe(path), no recompiling.
Randomness & Replay — Explicit per-call seeds and caller-owned deterministic sequences. Every entity and component stores its seed for full replay via seed signatures; generate(request, e.seed()) reproduces an entity with the same request and setup.
Identical Everywhere — A seed gives the same entity on every compiler, standard library and CPU (GCC, Clang, MSVC, Emscripten; x86-64 and ARM64), checked by known-answer tests. Each component draws from its own stream, so adding a component does not change the others.
Advanced Generation — Batch generation (synchronous and concurrent), named component groups, selective generation by key subset, component weights for probabilistic inclusion, and conditional components for logic-driven inclusion via should_generate(ctx).
Validation & Hooks — Per-component validate() with automatic retries, entity-level validator callbacks, and a generation_observer interface with 15 lifecycle hooks. Multiple observers can be attached simultaneously via add_observer / remove_observer.
Extensions — dasmig::ext::stats_observer tracks generation counts, skips, retries, and failures out of the box.
ECS Integration — Optional adapter headers for EnTT and Flecs. Register key→component mappings, then spawn() converts generated entities into typed ECS entities.
Serialization — entity.to_string(), operator<<, entity.to_map() for structured key–value export, and entity.to_json() with typed values, arrays, objects, nested documents from dotted keys (identity.age), and a replay signature that covers the inputs and the data behind the components.
Composable & Thread-Safe — Components can wrap name-generator and nickname-generator. Independent eg instances enable lock-free concurrent generation.
entitygen.hpp is the library released here. Keep core.hpp and the core/ directory (dasmig-core) in the same directory. You need to add
#include <dasmig/entitygen.hpp>
// For convenience.
using eg = dasmig::eg;
to the files you want to generate entities and set the necessary switches to enable C++23 (e.g., -std=c++23 for GCC and Clang).
Components draw random numbers from ctx.random() with the dasmig-core functions (dasmig::core::uniform_int, pick, bernoulli, ...), which give the same results on every platform. Version 2 changes every seeded result and the component random API; see Migrating from v1.
Define a component by implementing the component interface:
#include <dasmig/entitygen.hpp>
class character_class : public dasmig::component
{
public:
[[nodiscard]] std::wstring key() const override { return L"class"; }
[[nodiscard]] std::any generate(
const dasmig::generation_context& ctx) const override
{
static const std::vector<std::wstring> classes{
L"Warrior", L"Mage", L"Rogue", L"Healer"};
return dasmig::core::pick(ctx.random(), classes);
}
[[nodiscard]] std::wstring to_string(const std::any& value) const override
{
return default_to_string(value);
}
};
class age : public dasmig::component
{
public:
[[nodiscard]] std::wstring key() const override { return L"age"; }
[[nodiscard]] std::any generate(
const dasmig::generation_context& ctx) const override
{
return dasmig::core::uniform_int(ctx.random(), 18, 65);
}
[[nodiscard]] std::wstring to_string(const std::any& value) const override
{
return default_to_string(value);
}
};
Register components and generate entities:
using eg = dasmig::eg;
eg::instance()
.add(std::make_unique<character_class>())
.add(std::make_unique<age>());
// Generate and stream.
std::wcout << eg::instance().generate({}) << std::endl;
// e.g. "class: Mage age: 34"
// Typed access.
auto entity = eg::instance().generate({});
std::wstring cls = entity.get<std::wstring>(L"class");
int char_age = entity.get<int>(L"age");
// Reproducible with a seed.
auto seeded = eg::instance().generate({}, 42);
// Reusable per-call selection.
dasmig::entity_request request{
.component_keys = std::vector<std::wstring>{L"class"}};
auto partial = eg::instance().generate(request, 42);
request.count = 3;
auto batch = eg::instance().generate_batch(request, 42);
The positional generation overloads and generator seed / unseed and validator setters have been removed. See Migrating to the request-first API.
For the complete feature guide — component dependencies, custom types, seed signatures, batch generation, groups, weights, validation, event hooks, extensions, and more — see the Usage Guide.
For planned features — Python/Node.js/.NET wrappers and more — see the Roadmap.
# Example
make
# Tests
make test
# Targeted API, replay, selection, and validation tests (after building)
./build/test_runner "[request],[seed],[batch],[group],[validation],[kat]"
# Benchmarks (results in build/bench.tsv)
make bench
# Code coverage
make coverage
# API docs
make docs
Tested with:
-std=c++23)-std=c++23)/std:c++latest)| Dependency | Version | Bundled | Purpose |
|---|---|---|---|
| dasmig-core | 1.4 | Yes (core.hpp, core/) | Platform-independent random engine and distributions, JSON |
| Catch2 | 3.x | Yes (amalgamated) | Unit testing |
| EnTT, Flecs | - | No | Only for the optional adapter headers in dasmig/ext/ |
| Library | Description |
|---|---|
| address-generator | Postal addresses with real streets by place |
| biodata-generator | Procedural human physical characteristics |
| birth-generator | Demographically plausible birthdays |
| city-generator | Weighted city selection by population |
| country-generator | Weighted country selection by population |
| device-generator | Devices, browsers, user agents and IP addresses that fit together |
| email-generator | Email addresses in each country's style |
| interest-generator | Religion, hobbies and favourite media by country, age and sex |
| name-generator | Culturally appropriate full names |
| nickname-generator | Gamer-style nicknames |
| occupation-generator | Employment status, education and occupation by country, age and sex |
| persona-generator |
This library is released under the MIT License.
MIT License
Copyright (c) 2020-2026 Diego Dasso Migotto
| Complete characters composed from the other generators |
| phone-generator | Phone numbers valid in each country's numbering plan |
| relationship-generator | Families around a person: parents, siblings, partners and children |
| trait-generator | Personality traits with conflicts, synergies and Big Five axes |
| user-generator | Complete user records: account, username, email, phone and address |