-
Notifications
You must be signed in to change notification settings - Fork 12
Getting Started
string_theory uses the CMake build system. To get started on a Unix-like system (Linux, Mac, MSYS, etc), you can just build string_theory from the command line after installing CMake:
$ cd /path/to/string_theory
$ mkdir build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local ..
$ make && sudo make install
On Windows, you can also generate Visual Studio projects, either from the command line or from the CMake GUI:
> cd C:\Path\to\string_theory
> mkdir build-msvc
> cd build-msvc
> cmake -G "Visual Studio 14 2015" -DCMAKE_INSTALL_PREFIX="..\dist-msvc" ..
Open the generated .sln file and build the Release target,
- OR -
Build from the command line:
> cmake --build . --config Release
> cmake --build . --config Release --target INSTALL
If your project is built using CMake, it should be easy to add string_theory:
# CMakeLists.txt
# ...
find_package(string_theory REQUIRED)
# ...
add_executable(myapp ...)
target_link_libraries(myapp PUBLIC string_theory)
Then be sure to specify or locate the cmake module path when configuring your
project (e.g. -Dstring_theory_DIR=/usr/local/lib/cmake/string_theory
).
When using other build systems, you can just specify string_theory's include and library paths for your build system. For GNU makefiles, this may look something like:
STRING_THEORY_DIR = /usr/local
CPPFLAGS += -I$(STRING_THEORY_DIR)/include
If you create a useful module for your favorite build system, you can also contribute the necessary files to string_theory via a Pull Request.
#include <string_theory/string>
#include <string_theory/exceptions>
#include <string_theory/stdio>
int main(int argc, char *argv[])
{
ST::string greeting = ST_LITERAL("Hello");
// Literals can also use the _st user-literal operator if your compiler
// supports user-defined literals
ST::string name = "world"_st;
if (argc > 1) {
try {
// Alternatively, you can assume UTF-8 and substitute invalid
// byte sequences with
// ST::string::from_utf8(argv[1], ST_SIZE_AUTO, ST::substitute_invalid)
// The above method will also avoid throwing any exceptions.
name = ST::string::from_utf8(argv[1]);
} catch (const ST::unicode_error &) {
name = ST::string::from_latin_1(argv[1]);
}
}
ST::printf("{}, {}\n", greeting, name);
return 0;
}
#include <string_theory/format>
extern void log_line(const ST::string &line);
ST::string status_line(const ST::string &filename, int file_num, int total_files)
{
// "Processing file 004: Foobar.txt - 12.5%"
return ST::format("Processing file {>03}: {<20} - {4.1f}%", file_num,
filename, double(file_num) / double(total_files));
}
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; ++i) {
log_line(status_line(argv[i]));
// Process file...
}
return 0;
}
#include <string_theory/codecs>
#include <string_theory/stdio>
int main(int argc, char *argv)
{
if (argc < 2) {
ST::printf(stderr, "Usage: {} <mode> input\n", argv[0]);
ST::printf(stderr, "<mode>:\n");
ST::printf(stderr, " base64_encode\n");
ST::printf(stderr, " base64_decode\n");
ST::printf(stderr, " hex_encode\n");
ST::printf(stderr, " hex_decode\n");
return 1;
}
ST::string mode = argv[1];
ST::string input = argv[2];
ST::string result;
if (mode == "base64_encode") {
result = ST::base64_encode(input.to_utf8());
} else if (mode == "base64_decode") {
ST::char_buffer data = ST::base64_decode(input);
result = ST::string::from_utf8(data);
} else if (mode == "hex_encode") {
result = ST::hex_encode(input.to_utf8());
} else if (mode == "hex_decode") {
ST::char_buffer data = ST::hex_decode(input);
result = ST::string::from_utf8()
} else {
ST::printf(stderr, "ERROR: Unsupported mode: {}.\n", mode);
return 2;
}
ST::printf("{}\n", result);
return 0;
}
/* point3d.h */
#include <string_theory/formatter>
struct Point3D { double x, y, z; };
// This version will apply the specified floating point formatting rules
// to each of the rendered values x,y,z
inline void format_type(const ST::format_spec &format, ST::format_writer &output,
const Point3D &value)
{
output.append("Point3D{");
ST::format_type(format, output, value.x);
output.append(",");
ST::format_type(format, output, value.y);
output.append(",");
ST::format_type(format, output, value.z);
output.append("}");
}
// Could also format recursively. This will instead treat the upper-level
// formatting rules as a single string formatter. For example:
inline void format_type(const ST::format_spec &format, ST::format_writer &output,
const Point3D &value)
{
using namespace ST; // Use ADL if necessary
format_type(ST::format("Point3D{{{.2f},{.2f},{.2f}}", value.x, value.y, value.z));
}
#include <string_theory/stdio>
#include "point3d.h"
int main(int argc, char *argv[])
{
Point3D point{12.4, 42.0, -6.3};
ST::printf("It's located at {}\n", point);
return 0;
}
#include <string_theory/formatter>
#include "my_logger.h"
class my_log_writer : public ST::format_writer
{
public:
my_log_writer(const char *format_str, my_logger *logger)
: ST::format_writer(format_str), m_logger(logger) { }
my_log_writer &append(const char *data, size_t size) override
{
// NOTE: Prior to string_theory 3.0, you MUST check for
// ST_AUTO_SIZE. In string_theory 3.0 and later, formatters
// should not call append() with ST_AUTO_SIZE any more.
// if (size == ST_AUTO_SIZE)
// size = std::char_traits<char>::length(data);
m_logger->write_log(data, size);
return *this;
}
my_log_writer &append_char(char ch, size_t count = 1) override
{
ST::string buffer = ST::string::fill(count, ch);
m_logger->write_log(buffer.c_str(), count);
return *this;
}
};
template <typename... args_T>
void log_format(my_logger *logger, const char *fmt_str, args_T &&...args)
{
my_log_writer data(fmt_str, logger);
ST::apply_format(data, std::forward<args_T>(args)...);
}
int main(int argc, char *argv[])
{
my_logger *logger = get_logger();
log_format(logger, "Running {}\n", argv[0]);
return 0;
}