Skip to content

engdoreis/reisfmt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

reisfmt

This is a tiny implementation, header only of the c++23 std::print for embedded systems. It only depends on some headers of the standard lib.

This implementation is heavily based on c++20 features. So you need a compiler that support the features: Concepts.

Integration with CMake r

<!-- CMakelist.txt -->
cmake_minimum_required(VERSION 3.13)
include(FetchContent)

FetchContent_Declare(REISFMT
  GIT_REPOSITORY    https://github.com/engdoreis/reisfmt
  GIT_TAG           <git hash>
)
FetchContent_Populate(REISFMT)

set(NAME my_app)
add_executable(${NAME} main.cc)
target_include_directories(${NAME} PRIVATE "${reisfmt_SOURCE_DIR}/include")

Instantiate in your project

// log.hh
#include "fmt.h"
#include "uart.h"

struct LogUart{
  Uart* uart;
  // Implement your serialization here (UART, USB...)
  void write(const char* buf, size_t n) {
    while (n--) {
      uart->putc(*buf++);
    }
  }
};

using Log = reisfmt::Fmt<LogUart>;

//main.cc
#include "log.h"
//...
int main() {
// ...
  LogUart log_uart{uart0};
  Log log(log_uart);
  log.print("Hello {}", "World");
  return 0;
}

Extending the print function for custom types

The print function can be extended to print custom types in two different ways. The first option is recommended in most cases consist in implementing the concept Printable for the desired type.

struct Memory {
  size_t addr;
  size_t size;

  // Printable concept
  template <typename T>
  inline void print(reisfmt::Fmt<T> &fmt) {
    fmt.print("Memory: addr: {:#x}, size: {}", addr, size);
  }
};

The second option is more verbose and may be needed in some cases where the type is defined by an external library. Here we specialize the struct Formatter for the desired type.

struct Memory {
  size_t addr;
  size_t size;
};

namespace reisfmt {
template <typename T>
struct Formatter<T, Memory> {
  static inline void print(Fmt<T> &fmt, Memory &obj) {
    fmt.print("Memory: addr: {:#x}, size: {}", obj.addr, obj.size);
  }
};
}

Now you can print the struct Memory using the fmt library.

  fmt_.println("{}", Memory{0x1000'0000, 1024 * 256});

Openning curly brace

The openning curly braces is the only character that needs to be escaped.

  log.println("{{ Testing curly braces }", ); // Will print: "{ Testing curly braces }"

Formatting specification

This library follows the c++ standard library format specification defined here.

The following features below from the specification are implemented:

Spec Implemented
fill-and-align yes
sign no
# yes
width yes
precision no
locale no
type See below
Type Implememented
d yes
b yes
x yes
o yes
f no
a no
e no
g no
p no
? no

About

A tiny implementation of the c++23 std::print for embedded systems.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •