end2endzone / libVariant

libVariant is a c++ library which encapsulate any value of variant types

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

libVariant logo

libVariant

License: MIT Github Releases

libvariant is a C++ open-source library which encapsulate any value of variant types.

Status

Build:

Service Build Tests
AppVeyor Build status Tests status
Travis CI Build Status

Statistics:

AppVeyor Travic CI
Statistics Statistics

Purpose

The libVariant library allows one to create an instance of Variant class which is a type safe and value safe union between all known basic c++ types. An instance of a Variant class encapsulates a single value of any c++ type:

  • 8, 16, 32 and 64 bit signed and unsigned integers
  • 32 and 64 bit floating points
  • Strings.

The class can easily convert between any type of data when required and automatically handles all conversion combinations and minimizes lost of data.

The library is useful for declaring objects, interfaces, plugins or APIs to be type-independent. The need for a variant type is mostly required in designs where one does not want to implement conversion of c++ types using templates in every situation. Programmers can use the same procedures and functions to process variables with different internal representations (integers, strings, ...) without converting any data.

Without the Variant class, multiple copies of the same function must be implemented, each with their different type of data.

Features

The main features of the library are:

  • Compatible with the C++ 1998/2003 standard.
  • Type-safe, value-safe unions between all c++ basic types, including strings.
  • Holds any numeric values up to 64 bits.
  • Converts between any type of data as required.
  • No data loss on mathematical operations. The class supports automatic internal type promotion to prevent overflows.
  • Implements all c++ operators with all known native c++ types to prevent any unwanted implicit conversions to Variant. This make sure that no manipulation errors occurs while handling Variant instances.
  • Matches the same behavior as Visual Basic’s Variant type.

Usage

The following instructions show how to use the library with multiple source code examples:

Assign a value

Assign the value 5 of type int (sint16 / sint32) to a Variant.

Variant var;
var = 5;

Convert to string

Assign the value 5 of type int (sint16 / sint32) and read the value as a string.

Variant var;
var = 5;
std::string my_str = var.getString();

Automatic internal type promotion

The class can also do automatic conversions of the internal type to another type in order to minimize the loss of data.

Floating point promotion

Assign the value 5 of type int (sint16 / sint32) and then add 1.5 of type double (float64).

The internal type of the variant will be promoted to hold the expected result.

Variant var;
var = 5; // sets the internal type to 'int' (sint16 / sint32).
var += 1.5; // promotes the internal type to double (float64)
float64 f_value = var.getFloat64(); //internal value is set to 6.5.

If a Variant class with an internal type set to sint16 and a value of 5 is divided by 2 (sint16) then the internal value of the class will automatically convert to float64 to be able to hold a value of 2.5.

However, if the user still requests the internal value as sint16, then the returned value will be rounded down to 2 which is the same result as if the division would have been processed using the native c++ type int.

Variant var;
var.setSInt16(5);
var = var / 2;
float64 f_value = var.getFloat64(); // returns 2.5
sint16  i_value = var.getSInt16();  // returns 2

Value overflow promotion

The class is protected against unintentional overflows. Here is the process of computing intentional overflows:

sint8 value = 120;
sint8 addition = 10;
Variant var;
var.set(value);
var += addition; // promotes the internal type to sint16 with value 130 instead of overflow value.
sint8  overflow_value = var.getSInt8();  // results in value -126
sint16 promoted_value = var.getSInt16(); // results in value 130

Use Case

Implement a query language

Each column of a ResultSet may be of different type.

Storing values in a Variant type is a perfect candidate for type abstraction.

Provide GUI-editable properties in a generic manner

The Variant class can be used to implement a similar fashion of C# properties where property editors (property sheet) can edit a class attibute of any type.

An application that display a property sheet UI, must only implement a Variant value editor instead of having to implement each specific type of variable.

Implementing type-independent plugins

By defining plugin APIs with Variant class, the plugin author or the application can change their data-type requirements without affecting each other.

Plugin developers can change how they process variables with different internal representations (integers, strings, ...) and reuse the same API without doing any changes to the application which uses the plugin.

Parsing values from configuration files

Parsing an *.ini file always used to return string values. Parsing something like numChild=3 would return a const char * with the value 3 instead of int value = 3;.

Text parsers can be designed to always return a Variant when querying for a named variable in a file.

In the example above, the method allows the application to read numChild value as a string or directly as an integer.

Implementing reflection-like APIs on classes

A system can provide a reflection-like API if each classes of a system provides a list of Variant which encapsulates their attributes.

Using the Variant attributes, one can modify the attributes of a class using the Variant’s internal value.

Limitations

Automatic unsigned to signed conversions

A signed type always have priority over an unsigned type.

If the internal value of a Variant is set to an unsigned value and a mathematical operator is applied to the Variant using a signed value (of the same size) then the internal type of the Variant will change from unsigned to signed.

Note that the expected value from the mathematical operation is always preserved. The only change that may be unnoticed is the internal type changing from unsigned to signed.

For example, having a Variant set to value 4 (uint16) is multiplied by value 10 (sint16), then the internal type will automatically change to sint16 with a value of 40.

uint16 value = 4;
sint16 multiplicator = 10;
Variant var;
var.set(value);
var = var * multiplicator;
//var --> internal type is now sint16

*** Note that inverse operation DOES NOT convert the internal value to uint16. ***

sint16 value = 10;
uint16 multiplicator = 4;
Variant var;
var.set(value);
var = var * multiplicator;
//var --> internal type stays sint16 (internal type is NOT CHANGED to uint16)

If the internal type is unsigned (for instance uint32) and the operator's type is signed but of a different bit-size (for instance sint16), the conversion to a signed type also occurs but the size of the new type (in bits) is as big as the biggest type (in this example, sint32).

uint32 value = 123456;
sint16 multiplicator = 100;
Variant var;
var.set(value);
var = var * multiplicator;
//var --> internal type is now sint32

Build

Please refer to file INSTALL.md for details on how installing/building the application.

Platform

libVariant has been tested with the following platform:

  • Linux x86/x64
  • Windows x86/x64

Versioning

We use Semantic Versioning 2.0.0 for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE file for details

About

libVariant is a c++ library which encapsulate any value of variant types

License:MIT License


Languages

Language:C++ 93.2%Language:CMake 4.1%Language:Batchfile 1.2%Language:Shell 0.9%Language:C 0.4%Language:PowerShell 0.2%