C++ library suite released (cpplocate, cppassist, cppfs, cppexpose)

CG Internals released four of their projects: cpplocate, cppassist, cppfs, and cppexpose. Together, these projects consolidate and provide domain-agnostic features for C++. Most prominent features are run-time assets location, command-line argument parsing, logging, STL extensions, multi-threading and vectorization helpers, cross-platform file-system access, object reflection, scripting, and a plugin system.

All sources are published using an MIT-compatible license and are provided as installers for Windows and .deb packages within the cginternals PPA.

Short description of the four libraries:


cpplocate-logo

cpplocate is a cross-platform C++ library that provides tools for applications to locate their binary files and data assets, as well as those of dependent modules. It supports queries of different paths, depending on the type of the component in question (application, library, or application bundle). For the most basic use case, cpplocate is used to detect run-time data that is associated with a module, and we provide a convenience location function. Internally, cpplocate is implemented using plain C, providing a C++ interface for ease of use. For communities and software that don’t want to use C++, the liblocate within this project can be used instead.

Full description and documentation are available, too.

Example:

#include <cpplocate/cpplocate.h>

#include <glbinding/gl/gl.h>

const std::string assetPath = cpplocate::locatePath("data/cubescape", "share/glbinding", reinterpret_cast<void *>(&gl::glCreateShader));
// assetPath now contains the path to the directory containing "data/cubescape"


cppassist-logo

cppassist is a collection of cross-platform C++ functions, classes and libraries that are too small to be standalone. It acts like a storage point for useful and reusable code for everyone using C++.

Full description and documentation are available, too.

As of now, cppassist is structured into these modules:

  • cmdline: Command line arguments parser for console applications
  • flags: Flags type to help using enums as flags
  • fs: Classes to access raw files and their key-value structured header information
  • logging: Stream like logging functionality with customizable outputs (default output is to the console)
  • memory: Low-level memory management helpers
  • simd: Structures and algorithms for SIMD-like data processing, as introduced by GPUs. This is achieved by compiler extensions as SSE, AVX2, and AVX512
  • string: Utilities like conversion between string and numeric data types, convenience functions for string operations, and some advanced regex functionality
  • threading: Wrapper around concurrent loop execution
  • tokenizer: Low-level tokenizer as base for more elaborate text parsers
  • typelist: TypeList type that allows calling different instantiations of a templated method consecutively

Logging Example:

#include <cppassist/logging/logging.h>

cppassist::setVerbosityLevel(LogMessage::Debug + 2);

cppassist::critical() << "A normal critical message.";
cppassist::error() << "A normal error message.";
cppassist::warning() << "A normal warning message.";
cppassist::info() << "A normal info message.";
cppassist::debug() << "A normal debug message.";
cppassist::debug(1) << "Another debug message.";

cppassist::info("A") << "Info message from context A";
cppassist::warning("B") << "Warning from context B";
cppassist::critical("C") << "Critical message from context C";

String manipulation:

#include <cppassist/string/manipulation.h>

const auto commaSeparatedList = cppassist::join({ 1, 2, 3, 4, 5}, ",");
const auto stringVector = cppassist::split("1,2,3,4,5", ',', false);
const auto trimmedString = cppassist::trim("     Hallo     ");
const auto strippedString = cppassist::stripped("1-2-3-4-5-6", { '-' });

Threading:

#include <cppassist/threading/parallelfor.h>

bool parallelize = size > 25; // use parallel computation if threshold is reached

// Beware that start and end are both inclusive
cppassist::forEach(0u, size, [this](std::uint32_t number)
{
    // concurrent calls of this with 0 <= number <= size
}, parallelize);

Tokenizer:

#include <cppassist/tokenizer/Tokenizer.h>

// Create tokenizer for JSON
cppassist::Tokenizer tokenizer;

tokenizer.setOptions(
    cppassist::Tokenizer::OptionParseStrings
    | cppassist::Tokenizer::OptionParseNumber
    | cppassist::Tokenizer::OptionParseBoolean
    | cppassist::Tokenizer::OptionParseNull
    | cppassist::Tokenizer::OptionCStyleComments
    | cppassist::Tokenizer::OptionCppStyleComments
);

tokenizer.setQuotationMarks("\"");
tokenizer.setSingleCharacters("{}[],:");


cppfs-logo

cppfs is a cross-platform C++ library that provides an object-oriented abstraction for working with files and the file system. It can be used not only to access the local file system, but for remote and virtual file systems as well. By specializing the virtual backend interface, cppfs can be easily extended to support additional remote protocols or virtual file systems.

Full description and documentation are available, too.

Listing directory entries:

#include <cppfs/fs.h>
#include <cppfs/FileHandle.h>

using namespace cppfs;

void listDir(const std::string & path)
{
    FileHandle dir = fs::open(path);

    if (dir.isDirectory())
    {
        for (FileIterator it = dir.begin(); it != dir.end(); ++it)
        {
            std::string path = *it;
        }
    }
}

Open a file for reading or writing:

#include <cppfs/fs.h>
#include <cppfs/FileHandle.h>

using namespace cppfs;

void openFile(const std::string & filename)
{
    FileHandle fh = fs::open(filename);

    if (fh.isFile())
    {
        auto in = fh.createInputStream();
        // ...

        auto out = fh.createOutputStream();
        // ...
    }
}


cppexpose-logo

cppexpose is a cross-platform C++11 library that provides tools for introspection of types, properties, and classes. This allows for a C++ program to expose its interfaces into runtime, making it possible to, e.g., create automatic GUI representations for interfaces, or to expose them into a scripting environment. The implementation is based on standard C++ templates and does not use language extensions or macros, making it typesafe and usable with any C++11 compliant toolchain. Also, no meta compilation step is required.

Full description and documentation are available, too.

Components and Plugins:

int main(int, char * [])
{
    // Create a component manager
    cppexpose::ComponentManager componentManager;

    // Search for plugins in the current working directory
    componentManager.addPluginPath(".");
    componentManager.scanPlugins();

    // List available components
    std::cout << "Components:" << std::endl;
    std::cout << std::endl;
    for (cppexpose::AbstractComponent * component : componentManager.components())
    {
        std::cout << "----------------------------------------" << std::endl;
        std::cout << "name:        " << component->name() << std::endl;
        std::cout << "type:        " << component->type() << std::endl;
        std::cout << "description: " << component->description() << std::endl;
        std::cout << "tags:        " << component->tags() << std::endl;
        std::cout << "annotations: " << component->annotations() << std::endl;
        std::cout << "vendor:      " << component->vendor() << std::endl;
        std::cout << "version:     " << component->version() << std::endl;
        std::cout << "----------------------------------------" << std::endl;
        std::cout << std::endl;
    }
}

Reflection in Classes:

// Create object and print its initial contents
MyObject obj;
obj.print();

// Enumerate properties
std::cout << "Properties:" << std::endl;
for (auto it : obj.properties())
{
    cppexpose::AbstractProperty * property = it.second;
    std::cout << "- " << property->name() << " (" << property->typeName() << ")" << std::endl;
}
std::cout << std::endl;

Scripting:

int main(int, char * [])
{
    ScriptContext scriptContext;

    // Create scripting environment
    Object script("script");
    scriptContext.addGlobalObject(&script);

    MyObject obj ("obj");
    script.addProperty(&obj);

    TreeNode tree("tree");
    script.addProperty(&tree);

    // Provide a script console
    bool done = false;
    while (!done && !std::cin.eof())
    {
        // Prompt
        std::cout << "> " << std::flush;

        // Read command
        std::string cmd;
        std::getline(std::cin, cmd);

        // Process command
        if (cmd != "exit") {
            Variant result = scriptContext.evaluate(cmd);
            std::cout << result.toString() << std::endl;
        } else done = true;
    }

    // Exit application
    return 0;
}



Press Release created by Willy Scheibel, 25. October 2018.