145 <<
"Grid_Snapshot::at: coordinate (" <<
row <<
", " <<
col <<
") out of " <<
height <<
"x"
219template <
typename State>
243template <
typename State>
260namespace ca_io_detail {
262template <
typename Lattice>
266 static_assert(
Lattice::rank == 2,
"CA IO currently supports 2D frames");
273 while (b < s.size()
and std::isspace(
static_cast<unsigned char>(s[b])))
275 std::size_t e = s.size();
276 while (e > b
and std::isspace(
static_cast<unsigned char>(s[e - 1])))
278 return s.substr(b, e - b);
284 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
288inline bool blank(
const std::string &s)
290 for (
const char c : s)
291 if (
not std::isspace(
static_cast<unsigned char>(c)))
301 for (
const char c : t)
304 << what <<
": invalid unsigned size '" << s <<
"'";
307 << what <<
": size overflows ca_size_t";
319 if (t[i] ==
'-' or t[i] ==
'+')
326 for (; i < t.size(); ++i)
330 << what <<
": invalid coordinate '" << s <<
"'";
333 << what <<
": coordinate overflows ca_index_t";
342 std::istringstream
in(comment);
344 while (std::getline(
in, line))
353 std::ostringstream
out;
354 for (
const char c : s)
374 if (
static_cast<unsigned char>(c) < 0x20)
375 out <<
"\\u" << std::hex << std::setw(4) << std::setfill(
'0')
376 <<
static_cast<unsigned>(
static_cast<unsigned char>(c)) << std::dec
377 << std::setfill(
' ');
392 token = std::to_string(n);
393 token.push_back(glyph);
403 const std::string &body,
404 const std::size_t line_width)
408 const std::size_t width = line_width == 0 ? std::numeric_limits<std::size_t>::max() : line_width;
409 while (pos < body.size())
411 const std::size_t start = pos;
412 while (pos < body.size()
and std::isdigit(
static_cast<unsigned char>(body[pos])))
416 const std::size_t len = pos - start;
422 out.write(body.data() +
static_cast<std::ptrdiff_t
>(start),
static_cast<std::streamsize
>(len));
424 if (body[pos - 1] ==
'!')
434inline std::string
header_value(
const std::string &line,
const std::string &key)
436 std::istringstream
parts(line);
440 const auto eq =
part.find(
'=');
441 if (
eq == std::string::npos)
488 << format <<
": trailing characters in scalar '" << token <<
"'";
495 while (pos < s.size()
and std::isspace(
static_cast<unsigned char>(s[pos])))
497 const std::size_t start = pos;
498 if (pos < s.size()
and (s[pos] ==
'-' or s[pos] ==
'+'))
500 while (pos < s.size()
and std::isdigit(
static_cast<unsigned char>(s[pos])))
502 if (pos < s.size()
and s[pos] ==
'.')
505 while (pos < s.size()
and std::isdigit(
static_cast<unsigned char>(s[pos])))
508 if (pos < s.size()
and (s[pos] ==
'e' or s[pos] ==
'E'))
511 if (pos < s.size()
and (s[pos] ==
'-' or s[pos] ==
'+'))
513 while (pos < s.size()
and std::isdigit(
static_cast<unsigned char>(s[pos])))
522 const std::string
needle =
"\"" + key +
"\"";
527 <<
"JSON snapshot: missing ':' after '" << key <<
"'";
529 while (
colon < s.size()
and std::isspace(
static_cast<unsigned char>(s[
colon])))
531 const std::size_t start =
colon;
532 while (
colon < s.size()
and std::isdigit(
static_cast<unsigned char>(s[
colon])))
535 <<
"JSON snapshot: field '" << key <<
"' is not an unsigned integer";
547 if constexpr (std::is_integral_v<T>
and sizeof(
T) == 1
and not std::is_same_v<T, bool>)
574template <
typename Lattice>
578 const typename Lattice::state_type &dead =
typename Lattice::state_type{})
580 ca_io_detail::require_rank2<Lattice>(
"write_rle");
581 using coord_t =
typename Lattice::coord_type;
583 for (
const auto &line : ca_io_detail::split_comment_lines(
opts.name))
584 out <<
"#N " << line <<
'\n';
585 for (
const auto &line : ca_io_detail::split_comment_lines(
opts.comment))
586 out <<
"#C " << line <<
'\n';
588 const ca_size_t
rows = frame.
size(0);
589 const ca_size_t
cols = frame.
size(1);
592 if (
opts.trim_dead_border)
596 for (ca_size_t
r = 0;
r <
rows; ++
r)
597 for (ca_size_t c = 0; c <
cols; ++c)
598 if (frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}) != dead)
621 out <<
"x = " << width <<
", y = " << height <<
", rule = " <<
opts.rule <<
'\n';
624 if (height == 0
or width == 0)
630 for (ca_size_t
r =
r0;
r <
r1; ++
r)
635 for (ca_size_t c =
c0; c <
c1; ++c)
643 ca_io_detail::append_rle_token(body, run,
run_alive ?
'o' :
'b');
648 ca_io_detail::append_rle_token(body, run,
run_alive ?
'o' :
'b');
650 ca_io_detail::append_rle_token(body, 1,
'$');
655 ca_io_detail::write_wrapped_rle_body(
out, body,
opts.line_width);
656 ca_io_detail::ensure_stream_ok(
out,
"write_rle");
667template <
typename Lattice>
671 const typename Lattice::state_type &dead =
typename Lattice::state_type{})
673 std::ostringstream
out;
674 write_rle(
out, frame,
opts, dead);
707 if (line.size() >= 2
and (line[1] ==
'N' or line[1] ==
'n'))
708 pattern.
name = ca_io_detail::trim_copy(line.substr(2));
709 else if (line.size() >= 2
and (line[1] ==
'C' or line[1] ==
'c'))
716 const std::string x = ca_io_detail::header_value(line,
"x");
717 const std::string
y = ca_io_detail::header_value(line,
"y");
719 <<
"read_rle: missing x/y header in line '" << line <<
"'";
720 pattern.
width = ca_io_detail::parse_size_token(x,
"read_rle x");
721 pattern.
height = ca_io_detail::parse_size_token(
y,
"read_rle y");
722 pattern.
rule = ca_io_detail::header_value(line,
"rule");
727 for (
const char ch : line)
729 if (std::isdigit(
static_cast<unsigned char>(
ch)))
733 <<
"read_rle: run length overflows ca_size_t";
734 run = run * 10 +
digit;
736 else if (
ch ==
'b' or ch ==
'.')
740 <<
"read_rle: dead run exceeds row width";
744 else if (
ch ==
'o' or ch ==
'A')
748 <<
"read_rle: live run exceeds declared dimensions";
751 static_cast<ca_index_t>(cur_col + k)});
759 <<
"read_rle: row advance exceeds declared height";
772 <<
"read_rle: invalid body character '" <<
ch <<
"'";
787 std::istringstream
in(s);
808template <
typename Lattice>
814 const ca_index_t origin_row = 0,
815 const ca_index_t origin_col = 0)
817 ca_io_detail::require_rank2<Lattice>(
"load_binary_pattern");
818 using coord_t =
typename Lattice::coord_type;
820 <<
"load_binary_pattern: negative destination origin";
822 static_cast<ca_size_t
>(origin_col) + pattern.
width > frame.
size(1))
823 <<
"load_binary_pattern: pattern " << pattern.
height <<
"x" << pattern.
width
824 <<
" does not fit in frame " << frame.
size(0) <<
"x" << frame.
size(1);
827 for (
const auto &
cell : pattern.alive)
842template <
typename Lattice>
848 ca_io_detail::require_rank2<Lattice>(
"make_lattice_from_pattern");
849 Lattice frame({pattern.
height, pattern.
width}, dead);
850 load_binary_pattern(pattern, frame, alive, dead);
866template <
typename Lattice>
870 const typename Lattice::state_type &dead =
typename Lattice::state_type{})
872 ca_io_detail::require_rank2<Lattice>(
"write_plaintext");
873 using coord_t =
typename Lattice::coord_type;
874 for (
const auto &line : ca_io_detail::split_comment_lines(
opts.comment))
875 out <<
'!' << line <<
'\n';
877 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
879 for (ca_size_t c = 0; c < frame.
size(1); ++c)
880 out << (frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}) == dead
885 ca_io_detail::ensure_stream_ok(
out,
"write_plaintext");
896template <
typename Lattice>
900 const typename Lattice::state_type &dead =
typename Lattice::state_type{})
902 std::ostringstream
out;
903 write_plaintext(
out, frame,
opts, dead);
924 while (std::getline(
in, line))
937 for (
const char c : line)
938 if (c ==
'O' or c ==
'o' or c ==
'*' or c ==
'.')
942 <<
"read_plaintext: invalid character '" << c <<
"'";
963 std::istringstream
in(s);
980template <
typename Lattice>
985 ca_io_detail::require_rank2<Lattice>(
"write_life_106");
986 using coord_t =
typename Lattice::coord_type;
987 out <<
"#Life 1.06\n";
988 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
989 for (ca_size_t c = 0; c < frame.
size(1); ++c)
990 if (frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}) != dead)
991 out << c <<
' ' <<
r <<
'\n';
992 ca_io_detail::ensure_stream_ok(
out,
"write_life_106");
1016 while (std::getline(
in, line))
1018 const std::string t = ca_io_detail::trim_copy(line);
1023 if (t ==
"#Life 1.06")
1025 else if (t.size() >= 2
and (t[1] ==
'D' or t[1] ==
'd'))
1029 std::istringstream
ls(t);
1033 const ca_index_t col = ca_io_detail::parse_index_token(
xs,
"read_life_106 x");
1034 const ca_index_t row = ca_io_detail::parse_index_token(
ys,
"read_life_106 y");
1071template <
typename Lattice>
1074 const std::string &comment = {},
1075 const typename Lattice::state_type &dead =
typename Lattice::state_type{})
1077 ca_io_detail::require_rank2<Lattice>(
"write_life_105");
1078 using coord_t =
typename Lattice::coord_type;
1079 out <<
"#Life 1.05\n";
1080 for (
const auto &line : ca_io_detail::split_comment_lines(comment))
1081 out <<
"#D " << line <<
'\n';
1083 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
1085 for (ca_size_t c = 0; c < frame.
size(1); ++c)
1086 out << (frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}) == dead
1091 ca_io_detail::ensure_stream_ok(
out,
"write_life_105");
1134 while (std::getline(
in, line))
1136 const std::string t = ca_io_detail::trim_copy(line);
1141 if (t ==
"#Life 1.05")
1146 if (t.size() >= 2
and (t[1] ==
'D' or t[1] ==
'd'))
1151 if (t.size() >= 2
and (t[1] ==
'P' or t[1] ==
'p'))
1153 std::istringstream
ps(t.substr(2));
1157 <<
"read_life_105: malformed #P line '" << line <<
"'";
1158 block_col = ca_io_detail::parse_index_token(
xs,
"read_life_105 #P x");
1159 block_row = ca_io_detail::parse_index_token(
ys,
"read_life_105 #P y");
1169 for (
const char c : line)
1171 if (c ==
'*' or c ==
'O' or c ==
'o' or c ==
'.')
1176 if (c ==
'*' or c ==
'O' or c ==
'o')
1182 <<
"read_life_105: invalid row character '" << c <<
"'";
1206template <
typename Lattice>
1209 ca_io_detail::require_rank2<Lattice>(
"write_csv");
1210 using coord_t =
typename Lattice::coord_type;
1211 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
1213 for (ca_size_t c = 0; c < frame.
size(1); ++c)
1217 ca_io_detail::write_text_scalar(
1218 out, frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}));
1222 ca_io_detail::ensure_stream_ok(
out,
"write_csv");
1241template <
typename T>
1248 while (std::getline(
in, line))
1250 if (
opts.skip_empty_lines
and ca_io_detail::blank(line))
1254 std::istringstream
ls(line);
1255 while (std::getline(
ls, token,
opts.delimiter))
1256 values.
append(ca_io_detail::parse_scalar<T>(token,
"CSV snapshot"));
1257 if (line.empty()
and not opts.skip_empty_lines)
1262 <<
"read_csv_snapshot: row " <<
row <<
" has width " << values.
size() <<
" instead of "
1264 for (
const T &v : values)
1265 snap.cells.append(v);
1282template <
typename Lattice,
typename T>
1285 ca_io_detail::require_rank2<Lattice>(
"make_lattice_from_snapshot");
1291 frame.
set(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)},
1313template <
typename Lattice>
1316 ca_io_detail::require_rank2<Lattice>(
"write_json");
1317 using coord_t =
typename Lattice::coord_type;
1319 const auto nl =
opts.pretty ?
"\n" :
"";
1320 const auto i1 =
opts.pretty ?
" " :
"";
1321 const auto i2 =
opts.pretty ?
" " :
"";
1322 const auto sp =
opts.pretty ?
" " :
"";
1325 out <<
i1 <<
"\"type\":" <<
sp <<
"\"Aleph::CA::frame\"," <<
nl;
1326 out <<
i1 <<
"\"rank\":" <<
sp <<
"2," <<
nl;
1327 out <<
i1 <<
"\"height\":" <<
sp << frame.
size(0) <<
',' <<
nl;
1330 out <<
',' <<
nl <<
i1 <<
"\"rule\":" <<
sp <<
'"' << ca_io_detail::json_escape(
opts.rule) <<
'"';
1331 out <<
',' <<
nl <<
i1 <<
"\"cells\":" <<
sp <<
'[' <<
nl;
1332 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
1335 for (ca_size_t c = 0; c < frame.
size(1); ++c)
1341 ca_io_detail::write_text_scalar(
1342 out, frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}));
1347 if (
r + 1 < frame.
size(0))
1352 ca_io_detail::ensure_stream_ok(
out,
"write_json");
1369template <
typename T>
1372 std::ostringstream
ss;
1374 const std::string s =
ss.str();
1376 snap.
height = ca_io_detail::parse_json_size_field(s,
"height");
1377 snap.width = ca_io_detail::parse_json_size_field(s,
"width");
1379 const std::size_t key = s.find(
"\"cells\"");
1380 ah_domain_error_if(key == std::string::npos) <<
"JSON snapshot: missing cells field";
1381 std::size_t pos = s.find(
'[', key);
1382 ah_domain_error_if(pos == std::string::npos) <<
"JSON snapshot: missing cells array";
1388 while (pos < s.size()
and (std::isspace(
static_cast<unsigned char>(s[pos]))
or s[pos] ==
','))
1401 while (pos < s.size()
and std::isspace(
static_cast<unsigned char>(s[pos])))
1414 snap.cells.append(ca_io_detail::parse_json_number<T>(s, pos));
1418 <<
"JSON snapshot: row " <<
rows <<
" has width " <<
cols <<
" instead of " <<
snap.width;
1423 <<
"JSON snapshot: got " <<
rows <<
" rows instead of " <<
snap.height;
1443template <
typename Lattice,
typename Mapper>
1448 requires requires(
Mapper &&
m,
const typename Lattice::state_type &v) {
1449 {
m(v) } -> std::convertible_to<std::uint8_t>;
1452 ca_io_detail::require_rank2<Lattice>(
"write_pgm");
1453 using coord_t =
typename Lattice::coord_type;
1455 <<
"write_pgm: only 8-bit max_value in [1,255] is supported";
1456 out <<
"P5\n" << frame.
size(1) <<
' ' << frame.
size(0) <<
'\n' <<
opts.max_value <<
'\n';
1457 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
1458 for (ca_size_t c = 0; c < frame.
size(1); ++c)
1460 const std::uint8_t v =
static_cast<std::uint8_t
>(
1461 mapper(frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)})));
1462 out.write(
reinterpret_cast<const char *
>(&v), 1);
1464 ca_io_detail::ensure_stream_ok(
out,
"write_pgm");
1474template <
typename Lattice>
1495template <
typename Lattice,
typename Mapper>
1500 requires requires(
Mapper &&
m,
const typename Lattice::state_type &v) {
1501 {
m(v) } -> std::convertible_to<RGB8>;
1504 ca_io_detail::require_rank2<Lattice>(
"write_ppm");
1505 using coord_t =
typename Lattice::coord_type;
1507 <<
"write_ppm: only 8-bit max_value in [1,255] is supported";
1508 out <<
"P6\n" << frame.
size(1) <<
' ' << frame.
size(0) <<
'\n' <<
opts.max_value <<
'\n';
1509 for (ca_size_t
r = 0;
r < frame.
size(0); ++
r)
1510 for (ca_size_t c = 0; c < frame.
size(1); ++c)
1513 mapper(frame.
at(
coord_t{static_cast<ca_index_t>(r), static_cast<ca_index_t>(c)}));
1514 const char bytes[3] = {
static_cast<char>(
rgb.r),
static_cast<char>(
rgb.g),
1515 static_cast<char>(
rgb.b)};
1516 out.write(bytes, 3);
1518 ca_io_detail::ensure_stream_ok(
out,
"write_ppm");
1528template <
typename Lattice>
1547 std::ostream *out_ =
nullptr;
1549 bool closed_ =
false;
1564 *out_ <<
"{\n \"type\": \"Aleph::CA::frame-stream\",\n \"frames\": [\n";
1565 ca_io_detail::ensure_stream_ok(*out_,
"JSON_Frame_Stream_Writer");
1578 if (out_ !=
nullptr and not closed_)
1599 template <
typename Lattice>
1602 ca_io_detail::require_rank2<Lattice>(
"JSON_Frame_Stream_Writer::accept");
1603 ah_runtime_error_if(closed_) <<
"JSON_Frame_Stream_Writer::accept: stream already closed";
1607 *out_ <<
" {\n \"step\": " << step <<
",\n \"frame\": ";
1612 ca_io_detail::ensure_stream_ok(*out_,
"JSON_Frame_Stream_Writer::accept");
1626 *out_ <<
"\n ]\n}\n";
1628 ca_io_detail::ensure_stream_ok(*out_,
"JSON_Frame_Stream_Writer::close");
1641namespace ca_io_detail {
1654 catch (
const std::exception &e)
1682 return ca_io_detail::try_parse([&]
1704 return ca_io_detail::try_parse([&]
1707 },
"try_read_rle_string");
1726 return ca_io_detail::try_parse([&]
1729 },
"try_read_plaintext");
1748 return ca_io_detail::try_parse([&]
1751 },
"try_read_life_105");
1770 return ca_io_detail::try_parse([&]
1773 },
"try_read_life_106");
1797 return ca_io_detail::try_parse([&]
1800 },
"try_read_csv_snapshot");
C++20/23 compatibility layer: feature detection + Aleph:: polyfills.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_unless(C)
Throws std::domain_error if condition does NOT hold.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
static int cell(const aleph_ca_engine_t *e, size_t r, size_t c)
size_t size_t int32_t value
size_t size_t int32_t * out
Common typedefs and tag types for the Cellular Automata module.
Simple dynamic array with automatic resizing and functional operations.
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
void clear() noexcept
Empties the container.
T & append(const T &data)
Append a copy of data
void reserve(size_t cap)
Reserves cap cells into the array.
Streaming JSON writer for CA trajectories.
JSON_Frame_Stream_Writer(const JSON_Frame_Stream_Writer &)=delete
void close()
Finish the stream.
JSON_Frame_Stream_Writer(std::ostream &out, JSON_Write_Options opts={})
Start a JSON frame stream.
~JSON_Frame_Stream_Writer()
Finish the JSON document if it is still open.
void accept(std::size_t step, const Lattice &frame)
Append one frame to the stream.
Lattice that adds boundary-aware access on top of a storage.
void set(const coord_type &c, const state_type &v)
Strict write: throws if c is out of range.
typename Storage::state_type state_type
typename Storage::coord_type coord_type
static constexpr std::size_t rank
ca_size_t size() const noexcept
void fill(const state_type &value)
Set every cell to value.
state_type at(const coord_type &c) const
Strict access: throws if c is out of range.
Minimal std::expected-style result type for C++20.
Storage + topology that carries the cell values.
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
std::string trim_copy(const std::string &s)
std::string rle_token(ca_size_t n, char glyph)
auto try_parse(F &&parse, const char *context) -> expected< std::invoke_result_t< F & >, std::string >
Invoke a parser, translating any thrown exception into the error channel of expected.
void ensure_stream_ok(const std::ostream &out, const char *fn)
bool blank(const std::string &s)
T parse_scalar(const std::string &token, const char *format)
ca_index_t parse_index_token(const std::string &s, const char *what)
Array< std::string > split_comment_lines(const std::string &comment)
void finalise_absolute_pattern(Binary_Cell_Pattern &pattern, const Array< Coord_Vec< 2 > > &absolute, const bool have_extent, const ca_index_t min_row, const ca_index_t min_col, const ca_index_t max_row, const ca_index_t max_col)
ca_size_t parse_json_size_field(const std::string &s, const std::string &key)
void write_text_scalar(std::ostream &out, const T &value)
std::string header_value(const std::string &line, const std::string &key)
std::string json_escape(const std::string &s)
ca_size_t parse_size_token(const std::string &s, const char *what)
T parse_json_number(const std::string &s, std::size_t &pos)
std::string lower_copy(std::string s)
void require_rank2(const char *fn)
void append_rle_token(std::string &body, ca_size_t n, char glyph)
void write_wrapped_rle_body(std::ostream &out, const std::string &body, const std::size_t line_width)
expected< Binary_Cell_Pattern, std::string > try_read_life_106(std::istream &in)
Non-throwing variant of read_life_106.
Lattice make_lattice_from_snapshot(const Grid_Snapshot< T > &snap)
Construct a lattice from a numeric snapshot.
void write_pgm(std::ostream &out, const Lattice &frame, Mapper &&mapper, const NetPBM_Write_Options &opts={})
Write a binary PGM (P5) image.
void write_life_105(std::ostream &out, const Lattice &frame, const std::string &comment={}, const typename Lattice::state_type &dead=typename Lattice::state_type{})
Write a Life 1.05 file.
void write_plaintext(std::ostream &out, const Lattice &frame, const Plaintext_Write_Options &opts={}, const typename Lattice::state_type &dead=typename Lattice::state_type{})
Write a Life plaintext (.cells) pattern.
Binary_Cell_Pattern read_plaintext_string(const std::string &s)
Read a Life plaintext pattern from a string.
void write_life_106(std::ostream &out, const Lattice &frame, const typename Lattice::state_type &dead=typename Lattice::state_type{})
Write a Life 1.06 file.
std::ptrdiff_t ca_index_t
Signed coordinate component used by lattices and neighborhoods.
std::array< ca_index_t, N > Coord_Vec
Default coordinate vector.
expected< Binary_Cell_Pattern, std::string > try_read_plaintext(std::istream &in)
Non-throwing variant of read_plaintext.
std::string write_plaintext_string(const Lattice &frame, const Plaintext_Write_Options &opts={}, const typename Lattice::state_type &dead=typename Lattice::state_type{})
Return a Life plaintext document.
void write_rle(std::ostream &out, const Lattice &frame, const RLE_Write_Options &opts={}, const typename Lattice::state_type &dead=typename Lattice::state_type{})
Write a 2D frame in Conway RLE format.
void write_ppm(std::ostream &out, const Lattice &frame, Mapper &&mapper, const NetPBM_Write_Options &opts={})
Write a binary PPM (P6) image.
Binary_Cell_Pattern read_life_105(std::istream &in)
Read a Life 1.05 pattern.
void write_csv(std::ostream &out, const Lattice &frame, const CSV_Options &opts={})
Write a numeric CSV snapshot.
std::string write_rle_string(const Lattice &frame, const RLE_Write_Options &opts={}, const typename Lattice::state_type &dead=typename Lattice::state_type{})
Return a frame encoded as Conway RLE.
RLE_Pattern read_rle(std::istream &in)
Read a Conway RLE pattern.
Grid_Snapshot< T > read_json_snapshot(std::istream &in)
Read a JSON numeric snapshot produced by write_json.
RLE_Pattern read_rle_string(const std::string &s)
Read a Conway RLE pattern from a string.
Binary_Cell_Pattern read_life_106(std::istream &in)
Read a Life 1.06 pattern.
Binary_Cell_Pattern read_plaintext(std::istream &in)
Read a Life plaintext (.cells) pattern.
void write_json(std::ostream &out, const Lattice &frame, const JSON_Write_Options &opts={})
Write a JSON snapshot.
std::size_t ca_size_t
Unsigned size component used for extents and counts.
expected< Grid_Snapshot< T >, std::string > try_read_csv_snapshot(std::istream &in, const CSV_Options &opts={})
Non-throwing variant of read_csv_snapshot.
Lattice make_lattice_from_pattern(const Binary_Cell_Pattern &pattern, const typename Lattice::state_type &alive=static_cast< typename Lattice::state_type >(1), const typename Lattice::state_type &dead=typename Lattice::state_type{})
Construct a lattice with the exact dimensions of a pattern.
expected< RLE_Pattern, std::string > try_read_rle_string(const std::string &s)
Non-throwing variant of read_rle_string.
void load_binary_pattern(const Binary_Cell_Pattern &pattern, Lattice &frame, const typename Lattice::state_type &alive=static_cast< typename Lattice::state_type >(1), const typename Lattice::state_type &dead=typename Lattice::state_type{}, const ca_index_t origin_row=0, const ca_index_t origin_col=0)
Fill a lattice from a binary pattern.
expected< RLE_Pattern, std::string > try_read_rle(std::istream &in)
Non-throwing variant of read_rle.
Grid_Snapshot< T > read_csv_snapshot(std::istream &in, const CSV_Options &opts={})
Read a numeric CSV snapshot.
expected< Binary_Cell_Pattern, std::string > try_read_life_105(std::istream &in)
Non-throwing variant of read_life_105.
Main namespace for Aleph-w library functions.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Binary pattern shared by RLE, plaintext and Life formats.
std::string name
optional pattern name
ca_index_t origin_row
original row offset before normalisation
ca_size_t height
number of rows
ca_size_t width
number of columns
Array< std::string > comments
format comments without marker prefixes
ca_index_t origin_col
original column offset before normalisation
std::string rule
optional rule string, e.g. B3/S23
Array< Coord_Vec< 2 > > alive
live cells as {row, col}
Default binary grayscale mapper.
std::uint8_t alive_value
grayscale for live cells
std::uint8_t dead_value
grayscale for dead cells
State dead
state considered dead
std::uint8_t operator()(const State &v) const
Map a cell to one byte.
Default binary RGB mapper.
RGB8 dead_colour
colour for dead cells
State dead
state considered dead
RGB8 alive_colour
colour for live cells
RGB8 operator()(const State &v) const
Map a cell to RGB.
Options controlling CSV output and input.
char delimiter
separator between cells
bool skip_empty_lines
reader ignores empty/whitespace-only rows
Dense numeric snapshot used by CSV and JSON readers.
ca_size_t width
number of columns
ca_size_t height
number of rows
Array< T > cells
row-major payload
T at(ca_size_t row, ca_size_t col) const
Return the value at (row, col).
Options controlling JSON snapshot output.
bool pretty
pretty-print with indentation
std::string rule
optional rule field
Options controlling NetPBM output.
std::uint16_t max_value
NetPBM maximum sample value.
Options controlling Life plaintext output.
char dead
glyph for dead cells
char alive
glyph for live cells
std::string comment
optional ! comments, split on newlines
RGB byte triplet used by PPM exporters.
std::uint8_t g
green channel
friend constexpr bool operator==(RGB8, RGB8) noexcept=default
std::uint8_t b
blue channel
std::uint8_t r
red channel
Options controlling Conway RLE output.
std::string rule
rule field emitted in the header
std::size_t line_width
body wrap width; 0 disables wrapping
std::string comment
optional #C lines, split on newlines
bool trim_dead_border
crop to the live-cell bounding box
std::string name
optional #N line
FooMap m(5, fst_unit_pair_hash, snd_unit_pair_hash)
Dynamic array container with automatic resizing.
C++20 concepts for the Cellular Automata module.