Skip to content

natewind/cleario

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ClearIO

A header-only IO library implemented in C++20, internally a wrapper over stdio.

The library is under development and subject to change. Contributions are welcome (but keep in mind that I’m very opinionated). You can also log an issue if you spot a bug or if you want a particular feature not already listed in TODO.

Advantages

  • Clean and consistent interface
  • Pretty-printing STL containers and pointers
  • Initializing (multiple) variables on read (no mutation necessary)
  • No sync_with_stdio, so should be faster than iostream
  • No runtime format strings, so might be faster than stdio

Installation

Add it to your Git project as a submodule:

git submodule add git@github.com:natewind/cleario.git

Or simply clone:

git clone --recurse-submodules git@github.com:natewind/cleario.git

Include the public interface:

#include "cleario/include.hpp"

Input

To read a value of type T:

auto const x = clear::read<T>(); // x: T

To read multiple values of types Ts:

auto const xs = clear::read<Ts...>(); // xs: std::tuple<Ts...>

If the end of the file is reached or there are no values of type(s) T/Ts to read, the behaviour is undefined.

To read safely:

// maybe_x: std::optional<T>
auto const maybe_x = clear::safe_read<T>();

// maybe_xs: std::optional<std::tuple<Ts...>>
auto const maybe_xs = clear::safe_read<Ts...>();

Chars

auto const [a, b] = clear::read<char, char>(); // qw

Booleans

auto const [t, f] = clear::read<bool, bool>(); // True False

Integers

Integral types (except for char) in different bases:

auto const a = clear::read<int>();             // 123
auto const b = clear::read<clear::bin<int>>(); // 0b1111011
auto const c = clear::read<clear::oct<int>>(); // 0o173
auto const d = clear::read<clear::hex<int>>(); // 0x7b

Explicit decimal base to read an integer into char:

auto const e = clear::read<clear::dec<char>>(); // 123

If a read fails, characters from the input stream are consumed until the one that induced the failure.

Output

To print one or more values without a newline:

clear::print("Helo, World! ", 42, ' ', true); // Hello, World! 42 True

With a newline:

clear::println("Helo, World! ", 42, ' ', true); // Hello, World! 42 True

To flush stdout:

clear::flush();

All three functions return true on success and false on failure. print / println aborts after the first unsuccessful write.

Chars

clear::println('a', 'b', 'c'); // abc

Strings

  • char const*
  • std::string
  • std::string_view
auto const str = std::string("Qwerty");
clear::println(str); // Qwerty

Booleans

clear::println(true, ' ', false); // True False

Integers

Integral types (except for char) in different bases:

clear::println(150); // 150
clear::println(clear::bin {150}); // 0b10010110
clear::println(clear::oct {150}); // 0o226
clear::println(clear::hex {150}); // 0x96

Explicit decimal base to print char as an integer:

clear::println(clear::dec {'q'}); // 113

Floats

  • float
  • double
  • long double

Chooses the shortest notation between std::chars_format::fixed and std::chars_format::scientific:

clear::println(3.14); // 3.14
clear::println(-0.0000000005); // -5e-10

Pointers

  • T*
  • std::unique_ptr
  • std::shared_ptr
auto const x = 5;
auto const ptr = static_cast<void*>(&x);

clear::println(&x); // <int object at 0x7ffcb52c6c54>
clear::println(ptr); // <object at 0x7ffcb52c6c54>

Optionals

clear::println(std::optional<int> {}); // None
clear::println(std::optional {12}); // Some(12)

Tuples

clear::println(std::tuple(5, false, "qwerty")); // (5, False, qwerty)

Sequence containers

  • T[]
  • std::array
  • std::vector
  • std::deque
  • std::forward_list
  • std::list
auto const vec = std::vector {1, 2, 3, 4, 5};
clear::println(vec); // [1, 2, 3, 4, 5]

Associative containers

  • std::set
  • std::multiset
  • std::unordered_set
  • std::unordered_multiset
auto const set = std::set {1, 2, 3, 4, 5};
clear::println(set); // {1, 2, 3, 4, 5}
  • std::map
  • std::multimap
  • std::unordered_map
  • std::unordered_multimap
auto const map = std::unordered_map {{"a", 1}, {"b", 2}, {"c", 3}, {"d", 4}, {"e", 5}};
clear::println(map); // {e: 5, c: 3, b: 2, d: 4, a: 1}

User-defined types

Consider a type:

struct Point { int x, y; };

To make it printable, implement print for it by calling print on already printable types:

template <>
auto clear::io::print(Point const &point) -> bool
{
	return print('(', point.x, ", ", point.y, ')');
}

Try it out:

clear::println(Point {3, 4}); // (3, 4)

Files

To open a file:

auto file = clear::open("file.txt", "w");

The access modes are the same ones used with std::fopen (the default is "r+"). Files are movable (but not copyable) and close automatically when leaving the scope.

To open a file safely (because it can fail):

auto maybe_file = clear::safe_open("maybe_file.txt", "w"); // returns std::optional

To write to a file, simply use print / println and flush as member functions:

file.println("Helo, World! ", 42, ' ', true);

if (maybe_file)
	maybe_file->println("Helo, World! ", 42, ' ', true);

To read from a file, use read / safe_read as a member function:

auto const [a, b] = open("input.txt").read<char, int>();

About

A clean IO library for C++20

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages