A client for the SmartREST protocol from Cumulocity.
Fork of MbedSmartRest by
Revision 0:f76673e7f275, committed 2014-01-23
- Comitter:
- vwochnik
- Date:
- Thu Jan 23 14:36:46 2014 +0000
- Child:
- 1:ea43d8ee05fd
- Commit message:
- initial commit, only abstraction
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AbstractClient.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef ABSTRACTCLIENT_H +#define ABSTRACTCLIENT_H + +#include "DataGenerator.h" +#include "AbstractDataSource.h" +#include "AbstractDataSink.h" + +#define CLIENT_OK 0 +#define CLIENT_CONNECTION_ERROR 1 +#define CLIENT_INTERNAL_ERROR 2 + +/* + * The AbstractClient class provides a way to make requests to SmartREST. + */ +class AbstractClient +{ +public: + virtual ~AbstractClient() + { + } + + /** + * Begin a SmartREST request. This will establish a connection, + * send the start of a HTTP POST request and send the Host + * and Authorization header. + */ + virtual uint8_t beginRequest() = 0; + + /** + * Sends the X-Id device identifier header. + * @param identifier the identifier to be sent. + */ + virtual uint8_t sendIdentifier(const char*) = 0; + + /** + * Sends all data from the source as well as a Content-Length header + * over the established connection. + * @param generator the data generator for the data to send + */ + virtual uint8_t sendData(DataGenerator& generator) = 0; + + /** + * Ends the HTTP request. + */ + virtual uint8_t endRequest() = 0; + + /** + * Finishes the HTTP request and awaits a status header. + */ + 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. + */ + virtual void stop() = 0; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AbstractDataSink.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#ifndef ABSTRACTDATASINK_H +#define ABSTRACTDATASINK_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 Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#ifndef ABSTRACTDATASOURCE_H +#define ABSTRACTDATASOURCE_H + +#include <stdint.h> + +#define DS_STATUS_OK 0 +#define DS_STATUS_TIMEOUT 1 +#define DS_STATUS_CLOSED 2 + +/* + * 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 Jan 23 14:36:46 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 = (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(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; + DataGenerator **list = (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) { + DataGenerator **list = (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/Aggregator.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,120 @@ +/* + * 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 + +//#define AGGREGATOR_FIXED_SIZE 25 + +#include <stddef.h> +#include "DataGenerator.h" + +//#define AGGREGATOR_FIXED_SIZE 100 +#define AGGREGATOR_INITIAL_CAPACITY 50 +#define AGGREGATOR_MEMORY_INCREMENT 25 + +/** + * 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(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 + DataGenerator *_list[AGGREGATOR_FIXED_SIZE]; + #else + 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/CharValue.cpp Thu Jan 23 14:36:46 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/CharValue.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,58 @@ +/* + * 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 "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/ComposedRecord.cpp Thu Jan 23 14:36:46 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 = (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(Value& value) +{ + #ifndef COMPOSED_FIXED_SIZE + if (_capacity == _count) { + size_t capacity = _capacity + COMPOSED_MEMORY_INCREMENT; + Value **values = (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; +} + +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 Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,68 @@ +/* + * 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 "DataGenerator.h" +#include "Record.h" +#include "Value.h" + +//#define COMPOSED_FIXED_SIZE 25 +#define COMPOSED_INITIAL_CAPACITY 10 +#define COMPOSED_MEMORY_INCREMENT 5 + +/** + * This value set collects values and serializes them. + */ +class ComposedRecord : public Record +{ +public: + ComposedRecord(bool=false); + ~ComposedRecord(); + + ComposedRecord& add(Value&); + void clear(); + + size_t values() const; + Value& value(size_t index) const; + + DataGenerator* copy() const; + +private: + #ifndef COMPOSED_FIXED_SIZE + 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/DataGenerator.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,67 @@ +/* + * 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 <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 clone on the heap with no dependent stack variables. + * All external data has to be copied aswell. + * @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 Jan 23 14:36:46 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/FloatValue.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,65 @@ +/* + * 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 <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/IntegerValue.cpp Thu Jan 23 14:36:46 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/IntegerValue.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,53 @@ +/* + * 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 "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/NullValue.cpp Thu Jan 23 14:36:46 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/NullValue.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,51 @@ +/* + * 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 "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/ParsedRecord.cpp Thu Jan 23 14:36:46 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; +} + +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/ParsedRecord.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,65 @@ +/* + * 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 "DataGenerator.h" +#include "Record.h" +#include "Value.h" + +#define PARSED_FIXED_SIZE 16 + +class Parser; + +/** + * This value set collects values and serializes them. + */ +class ParsedRecord : public Record +{ +public: + ParsedRecord(); + ~ParsedRecord(); + + size_t values() const; + Value& value(size_t index) const; + + DataGenerator* copy() const; + +private: + void set(const char*, size_t); + +private: + Value *_values[PARSED_FIXED_SIZE]; + size_t _count; + +friend class Parser; +}; + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ParsedValue.cpp Thu Jan 23 14:36:46 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/ParsedValue.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,61 @@ +/* + * 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 "Value.h" +#include "CharValue.h" + +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 Jan 23 14:36:46 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/Parser.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,77 @@ +/* + * 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. + */ + +#ifndef PARSER_H +#define PARSER_H + +#include <stddef.h> +#include <stdint.h> +#include "ParsedRecord.h" +#include "AbstractDataSource.h" + +#define PARSER_BUFFER_SIZE 81 + +#define PARSER_SUCCESS 0 +#define PARSER_TIMEOUT_ERROR 1 +#define PARSER_END_OF_RESPONSE 2 +#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/Record.cpp Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,31 @@ +#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 Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,62 @@ +/* + * 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 "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 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 Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,162 @@ +/* + * 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) { + ret = send(generator); + if (ret != SMARTREST_SUCCESS) + return ret; + ret = receive(record); + if (ret != SMARTREST_SUCCESS) + return ret; + stop(); + + if (setMoGid(record)) + return SMARTREST_SUCCESS; + } + return SMARTREST_INTERNAL_ERROR; +} + +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; +} + +uint8_t SmartRest::setMoGid(Record& record) +{ + long mogid; + + *_mogid = 0; + + if ((record.values() < 2) || (record.value(0).integerValue() != 20)) + return 0; + + if (record.value(1).integerValue() == 0) + return 0; + + mogid = record.value(1).integerValue(); + + if (!snprintf(_mogid, SMARTREST_MOGID_BUFFER_SIZE, "%ld", mogid)) + *_mogid = 0; + + return 1; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SmartRest.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,109 @@ +/* + * 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. + */ + +#ifndef SMARTREST_H +#define SMARTREST_H + +#include <stddef.h> +#include <stdint.h> +#include "AbstractClient.h" +#include "Record.h" +#include "ParsedRecord.h" +#include "Parser.h" +#include "ComposedRecord.h" + +#define SMARTREST_MOGID_BUFFER_SIZE 11 +#define SMARTREST_SUCCESS 0 +#define SMARTREST_CONNECTION_FAILED 1 +#define SMARTREST_INTERNAL_ERROR 2 +#define SMARTREST_TIMEOUT_ERROR 3 +#define SMARTREST_END_OF_RESPONSE 4 +#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: + /** + * 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(); + uint8_t 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/StaticData.cpp Thu Jan 23 14:36:46 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/StaticData.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,55 @@ +/* + * 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 <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/Value.h Thu Jan 23 14:36:46 2014 +0000 @@ -0,0 +1,97 @@ +/* + * 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. + */ + +#ifndef VALUE_H +#define VALUE_H + +#include <stddef.h> +#include <stdint.h> +#include "AbstractDataSink.h" + +#define VALUE_NULL 0 +#define VALUE_INTEGER 1 +#define VALUE_FLOAT 2 +#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