Skip to content

Quick and dirty runtime-based string interpolation library for C++

License

Notifications You must be signed in to change notification settings

EclipseMenu/rift

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RIFT

Runtime Interpreted Formatter
Quick and dirty runtime-based string interpolation library for C++.

Note: This library is still in development and is not yet ready for production use.

What is RIFT?

RIFT is a simple, lightweight, and easy-to-use runtime interpreted string formatting library. It is designed to be used for easier string interpolation in C++. It allows you to perform basic calculations and string manipulations directly in the string itself:

#include <iostream>
#include <rift.hpp>

int main() {
    std::cout << rift::format("Test #{number * 2}, Hello {name}!", {
        {"number", rift::Value::from(210)},
        {"name", rift::Value::from("World")}
    }) << std::endl; // Prints "Test #420, Hello World!"
    return 0;
}

Examples

Here are some examples of what you can do with RIFT:

#include <iostream>
#include <rift.hpp>

int main() {
    // Basic string interpolation
    std::cout << rift::format("Hello {name}!", {
        {"name", rift::Value::from("World")}
    }) << std::endl; // Prints "Hello World!"
    
    // Basic arithmetic
    std::cout << rift::format("2 + 2 * 2 = {2 + 2 * 2}!") << std::endl;
    // Prints "2 + 2 * 2 = 6!"
    
    // Arithmetic with variables
    std::cout << rift::format("2 + 2 * {number} = {2 + 2 * number}!", {
        {"number", rift::Value::from(3)}
    }) << std::endl; // Prints "2 + 2 * 3 = 8!"
    
    // Logical expressions
    std::cout << rift::format("Is 2 + 2 equal to 4? {2 + 2 == 4}!") << std::endl;
    // Prints "Is 2 + 2 equal to 4? true!"
    
    // Ternary operator
    std::cout << rift::format("Is 2 + 2 equal to 4? {2 + 2 == 4 ? 'Yes' : 'No'}!") << std::endl;
    // Prints "Is 2 + 2 equal to 4? Yes!"
    
    // Built-in functions
    std::cout << rift::format("The length of 'Hello, World!' is {len('Hello, World!')}") << std::endl;
    // Prints "The length of 'Hello, World!' is 13"
    std::cout << rift::format("The first character of 'Hello, World!' is {substr('Hello, World!', 0, 1)}") << std::endl;
    // Prints "The first character of 'Hello, World!' is H"
    std::cout << rift::format("Random number between 0 and 10: {random(0, 10)}") << std::endl;
    // Prints "Random number between 0 and 10: <random number>"
    std::cout << rift::format("TO UPPER: {toUpper('hello, world!')}") << std::endl;
    // Prints "TO UPPER: HELLO, WORLD!"
    std::cout << rift::format("to lower: {toLower('HELLO, WORLD!')}") << std::endl;
    // Prints "to lower: hello, world!"
    std::cout << rift::format("Trim whitespace: {trim('  Hello, World!  ')}") << std::endl;
    // Prints "Trim whitespace: Hello, World!"
    std::cout << rift::format("Replacing: {replace('Hello, World!', 'World', 'Universe')}") << std::endl;
    // Prints "Replacing: Hello, Universe!"
    
    // Error handling is built-in
    std::cout << rift::format("This is an invalid expression: {2 + 2!") << std::endl;
    // Prints "<error>" - general case for errors
    std::cout << rift::format("Dividing strings: {'hi' / 3}") << std::endl;
    // Prints "Dividing strings: <error: division of strings>" - specific error message
}

How does it work?

Under the hood, RIFT uses a simple lexer and parser to tokenize and parse the input string. Each { ... } block is parsed as an expression, which is then evaluated at runtime. The result is then converted to a string and inserted back into the original string.
You can provide any variables you want (only integers, floats, bools and strings are supported) to the script compiler, which will then be used to evaluate the expressions.

How do I use it?

To use RIFT, simply include the rift.hpp header file in your project. You can then use the rift::format for a quick format, or use the full syntax like so:

#include <iostream>
#include <rift.hpp>

int main() {
    auto* script = rift::compile("Test #{number * 2}, Hello {name}!");
    
    if (script == nullptr) {
        std::cerr << "Failed to compile script!" << std::endl;
        return 1;
    }
    
    script->setVariable("number", 210);
    script->setVariable("name", "World");
    
    std::cout << script->run() << std::endl; // Prints "Test #420, Hello World!"
    return 0;
}

Why should I use RIFT over other libraries?

RIFT is designed as "Runtime" and "Turing complete" string interpolation library. This means that you can perform any calculations and string manipulations directly in the string itself, having to provide only the format string and the variables. This makes it useful in cases, where the user can provide their own format strings, and you want to allow them to do some basic calculations in the string itself.

Building

RIFT is a static library which can be built using CMake. To include the library in your project, simply add the following to your CMakeLists.txt:

add_subdirectory(path/to/rift)
target_link_libraries(your_target PRIVATE rift)

License

RIFT is licensed under the MIT License. See the LICENSE file for more information.

Releases

No releases published

Packages

No packages published