A client for the SmartREST protocol from Cumulocity.
Fork of MbedSmartRest by
Revision 8:762dc52db813, committed 2014-02-02
- Comitter:
- vwochnik
- Date:
- Sun Feb 02 14:55:57 2014 +0000
- Parent:
- 7:26524a6a04a1
- Child:
- 9:3bbb83e7cbfd
- Commit message:
- fix
Changed in this revision
--- a/SmartRest.lib Sun Feb 02 14:55:16 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -SmartRest#fc337461afe3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/AbstractClient.h Sun Feb 02 14:55:57 2014 +0000 @@ -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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#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. + * + * 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/SmartRest/AbstractDataSink.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,89 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#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/SmartRest/AbstractDataSource.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,104 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#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/SmartRest/Aggregator.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,163 @@ +/* + * 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 AGGREGATOR_FIXED_SIZE +Aggregator::Aggregator(size_t capacity, bool growing, bool copy) +{ + _alloc = copy; + _growing = growing; + _initial = _capacity = capacity; + _list = (const DataGenerator**)malloc(_capacity*sizeof(DataGenerator*)); + _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 AGGREGATOR_FIXED_SIZE + free(_list); + #endif +} + +bool Aggregator::add(const DataGenerator& generator) +{ + if (this == &generator) + return false; + #ifndef AGGREGATOR_FIXED_SIZE + if (_length == _capacity) { + if (!_growing) + return false; + + size_t capacity = _capacity + 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 == 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 AGGREGATOR_FIXED_SIZE + if (_growing) { + const DataGenerator **list = (const DataGenerator**)realloc(_list, + _initial*sizeof(DataGenerator*)); + if (list == NULL) + return; + _list = list; + _capacity = _initial; + } + #endif +} + +size_t Aggregator::length() +{ + return _length; +} + +bool Aggregator::full() +{ + #ifndef AGGREGATOR_FIXED_SIZE + return (_growing) ? false : (_length == _capacity); + #else + return (_length == AGGREGATOR_FIXED_SIZE); + #endif +} + +size_t Aggregator::capacity() +{ + #ifndef AGGREGATOR_FIXED_SIZE + return (_growing) ? 0 : _capacity; + #else + return 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 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/SmartRest/Aggregator.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,126 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> +#include "DataGenerator.h" + +#ifndef AGGREGATOR_INITIAL_CAPACITY +#define AGGREGATOR_INITIAL_CAPACITY 50 +#endif +#ifndef AGGREGATOR_MEMORY_INCREMENT +#define AGGREGATOR_MEMORY_INCREMENT 25 +#endif +//#define 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. + */ +class Aggregator : public DataGenerator +{ +public: + #ifndef 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=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 AGGREGATOR_FIXED_SIZE + const DataGenerator *_list[AGGREGATOR_FIXED_SIZE]; + #else + const DataGenerator **_list; + #endif + size_t _length; + bool _alloc; + #ifndef AGGREGATOR_FIXED_SIZE + size_t _capacity, _initial; + bool _growing; + #endif +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/CharValue.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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) || (strlen(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/SmartRest/CharValue.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,62 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "Value.h" + +/** + * A basic character value. This value type behaves simmilar to a null + * value if the ommitted string is empty. + */ +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/SmartRest/ComposedRecord.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,116 @@ +/* + * 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 COMPOSED_FIXED_SIZE + _capacity = COMPOSED_INITIAL_CAPACITY; + _values = (const Value**)malloc(_capacity*sizeof(Value*)); + #endif + _count = 0; +} + +ComposedRecord::~ComposedRecord() +{ + if (_alloc) { + for (size_t n = 0; n < _count; n++) + delete _values[n]; + } + #ifndef COMPOSED_FIXED_SIZE + free(_values); + #endif +} + +ComposedRecord& ComposedRecord::add(const Value& value) +{ + #ifndef COMPOSED_FIXED_SIZE + if (_capacity == _count) { + size_t capacity = _capacity + COMPOSED_MEMORY_INCREMENT; + const Value **values = (const Value**)realloc(_values, + capacity*sizeof(Value*)); + if (values == NULL) + return *this; + _values = values; + _capacity = capacity; + } + #else + if (_count == COMPOSED_FIXED_SIZE) + return *this; + #endif + + if (_alloc) { + Value *copy = value.copy(); + if (copy == NULL) + return *this; + _values[_count++] = copy; + } else { + _values[_count++] = &value; + } + return *this; +} + +void ComposedRecord::clear() +{ + _count = 0; + #ifndef COMPOSED_FIXED_SIZE + if (_capacity > COMPOSED_INITIAL_CAPACITY) { + Value** values = (Value**)realloc(_values, + COMPOSED_INITIAL_CAPACITY*sizeof(Value*)); + if (values == NULL) + return; + _capacity = COMPOSED_INITIAL_CAPACITY; + } + #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/SmartRest/ComposedRecord.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,76 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "DataGenerator.h" +#include "Record.h" +#include "Value.h" + +#ifndef COMPOSED_INITIAL_CAPACITY +#define COMPOSED_INITIAL_CAPACITY 10 +#endif +#ifndef COMPOSED_MEMORY_INCREMENT +#define COMPOSED_MEMORY_INCREMENT 5 +#endif +//#define COMPOSED_FIXED_SIZE 25 + +/** + * This value set collects values and serializes them. + */ +class ComposedRecord : public Record +{ +public: + ComposedRecord(bool=false); + ~ComposedRecord(); + + ComposedRecord& add(const Value&); + void clear(); + + size_t values() const; + const Value& value(size_t index) const; + + DataGenerator* copy() const; + +private: + #ifndef COMPOSED_FIXED_SIZE + const Value **_values; + size_t _capacity; + #else + Value *_values[COMPOSED_FIXED_SIZE]; + #endif + size_t _count; + bool _alloc; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/DataGenerator.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,72 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#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/SmartRest/FloatValue.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,137 @@ +/* + * 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> + +FloatValue::FloatValue(double number, uint8_t digits, bool zflag) +{ + _negative = (number < 0.0); + _zflag = zflag; + if (_negative) + _number = -number; + else + _number = number; + _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; + + if (isnan(_number)) return sink.write("nan"); + if (isinf(_number)) return sink.write("inf"); + if (_number > 4294967040.0) return sink.write("ovf"); + + if (_negative) + sink.write('-'); + + double number = _number, rounding = 0.5; + for (uint8_t i = 0; i < _digits; ++i) + rounding /= 10.0; + number += rounding; + + unsigned long int_part = (unsigned long)number; + double 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 +{ + if ((isnan(_number)) || (isinf(_number)) || + (_number > 4294967040.0)) + return 3; + + size_t l = 0; + + if (_negative) + l++; + + double number = _number, rounding = 0.5; + for (uint8_t i = 0; i < _digits; ++i) + rounding /= 10.0; + number += rounding; + + unsigned long 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); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/FloatValue.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,69 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdint.h> +#include "Value.h" + +/** + * A floating-point value. + */ +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, 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; + +private: + double _number; + bool _negative; + uint8_t _digits; + bool _zflag; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/IntegerValue.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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/SmartRest/IntegerValue.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,57 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "Value.h" + +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/SmartRest/NullValue.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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/SmartRest/NullValue.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,55 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "Value.h" + +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/SmartRest/ParsedRecord.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,80 @@ +/* + * 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; +} + +ParsedRecord::~ParsedRecord() +{ + for (size_t n = 0; n < _count; n++) + delete _values[n]; +} + +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; +} + +void ParsedRecord::set(const char *strs, size_t count) +{ + for (size_t n = 0; n < _count; n++) + delete _values[n]; + + if (count > PARSED_FIXED_SIZE) + count = PARSED_FIXED_SIZE; + _count = count; + const char *ptr = strs; + for (size_t n = 0; n < count; n++) { + _values[n] = new ParsedValue(ptr, false); + ptr += strlen(ptr) + 1; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/ParsedRecord.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,71 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "DataGenerator.h" +#include "Record.h" +#include "Value.h" + +#ifndef PARSED_FIXED_SIZE +#define PARSED_FIXED_SIZE 24 +#endif + +class Parser; + +/** + * This value set collects values and serializes them. + */ +class ParsedRecord : public Record +{ +public: + ParsedRecord(); + ~ParsedRecord(); + + size_t values() const; + const Value& value(size_t index) const; + + DataGenerator* copy() const; + +private: + void set(const char*, size_t); + +private: + const Value *_values[PARSED_FIXED_SIZE]; + size_t _count; + +friend class Parser; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/ParsedValue.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,128 @@ +/* + * 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 "NullValue.h" +#include "IntegerValue.h" +#include "FloatValue.h" +#include "CharValue.h" +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +ParsedValue::ParsedValue(const char *str, bool copy) : _value(str, copy) +{ + if (_value.valueType() != VALUE_NULL) { + _type = VALUE_CHARACTER; + extractValue(); + } else { + _type = VALUE_NULL; + } +} + +uint8_t ParsedValue::valueType() const +{ + return _type; +} + +long ParsedValue::integerValue() const +{ + if (_type != VALUE_INTEGER) + return 0; + return _integer; +} + +double ParsedValue::floatValue() const +{ + if (_type != VALUE_FLOAT) + return 0.0; + 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() +{ + int len; + const char *str = _value.characterValue(); + + sscanf(str, "%li%n", &_integer, &len); + if ((size_t)len == strlen(str)) { + _type = VALUE_INTEGER; + return; + } + + sscanf(str, "%lf%n", &_float, &len); + if ((size_t)len == strlen(str)) { + bool floating = false; + _digits = 0; + _zflag = false; + for (char c, *ptr = (char*)str; (c = *ptr) > 0; ptr++) { + if (floating) { + if (c == '.') + return; + _digits++; + } else { + if (c == '.') + floating = true; + else if (isdigit(c)) + _zflag = true; + } + } + if (!((floating) && (!_digits))) { + _type = VALUE_FLOAT; + return; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/ParsedValue.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,69 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "Value.h" +#include "CharValue.h" + +#ifndef PARSED_FIXED_SIZE +#define PARSED_FIXED_SIZE 16 +#endif + +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/SmartRest/Parser.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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 >= 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/SmartRest/Parser.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,94 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> +#include <stdint.h> +#include "ParsedRecord.h" +#include "AbstractDataSource.h" + +#ifndef PARSER_BUFFER_SIZE +#define 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 CSV parser implementation. + * This class parses CSV rows from a stream. + */ +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[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/SmartRest/Record.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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/SmartRest/Record.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,66 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#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/SmartRest.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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 <stdio.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(Record& record) +{ + long mogid; + + *_mogid = 0; + + if ((record.values() < 2) || (record.value(0).integerValue() != 20)) + return false; + + if (record.value(1).integerValue() == 0) + return false; + + mogid = record.value(1).integerValue(); + + if (!snprintf(_mogid, SMARTREST_MOGID_BUFFER_SIZE, "%ld", mogid)) + *_mogid = 0; + + return true; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/SmartRest.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,130 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> +#include <stdint.h> +#include "AbstractClient.h" +#include "ParsedRecord.h" +#include "Parser.h" + +#ifndef SMARTREST_MOGID_BUFFER_SIZE +#define SMARTREST_MOGID_BUFFER_SIZE 11 +#endif + +/** 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 Arduino client implementation. + * This class provides methods to send a request and receive a response + * from the server. + */ +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(); + +private: + uint8_t beginRequest(); + uint8_t awaitResponse(); + bool setMoGid(Record&); + +private: + AbstractClient& _client; + AbstractDataSource *_source; + Parser _parser; + const char *_identifier; + char _mogid[SMARTREST_MOGID_BUFFER_SIZE]; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest/StaticData.cpp Sun Feb 02 14:55:57 2014 +0000 @@ -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/SmartRest/StaticData.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,59 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stddef.h> +#include "DataGenerator.h" + +/* + * The StaticData class provides a way to stream data to a + * connection.. + */ +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/SmartRest/Value.h Sun Feb 02 14:55:57 2014 +0000 @@ -0,0 +1,110 @@ +/* + * 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 + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#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