libutilsv4.1.0
Technical documentation

libutils, a C++20 utility librarylibutils, une bibliothèque utilitaire C++20

Exceptions, verbose, CLI, arguments, TCP network, processes and shared memory, encryption, custom types and algorithms, in one static library distributed as RPM / DEB packages. The details of every class are in the wiki.Exceptions, verbose, CLI, arguments, réseau TCP, processus et mémoire partagée, chiffrement, types et algorithmes, dans une seule bibliothèque statique distribuée en paquets RPM / DEB. Le détail de chaque classe est dans le wiki.

1. Overview1. Vue d'ensemble

Everything is in the namespace utils::. A project includes only the root header <utils/utils.hpp> and chooses the sections it needs with defines placed before it; nothing defined means everything.Tout est dans le namespace utils::. Un projet inclut seulement l'en-tête racine <utils/utils.hpp> et choisit les sections voulues avec des defines placés avant ; sans define, tout est inclus.

utils/utils.hpp _Handling _Exception · _Verbose · _Pool (_Middleware) _Cli · _Arguments _Network (_Socket) utils::exception, verbose, pool, cli, arguments, network _Tools _Math (_Geometry, _Trigo) · _Concepts _Encapsulation · _System _CustomType (_Vector, _Matrix, _BLT) _Manip · _Algorithms · _Security _Attribute
Figure 1: the defines of utils.hpp (a group enables its sections, a section its sub-sections).Figure 1 : les defines de utils.hpp (un groupe active ses sections, une section ses sous-sections).
PointPointValueValeur
LanguageLangageC++20, built with clang++ and CMake (>= 3.20)C++20, compilé avec clang++ et CMake (>= 3.20)
LibraryBibliothèquestatic: libutils.a (optimized), libutils_debug.a, libutils_asan.astatique : libutils.a (optimisée), libutils_debug.a, libutils_asan.a
PlatformsPlateformesUnix (Linux, BSD, macOS) and Windows x86_64 (cross compiled with MinGW-w64), same API (section 7)Unix (Linux, BSD, macOS) et Windows x86_64 (compilation croisée MinGW-w64), même API (section 7)
DependencyDépendanceOpenSSL >= 3.0 (encryption, Base64)OpenSSL >= 3.0 (chiffrement, Base64)
VersionVersionutils::version ("v4.1.0"), __LIBUTILS_VERSION__

2. Install & integrate2. Installer & intégrer

2.1 Install2.1 Installation

curl -fsSL https://raw.githubusercontent.com/TsukiNi22/libutils/main/setup.sh | bash -s
sudo dnf install libutils
curl -fsSL https://raw.githubusercontent.com/TsukiNi22/libutils/main/setup.sh | bash -s
sudo apt install libutils
git clone https://github.com/TsukiNi22/libutils.git && cd libutils
export BUILD_DIR=build
cmake -S . -B $BUILD_DIR
sudo cmake --build $BUILD_DIR --target install --parallel $(nproc)
sudo dnf install mingw64-libutils    # Fedora (requires mingw64-openssl)
sudo apt install mingw64-libutils    # Debian / Ubuntu (OpenSSL for MinGW built by hand)
export BUILD_DIR=build-windows
cmake -S . -B $BUILD_DIR -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/mingw-w64.cmake -DCMAKE_BUILD_TYPE=Optimized
cmake --build $BUILD_DIR --parallel $(nproc)
cmake --install $BUILD_DIR --prefix <windows_prefix>   # include/, lib/libutils.a, lib/cmake/utils/
cmake --build $BUILD_DIR --target package               # mingw64-libutils-* RPM/DEB
PackagePaquetContentContenu
libutilslibutils-dev + libutils-op
libutils-devheaders, CMake configuration (requires openssl-devel / libssl-dev)en-têtes, configuration CMake (nécessite openssl-devel / libssl-dev)
libutils-op / -db / -asoptimized / debug / asan library (+ libutils-dev-op, -db, -as)bibliothèque optimisée / debug / asan (+ libutils-dev-op, -db, -as)
mingw64-libutilsWindows: mingw64-libutils-dev + mingw64-libutils-op, installed in the MinGW sysrootWindows : mingw64-libutils-dev + mingw64-libutils-op, installés dans le sysroot MinGW
mingw64-libutils-op / -dbWindows optimized / debug library (+ mingw64-libutils-dev-op, -db), no asan with MinGWbibliothèque Windows optimisée / debug (+ mingw64-libutils-dev-op, -db), pas d'asan avec MinGW
*-prepre-release channel, replaced by any release of the same version or highercanal pre-release, remplacé par toute release de version égale ou supérieure

2.2 Integrate2.2 Intégrer

find_package(utils 4.1.0 REQUIRED)
target_link_libraries(${TARGET} PRIVATE utils::utils)   # includes, static lib & OpenSSL
#define _Network
#define _Cli
#include <utils/utils.hpp>

The library linked follows the CMAKE_BUILD_TYPE of the project: Debug uses libutils_debug.a, Asan libutils_asan.a, anything else libutils.a; a missing package stops the configuration with the name of the package to install.La bibliothèque liée suit le CMAKE_BUILD_TYPE du projet : Debug utilise libutils_debug.a, Asan libutils_asan.a, le reste libutils.a ; un paquet manquant arrête la configuration en donnant le paquet à installer.

Same CMake code for Linux and Windows: configure the project with a MinGW toolchain whose CMAKE_FIND_ROOT_PATH is the MinGW sysroot (cmake/toolchain/mingw-w64.cmake of libutils, or /usr/share/mingw/toolchain-mingw64.cmake on Fedora) and find_package finds the mingw64-libutils* packages (utils::utils also links ws2_32). No Asan package with MinGW: build in Debug with mingw64-libutils-db.Même code CMake pour Linux et Windows : configurer le projet avec un toolchain MinGW dont le CMAKE_FIND_ROOT_PATH est le sysroot MinGW (cmake/toolchain/mingw-w64.cmake de libutils, ou /usr/share/mingw/toolchain-mingw64.cmake sur Fedora) et find_package trouve les paquets mingw64-libutils* (utils::utils lie aussi ws2_32). Pas de paquet Asan avec MinGW : compiler en Debug avec mingw64-libutils-db.

utils.hpp has no global guard: put the defines before every include of it, a bare include after a partial one only gets the sections already defined.utils.hpp n'a pas de garde globale : mettre les defines avant chaque include, un include nu après un include partiel n'obtient que les sections déjà définies.

3. Sections3. Sections

DefineNamespaceContentContenu
_Exceptionutils::exceptionexceptions with a type and a code, formatted outputexceptions avec un type et un code, sortie formatée
_Verboseutils::verboseatomic global level, locked output macrosniveau global atomique, macros de sortie verrouillées
_Poolutils::poolCluster<T>, Middlewares<T, U>
_Cliutils::cliinteractive command line: commands, history, hints, completion, hooks, middlewaresligne de commande interactive : commandes, historique, indices, complétion, hooks, middlewares
_Argumentsutils::argumentsArgParser (usages, flags, options, env), Settings (typed values, casts)
_Networkutils::networkServer, Client, ISocket / ASocket / TCPSocket
_Mathutils::mathcoordinates, CFrame, point rotation, look vector, deg / radcoordonnées, CFrame, rotation de points, vecteur de visée, deg / rad
_Conceptsutils::conceptsoperation concepts (AddableWith, Comparable...)concepts d'opérations (AddableWith, Comparable...)
_Encapsulationutils::encapsulationPipe, Dup, Process, Poll, SharedObject, SharedMemory
_Systemutils::systemIdHandler, Scheduler, LoadBalancer
_CustomTypeutils::typeVector2/3, OVector2/3, Matrix, OMatrix, BidirectionalLookupTable, Freezable, Worker
_Maniputils::iomanip, utils::smanipANSI sequences, format, FixedString, Base64Codec, EETPParserséquences ANSI, format, FixedString, Base64Codec, EETPParser
_Algorithmsutils::algorithmsc2dmp-hsm (string distance), s.o.s (steganography)c2dmp-hsm (distance entre chaînes), s.o.s (stéganographie)
_Securityutils::securityAESKey, RSAKey, CommonRSAKey, observers / memory leak notifierobservers / notifier de fuites mémoire
_Platformutils::platformPOSIX calls for Unix & Windows (close, socket, epoll_wait, dlopen, tcgetattr...), UTILS_UNIX / UTILS_WINDOWSappels POSIX pour Unix & Windows (close, socket, epoll_wait, dlopen, tcgetattr...), UTILS_UNIX / UTILS_WINDOWS
_Attributemacrosmacros_hot, _nodiscard, _likely, _migration(x, y, z)...

The full dependency view of the headers, classes and calls is on the graph page.La vue complète des dépendances entre en-têtes, classes et appels est sur la page graphe.

4. Errors4. Erreurs

Every error is an exception carrying a type and a code, never a return code. The codes are generated at the build from cmake/config/exceptions/**/*.json; a project adds its own codes (ExternalCode) with the same JSON format.Chaque erreur est une exception portant un type et un code, jamais un code de retour. Les codes sont générés au build depuis cmake/config/exceptions/**/*.json ; un projet ajoute ses propres codes (ExternalCode) avec le même format JSON.

ClassClasseTypeMeaningSens
NoneExceptionNonenot an error (ex: help displayed, Exit)pas une erreur (ex : aide affichée, Exit)
WarningExceptionWarningthe program can continuele programme peut continuer
ErrorExceptionErrorerror of the callerreur de l'appel
CustomExceptiongivendonnécombination of typescombinaison de types
FatalExceptionFatalprints and calls std::abort() from its constructoraffiche puis appelle std::abort() depuis son constructeur
try {
    server.start();
} catch (const utils::exception::IException& e) {
    if (e.getCode() == utils::exception::InternalCode::AlreadyRunning) return;
    std::cerr << e.formated() << std::endl; // [Error] file:line (origin) -> message / function = info
}

A code can restrict its allowed types; a forbidden combination ends with FatalException(ExceptionCodeRestriction). Many methods take failsafe (print a warning instead of throwing) or safe_mode (lock).Un code peut restreindre ses types autorisés ; une combinaison interdite finit en FatalException(ExceptionCodeRestriction). Beaucoup de méthodes prennent failsafe (avertir au lieu de lever) ou safe_mode (verrou).

5. Network & EETP5. Réseau & EETP

A Server and a Client exchange payloads (strings ended by a separator, '\n' by default) through a socket object. listen() reads what is available without blocking, join() waits for the next epoll event; stop() / kill() can be called from another thread. On Windows the sockets use Winsock 2 and the epoll is emulated over WSAPoll.Un Server et un Client échangent des payloads (chaînes terminées par un séparateur, '\n' par défaut) via un objet socket. listen() lit ce qui est disponible sans bloquer, join() attend le prochain événement epoll ; stop() / kill() peuvent être appelés depuis un autre thread. Sous Windows les sockets utilisent Winsock 2 et l'epoll est émulé avec WSAPoll.

Client Server TCPSocket TCPSocket + epoll payload '\n' payload '\n' ... TCP EETPParser::format / parse
Figure 2: the network layers; the EETP parser is optional, on top of the payloads.Figure 2 : les couches réseau ; le parser EETP est optionnel, au-dessus des payloads.

5.1 EETP protocol5.1 Protocole EETP

EETPParser keeps the keys of each peer: the client sends SYN (its RSA public key, encrypted with the common RSA key of ~/.ssh/common), the server answers SO (a new AES-256 key, encrypted with the client key), then every message is AES-256-GCM encrypted with a new random iv.EETPParser garde les clés de chaque pair : le client envoie SYN (sa clé publique RSA, chiffrée avec la clé RSA commune de ~/.ssh/common), le serveur répond SO (une nouvelle clé AES-256, chiffrée avec la clé du client), puis chaque message est chiffré en AES-256-GCM avec un nouvel iv aléatoire.

TypeDirectionSensContentContenu
SYNclient → serverclient RSA public key (common RSA)clé publique RSA du client (RSA commune)
SOserver → clientAES-256 key (client RSA)clé AES-256 (RSA du client)
otherautre↔AES-256-GCM, frame <iv><tag> ETB <content>, Base64 encodedAES-256-GCM, trame <iv><tag> ETB <contenu>, encodée en Base64
EM↔disconnection, never encrypteddéconnexion, jamais chiffrée

The framing changed in v3.0.0: both sides must use v3.0.0 or later.Le format des trames a changé en v3.0.0 : les deux côtés doivent utiliser v3.0.0 ou plus.

6. Processes & IPC6. Processus & IPC

Process wraps fork / execvp / waitpid with pipes and fd duplications applied in the child; Poll wraps epoll; SharedObject loads a .so. SharedMemory passes messages between processes through a POSIX shared memory split in slots. On Windows: CreateProcess, WSAPoll, LoadLibrary (.dll) and a file mapping with a named event (section 7).Process encapsule fork / execvp / waitpid avec pipes et duplications de fd appliquées dans le fils ; Poll encapsule epoll ; SharedObject charge un .so. SharedMemory fait passer des messages entre processus via une mémoire partagée POSIX découpée en slots. Sous Windows : CreateProcess, WSAPoll, LoadLibrary (.dll) et un file mapping avec un événement nommé (section 7).

/name (shm) ShmMetadata: size, queue, connected, readable (futex), sequence slot 0 flag · target slot 1 slot ... slot n-1 process A send(bytes, target) process B reader thread
Figure 3: a writer claims a free slot (flag 0 → 1), writes, publishes it (flag 2) and wakes the readers; the reader thread of each instance copies the messages addressed to it into a local storage read with read().Figure 3 : un écrivain réserve un slot libre (flag 0 → 1), écrit, le publie (flag 2) et réveille les lecteurs ; le thread lecteur de chaque instance copie les messages qui lui sont adressés dans un stockage local lu avec read().

A message is addressed to one reader (Target(limit, ownership)) or to every reader (Target(limit), 0 = all the connected ones). An Id{id, ownership} links the answers of a conversation, join() waits for a message and returns when the memory is closed.Un message vise un lecteur (Target(limit, ownership)) ou tous (Target(limit), 0 = tous les connectés). Un Id{id, ownership} relie les réponses d'une conversation, join() attend un message et rend la main quand la mémoire est fermée.

7. Platforms7. Plateformes

Every class has the same API on Unix and Windows: the library only calls the system through utils::platform::, whose functions have the names, arguments and contract of POSIX (-1 and errno). On Unix they are the system calls, on Windows a Win32 / Winsock / CRT implementation. The same calls are given to the programs by the section _Platform.Chaque classe a la même API sous Unix et Windows : la bibliothèque n'appelle le système que via utils::platform::, dont les fonctions ont les noms, arguments et contrat de POSIX (-1 et errno). Sous Unix ce sont les appels système, sous Windows une implémentation Win32 / Winsock / CRT. Les mêmes appels sont donnés aux programmes par la section _Platform.

Server, Client, Poll, Process, Cli, SharedObject, Pipe... utils::platform (close, socket, epoll_wait, dlopen...) Unix: system calls Windows: Win32 / Winsock / CRT
Figure 4: one code for both platforms, the difference is inside utils::platform.Figure 4 : un seul code pour les deux plateformes, la différence est dans utils::platform.

7.1 Calls7.1 Appels

HeaderEn-têteCallsAppelsWindows implementationImplémentation Windows
Unistd.hppclose, read, write, pipe, dup, dup2, isatty, poll, getpid, readlink, strerrorCRT, or Winsock for a socket; poll also on the console / pipes / files; strerror knows the socket errorsCRT, ou Winsock pour un socket ; poll aussi sur la console / les pipes / les fichiers ; strerror connaît les erreurs de socket
Socket.hppsocket, connect, bind, listen, accept, recv, send, setsockopt, getsockname, getpeername, getaddrinfoWinsock 2 started on the first use, errors translated in errnoWinsock 2 démarré au premier appel, erreurs traduites dans errno
Epoll.hppepoll_create1, epoll_ctl, epoll_waitemulation over WSAPoll: sockets only, level triggered, EPOLLONESHOT emulatedémulation avec WSAPoll : sockets seulement, niveau, EPOLLONESHOT émulé
Dlfcn.hppdlopen, dlsym, dlclose, dlerror, dladdrLoadLibraryA, GetProcAddress, FreeLibrary, GetModuleHandleExA
Termios.hpptcgetattr, tcsetattrconsole mode (ICANON = line input, ECHO, ISIG = ctrl+c, VT input)mode de la console (ICANON = saisie en ligne, ECHO, ISIG = ctrl+c, entrée VT)

7.2 Differences7.2 Différences

No fork on Windows: Process::spawn() and a dup on a fd other than 0, 1, 2 raise a FatalException (UndefinedCall). spawn(path, args) uses CreateProcess.Pas de fork sous Windows : Process::spawn() et un dup sur un autre fd que 0, 1, 2 lèvent une FatalException (UndefinedCall). spawn(path, args) utilise CreateProcess.

Other differences: Poll / Client / Server only handle sockets (at most 10 ms of latency), a Process has no signal, ctrl+z is a char for the Cli, a SharedMemory disappears with its last handle. Include <windows.h> before <utils/utils.hpp> (it declares a member named _unused, a libutils macro), or define WIN32_LEAN_AND_MEAN.Autres différences : Poll / Client / Server ne gèrent que des sockets (10 ms de latence au plus), un Process n'a pas de signal, ctrl+z est un caractère pour le Cli, une SharedMemory disparaît avec son dernier handle. Inclure <windows.h> avant <utils/utils.hpp> (il déclare un membre nommé _unused, une macro de libutils), ou définir WIN32_LEAN_AND_MEAN.

8. Build, tests & CI8. Build, tests & CI

CommandCommandeResultRésultat
cmake -S . -B build -DCMAKE_BUILD_TYPE=Optimized|Debug|Asanlibutils.a / libutils_debug.a / libutils_asan.a
cmake --build build --target releasethe 3 librariesles 3 bibliothèques
cmake --build build --target package_releaseevery RPM / DEB packagetous les paquets RPM / DEB
-DBUILD_TESTS=ON + ctest --test-dir buildGoogleTest unit tests (unit_tests at the root)tests unitaires GoogleTest (unit_tests à la racine)
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/mingw-w64.cmakeWindows build (MinGW-w64), tests run with wine by ctest, mingw64-libutils-* RPM/DEB packages (MinGW sysroot)build Windows (MinGW-w64), tests lancés avec wine par ctest, paquets RPM/DEB mingw64-libutils-* (sysroot MinGW)
Dispatch Unit Tests Build Packages Build Libraries docker-image build else
Figure 5: the CI on every push of main or of a v* tag ([ignore] skips it).Figure 5 : la CI à chaque push sur main ou d'un tag v* ([ignore] la saute).
TriggerDéclencheurResultRésultat
tag vX.Y.Ztag vX.Y.Zstable packagespaquets stables
tag vX.Y.Z-<suffix> or commit [build]tag vX.Y.Z-<suffixe> ou commit [build]-pre packages (5 last versions kept)paquets -pre (5 dernières versions gardées)
commit [release] or any package buildcommit [release] ou tout build de paquetsnotification of docker-imagenotification de docker-image

9. Licenses9. Licences

ComponentComposantLicenseLicence
libutils (its own code)libutils (son propre code)MIT
include/utils/algorithms/ (c2dmp-hsm, s.o.s)CC BY-NC-SA 4.0
OpenSSLApache-2.0 (linked, system package)Apache-2.0 (liée, paquet système)

The MIT license doesn't apply to the dependencies: the synced algorithms can't be used commercially without an agreement with the author (THIRD_PARTY_NOTICES.md).La licence MIT ne s'applique pas aux dépendances : les algorithmes synchronisés ne peuvent pas être utilisés commercialement sans accord de l'auteur (THIRD_PARTY_NOTICES.md).