Own fork of MbedSmartRest

Dependents:   MbedSmartRestMain MbedSmartRestMain

Fork of MbedSmartRest by Cumulocity Official

Files at this revision

API Documentation at this revision

Comitter:
Cumulocity
Date:
Thu Jul 03 20:38:04 2014 +0200
Child:
1:9a11a331e340
Commit message:
Updated from revision 0413a0179eb6

Changed in this revision

.AbstractDataSink.h.swp Show annotated file Show diff for this revision Revisions of this file
AbstractClient.h Show annotated file Show diff for this revision Revisions of this file
AbstractDataSink.h Show annotated file Show diff for this revision Revisions of this file
AbstractDataSource.h Show annotated file Show diff for this revision Revisions of this file
Aggregator.cpp Show annotated file Show diff for this revision Revisions of this file
Aggregator.h Show annotated file Show diff for this revision Revisions of this file
CharValue.cpp Show annotated file Show diff for this revision Revisions of this file
CharValue.h Show annotated file Show diff for this revision Revisions of this file
ComposedRecord.cpp Show annotated file Show diff for this revision Revisions of this file
ComposedRecord.h Show annotated file Show diff for this revision Revisions of this file
DataGenerator.h Show annotated file Show diff for this revision Revisions of this file
FloatValue.cpp Show annotated file Show diff for this revision Revisions of this file
FloatValue.h Show annotated file Show diff for this revision Revisions of this file
HTTPResponseFilter.cpp Show annotated file Show diff for this revision Revisions of this file
HTTPResponseFilter.h Show annotated file Show diff for this revision Revisions of this file
IntegerValue.cpp Show annotated file Show diff for this revision Revisions of this file
IntegerValue.h Show annotated file Show diff for this revision Revisions of this file
MbedClient.cpp Show annotated file Show diff for this revision Revisions of this file
MbedClient.h Show annotated file Show diff for this revision Revisions of this file
MbedDataSink.cpp Show annotated file Show diff for this revision Revisions of this file
MbedDataSink.h Show annotated file Show diff for this revision Revisions of this file
MbedDataSource.cpp Show annotated file Show diff for this revision Revisions of this file
MbedDataSource.h Show annotated file Show diff for this revision Revisions of this file
MbedSmartRest.cpp Show annotated file Show diff for this revision Revisions of this file
MbedSmartRest.h Show annotated file Show diff for this revision Revisions of this file
NullValue.cpp Show annotated file Show diff for this revision Revisions of this file
NullValue.h Show annotated file Show diff for this revision Revisions of this file
ParsedRecord.cpp Show annotated file Show diff for this revision Revisions of this file
ParsedRecord.h Show annotated file Show diff for this revision Revisions of this file
ParsedValue.cpp Show annotated file Show diff for this revision Revisions of this file
ParsedValue.h Show annotated file Show diff for this revision Revisions of this file
Parser.cpp Show annotated file Show diff for this revision Revisions of this file
Parser.h Show annotated file Show diff for this revision Revisions of this file
Record.cpp Show annotated file Show diff for this revision Revisions of this file
Record.h Show annotated file Show diff for this revision Revisions of this file
SmartRest.cpp Show annotated file Show diff for this revision Revisions of this file
SmartRest.h Show annotated file Show diff for this revision Revisions of this file
StaticData.cpp Show annotated file Show diff for this revision Revisions of this file
StaticData.h Show annotated file Show diff for this revision Revisions of this file
Value.h Show annotated file Show diff for this revision Revisions of this file
b64.cpp Show annotated file Show diff for this revision Revisions of this file
b64.h Show annotated file Show diff for this revision Revisions of this file
config.h Show annotated file Show diff for this revision Revisions of this file
Binary file .AbstractDataSink.h.swp has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AbstractClient.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,122 @@
+/*
+ * AbstractClient.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file AbstractClient.h
+ * An abstraction layer for the SmartREST http client.
+ */
+
+#ifndef ABSTRACTCLIENT_H
+#define ABSTRACTCLIENT_H
+
+#include "config.h"
+#include "DataGenerator.h"
+#include "AbstractDataSource.h"
+#include "AbstractDataSink.h"
+
+/** Return value indicating that the operation has been successful. */
+#define CLIENT_OK 0
+/** Return value indicating that there has been a connection error. */
+#define CLIENT_CONNECTION_ERROR 1
+/** Return value indicating that an internal error occurred. */
+#define CLIENT_INTERNAL_ERROR 2
+
+/*
+ * An abstraction layer for the SmartREST http client.
+ * Constructor arguments such as username and password strings must
+ * not be cpoied but instead stored as pointer as they are subject to
+ * change.
+ * 
+ * All methods have to be called in the following order:
+ * - beginRequest()
+ * - sendIdentifier() (optional)
+ * - sendData() (optional)
+ * - endRequest()
+ * - awaitResponse()
+ * - receiveData() (optional)
+ * - stop()
+ * 
+ * Additionally, stop() can be called at any time to reset the state of
+ * this instance.
+ */
+class AbstractClient
+{
+public:
+    virtual ~AbstractClient() { };
+
+    /**
+     * Begins a new request. This method has to be the first call for
+     * any request. A connection to the server will be established
+     * and the start of a HTTP post request will be sent over the
+     * connection including Host and Authorization headers.
+     */
+    virtual uint8_t beginRequest() = 0;
+
+    /**
+     * Sends the X-Id device identifier header.
+     * @param identifier the identifier to be sent. The value has to remain
+     *                   valid for the entire request.
+     */
+    virtual uint8_t sendIdentifier(const char*) = 0;
+
+    /**
+     * Sends POST data over the connection. Before the data is sent,
+     * a Content-Length header is also sent over the connection. if the
+     * estimated length does not match the actual conten length,
+     * unexpected behavior will occur.
+     * @param generator the data generator for the data to be sent
+     */
+    virtual uint8_t sendData(DataGenerator& generator) = 0;
+
+    /**
+     * Finishes the request. In case no data has been sent over the
+     * connection, this method will send twice carriage-return new-line.
+     */
+    virtual uint8_t endRequest() = 0;
+
+    /**
+     * Blocks until the start of a response has been received.
+     */
+    virtual uint8_t awaitResponse() = 0;
+
+    /**
+     * Returns a data source for reading data.
+     * When no data can be read for whatever reason,
+     * a data source with an error state may be returned.
+     * @return the data source to read from
+     */
+    virtual AbstractDataSource& receiveData() = 0;
+
+    /**
+     * Resets the connection. This method can be called at any time
+     * and resets the state of this instance.
+     */
+    virtual void stop() = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AbstractDataSink.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,86 @@
+/*
+ * AbstractDataSink.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file AbstractDataSink.h
+ * An abstraction for a data sink which can be used to send data
+ * over a connection.
+ * 
+ * Following write actions are supported:
+ * - write a character
+ * - write a buffer of certain length
+ * - write a character string
+ * - write an unsigned number
+ */
+
+#ifndef ABSTRACTDATASINK_H
+#define ABSTRACTDATASINK_H
+
+#include "config.h"
+#include <stddef.h>
+
+/*
+ * The AbstractDataSink class provides a way to write data to a
+ * connection.
+ */
+class AbstractDataSink
+{
+public:
+    virtual ~AbstractDataSink() { };
+
+    /**
+     * Writes a single character.
+     * @param c the character to write
+     * @return the number of characters written, in this case 1 or 0
+     */
+    virtual size_t write(char c) = 0;
+
+    /**
+     * Writes a buffer.
+     * @param buf the buffer to write
+     * @param length the length of the buffer in bytes
+     * @return the number of characters written
+     */
+    virtual size_t write(void *buf, size_t length) = 0;
+
+    /**
+     * Writes a character string.
+     * @param str the string to write
+     * @return the number of characters written
+     */
+    virtual size_t write(const char *str) = 0;
+
+    /**
+     * Writes a number with base 10.
+     * @param number the number to write
+     * @return the number of digits written
+     */
+    virtual size_t write(unsigned long number) = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AbstractDataSource.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,101 @@
+/*
+ * AbstractDataSource.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file AbstractDataSource.h
+ * An abstraction layer which provides means to read data from a
+ * connection.
+ * 
+ * Example:
+ * @code
+ * AbstractDataSource source;
+ * char c;
+ * while (((c = source.read()) > 0) || (source.status() == DS_STATUS_OK)) {
+ *     // read action
+ * }
+ * switch (source.status()) {
+ * case DS_STATUS_OK:
+ *     // ok
+ * case DS_STATUS_CLOSED:
+ *     // connection closed
+ * case DS_STATUS_TIMEOUT:
+ *     // timeout
+ * default:
+ *     // other error
+ * }
+ * @encode
+ * 
+ */
+
+#ifndef ABSTRACTDATASOURCE_H
+#define ABSTRACTDATASOURCE_H
+
+#include "config.h"
+#include <stdint.h>
+
+/** Return value indicating that no error has occurred. */
+#define DS_STATUS_OK 0
+/** Return value indicating that the connection has been closed by this
+ * or the foreign host. */
+#define DS_STATUS_CLOSED 1
+/** Return value indicating a transmission timeout. */
+#define DS_STATUS_TIMEOUT 2
+/** Return value indicating a state error. */
+#define DS_STATUS_ERROR 3
+
+/*
+ * The AbstractDataSource class provides a way to read data from a
+ * connection.
+ */
+class AbstractDataSource
+{
+public:
+    virtual ~AbstractDataSource() { };
+
+    /**
+     * Reads one character. When successful, the returned value
+     * represents the character. Otherwise, status() will return a
+     * non-zero value. This function is blocking.
+     * @return the caracter read or zero. If the return value is
+     * non-zero, status() is zero. Otherwise, check status() for a
+     * non-zero value.
+     */
+    virtual char read() = 0;
+
+    /**
+     * Returns the current read state. If a non-zero value is returned,
+     * there is an error. Otherwise, everything is ok.
+     * DS_STATUS_TIMEOUT means that there has been a read timeout.
+     * DS_STATUS_CLOSED means that the connection has been closed
+     * by either this or the foreign host.
+     * @return the status value
+     */
+    virtual uint8_t status() = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Aggregator.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,167 @@
+/*
+ * Aggregator.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "Aggregator.h"
+#include <stdlib.h>
+
+#ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+Aggregator::Aggregator(size_t capacity, bool growing, bool copy)
+{
+    _alloc = copy;
+    _growing = growing;
+    _capacity = 0;
+    _list = NULL;
+    _initial = capacity;
+    _length = 0;
+}
+#else
+Aggregator::Aggregator(bool copy)
+{
+    _alloc = copy;
+    _length = 0;
+}
+#endif
+
+Aggregator::~Aggregator()
+{
+    if (_alloc) {
+        for (size_t n = 0; n < _length; n++)
+            delete _list[n];
+    }
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    if (_list != NULL)
+        free(_list);
+    #endif
+}
+
+bool Aggregator::add(const DataGenerator& generator)
+{
+    if (this == &generator)
+        return false;
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    if (_length == _capacity) {
+        size_t capacity;
+
+        if ((!_growing) && (_capacity != 0))
+            return false;
+
+        if (_capacity == 0)
+            capacity = _initial;
+        else
+            capacity = _capacity + SMARTREST_AGGREGATOR_MEMORY_INCREMENT;
+
+        const DataGenerator **list = (const DataGenerator**)realloc(_list,
+            capacity*sizeof(DataGenerator*));
+        if (list == NULL)
+            return false;
+        _list = list;
+        _capacity = capacity;
+    }
+    #else
+    if (_length == SMARTREST_AGGREGATOR_FIXED_SIZE)
+        return false;
+    #endif
+
+    if (_alloc) {
+        DataGenerator *copy = generator.copy();
+        if (copy == NULL)
+            return false;
+        _list[_length++] = copy;
+    } else {
+        _list[_length++] = &generator;
+    }
+    return true;
+}
+
+void Aggregator::clear()
+{
+    if (_alloc) {
+        for (size_t n = 0; n < _length; n++)
+            delete _list[n];
+    }
+    _length = 0;
+
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    if (_list != NULL)
+        free(_list);
+   _list = NULL;
+    _capacity = 0;
+    #endif
+}
+
+size_t Aggregator::length()
+{
+    return _length;
+}
+
+bool Aggregator::full()
+{
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    return (_growing) ? false : (_length == _capacity);
+    #else
+    return (_length == SMARTREST_AGGREGATOR_FIXED_SIZE);
+    #endif
+}
+
+size_t Aggregator::capacity()
+{
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    return (_growing) ? 0 : _capacity;
+    #else
+    return SMARTREST_AGGREGATOR_FIXED_SIZE;
+    #endif
+}
+
+size_t Aggregator::writeTo(AbstractDataSink& sink) const
+{
+    size_t len = 0;
+    for (size_t n = 0; n < _length; n++)
+        len += _list[n]->writeTo(sink);
+    return len;
+}
+
+size_t Aggregator::writtenLength() const
+{
+    size_t len = 0;
+    for (size_t n = 0; n < _length; n++)
+        len += _list[n]->writtenLength();
+    return len;
+}
+
+DataGenerator* Aggregator::copy() const
+{
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    Aggregator *copy = new Aggregator(_length, _growing, true);
+    #else
+    Aggregator *copy = new Aggregator(true);
+    #endif
+    for (size_t n = 0; n < _length; n++)
+        copy->add(*_list[n]);
+    return copy;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Aggregator.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,155 @@
+/*
+ * Aggregator.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef AGGREGATOR_H
+#define AGGREGATOR_H
+
+#include "config.h"
+#include <stddef.h>
+#include "DataGenerator.h"
+
+#ifndef SMARTREST_AGGREGATOR_INITIAL_CAPACITY
+#define SMARTREST_AGGREGATOR_INITIAL_CAPACITY 50
+#endif
+#ifndef SMARTREST_AGGREGATOR_MEMORY_INCREMENT
+#define SMARTREST_AGGREGATOR_MEMORY_INCREMENT 25
+#endif
+//#define SMARTREST_AGGREGATOR_FIXED_SIZE 100
+
+/**
+ * An aggregator of data generators. This class can aggregate instances of
+ * itself.
+ * If the aggregator is set to copying all added data generators using
+ * the copy() method, all objects are being properly deallocated on
+ * destruction.
+ * 
+ * Example:
+ * @code
+ * // Given: A concrete SmartRest implementation.
+ * SmartRest client;
+ * 
+ * // sets up a growing aggregator which copies all added objects
+ * // to the heap
+ * Aggregator buffer(25, true, true);
+ * 
+ * // random data collection
+ * for (uint8_t i = 0; i < 32; ++i) {
+ *     // Note: ComposedRecord is not copying any values into the heap
+ *     // because the availability of its values in guaranteed during the
+ *     // instance's lifetime.
+ *     ComposedRecord record(false);
+ *     
+ *     CharValue msgId(100);
+ *     IntegerValue number(i);
+ *     record.add(msgId).add(number);
+ *     
+ *     // Note: ComposedRecord is now cloned into the heap to extend its
+ *     // lifetime beyond this code block.
+ *     buffer.add(record);
+ * }
+ * 
+ * // send the bulk request
+ * uint8_t ret = client.send(buffer);
+ * if (ret != SMARTREST_SUCCESS) {
+ *     // error handling
+ * }
+ * @encode
+ */
+class Aggregator : public DataGenerator
+{
+public:
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    /**
+     * Creates a new Aggregator instance.
+     * @param capacity the initial capacity of the instance
+     * @param growing specifies the capability of this instance to grow
+     * @param copy specifies whether all added data generators shall be
+     *             copied using the copy() method
+     */
+    Aggregator(size_t=SMARTREST_AGGREGATOR_INITIAL_CAPACITY, bool=true, bool=false);
+    #else
+    /**
+     * Creates a new Aggregator instance.
+     * @param copy specifies whether all added data generators shall be
+     *             copied using the copy() method
+     */
+    Aggregator(bool=false);
+    #endif
+    ~Aggregator();
+
+    /**
+     * Adds a data generator to the aggregator.
+     * @param generator the data generator to add
+     * @return true if added, false otherwise.
+     */
+    bool add(const DataGenerator&);
+
+    /**
+     * Clears the aggregator. The capacity will shrink to it's initial
+     * size.
+     */
+    void clear();
+
+    /**
+     * Returns the number of data generators aggregated by this instance.
+     * @return the number of data generators aggregated
+     */
+    size_t length();
+
+    /**
+     * Returns whether the aggregator is full. If growing, this will
+     * always return false.
+     * @return whether the aggregator is full
+     */
+    bool full();
+
+    /**
+     * Returns the capacity of the aggregator. This will always return zero
+     * if the aggregator is growing.
+     */
+    size_t capacity();
+
+    size_t writeTo(AbstractDataSink&) const;
+    size_t writtenLength() const;
+    DataGenerator* copy() const;
+
+private:
+    #ifdef SMARTREST_AGGREGATOR_FIXED_SIZE
+    const DataGenerator *_list[SMARTREST_AGGREGATOR_FIXED_SIZE];
+    #else
+    const DataGenerator **_list;
+    #endif
+    size_t _length;
+    bool _alloc;
+    #ifndef SMARTREST_AGGREGATOR_FIXED_SIZE
+    size_t _capacity, _initial;
+    bool _growing;
+    #endif
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CharValue.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,137 @@
+/*
+ * CharValue.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "CharValue.h"
+#include "NullValue.h"
+#include <stdlib.h>
+#include <string.h>
+
+inline int8_t __charvalue_need_escape(const char *str);
+
+CharValue::CharValue(const char *str, bool copy)
+{
+    if ((str == NULL) || (*str == '\0')) {
+        _alloc = false;
+        _str = NULL;
+    } else {
+        _alloc = copy;
+        if (copy) {
+            _str = (const char*)malloc(strlen(str)*sizeof(char));
+            strcpy((char*)_str, str);
+        } else {
+            _str = str;
+        }
+    }
+}
+
+CharValue::~CharValue()
+{
+    if (_alloc)
+        free((void*)_str);
+}
+
+uint8_t CharValue::valueType() const
+{
+    if (_str == NULL)
+        return VALUE_NULL;
+    return VALUE_CHARACTER;
+}
+
+long CharValue::integerValue() const
+{
+    return 0;
+}
+
+double CharValue::floatValue() const
+{
+    return 0.0;
+}
+
+const char * CharValue::characterValue() const
+{
+    return _str;
+}
+
+size_t CharValue::write(AbstractDataSink& sink) const
+{
+    if (_str == NULL)
+        return 0;
+    size_t n = 0;
+    int8_t esc = __charvalue_need_escape(_str) ? 1 : 0;
+    if (esc) n += sink.write('"');
+    for (char *q = (char*)_str, c; (c = *q) != 0; q++) {
+        if ((esc) && (c == '"'))
+            n += sink.write('"');
+        n += sink.write(c);
+    }
+    if (esc) n += sink.write('"');
+    return n;
+}
+
+size_t CharValue::length() const
+{
+    if (_str == NULL)
+        return 0;
+    size_t n = 0;
+    int8_t esc = __charvalue_need_escape(_str) ? 1 : 0;
+    if (esc)
+        n += 2;
+    for (char *q = (char*)_str, c; (c = *q) != 0; q++) {
+        if ((esc) && (c == '"'))
+            n++;
+        n++;
+    }
+    return n;
+}
+
+int8_t __charvalue_need_escape(const char *str)
+{
+    int8_t w = 0;
+    for (char c; (c = *str) != 0; str++) {
+        if ((c == ' ') || (c == '\t')) {
+            if (w == 0)
+                return 1;
+            w = 2;
+        } else {
+            w = 1;
+            if ((c == '"') || (c == ',') || (c == '\r') || (c == '\n'))
+                return 1;
+        }
+    }
+    if (w == 2)
+        return 1;
+    return 0;
+}
+
+Value* CharValue::copy() const
+{
+    if (_str == NULL)
+        return new NullValue();
+    return new CharValue(_str, true);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CharValue.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * CharValue.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef CHARVALUE_H
+#define CHARVALUE_H
+
+#include "config.h"
+#include "Value.h"
+
+/**
+ * A basic character value. This value type behaves simmilar to a null
+ * value if the ommitted string is empty.
+ * 
+ * Example:
+ * @code
+ * // A string
+ * CharValue str("Hello World!");
+ * 
+ * // a null value
+ * CharValue null("");
+ * 
+ * // another null value
+ * CharValue null2(NULL);
+ * @encode
+ */
+class CharValue : public Value
+{
+public:
+    CharValue(const char*, bool=false);
+    ~CharValue();
+
+    uint8_t valueType() const;
+    long integerValue() const;
+    double floatValue() const;
+    const char * characterValue() const;
+
+    size_t write(AbstractDataSink&) const;
+    size_t length() const;
+    Value* copy() const;
+
+private:
+    const char *_str;
+    bool _alloc;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ComposedRecord.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,124 @@
+/*
+ * ComposedRecord.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ComposedRecord.h"
+#include "NullValue.h"
+#include <stdlib.h>
+#include <string.h>
+
+ComposedRecord::ComposedRecord(bool copy)
+{
+    _alloc = copy;
+    #ifndef SMARTREST_COMPOSED_FIXED_SIZE
+    _capacity = 0;
+    _values = NULL;
+    #endif
+    _count = 0;
+}
+
+ComposedRecord::~ComposedRecord()
+{
+    if (_alloc) {
+        for (size_t n = 0; n < _count; n++)
+            delete _values[n];
+    }
+    #ifndef SMARTREST_COMPOSED_FIXED_SIZE
+    if (_values != NULL)
+        free(_values);
+    #endif
+}
+
+bool ComposedRecord::add(const Value& value)
+{
+    #ifndef SMARTREST_COMPOSED_FIXED_SIZE
+    if (_capacity == _count) {
+        size_t capacity;
+        if (_capacity == 0)
+            capacity = SMARTREST_COMPOSED_INITIAL_CAPACITY;
+        else
+            capacity = _capacity + SMARTREST_COMPOSED_MEMORY_INCREMENT;
+
+        const Value **values = (const Value**)realloc(_values,
+            capacity*sizeof(Value*));
+        if (values == NULL)
+            return false;
+        _values = values;
+        _capacity = capacity;
+    }
+    #else
+    if (_count == SMARTREST_COMPOSED_FIXED_SIZE)
+        return false;
+    #endif
+
+    if (_alloc) {
+        Value *copy = value.copy();
+        if (copy == NULL)
+            return false;
+        _values[_count++] = copy;
+    } else {
+        _values[_count++] = &value;
+    }
+    return true;
+}
+
+void ComposedRecord::clear()
+{
+    if (_alloc) {
+        for (size_t n = 0; n < _count; n++)
+            delete _values[n];
+    }
+    _count = 0;
+
+    #ifndef SMARTREST_COMPOSED_FIXED_SIZE
+    if (_values != NULL)
+        free(_values);
+    _values = NULL;
+    _capacity = 0;
+    #endif
+}
+
+size_t ComposedRecord::values() const
+{
+    return _count;
+}
+
+const Value& ComposedRecord::value(size_t index) const
+{
+    if (index >= _count)
+        return aNullValue;
+    return *_values[index];
+}
+
+DataGenerator* ComposedRecord::copy() const
+{
+    ComposedRecord *copy = new ComposedRecord(true);
+    for (size_t n = 0; n < _count; n++)
+        copy->add(*_values[n]);
+    return copy;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ComposedRecord.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,94 @@
+/*
+ * ComposedRecord.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef COMPOSEDRECORD_H
+#define COMPOSEDRECORD_H
+
+#include "config.h"
+#include "DataGenerator.h"
+#include "Record.h"
+#include "Value.h"
+
+#ifndef SMARTREST_COMPOSED_INITIAL_CAPACITY
+#define SMARTREST_COMPOSED_INITIAL_CAPACITY 10
+#endif
+#ifndef SMARTREST_COMPOSED_MEMORY_INCREMENT
+#define SMARTREST_COMPOSED_MEMORY_INCREMENT 5
+#endif
+//#define SMARTREST_COMPOSED_FIXED_SIZE 25
+
+/**
+ * This value set collects values and serializes them into a SmartRequest.
+ * 
+ * Example 1 (low memory usage):
+ * @code
+ * // this record does not copy added values into the heap because the
+ * // lifetime of the instance does not exceed the lifetime of its added
+ * // values.
+ * ComposedRecord record(false);
+ * IntegerValue msgId(100);
+ * CharValue str("Hello World!");
+ * FloatValue num(3.1415, 2);
+ * record.add(msgId).add(str).add(num);
+ * @encode
+ * 
+ * Example 2 (short form):
+ * @code
+ * // this record needs to copy added values due to the limited
+ * // lifetime of temporary objects.
+ * ComposedRecord record(true);
+ * record.add(IntegerValue(100)).add(CharValue("Hello World!");
+ * record.add(FloatValue(3.1415, 2));
+ * @encode
+ */
+class ComposedRecord : public Record
+{
+public:
+    ComposedRecord(bool=false);
+    ~ComposedRecord();
+
+    bool add(const Value&);
+    void clear();
+
+    size_t values() const;
+    const Value& value(size_t index) const;
+
+    DataGenerator* copy() const;
+
+private:
+    #ifndef SMARTREST_COMPOSED_FIXED_SIZE
+    const Value **_values;
+    size_t _capacity;
+    #else
+    const Value *_values[SMARTREST_COMPOSED_FIXED_SIZE];
+    #endif
+    size_t _count;
+    bool _alloc;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DataGenerator.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,69 @@
+/*
+ * DataGenerator.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DATAGENERATOR_H
+#define DATAGENERATOR_H
+
+#include "config.h"
+#include <stddef.h>
+#include "AbstractDataSink.h"
+
+/*
+ * The DataGenerator class provides a way to stream data to a
+ * connection..
+ */
+class DataGenerator
+{
+public:
+    virtual ~DataGenerator()
+    {
+    }
+
+    /**
+     * Writes the object to the specified destination.
+     * @param s the destination
+     * @return the number of bytes written
+     */
+    virtual size_t writeTo(AbstractDataSink&) const = 0;
+
+    /**
+     * Returns the estimated number of bytes which will be written.
+     * @return the estimated number of bytes printed
+     */
+    virtual size_t writtenLength() const = 0;
+
+    /**
+     * Creates a deep copy on the heap. The class type may be different.
+     * The only thing guaranteed is that the copy behaves exactly
+     * the same.
+     * @return cloned object with no memory dependencies
+     */
+    virtual DataGenerator* copy() const = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FloatValue.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,184 @@
+/*
+ * FloatValue.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "FloatValue.h"
+#include <math.h>
+#include <stdio.h>
+
+FloatValue::FloatValue(double number, uint8_t digits, bool zflag)
+{
+    _negative = (number < 0.0);
+    _zflag = zflag;
+    if (_negative)
+        _number = -number;
+    else
+        _number = number;
+    if (digits == SMARTREST_FLOATVALUE_DETECTPREC)
+        _digits = detectPrecision(_number);
+    else
+        _digits = digits;
+}
+
+uint8_t FloatValue::valueType() const
+{
+    return VALUE_FLOAT;
+}
+
+long FloatValue::integerValue() const
+{
+    return 0L;
+}
+
+double FloatValue::floatValue() const
+{
+    return (_negative) ? -_number : _number;
+}
+
+const char * FloatValue::characterValue() const
+{
+    return 0;
+}
+
+size_t FloatValue::write(AbstractDataSink& sink) const
+{
+    size_t n = 0;
+    double number, rounding;
+    uint8_t i;
+    unsigned long int_part;
+    double remainder;
+
+    if (isnan(_number))
+        return sink.write("nan");
+
+    if (_negative)
+        n += sink.write('-');
+
+    if (isinf(_number)) {
+        n += sink.write("inf");
+        return n;
+    }
+
+    number = _number;
+    rounding = 0.5;
+    for (i = 0; i < _digits; ++i)
+        rounding /= 10.0;
+    number += rounding;
+
+    int_part = (unsigned long)number;
+    remainder = number - (double)int_part;
+
+    if ((_zflag) || (int_part))
+        n += sink.write(int_part);
+
+    if (_digits == 0)
+        return n;
+    n += sink.write("."); 
+
+    uint8_t digits = _digits;
+    while (digits-- > 0) {
+        remainder *= 10.0;
+        unsigned long l = (unsigned long)remainder;
+        n += sink.write(l);
+        remainder -= l; 
+    } 
+
+    return n;
+}
+
+size_t FloatValue::length() const
+{
+    size_t l = 0;
+    double number, rounding;
+    unsigned long n;
+    uint8_t i;
+
+    if (isnan(_number))
+        return 3;
+
+    if (_negative)
+        l++;
+
+    if (isinf(_number)) {
+        l += 3;
+        return l;
+    }
+
+    number = _number;
+    rounding = 0.5;
+    for (i = 0; i < _digits; ++i)
+        rounding /= 10.0;
+    number += rounding;
+
+    n = (unsigned long)number;
+    if ((_zflag) || (n)) {
+        do {
+            n /= 10;
+            l++;
+        } while(n);
+    }
+
+    if (_digits > 0)
+        l += 1 + _digits;
+
+    return l;
+}
+
+Value* FloatValue::copy() const
+{
+    double number;
+
+    number = (_negative) ? -_number : _number;
+    return new FloatValue(number, _digits, _zflag);
+}
+
+uint8_t FloatValue::detectPrecision(double n)
+{
+    uint8_t prec = 0, count = 0;
+    int8_t d;
+
+    if ((isinf(n)) || (isnan(n)))
+        return 0;
+
+    n -= (long)n;
+
+    while ((prec < 6) && (count < 3)) {
+        n *= 10;
+        d = (uint8_t)n;
+
+        if (count == 0) {
+            if ((d <= 0) || (d >= 9))
+                count++;
+        } else {
+            count++;
+        }
+        prec++;
+        n -= d;
+    }
+
+    return --prec;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FloatValue.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,81 @@
+/*
+ * FloatValue.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef FLOATVALUE_H
+#define FLOATVALUE_H
+
+#include "config.h"
+#include <stdint.h>
+#include "Value.h"
+
+#define SMARTREST_FLOATVALUE_DETECTPREC 255
+
+/**
+ * A floating-point value.
+ * 
+ * Example:
+ * @code
+ * // decleration                       // serialized form
+ * FloatValue val1(3.1415, 2);          // 3.14
+ * FloatValue val2(3.1234, 0);          // 3
+ * FloatValue val3(3.95, 0);            // 4
+ * FloatValue val4(0.55, 1, false);     // .5
+ * FloatValue val4(0.55, 2, true);      // 0.55
+ * @encode
+ */
+class FloatValue : public Value
+{
+public:
+    /**
+     * Creates a new instance of a floating-point value.
+     * @param number the floating-point number
+     * @param digits precision in number of digits
+     * @param zflag whether to write a zero before the floating point
+     */
+    FloatValue(double, uint8_t=SMARTREST_FLOATVALUE_DETECTPREC, bool=true);
+
+    uint8_t valueType() const;
+    long integerValue() const;
+    double floatValue() const;
+    const char * characterValue() const;
+
+    size_t write(AbstractDataSink&) const;
+    size_t length() const;
+    Value* copy() const;
+
+protected:
+    uint8_t detectPrecision(double);
+
+private:
+    double _number;
+    bool _negative;
+    uint8_t _digits;
+    bool _zflag;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPResponseFilter.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,174 @@
+/*
+ * HTTPResponseFilter.cpp
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "HTTPResponseFilter.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+
+const char *cExpectedStatus = "HTTP/1.* ";
+const char *cContentLength = "Content-Length: ";
+
+HTTPResponseFilter::HTTPResponseFilter(AbstractDataSource& source) : _source(source), _state(RESPF_STATE_INIT)
+{
+    _length = _read = 0;
+}
+
+HTTPResponseFilter::~HTTPResponseFilter()
+{
+}
+
+char HTTPResponseFilter::read()
+{
+    if (_state != RESPF_STATE_READ_HEADERS)
+        return 0;
+    if ((_length > 0) && (_length == _read))
+        return 0;
+    _read++;
+    return _source.read();
+}
+
+uint8_t HTTPResponseFilter::status()
+{
+    if (_state != RESPF_STATE_READ_HEADERS)
+        return DS_STATUS_ERROR;
+    if ((_length > 0) && (_length == _read))
+        return DS_STATUS_CLOSED;
+    return _source.status();
+}
+
+uint16_t HTTPResponseFilter::readStatus()
+{
+    uint16_t res = 0;
+    uint8_t state = 0;
+    char c;
+    size_t offset = 0;
+    uint8_t status = DS_STATUS_OK;
+    
+    if (_state != RESPF_STATE_INIT)
+        return 0;
+
+    while ((state < 3) && (((c = _source.read()) > 0) || ((status = _source.status()) == DS_STATUS_OK))) {
+        switch (state) {
+        case 0: // read expected status line
+            if ((cExpectedStatus[offset] != c) && (cExpectedStatus[offset] != '*'))
+                state = 3;
+            offset++;
+            if (offset == strlen(cExpectedStatus)) {
+                state = 1;
+            }
+            break;
+        case 1:
+            if (isspace(c))
+                state = 2;
+            if (isdigit(c))
+                res = (res * 10) + (c - '0');
+            break;
+        case 2:
+            if (c == '\n')
+                state = 3;
+            break;
+        }
+    }
+
+    if ((status != DS_STATUS_OK) || (state != 3))
+        return 0;
+
+    _state = RESPF_STATE_READ_STATUS;        
+    return res;
+}
+
+bool HTTPResponseFilter::skipHeaders()
+{
+    uint16_t res = 0;
+    uint8_t state = 0;
+    char c;
+    size_t offset = 0;
+    uint8_t status = DS_STATUS_OK;
+
+    if (_state != RESPF_STATE_READ_STATUS)
+        return false;
+
+    while ((state < 5) && (((c = _source.read()) > 0) || ((status = _source.status()) == DS_STATUS_OK))) {
+        switch (state) {
+        case 0: // start of line
+            if (offset == 0) {
+                if (cContentLength[0] == c)
+                    state = 1;
+                if (c == '\r')
+                    state = 4;
+            } else {
+                if (c == '\r')
+                    state = 3;
+            }
+            offset++;
+            break;
+        case 1:
+            if (c == '\r')
+                state = 3;
+            else if (cContentLength[offset] != c)
+                state = 0;
+            else if (offset == strlen(cContentLength)-1)
+                state = 2;
+            offset++;
+            break;
+        case 2:
+            if (isdigit(c))
+                _length = (_length * 10) + (c - '0');
+            else if (c == '\r')
+                state = 3;
+            else
+                state = 0;
+            offset++;
+            break;
+        case 3:
+            if (c == '\n') {
+                state = 0;
+                offset = 0;
+            }
+            break;
+        case 4:
+            if (c == '\n')
+                state = 5;
+            break;
+        }
+    }
+
+    if ((status != DS_STATUS_OK) || (state != 5))
+        return false;
+        
+    _state = RESPF_STATE_READ_HEADERS;
+    return true;
+}
+
+void HTTPResponseFilter::reset()
+{
+    _state = RESPF_STATE_INIT;
+    _length = _read = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPResponseFilter.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * HTTPResponseFilter.h
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef HTTPRESPONSEFILTER_H
+#define HTTPRESPONSEFILTER_H
+
+#include <stddef.h>
+#include "AbstractDataSource.h"
+
+#define RESPF_STATE_INIT 0
+#define RESPF_STATE_READ_STATUS 1
+#define RESPF_STATE_READ_HEADERS 2
+
+/**
+ * Reads and evaluates a HTTP response.
+ * The read() and status() methods allow access to the response content
+ * without HTTP headers.
+ */
+class HTTPResponseFilter : public AbstractDataSource
+{
+public:
+    HTTPResponseFilter(AbstractDataSource& source);
+    ~HTTPResponseFilter();
+    
+    char read();
+    uint8_t status();
+
+    uint16_t readStatus();
+    bool skipHeaders();
+    
+    void reset();
+
+private:
+    AbstractDataSource& _source;
+    uint8_t _state;
+    size_t _length, _read;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IntegerValue.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,92 @@
+/*
+ * IntegerValue.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "IntegerValue.h"
+
+IntegerValue::IntegerValue(long number)
+{
+    _negative = (number < 0L);
+    if (_negative)
+        _number = -number;
+    else
+        _number = number;
+}
+
+uint8_t IntegerValue::valueType() const
+{
+    return VALUE_INTEGER;
+}
+
+long IntegerValue::integerValue() const
+{
+    return (_negative) ? -_number : _number;
+}
+
+double IntegerValue::floatValue() const
+{
+    return 0.0;
+}
+
+const char * IntegerValue::characterValue() const
+{
+    return 0;
+}
+
+size_t IntegerValue::write(AbstractDataSink& sink) const
+{
+    size_t n = 0;
+    if (_negative)
+        n += sink.write('-');
+    n += sink.write(_number);
+    return n;
+}
+
+size_t IntegerValue::length() const
+{
+    size_t l = 0;
+
+    if (_negative)
+        l++;
+
+    unsigned long n = _number;
+
+    do {
+        n /= 10;
+        l++;
+    } while(n);
+    return l;
+}
+
+Value* IntegerValue::copy() const
+{
+    long number;
+
+    number = (_negative) ? -_number : _number;
+    return new IntegerValue(number);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IntegerValue.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * IntegerValue.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef NUMBERVALUE_H
+#define NUMBERVALUE_H
+
+#include "config.h"
+#include "Value.h"
+
+/**
+ * Represents an integer value.
+ * 
+ * Example:
+ * @code
+ * IntegerValue val(100);
+ * @encode
+ */
+class IntegerValue : public Value
+{
+public:
+    IntegerValue(long);
+
+    uint8_t valueType() const;
+    long integerValue() const;
+    double floatValue() const;
+    const char * characterValue() const;
+
+    size_t write(AbstractDataSink&) const;
+    size_t length() const;
+    Value* copy() const;
+
+private:
+    unsigned long _number;
+    bool _negative;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedClient.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,198 @@
+/*
+ * MbedClient.cpp
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "MbedClient.h"
+#include <stdlib.h>
+#include <string.h>
+#include "b64.h"
+#include "mbed.h"
+
+MbedClient::MbedClient(const char* host, uint16_t port, const char* username, const char* password)
+    : _host(host), _port(port), _username(username), _password(password), _filter(_source), _source(_sock), _sink(_sock), _sock()
+{
+    _state = MBED_STATE_INIT;
+}
+
+MbedClient::~MbedClient()
+{
+}
+
+uint8_t MbedClient::beginRequest()
+{
+    if (_state != MBED_STATE_INIT)
+        return CLIENT_INTERNAL_ERROR;
+
+    if (_sock.connect(_host, _port) < 0) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+
+    if ((!send("POST /s HTTP/1.0\r\n")) ||
+        (!send("Host: ")) ||
+        (!send(_host)) ||
+        (!send("\r\n")))
+        return CLIENT_CONNECTION_ERROR;
+    
+    if ((strlen(_username) > 0) && (strlen(_password) > 0)) {
+        if (!sendBasicAuth())
+            return CLIENT_CONNECTION_ERROR;
+    }
+
+    _state = MBED_STATE_IN_REQUEST;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::sendIdentifier(const char* identifier)
+{
+    if (_state != MBED_STATE_IN_REQUEST)
+        return CLIENT_INTERNAL_ERROR;
+
+    if ((identifier != NULL) && (strlen(identifier) != 0)) {
+        if ((!send("X-Id: ")) ||
+            (!send(identifier)) ||
+            (!send("\r\n")))
+            return CLIENT_CONNECTION_ERROR;
+    }
+
+    _state = MBED_STATE_SENT_ID;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::sendData(DataGenerator& generator)
+{
+    size_t len; char lenstr[8];
+    
+    if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID))
+        return CLIENT_INTERNAL_ERROR;
+    
+    len = generator.writtenLength();
+    snprintf(lenstr, 8, "%ld", len);
+    
+    if ((!send("Content-Length: ")) ||
+        (!send(lenstr)) ||
+        (!send("\r\n\r\n")))
+        return CLIENT_CONNECTION_ERROR;
+
+    if (generator.writeTo(_sink) != len) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+    
+    _state = MBED_STATE_SENT_DATA;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::endRequest()
+{
+    if ((_state != MBED_STATE_IN_REQUEST) && (_state != MBED_STATE_SENT_ID) && (_state != MBED_STATE_SENT_DATA))
+        return CLIENT_INTERNAL_ERROR;
+    
+    if (_state != MBED_STATE_SENT_DATA) {
+        // send end of headers
+        if (!send("\r\n"))
+            return CLIENT_CONNECTION_ERROR;
+    }
+    
+    if (!_sink.flush()) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+    
+    _state = MBED_STATE_REQ_COMPLETE;
+    return CLIENT_OK;
+}
+
+uint8_t MbedClient::awaitResponse()
+{
+    if (_state != MBED_STATE_REQ_COMPLETE)
+        return CLIENT_INTERNAL_ERROR;
+    
+    if ((_filter.readStatus() != 200) || (!_filter.skipHeaders())) {
+        stop();
+        return CLIENT_CONNECTION_ERROR;
+    }
+    
+    _state = MBED_STATE_RECVD_RESPONSE;
+    return CLIENT_OK;
+}
+
+AbstractDataSource& MbedClient::receiveData()
+{
+    return _filter;
+}
+
+void MbedClient::stop()
+{
+    _sock.close();
+    _source.reset();
+    _sink.reset();
+    _filter.reset();
+    _state = MBED_STATE_INIT;
+}
+
+bool MbedClient::send(const char *str)
+{
+    if (_sink.write(str) != strlen(str)) {
+        stop();
+        return false;
+    }
+    return true;
+}
+
+bool MbedClient::sendBasicAuth()
+{
+    size_t ul, pl; unsigned char input[3]; unsigned char output[5];
+    int inputOffset = 0;
+
+    if (!send("Authorization: Basic "))
+        return false;
+        
+    ul = strlen(_username);
+    pl = strlen(_password);
+
+    for (int i = 0; i < (ul+1+pl); i++) {
+        if (i < ul)
+            input[inputOffset++] = _username[i];
+        else if (i == ul)
+            input[inputOffset++] = ':';
+        else
+            input[inputOffset++] = _password[i-(ul+1)];
+
+        if ((inputOffset == 3) || (i == ul+pl)) {
+            b64_encode(input, inputOffset, output, 4);
+            output[4] = '\0';
+            if (!send((char*)output))
+                return false;
+            inputOffset = 0;
+        }
+    }
+    
+    if (!send("\r\n"))
+        return false;
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedClient.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,73 @@
+/*
+ * MbedClient.h
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MBEDCLIENT_H
+#define MBEDCLIENT_H
+
+#include <stdint.h>
+#include "AbstractClient.h"
+#include "TCPSocketConnection.h"
+#include "MbedDataSource.h"
+#include "MbedDataSink.h"
+#include "HTTPResponseFilter.h"
+
+#define MBED_STATE_INIT 0
+#define MBED_STATE_IN_REQUEST 1
+#define MBED_STATE_SENT_ID 2
+#define MBED_STATE_SENT_DATA 3
+#define MBED_STATE_REQ_COMPLETE 4
+#define MBED_STATE_RECVD_RESPONSE 5
+#define MBED_STATE_RECV_DATA 6
+
+class MbedClient : public AbstractClient {
+public:
+    MbedClient(const char*, uint16_t, const char*, const char*);
+    ~MbedClient();
+
+    uint8_t beginRequest();
+    uint8_t sendIdentifier(const char*);
+    uint8_t sendData(DataGenerator& generator);
+    uint8_t endRequest();
+    uint8_t awaitResponse();
+    AbstractDataSource& receiveData();
+    void stop();
+
+protected:
+    bool send(const char *str);
+    bool sendBasicAuth();
+
+private:
+    const char *_host, *_username, *_password;
+    uint16_t _port, _state;
+    TCPSocketConnection _sock;
+    MbedDataSource _source;
+    MbedDataSink _sink;
+    HTTPResponseFilter _filter;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedDataSink.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,130 @@
+/*
+ * MbedDataSink.cpp
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "MbedDataSink.h"
+#include "MbedClient.h"
+#include <stdlib.h>
+#include <string.h>
+
+#include "mbed.h"
+
+MbedDataSink::MbedDataSink(TCPSocketConnection& sock) : _len(0), _sock(sock)
+{
+}
+
+MbedDataSink::~MbedDataSink()
+{
+}
+
+size_t MbedDataSink::write(char c)
+{
+    while (MBED_SINK_BUFFER_SIZE - _len < 1) {
+        if (!send())
+            return 0;
+    }
+    
+    _buf[_len++] = c;
+    return 1;
+}
+
+size_t MbedDataSink::write(void *buf, size_t length)
+{
+    size_t sent = 0, len;
+    
+    while (sent < length) {
+        while (MBED_SINK_BUFFER_SIZE - _len < 1) {
+            if (!send())
+                return 0;
+        }
+        
+        if (MBED_SINK_BUFFER_SIZE - _len >= length-sent)
+            len = length-sent;
+        else
+            len = MBED_SINK_BUFFER_SIZE - _len;
+        
+        memcpy(_buf+_len, (char*)buf+sent, len);
+        _len += len;
+        sent += len;
+    }
+    
+    return length;
+}
+
+size_t MbedDataSink::write(const char *str)
+{
+    return write((void*)str, strlen(str));
+}
+
+size_t MbedDataSink::write(unsigned long number)
+{
+    char str[24];
+    
+    snprintf(str, 24, "%lu", number);
+    return write(str);
+}
+
+bool MbedDataSink::flush()
+{
+    while (_len > 0) {
+        if (!send())
+            return false;
+    }
+    
+    return true;
+}
+
+bool MbedDataSink::send()
+{
+    int ret;
+    
+    if (!_sock.is_connected())
+        return false;
+
+    _sock.set_blocking(true);
+    ret = _sock.send(_buf, _len);
+    
+    //TODO: fix bug in u-blox so no longer wait is needed
+    wait(0.5);
+    
+    if (ret < 0){
+        puts("Send failed.");
+        return false;
+    }
+    
+    // move rest of buffer
+    if ((ret > 0) && (ret < _len))
+        memmove(_buf, _buf+ret, _len-ret);
+    
+    _len -= ret;
+    return true;
+}
+
+void MbedDataSink::reset()
+{
+    _len = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedDataSink.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,65 @@
+/*
+ * MbedDataSink.h
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MBEDDATASINK_H
+#define MBEDDATASINK_H
+
+#include <stddef.h>
+#include "AbstractDataSink.h"
+#include "TCPSocketConnection.h"
+
+#define MBED_SINK_BUFFER_SIZE 60
+
+class MbedClient;
+
+class MbedDataSink : public AbstractDataSink
+{
+public:
+    MbedDataSink(TCPSocketConnection& sock);
+    ~MbedDataSink();
+    
+    size_t write(char c);
+    size_t write(void *buf, size_t length);
+    size_t write(const char *str);
+    size_t write(unsigned long number);
+    
+    
+protected:
+    bool flush();
+    bool send();
+    void reset();
+
+private:
+    TCPSocketConnection& _sock;
+    char _buf[MBED_SINK_BUFFER_SIZE];
+    size_t _len;
+
+friend class MbedClient;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedDataSource.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,88 @@
+/*
+ * MbedDataSource.cpp
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "MbedDataSource.h"
+#include "stdio.h"
+
+MbedDataSource::MbedDataSource(TCPSocketConnection& sock) : _sock(sock)
+{
+    _offset = _len = 0;
+    _timeout = false;
+}
+
+MbedDataSource::~MbedDataSource()
+{
+}
+
+char MbedDataSource::read()
+{
+    while (_offset == _len) {
+        if (!receive())
+            return 0;
+    }
+    
+    return _buf[_offset++];
+}
+
+uint8_t MbedDataSource::status()
+{
+    if (!_sock.is_connected())
+        return DS_STATUS_CLOSED;
+    
+    if (_timeout)
+        return DS_STATUS_TIMEOUT;
+    
+    return DS_STATUS_OK;
+}
+
+bool MbedDataSource::receive()
+{
+    int ret;
+
+    if (status() != DS_STATUS_OK)
+        return false;
+    
+    _sock.set_blocking(true, 60000);
+    ret = _sock.receive(_buf, MBED_SOURCE_BUFFER_SIZE);
+    
+    if (ret < 0) {
+        _timeout = true;
+        return false;
+    }
+    
+    _len = (size_t)ret;
+    _offset = 0;
+    
+    return true;
+}
+
+void MbedDataSource::reset()
+{
+    _len = _offset = 0;
+    _timeout = false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedDataSource.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,62 @@
+/*
+ * MbedDataSource.h
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MBEDDATASOURCE_H
+#define MBEDDATASOURCE_H
+
+#include <stddef.h>
+#include "AbstractDataSource.h"
+#include "TCPSocketConnection.h"
+
+#define MBED_SOURCE_BUFFER_SIZE 60
+
+class MbedClient;
+
+class MbedDataSource : public AbstractDataSource
+{
+public:
+    MbedDataSource(TCPSocketConnection& sock);
+    ~MbedDataSource();
+
+    char read();
+    uint8_t status();
+
+protected:
+    bool receive();
+    void reset();
+
+private:
+    TCPSocketConnection& _sock;
+    char _buf[MBED_SOURCE_BUFFER_SIZE];
+    size_t _len, _offset;
+    bool _timeout;
+
+friend class MbedClient;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedSmartRest.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,33 @@
+/*
+ * MbedSmartRest.cpp
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+ #include "MbedSmartRest.h"
+
+MbedSmartRest::MbedSmartRest(const char* host, uint16_t port, const char* username, const char* password, const char* identifier) : SmartRest(_client, identifier), _client(host, port, username, password)
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MbedSmartRest.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ * MbedSmartRest.h
+ *
+ * Created on: Feb 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MBEDSMARTREST_H
+#define MBEDSMARTREST_H
+
+#include "SmartRest.h"
+#include "MbedClient.h"
+
+class MbedSmartRest : public SmartRest
+{
+public:
+    MbedSmartRest(const char*, uint16_t, const char*, const char*, const char*);
+
+private:
+    MbedClient _client;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NullValue.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,71 @@
+/*
+ * NullValue.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "NullValue.h"
+
+NullValue aNullValue;
+
+NullValue::NullValue()
+{
+}
+
+uint8_t NullValue::valueType() const
+{
+    return VALUE_NULL;
+}
+
+long NullValue::integerValue() const
+{
+    return 0;
+}
+
+double NullValue::floatValue() const
+{
+    return 0.0;
+}
+
+char * NullValue::characterValue() const
+{
+    return NULL;
+}
+
+size_t NullValue::write(AbstractDataSink&) const
+{
+    return 0;
+}
+
+size_t NullValue::length() const
+{
+    return 0;
+}
+
+Value* NullValue::copy() const
+{
+    return new NullValue();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NullValue.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * NullValue.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef NULLVALUE_H
+#define NULLVALUE_H
+
+#include "config.h"
+#include "Value.h"
+
+/**
+ * Represents a null value.
+ * 
+ * Example:
+ * @code
+ * // You may use:
+ * NullValue nullv;
+ * // You should use whenever possible:
+ * aNullValue;
+ * @encode
+ */
+class NullValue : public Value
+{
+public:
+    NullValue();
+
+    uint8_t valueType() const;
+    long integerValue() const;
+    double floatValue() const;
+    char * characterValue() const;
+
+    size_t write(AbstractDataSink&) const;
+    size_t length() const;
+    Value* copy() const;
+};
+
+extern NullValue aNullValue;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParsedRecord.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,115 @@
+/*
+ * ParsedRecord.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ParsedRecord.h"
+#include "ComposedRecord.h"
+#include "ParsedValue.h"
+#include "NullValue.h"
+#include <stdlib.h>
+#include <string.h>
+
+ParsedRecord::ParsedRecord()
+{
+    _count = 0;
+#ifdef SMARTREST_PARSED_DYNAMIC_ALLOC
+    _values = NULL;
+#endif
+}
+
+ParsedRecord::~ParsedRecord()
+{
+    clear();
+
+#ifdef SMARTREST_PARSED_DYNAMIC_ALLOC
+    if (_values != NULL)
+        free(_values);
+#endif
+}
+
+size_t ParsedRecord::values() const
+{
+    return _count;
+}
+
+const Value& ParsedRecord::value(size_t index) const
+{
+    if (index >= _count)
+        return aNullValue;
+    return *_values[index];
+}
+
+DataGenerator* ParsedRecord::copy() const
+{
+    ComposedRecord *copy = new ComposedRecord(true);
+    for (size_t n = 0; n < _count; n++)
+        copy->add(*_values[n]);
+    return copy;
+}
+
+const char * ParsedRecord::rawValue(size_t index) const
+{
+    if (index >= _count)
+        return NULL;
+
+    const char *ptr = _buffer;
+    for (size_t n = 0; n < index; n++) {
+        ptr += strlen(ptr) + 1;
+    }
+
+    return ptr;
+}
+
+void ParsedRecord::set(const char *buffer, size_t count)
+{
+    clear();
+    
+#ifdef SMARTREST_PARSED_DYNAMIC_ALLOC
+    const Value **values = (const Value**)realloc(_values, count*sizeof(Value*));
+    if (values == NULL)
+        return;
+    _values = values;
+#else
+    if (count > SMARTREST_PARSED_FIXED_SIZE)
+        count = SMARTREST_PARSED_FIXED_SIZE;
+#endif
+
+    const char *ptr = buffer;
+    for (size_t n = 0; n < count; n++) {
+        _values[n] = new ParsedValue(ptr, false);
+        ptr += strlen(ptr) + 1;
+    }
+
+    _count = count;
+    _buffer = buffer;
+}
+
+void ParsedRecord::clear()
+{
+    for (size_t n = 0; n < _count; n++)
+        delete _values[n];
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParsedRecord.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,110 @@
+/*
+ * ParsedRecord.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PARSEDRECORD_H
+#define PARSEDRECORD_H
+
+#include "config.h"
+#include "DataGenerator.h"
+#include "Record.h"
+#include "Value.h"
+
+#ifndef SMARTREST_PARSED_DYNAMIC_ALLOC
+#ifndef SMARTREST_PARSED_FIXED_SIZE
+#define SMARTREST_PARSED_FIXED_SIZE 24
+#endif
+#endif
+
+class Parser;
+
+/**
+ * This class provides accessors for values in a parsed record.
+ * 
+ * Example:
+ * @code
+ * // given a concrete SmartRest client instance
+ * SmartRest client;
+
+ * ParsedRecord record;
+ * if (client.receive(record) == SMARTREST_SUCCESS) {
+ *     for (size_ i = 0; i < record.values(); i++) {
+ *         const Value& val = record.value(i);
+ *         switch (val.valueType()) {
+ *         case VALUE_NULL:
+ *             printf("Null value.\n");
+ *             break;
+ *         case VALUE_CHARACTER:
+ *             printf("Character value: %s\n", val.characterValue());
+ *             break;
+ *         case VALUE_INTEGER:
+ *             printf("Integer value: %d\n", val.integerValue());
+ *             break;
+ *         case VALUE_FLOAT:
+ *             printf("Float value: %lf\n", val.floatValue());
+ *             break;
+ *         }
+ *     }
+ * }
+ * @encode
+ */
+class ParsedRecord : public Record
+{
+public:
+    ParsedRecord();
+    ~ParsedRecord();
+
+    size_t values() const;
+    const Value& value(size_t index) const;
+
+    DataGenerator* copy() const;
+
+    /**
+     * Returns the raw value string by index
+     * @param index the index of the value
+     * @return a pointer to the raw value
+     */
+    const char * rawValue(size_t index) const;
+
+protected:
+    void set(const char*, size_t);
+    void clear();
+
+private:
+#ifdef SMARTREST_PARSED_DYNAMIC_ALLOC
+    const Value **_values;
+#else
+    const Value *_values[SMARTREST_PARSED_FIXED_SIZE];
+#endif
+    const char *_buffer;
+    size_t _count;
+
+friend class Parser;
+};
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParsedValue.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,160 @@
+/*
+ * ParsedValue.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ParsedValue.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include "NullValue.h"
+#include "IntegerValue.h"
+#include "FloatValue.h"
+#include "CharValue.h"
+
+ParsedValue::ParsedValue(const char *str, bool copy) : _value(str, copy), _float(0.0), _digits(0), _zflag(false), _integer(0l)
+{
+    if (_value.valueType() != VALUE_NULL) {
+        _type = VALUE_CHARACTER;
+        extractValue();
+    } else {
+        _type = VALUE_NULL;
+    }
+}
+
+uint8_t ParsedValue::valueType() const
+{
+    return _type;
+}
+
+long ParsedValue::integerValue() const
+{
+    return _integer;
+}
+
+double ParsedValue::floatValue() const
+{
+    return _float;
+}
+
+const char * ParsedValue::characterValue() const
+{
+    if (_type != VALUE_CHARACTER)
+        return NULL;
+    return _value.characterValue();
+}
+
+size_t ParsedValue::write(AbstractDataSink& sink) const
+{
+    return _value.write(sink);
+}
+
+size_t ParsedValue::length() const
+{
+    return _value.length();
+}
+
+Value* ParsedValue::copy() const
+{
+    if (_type == VALUE_NULL)
+        return new NullValue();
+    if (_type == VALUE_INTEGER)
+        return new IntegerValue(_integer);
+    if (_type == VALUE_FLOAT)
+        return new FloatValue(_float, _digits, _zflag);
+    return new CharValue(_value.characterValue(), true);
+}
+
+void ParsedValue::extractValue()
+{
+    const char *str; char *ptr, c;
+    bool floating = false, zflag = false, negative = false;
+    uint8_t digits = 0;
+    
+    str = _value.characterValue();
+
+    if (isspace(*str))
+        return;
+
+    // easy check for nan
+    if (strcmp(str, "nan") == 0) {
+        _float = NAN;
+        _type = VALUE_FLOAT;
+        return;
+    }
+
+    if (*str == '-') {
+        negative = true;
+        str++;
+    }
+        
+    if (strcmp(str, "inf") == 0) {
+        _float = (negative) ? -INFINITY : INFINITY;
+        _type = VALUE_FLOAT;
+        return;
+    }
+
+    for (ptr = (char*)str; (c = *ptr) != 0; ptr++) {
+        if (floating) {
+            if (!isdigit(c))
+                return;
+            digits++;
+        } else {
+            if (c == '.') {
+                if (*(ptr+1) == '\0')
+                    return;
+                floating = true;
+            } else if (isdigit(c)) {
+                _zflag = true;
+            } else {
+                return;
+            }
+        }
+    }
+
+    if (floating) {
+        errno = 0;
+        if ((((_float = strtod(str, &ptr)) != 0.0) || (errno == 0)) &&
+            (*ptr == '\0')) {
+            if (negative)
+                _float = -_float;
+            _zflag = zflag;
+            _digits = digits;
+            _type = VALUE_FLOAT;
+        }
+    } else {
+        errno = 0;
+        if ((((_integer = strtol(str, &ptr, 10)) != 0) || (errno == 0)) &&
+            (*ptr == '\0')) {
+            if (negative)
+                _integer = -_integer;
+            _type = VALUE_INTEGER;
+            return;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParsedValue.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,92 @@
+/*
+ * ParsedValue.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef PARSEDVALUE_H
+#define PARSEDVALUE_H
+
+#include "config.h"
+#include "Value.h"
+#include "CharValue.h"
+
+#ifndef SMARTREST_PARSED_FIXED_SIZE
+#define SMARTREST_PARSED_FIXED_SIZE 16
+#endif
+
+/**
+ * Provides access to a parsed value by implementing the value interface.
+ * 
+ * Example:
+ * @code
+ * // given a filled parsed record
+ * ParsedRecord record;
+ * 
+ * // get first value
+ * const Value& val = record.value(0);
+ * switch (val.valueType()) {
+ * case VALUE_NULL:
+ *     printf("Null value.\n");
+ *     break;
+ * case VALUE_CHARACTER:
+ *     printf("Character value: %s\n", val.characterValue());
+ *     break;
+ * case VALUE_INTEGER:
+ *     printf("Integer value: %d\n", val.integerValue());
+ *     break;
+ * case VALUE_FLOAT:
+ *     printf("Float value: %lf\n", val.floatValue());
+ *     break;
+ * }
+ * @encode
+ */
+class ParsedValue : public Value
+{
+public:
+    ParsedValue(const char*, bool=false);
+
+    uint8_t valueType() const;
+    long integerValue() const;
+    double floatValue() const;
+    const char * characterValue() const;
+
+    size_t write(AbstractDataSink&) const;
+    size_t length() const;
+    Value* copy() const;
+
+private:
+    void extractValue();
+
+private:
+    CharValue _value;
+    uint8_t _type;
+    double _float;
+    uint8_t _digits;
+    bool _zflag;
+    long _integer;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Parser.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,180 @@
+/*
+ * Parser.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "Parser.h"
+
+#define STATE_BLANK 0
+#define STATE_STRUCTURE 1
+#define STATE_VALUE 2
+#define STATE_INQUOTES 3
+#define STATE_AFTERQUOTE 4
+#define STATE_COMPLETE 5
+#define STATE_ERROR 6
+
+Parser::Parser()
+{
+    reset();
+}
+
+uint8_t Parser::readFrom(AbstractDataSource& source, ParsedRecord& record)
+{
+    uint8_t status; char read;
+
+    reset();
+    record.set(NULL, 0);
+
+    while ((_state < STATE_COMPLETE) &&
+           (((read = source.read()) > 0 ) ||
+            ((status = source.status()) == DS_STATUS_OK)))
+        parse(read);
+
+    if (_state == STATE_COMPLETE)
+        record.set(_buffer, _count);
+
+    if (_state == STATE_COMPLETE)
+        return PARSER_SUCCESS;
+    else if (_state == STATE_BLANK)
+        if (status == DS_STATUS_CLOSED)
+            return PARSER_END_OF_RESPONSE;
+        else
+            return PARSER_TIMEOUT_ERROR;
+    else
+        if (status == DS_STATUS_TIMEOUT)
+            return PARSER_TIMEOUT_ERROR;
+        else
+            return PARSER_PARSE_ERROR;
+}
+
+void Parser::parse(char c)
+{
+    if (_ptr-_buffer >= SMARTREST_PARSER_BUFFER_SIZE) {
+        _state = STATE_ERROR;
+        return;
+    }
+
+    switch (_state) {
+    case STATE_BLANK:
+        _state = STATE_STRUCTURE;
+    case STATE_STRUCTURE:
+        switch (c) {
+        case ' ':
+        case '\t':
+        case '\r':
+            break;
+        case '"':
+            _state = STATE_INQUOTES;
+            break;
+        case ',':
+            close();
+            break;
+        case '\0':
+        case '\n':
+            if ((_count == 0) && (_length == 0)) {
+                _state = STATE_BLANK;
+            } else {
+                close();
+                _state = STATE_COMPLETE;
+            }
+            break;
+        default:
+            if (_length > 0) {
+                _state = STATE_ERROR;
+            } else {
+                _state = STATE_VALUE;
+                parse(c);
+            }
+            break;
+        }
+        break;
+    case STATE_VALUE:
+        switch (c) {
+        case ',':
+        case '\n':
+            _state = STATE_STRUCTURE;
+            parse(c);
+            break;
+        case '"':
+            _state = STATE_ERROR;
+            break;
+        default:
+            if ((c == ' ') || (c == '\t') || (c == '\r'))
+                _trailing++;
+            else
+                _trailing = 0;
+            append(c);
+            break;
+        }
+        break;
+    case STATE_INQUOTES:
+        switch (c) {
+        case '"':
+            _state = STATE_AFTERQUOTE;
+            break;
+        default:
+            append(c);
+            break;
+        }
+        break;
+    case STATE_AFTERQUOTE:
+        switch (c) {
+        case '"':
+            append(c);
+            _state = STATE_INQUOTES;
+            break;
+        default:
+            _state = STATE_STRUCTURE;
+            parse(c);
+            break;
+        }
+        break;
+    }
+}
+
+void Parser::append(char c)
+{
+    *_ptr++ = c;
+    _length++;
+}
+
+void Parser::close()
+{
+    _ptr -= _trailing;
+    *_ptr++ = 0;
+    _trailing = 0;
+    _length = 0;
+    _count++;
+}
+
+void Parser::reset()
+{
+    _state = STATE_BLANK;
+    _ptr = _buffer;
+    _count = 0;
+    _trailing = 0;
+    _length = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Parser.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,117 @@
+/*
+ * Parser.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file Parser.h
+ * A CSV parser utilizing an AbstractDataSource instance for reading from
+ * a connection.
+ */
+
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "config.h"
+#include <stddef.h>
+#include <stdint.h>
+#include "ParsedRecord.h"
+#include "AbstractDataSource.h"
+
+#ifndef SMARTREST_PARSER_BUFFER_SIZE
+#define SMARTREST_PARSER_BUFFER_SIZE 81
+#endif
+
+/** Return value indicating that no error occurred. */
+#define PARSER_SUCCESS 0
+/** Return value indicating that a transmission timeout occurred during
+ * the transmission of a record. */
+#define PARSER_TIMEOUT_ERROR 1
+/** Return value indicating the end of response. */
+#define PARSER_END_OF_RESPONSE 2
+/** Return value indicating a parse error. */
+#define PARSER_PARSE_ERROR 3
+
+/*
+ * A record parser reading from a data source.
+ * 
+ * Example:
+ * @code
+ * // given a concrete data sorce
+ * AbstractDataSource source;
+ * 
+ * Parser parser;
+ * ParsedRecord record;
+ * uint8_t ret;
+ * 
+ * while ((ret = parser.readFrom(source, record)) == PARSER_SUCCESS) {
+ *     // read record
+ * }
+
+ * // error handling
+ * switch (ret) {
+ * case PARSER_END_OF_RESPONSE:
+ *     // no error; end of response
+ *     break;
+ * case PARSER_TIMEOUT_ERROR:
+ *     // timeout error
+ *     break;
+ * default:
+ *     // parse error
+ *     break;
+ * }
+ * @encode
+ */
+class Parser
+{
+public:
+    /*
+     * Creates a new Parser instance.
+     */
+    Parser();
+
+    /*
+     * Parses a row from a stream.
+     * @param source the source to read from
+     * @param row the object written to
+     * @return a non-zero value if and only if an error occured.
+     */
+    uint8_t readFrom(AbstractDataSource&,ParsedRecord&);
+
+private:
+    void parse(char);
+    void append(char);
+    void close();
+    void reset();
+
+private:
+    char _buffer[SMARTREST_PARSER_BUFFER_SIZE];
+    uint8_t _state;
+    char *_ptr;
+    size_t _count, _length, _trailing;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Record.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,59 @@
+/*
+ * Record.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "Record.h"
+
+size_t Record::writeTo(AbstractDataSink& sink) const
+{
+    size_t written = 0;
+    for (size_t n = values(), i = 0; i < n; i++) {
+        written += value(i).write(sink);
+        if (i < n-1)
+            written += sink.write(',');
+    }
+    written += sink.write('\r');
+    written += sink.write('\n');
+    return written;
+}
+
+size_t Record::writtenLength() const
+{
+    size_t written = 2;
+    for (size_t n = values(), i = 0; i < n; i++) {
+        written += value(i).length();
+        if (i < n-1)
+            written++;
+    }
+    return written;
+}
+
+Record::operator bool() const
+{
+    return values() > 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Record.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * Record.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include "config.h"
+#include "DataGenerator.h"
+#include "Value.h"
+
+/**
+ * A record which can be read and serialized. 
+ */
+class Record : public DataGenerator
+{
+public:
+    virtual ~Record() { };
+
+    /**
+     * Returns the number of values in this record.
+     * @return number of values in this record
+     */
+    virtual size_t values() const = 0;
+
+    /**
+     * Returns the value object by index
+     * @param index the index of the value
+     * @return a copy of a value object
+     */
+    virtual const Value& value(size_t index) const = 0;
+
+    size_t writeTo(AbstractDataSink&) const;
+    size_t writtenLength() const;
+
+    operator bool() const;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmartRest.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,164 @@
+/*
+ * SmartRest.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "SmartRest.h"
+#include <stdlib.h>
+#include <string.h>
+
+SmartRest::SmartRest(AbstractClient& client, const char *identifier) : _client(client), _identifier(identifier)
+{
+    _source = NULL;
+    _mogid[0] = 0;
+}
+
+int8_t SmartRest::send(DataGenerator& generator)
+{
+    uint8_t res;
+
+    res = beginRequest();
+    if (res != SMARTREST_SUCCESS)
+        return res;
+
+    _client.sendData(generator);
+    return awaitResponse();
+}
+
+int8_t SmartRest::receive(ParsedRecord& record)
+{
+    uint8_t res;
+    
+    if (_source == NULL)
+        return SMARTREST_INTERNAL_ERROR;
+
+    res = _parser.readFrom(*_source, record);
+
+    switch (res) {
+    case PARSER_SUCCESS:
+        return SMARTREST_SUCCESS;
+    case PARSER_END_OF_RESPONSE:
+        return SMARTREST_END_OF_RESPONSE;
+    case PARSER_TIMEOUT_ERROR:
+        return SMARTREST_TIMEOUT_ERROR;
+    }
+    return SMARTREST_INTERNAL_ERROR;
+}
+
+int8_t SmartRest::bootstrap(DataGenerator& generator)
+{
+    ParsedRecord record;
+    int8_t ret;
+
+    ret = beginRequest();
+    if (ret != SMARTREST_SUCCESS)
+        return ret;
+    ret = awaitResponse();
+    if (ret != SMARTREST_SUCCESS)
+        return ret;
+    ret = receive(record);
+    if (ret != SMARTREST_SUCCESS)
+        return ret;
+    if (!record) {
+        return SMARTREST_INTERNAL_ERROR;
+    }
+    stop();
+
+    if (setMoGid(record))
+        return SMARTREST_SUCCESS;
+
+    if (record.value(0).integerValue() != 40)
+        return SMARTREST_INTERNAL_ERROR;
+
+    ret = send(generator);
+    if (ret != SMARTREST_SUCCESS)
+        return ret;
+    ret = receive(record);
+    if (ret != SMARTREST_SUCCESS)
+        return ret;
+    stop();
+
+    if (!setMoGid(record))
+        return SMARTREST_INTERNAL_ERROR;
+
+    return SMARTREST_SUCCESS;
+}
+
+void SmartRest::stop()
+{
+    _source = NULL;
+    _client.stop();
+}
+
+uint8_t SmartRest::beginRequest()
+{
+    int res;
+
+    res = _client.beginRequest();
+    if (res == CLIENT_CONNECTION_ERROR) {
+        return SMARTREST_CONNECTION_FAILED;
+    } else if (res != CLIENT_OK) {
+        return SMARTREST_INTERNAL_ERROR;
+    }
+    if (strlen(_mogid)) {
+        if (_client.sendIdentifier(_mogid) != CLIENT_OK)
+            return SMARTREST_INTERNAL_ERROR;
+    } else {
+        if (_client.sendIdentifier(_identifier) != CLIENT_OK)
+            return SMARTREST_INTERNAL_ERROR;
+    }
+    return SMARTREST_SUCCESS;
+}
+
+uint8_t SmartRest::awaitResponse()
+{
+    if ((_client.endRequest() != CLIENT_OK) ||
+        (_client.awaitResponse() != CLIENT_OK))
+        return SMARTREST_INTERNAL_ERROR;
+    _source = &_client.receiveData();
+    return SMARTREST_SUCCESS;
+}
+
+bool SmartRest::setMoGid(ParsedRecord& record)
+{
+    const char *mogid;
+
+    *_mogid = 0;
+    if ((record.values() < 2) || (record.value(0).integerValue() != 20))
+        return false;
+
+    if ((record.value(1).valueType() != VALUE_INTEGER) ||
+        (record.value(1).integerValue() <= 0))
+        return false;
+
+    mogid = record.rawValue(1);
+    if (strlen(mogid)+1 > sizeof(_mogid))
+        return false;
+
+    strcpy(_mogid, mogid);
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SmartRest.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,150 @@
+/*
+ * SmartRest.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file SmartRest.h
+ * The main SmartRest facade class. This class is abstract, because the
+ * actual implementation has to supply a client.
+ */
+
+#ifndef SMARTREST_H
+#define SMARTREST_H
+
+#include "config.h"
+#include <stddef.h>
+#include <stdint.h>
+#include "AbstractClient.h"
+#include "ParsedRecord.h"
+#include "Parser.h"
+
+/** Return value indicating that no error occurred. */
+#define SMARTREST_SUCCESS 0
+/** Return value indicating that the connection has been closed during
+ * data transmission. */
+#define SMARTREST_CONNECTION_FAILED 1
+/** Return value indicating an internal state error. */
+#define SMARTREST_INTERNAL_ERROR 2
+/** Return value indicating a transmission timeout. */
+#define SMARTREST_TIMEOUT_ERROR 3
+/** Return value indicating an end of response indicated by the
+ * Content-Length header. */
+#define SMARTREST_END_OF_RESPONSE 4
+/** Return value indicating that the connection has been closed. */
+#define SMARTREST_CONNECTION_CLOSED 5
+
+/**
+ * SmartRest client implementation.
+ * This class provides methods to send a request and receive a response
+ * from the server.
+ * 
+ * Example:
+ * @code
+ * // given a concrete SmartRest implementation and a template
+ * SmartRest client;
+ * StaticData template;
+ * 
+ * // bootstrap
+ * if (client.bootstrap(template) != SMARTREST_SUCCESS) {
+ *     // error handling
+ *     return;
+ * }
+ * 
+ * if (client.send(StaticData("100,Hello")) != SMARTREST_SUCCESS) {
+ *     // error handling
+ * }
+ * 
+ * uint8_t ret;
+ * while ((ret = client.receive(record)) == SMARTREST_SUCCESS) {
+ *     // work with data
+ * }
+ * 
+ * // error handling
+ * 
+ * // call after every request.
+ * client.stop();
+ * @encode
+ */
+class SmartRest
+{
+protected:
+    /**
+     * Creates a new GenericSmartRest object.
+     * @param client the abstract client to use
+     * @param identifier the device identifier
+     */
+    SmartRest(AbstractClient&, const char*);
+
+public:
+    virtual ~SmartRest() { };
+
+    /**
+     * Sends a smart request.
+     * @param generator the generator which will generate the data to be
+     *                  sent.
+     * @return a non-zero value if and only if an error occured
+     */
+    int8_t send(DataGenerator&);
+
+    /**
+     * Tries to receive a parsed response row.
+     * When the function succeeds, but the row pointer is NULL, there are
+     * no more rows to be read.
+     * @param record an instance to where the parsed row is written
+     * @return a non-zero value if and only if an error occured
+     */
+    int8_t receive(ParsedRecord&);
+
+    /*
+     * Initiates the SmartRest bootstrap process.
+     * When successful, the template identifier will be replaced by the
+     * global managed object ID in future requests.
+     * @param generator the generator which will generate the data to be
+     *                  sent as a template.
+     * @return a non-zero value if and only if an error occured
+     */
+    int8_t bootstrap(DataGenerator&);
+
+    /*
+     * Closes the connection.
+     */
+    void stop();
+
+protected:
+    uint8_t beginRequest();
+    uint8_t awaitResponse();
+    bool setMoGid(ParsedRecord&);
+
+private:
+    AbstractClient& _client;
+    AbstractDataSource *_source;
+    Parser _parser;
+    const char *_identifier;
+    char _mogid[8 * sizeof(long) + 1];
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StaticData.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,78 @@
+/*
+ * StaticData.cpp
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "StaticData.h"
+#include <stdlib.h>
+#include <string.h>
+
+StaticData::StaticData(void* buffer, size_t length, bool copy)
+{
+    _alloc = copy;
+    _len = length;
+    if (copy) {
+        _buf = malloc(length);
+        memcpy(_buf, buffer, length);
+    } else {
+        _buf = buffer;
+    }
+}
+
+StaticData::StaticData(const char* string, bool copy)
+{
+    _alloc = copy;
+    if (copy) {
+        _len = strlen(string)*sizeof(char);
+        _buf = malloc(_len);
+        memcpy(_buf, string, _len);
+    } else {
+        _buf = (void*)string;
+        _len = strlen(string)*sizeof(char);
+    }
+}
+
+StaticData::~StaticData()
+{
+    if (_alloc)
+        free(_buf);
+}
+
+size_t StaticData::writeTo(AbstractDataSink& sink) const
+{
+    return sink.write((void*)_buf, _len*sizeof(char));
+}
+
+size_t StaticData::writtenLength() const
+{
+    return _len;
+}
+
+DataGenerator* StaticData::copy() const
+{
+    return new StaticData(_buf, _len, true);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/StaticData.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,64 @@
+/*
+ * StaticData.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef STATICDATA_H
+#define STATICDATA_H
+
+#include "config.h"
+#include <stddef.h>
+#include "DataGenerator.h"
+
+/*
+ * A static data store mechanism streaming data to a sink.
+ * 
+ * Example:
+ * @code
+ * // given a concrete data sink
+ * AbstractDataSink sink;
+
+ * StaticData data("Hello World!");
+ * assert(data.writtenLength() == data.writeTo(sink));
+ * @encode
+ */
+class StaticData : public DataGenerator
+{
+public:
+    StaticData(void*, size_t, bool=false);
+    StaticData(const char*, bool=false);
+    ~StaticData();
+    size_t writeTo(AbstractDataSink&) const;
+    size_t writtenLength() const;
+    DataGenerator* copy() const;
+
+private:
+    void *_buf;
+    size_t _len;
+    bool _alloc;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Value.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,107 @@
+/*
+ * Value.h
+ *
+ * Created on: Nov 1, 2013
+ * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
+ *
+ * Copyright (c) 2013 Cumulocity GmbH
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file Value.h
+ * Represents a generic data value.
+ */
+
+#ifndef VALUE_H
+#define VALUE_H
+
+#include "config.h"
+#include <stddef.h>
+#include <stdint.h>
+#include "AbstractDataSink.h"
+
+/** Return value indicating a null value. */
+#define VALUE_NULL 0
+/** Return value indicating an integer value. */
+#define VALUE_INTEGER 1
+/** Return value indicating a floating-point number. */
+#define VALUE_FLOAT 2
+/** Return value indicating a character string. */
+#define VALUE_CHARACTER 3
+
+/**
+ * A generic value offering means to obtain the value type and contents
+ * as well as writing the value to a sink.
+ */
+class Value
+{
+public:
+    virtual ~Value() { };
+
+    /**
+     * Returns the value type which can be VALUE_NULL, VALUE_INTEGER,
+     * VALUE_FLOAT or VALUE_CHARACTER.
+     * @return the value type
+     */
+    virtual uint8_t valueType() const = 0;
+
+    /**
+     * Returns the integer value if an integer type, otherwise zero.
+     * @return integer value
+     */
+    virtual long integerValue() const = 0;
+
+    /**
+     * Returns the float value if a float type, otherwise zero.
+     * @return float value
+     */
+    virtual double floatValue() const = 0;
+
+    /**
+     * Returns the character value if a character type, otherwise zero.
+     * @return character value
+     */
+    virtual const char * characterValue() const = 0;
+
+    /**
+     * Writes the value to a sink.
+     * If necessary, quotes and escape characters may be added.
+     * @param sink the sink to write the value to
+     * @return the number of bytes written
+     */
+    virtual size_t write(AbstractDataSink&) const = 0;
+
+    /**
+     * Returns the number of bytes required to write this value to a sink.
+     * @return number of bytes required to write this value
+     */
+    virtual size_t length() const = 0;
+
+    /**
+     * Copies this value to the heap. Referenced contents must also be
+     * copied.
+     * @return a new value instance allocated on the heap
+     */
+    virtual Value* copy() const = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/b64.cpp	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,70 @@
+// Simple Base64 code
+// (c) Copyright 2010 MCQN Ltd.
+// Released under Apache License, version 2.0
+
+#include "b64.h"
+
+/* Simple test program
+#include <stdio.h>
+void main()
+{
+    char* in = "amcewen";
+    char out[22];
+
+    b64_encode(in, 15, out, 22);
+    out[21] = '\0';
+
+    printf(out);
+}
+*/
+
+int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen)
+{
+    // Work out if we've got enough space to encode the input
+    // Every 6 bits of input becomes a byte of output
+    if (aOutputLen < (aInputLen*8)/6)
+    {
+        // FIXME Should we return an error here, or just the length
+        return (aInputLen*8)/6;
+    }
+
+    // If we get here we've got enough space to do the encoding
+
+    const char* b64_dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    if (aInputLen == 3)
+    {
+        aOutput[0] = b64_dictionary[aInput[0] >> 2];
+        aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)];
+        aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2|(aInput[2]>>6)];
+        aOutput[3] = b64_dictionary[aInput[2]&0x3F];
+    }
+    else if (aInputLen == 2)
+    {
+        aOutput[0] = b64_dictionary[aInput[0] >> 2];
+        aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)];
+        aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2];
+        aOutput[3] = '=';
+    }
+    else if (aInputLen == 1)
+    {
+        aOutput[0] = b64_dictionary[aInput[0] >> 2];
+        aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4];
+        aOutput[2] = '=';
+        aOutput[3] = '=';
+    }
+    else
+    {
+        // Break the input into 3-byte chunks and process each of them
+        int i;
+        for (i = 0; i < aInputLen/3; i++)
+        {
+            b64_encode(&aInput[i*3], 3, &aOutput[i*4], 4);
+        }
+        if (aInputLen % 3 > 0)
+        {
+            // It doesn't fit neatly into a 3-byte chunk, so process what's left
+            b64_encode(&aInput[i*3], aInputLen % 3, &aOutput[i*4], aOutputLen - (i*4));
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/b64.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,6 @@
+#ifndef b64_h
+#define b64_h
+
+int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Thu Jul 03 20:38:04 2014 +0200
@@ -0,0 +1,33 @@
+#ifndef _SMARTREST_CONFIG_H
+#define _SMARTREST_CONFIG_H 1
+ 
+/* Define the fixed array size of the Aggregator module. This disables dynamic
+   memory management. */
+#define SMARTREST_AGGREGATOR_FIXED_SIZE 100
+
+/* Define the initial capacity of the Aggregator module. */
+//#define SMARTREST_AGGREGATOR_INITIAL_CAPACITY  50 
+
+/* Define the memory increment of the Aggregator module. */
+//#define SMARTREST_AGGREGATOR_MEMORY_INCREMENT  25 
+
+/* Define the fixed array size of a ComposedRecord instance. This disables
+   dynamic memory management. */
+#define SMARTREST_COMPOSED_FIXED_SIZE 10
+
+/* Define the initial capacity of a ComposedRecord instance. */
+//#define SMARTREST_COMPOSED_INITIAL_CAPACITY  10 
+
+/* Define the memory increment of a ComposedRecord instance. */
+//#define SMARTREST_COMPOSED_MEMORY_INCREMENT  5 
+
+/* Define, whether a ParsedRecord instance shall use dynamic allocation. */
+//#define SMARTREST_PARSED_DYNAMIC_ALLOC  1 
+
+/* Define the fixed array size of a ParsedRecord instance. */
+#define SMARTREST_PARSED_FIXED_SIZE  10
+
+/* Define the buffer size of the Parser module. */
+#define SMARTREST_PARSER_BUFFER_SIZE  81 
+
+#endif