VarAPI
The VarAPI
library manages data objects for the API
framework.
#
Binary Data Management- View: View of any data on the stack/heap/static
- Data: Dynamic heap data
A View
can only refer to data that already exists. It doesn't allocate memory in any way. It infers the size of the
target where possible. It can be implicitly constructed from Data
, String
, StringView
, and const char *
(c-style
string). A View
can be explicitly constructed from fundamental types where the size is known at compile time.
A
View
is used when passing data to file operations.
#include <fs.hpp>#include <var.hpp>
typedef struct { int version char name[32]} my_header_t
my_header_t header
//fill headerView(header).fill<u8>(0xaa)
//Use view to read data into headerFile("path.data").read(View(header))
A View
cannot be constructed from a class or any type where the size is not known at compile-time. The following won't
compile:
#include <var.hpp>
int my_function(int size){ File f //can't compile this View(f).fill(0)
char buffer2[64] View buffer_view(buffer2) // this is OK View(buffer_view).fill(0) //this won't compile (static_assert)}
The Data
class uses the heap to dynamically allocate memory. Generally, it should be used sparingly if you are trying
to maximize performance.
#include <var.hpp>
//converts the string to 16 bytes of dataData hex = Data::from_string("00112233445566778899AABBCCDDEEFF")
#
ContainersThese classes are all API-style wrappers for the equivalent std::container
.
Other than
Array
these usemalloc
/free
under the hood.
- Vector: wrapper for std::vector
- Array: wrapper for std::array
- Queue: wrapper for std::deque (one sided)
- Stack: wrapper for std::stack
- Deque: wrapper for std::deque
#
StringsStrings use one of three types:
StringView
: wrapper for C++17std::string_view
StackString<int size>
: Template class for fixed buffer-sized strings (on the)String
: wrapper for C++std::string
(uses dynamic memory allocation for longer strings)
StringView
The StringView
is just a view (pointer and length) of the string. The data must be held elsewhere. The length is a
fixed maximum size at construction though you can narrow the view through other methods.
VarAPI is designed to use StringView
as the most basic string. All string types (including const char*
) are
implicitly converted to StringView
.
All these guidelines also apply to
std::string_view
.
- Always pass
StringView
by value - Always use
const StringView
when passing a string parameter to a method - Avoid using
StringView
as a local variable (useauto
instead) - Don't return a
StringView
unless you are sure about the lifetime of the string being viewed and the lifetime of the owner taking the return.
StringView
does not guarantee null-termination.
StackString
There are several standard StackString
declarations for common usage:
IdString
short string (up to 24 bytes) for unique (random or time-based) string idsKeyString
short string (up to 48 bytes) for things like JSON keysPathString
for file paths- Size is OS dependent (
PATH_MAX
) - The
&
operator is used for concatenation - The
/
operator concatenates by inserting '/'
- Size is OS dependent (
GeneralString
for larger strings- Size is up to 256 bytes for embedded and 2048 for win/mac/linux.
- The
|
operator is used for concatenation
NumberString
for easily converting a number to a string (up to 64 bytes length)- Special constructor to immediately convert numbers to strings
Here are the StackString
examples:
#include <fs.hpp>#include <var.hpp>#include <chrono.hpp>
int i = 0const auto key = KeyString().format("key-%d", i++)//or with a NumberString()const KeyString key = NumberString(i++, "key-%d").string_view()
// creates "directory/key-0.txt"const auto path = "directory" / key & ".txt"
//implicit conversion to StringView is built-in//File(const StringView path) opens a fileFile("directory" / key & ".txt")
const StringView name = "general"GeneralString general = "this is a " | name | " string."
GeneralString with_numbers = "there are " | NumberString(general.length()) | " characters in general".
//This is really bad -- never do this//`discard_string` will refer to a PathString rvalue that is destroyedconst StringView discard_string = "directory" / key & ".txt"
//This is the way to do it (let the compiler worry about the type)const auto make_it_happen_string0 = "directory" / key & ".txt"const auto make_it_happen_string1 = "directory" | key | ".txt"
Stack strings are always null-terminated and provide a cstring()
method to access a const char *
.
String
The String
class (a wrapper for std::string) should only be used when the string length is unknown and definitely will
not fit in a StackString
type.
String
class uses the +
operator to concatenate.
String
comes with a performance penalty (malloc
/free
). So it is never created
implicitly. StringView::to_string()
will promote just about anything to String
.
String
is always null-terminated and provides a cstring()
method to access a const char *
.
#include <var.hpp>
//PathString usedprintf("%s\n", ("path" & "string").cstring())//GeneralString usedprintf("%s\n", ("path" | "string").cstring())
//String usedprintf("%s\n", ("just a " + "string").cstring())
typedef struct { int version char name[32]} my_header_t
my_header_t header
//Use a string with View::to_string() because//the length is unknown and can exceed StackString lengthsString view_string = View(header).to_string()