KeyValue is a cross-platform library for making C++ objects accessible through LibreOffice[1] Calc, Excel and other front-ends. Experience of spreadsheet users is enhanced by an object model and a handy key-value based interface.
KeyValue does more than just helping creating spreadsheet functions. The object model allows end-users to build C++ objects through the front-ends. These objects are stored in a repository for later use at user's request. Additionally, KeyValue provides a set of services for an effective use of these objects.
The library is named ater one of its main features: The key-value based interface. Parameters are passed to functions through key-value pairs in contrast to the standard positional interfaces of LibreOffice Calc, Excel, C/C++, etc.
For instance, consider a function which requires stock prices at different dates. Two vectors have to be passed: A vector of dates and a vector of prices. In a positional interface these two vectors would be provided in a specific order, say, first the vector of dates followed by the vector of prices. In contrast, KeyValue allows a label (or key) to be attached to each vector (the value associated to the key) in order to distinguish their meanings. In the example, the keys could be Dates and Prices while the values would be the vectors of dates and prices themselves.
To give a taste of KeyValue, let us develop this example a bit further. Suppose we want to write a C++ function that, given a set of dates and corresponding stock prices, returns to the spreadsheet the earliest date where the stock has reached its lowest level. In the termsheet we would see something like in Figure 1.
The C++ code (see
bridge-example/bridge-example/processor/LowTime.cpp
)
would be similar to:
value::Value
Calculator
<LowTime>::getValue
(constDataSet
&data
) const { // A constkey::MonotoneBoundedVector
<ptime
,key::StrictlyIncreasing
>keyDates
("Dates"); // B const::std::vector
<ptime
>&dates
(*data
.getValue
(keyDates
)); // C constkey::MonotoneBoundedVector
<double,key::NonMonotone
,key::Geq
>keyPrices
("Prices", 0.0,dates
.size
()); // D const::std::vector
<double>&prices
(*data
.getValue
(keyPrices
)); // E doublelowPrice
=prices
[0]; // Fptime
lowDate
=dates
[0]; for (size_ti
=1;i
<prices
.size
(); ++i
) if (prices
[i
] <lowPrice
) {lowPrice
=prices
[i
];lowDate
=dates
[i
]; } // G returnlowDate
; // H }
Without getting deeply into details, we shall comment some important points of this example:
Functions returning values to the spreadsheet are
specializations of template class
of which
Calculator
is the main
method. The template type parameter
getValue
()
is just a tag
identifier to distinguish between different functions.LowTime
Variable
holds
information about the key Dates including the
label "keyDates
Dates
" that appears on the spreadsheet. Its
type is an instantiation of
for type parameters key::MonotoneBoundedVector
and
ptime
.
This means that the expected type of value is a
key::StrictlyIncreasing
[2] whose elements are in increasing order.::std::vector
<ptime
>
A few generic keys like
are implemented. We can implement application specific keys when
no generic key fits our needs or whenever this proves to be
convenient. For instance, implementing a class named
key::MonotoneBoundedVector
can be useful if key
Dates is used very often. In such case,
Dates
would hold all the above
information and line B would be replaced
byDates
constDates
keyDates
;
The method
retrieves the
DataSet
::getValue
()
containing the dates. At this time, all the information contained
in ::std::vector
<ptime
>
is used. In
particular, the constraints on the input are verified and an
exception is thrown if the check fails. Therefore, if execution
gets to next line, we can safely assume that dates are in
increasing order.keyDates
Variable
holds
information about the key Prices: the label
"keyPrices
Prices
" and its expected type of value,
that is, a
of size
::std::vector
<double>
with elements greater than or equal to zero.dates
.size
()
This line of code retrieves the
containing the prices and, if execution gets to next line, we can
be sure that ::std::vector
<double>
and
prices
dates
have the same size and all
' elements are positive.
Otherwise an exception is thrown.prices
This bit of code could be part of the library which KeyValue helps to make accessible through LibreOffice Calc or Excel. We placed it here for illustration purposes only.
While the type returned by
is
Calculator
<LowTime
>::getValue
()
the code
above returns a value::Value
. For
convenience, KeyValue implements implicit conversions to
ptime
from several
types including value::Value
bool
,
double
,
,
string
,
ptime
,
etc.::std::vector
<double>
More than just a nice interface, KeyValue provides memory management, dependency control, exception handling, caching (memoization) and other services.
The two main examples of front-ends (both provided with KeyValue) are LibreOffice Calc and Excel. A third example is an XML parser. Other front-ends may be easily implemented thanks to KeyValue's modular design represented in Figure 2.
There are four layers. The main layer is occupied by KeyValue alone
and is completly independent, that is, does not #include
any
header file from other layers.
The top layer is populated by front-ends. Components of this layer
only #include
header files from KeyValue. (Fact indicated by
the down arrow.)
The bottom layer hosts the core library, that is, the C++ library which we want to use through the front-ends with KeyValue's help. This layer is also independent. As previously mentioned, the code between lines F and G in the example above would be better placed in the core library.
The bridge layer connects KeyValue
and the core library. Bridge #include
s files from both layers
that it is connected to. The code given in the example above would be part
of this layer.
In addition to KeyValue layer, the distibuted code contains the front-ends (excluding the XLM parser which will be available in a future release). KeyValue users have to implement the bridge and core library. If they wish, they can also easily implement other front-ends.
[1] As many LibreOffice users are aware, this office suite is a fork of OpenOffice.org started in 2010. KeyValue dates prior to this fork and used to provide an OpenOffice.org Calc add-in. However, since release 0.3, KeyValue replaced the OpenOffice.org add-in by the LibreOffice one. As of this writing, the two suites are still very similar and the LibreOffice extension will probably work for OpenOffice.org as well.
Notice also that, for the aforementioned reasons, one can find several mentions to OpenOfice.org in KeyValue's code, file names, documentation, etc. Nevertheless, we emphasize that KeyValue focuses on LibreOffice and no longer on OpenOffice.org.