diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..b708ee9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,168 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: "^ IWYU pragma:" +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + - Regex: "^<.*" + Priority: 2 + SortPriority: 0 + - Regex: ".*" + Priority: 3 + SortPriority: 0 +IncludeIsMainRegex: "([-_](test|unittest))?$" +IncludeIsMainSourceRegex: "" +IndentCaseLabels: true +IndentGotoLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: "" +MacroBlockEnd: "" +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - "c++" + - "C++" + CanonicalDelimiter: "" + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: "" + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +--- + diff --git a/.travis.yml b/.travis.yml index 27957e5..ed234ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ addons: - llvm-dev - libclang-dev - clang + - valgrind before_script: - mkdir build @@ -23,3 +24,4 @@ script: - cmake --build build --config Debug --target all - cd build - ctest -C Debug -T test --output-on-failure + - ctest -C Debug -T memcheck --output-on-failure diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 0f0d740..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "platformio.platformio-ide" - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b4d8c35 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools" +} \ No newline at end of file diff --git a/ArduinoQueue.h b/ArduinoQueue.h index 95cfc22..47339c5 100644 --- a/ArduinoQueue.h +++ b/ArduinoQueue.h @@ -1,12 +1,12 @@ /* - Author: Einar Arnason - email: einsiarna@gmail.com + Author: Einar Arnason + email: einsiarna@gmail.com - A lightweight linked list type queue implementation, - meant for microcontrollers. + A lightweight linked list type queue implementation, + meant for microcontrollers. - Usage and further info: - https://github.com/EinarArnason/ArduinoQueue + Usage and further info: + https://github.com/EinarArnason/ArduinoQueue */ #pragma once @@ -17,173 +17,188 @@ #include "WProgram.h" #endif -template class ArduinoQueue { +template +class ArduinoQueue { class Node { - public: + public: T item; - Node *next; + Node* next; Node() { next = nullptr; } - ~Node() { next = nullptr; } }; - Node *_head; - Node *_tail; - unsigned int _max_items; - unsigned int _max_memory; - unsigned int _items_cnt; - -public: - ArduinoQueue(unsigned int max_items = 100, unsigned int max_memory = 0) { - _head = nullptr; - _tail = nullptr; - - /* - If the max memory has not - been defined or is 0, then - the queue size is set by - the max number of items: - */ - if (max_memory == 0) { - _max_items = max_items; - _max_memory = max_items * sizeof(T); - } - /* - If the max memory has been - set then the queue size is - defined by the memory size - when the max items is 0. - If the user gave a max item - size, then the queue size - will be capped by the number - of items. - */ - else { - _max_items = max_memory / sizeof(T); - _max_memory = _max_items * sizeof(T); - if (max_items != 0) { - if (_max_items > max_items) - _max_items = max_items; - } + Node* head; + Node* tail; + unsigned int maxItems; + unsigned int maxMemory; + unsigned int count; + + public: + ArduinoQueue(unsigned int maxItems = (unsigned int)-1, + unsigned int maxMemory = (unsigned int)-1) { + this->head = nullptr; + this->tail = nullptr; + this->count = 0; + this->maxMemory = maxMemory; + this->maxItems = maxMemory / sizeof(Node); + + if (maxItems != 0 && this->maxItems > maxItems) { + this->maxItems = maxItems; } - _items_cnt = 0; } ~ArduinoQueue() { - for (Node *node = _head; node != nullptr; node = _head) { - _head = node->next; + for (Node* node = head; node != nullptr; node = head) { + head = node->next; delete node; } } /* - Push an item to the queue. - Returns false if memory is - full, or true if the item - was added to queue. + Push an item to the queue. + Returns false if memory is + full, or true if the item + was added to queue. */ bool enqueue(T item) { - if (_items_cnt == _max_items) { + if (count == maxItems) { return false; } - Node *node = new Node; + + Node* node = new Node; if (node == nullptr) { return false; } node->item = item; - if (_head == nullptr) { - _head = node; - _tail = node; - _items_cnt++; + if (head == nullptr) { + head = node; + tail = node; + count++; + return true; } - _tail->next = node; - _tail = node; - _items_cnt++; + tail->next = node; + tail = node; + count++; + return true; } /* - Pop the front of the queue. - Because exceptions are not - usually implemented for - microcontrollers, if queue - is empty, a dummy item is - returned. + Pop the front of the queue. + Because exceptions are not + usually implemented for + microcontrollers, if queue + is empty, a dummy item is + returned. */ T dequeue() { - if ((_items_cnt == 0) || (_head == nullptr)) { + if ((count == 0) || (head == nullptr)) { return T(); } - Node *node = _head; - _head = node->next; + Node* node = head; + head = node->next; T item = node->item; delete node; node = nullptr; - if (_head == nullptr) { - _tail = nullptr; + if (head == nullptr) { + tail = nullptr; } - _items_cnt--; + count--; return item; } /* - Returns true if the queue - is empty, false otherwise. + Returns true if the queue + is empty, false otherwise. */ - bool isEmpty() { return _head == nullptr; } + bool isEmpty() { return head == nullptr; } /* - Returns true if the queue - is full, false otherwise. + Returns true if the queue + is full, false otherwise. */ - bool isFull() { return _items_cnt == _max_items; } + bool isFull() { return count == maxItems; } /* - Returns the number of items - currently in the queue. + Returns the number of items + currently in the queue. */ - unsigned int item_count() { return _items_cnt; } + unsigned int itemCount() { return count; } /* - Returns the size of the - queue item in bytes. + Returns the size of the + queue item in bytes. */ - unsigned int item_size() { return sizeof(T); } + unsigned int itemSize() { return sizeof(Node); } /* - Returns the size of the queue - (maximum number of items) + Returns the size of the queue + (maximum number of items) */ - unsigned int max_queue_size() { return _max_items; } + unsigned int maxQueueSize() { return maxItems; } /* - Returns the size of the queue - (maximum size in bytes) + Returns the size of the queue + (maximum size in bytes) */ - unsigned int max_memory_size() { return _max_memory; } + unsigned int maxMemorySize() { return maxMemory; } + + /* + Get the item in the front + of the queue. + Because exceptions are not + usually implemented for + microcontrollers, if queue + is empty, a dummy item is + returned. + */ + T getHead() { + if ((count == 0) || (head == nullptr)) { + return T(); + } + + T item = head->item; + return item; + } /* - Get the item in the front - of the queue. - Because exceptions are not - usually implemented for - microcontrollers, if queue - is empty, a dummy item is - returned. + Get the item in the back + of the queue. + Because exceptions are not + usually implemented for + microcontrollers, if queue + is empty, a dummy item is + returned. */ - T front() { - if ((_items_cnt == 0) || (_head == nullptr)) { + T getTail() { + if ((count == 0) || (head == nullptr)) { return T(); } - T item = _head->item; + + T item = tail->item; return item; } + + /* + Depricated functions + */ + + // Depricated, use getHead() instead + T front() { return getHead(); } + // Depricated, use itemCount() instead + unsigned int item_count() { return itemCount(); } + // Depricated, use itemSize() instead + unsigned int item_size() { return itemSize(); } + // Depricated, use maxQueueSize() instead + unsigned int max_queue_size() { return maxQueueSize(); } + // Depricated, use maxMemorySize() instead + unsigned int max_memory_size() { return maxMemorySize(); } }; diff --git a/CMakeLists.txt b/CMakeLists.txt index 94bb4d0..dbd6a76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0.0) -project(ArduinoQueue VERSION 1.2.0) +project(ArduinoQueue VERSION 1.2.2) include(CTest) enable_testing() diff --git a/README.md b/README.md index f18018e..c1211bb 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Finally use the following functions: intQueue.enqueue(1); // Adds number 1 to the queue intQueue.enqueue(123); // Adds number 123 to the queue int number = intQueue.dequeue(); // Will return number 1 and remove it from the queue -int number = intQueue.front(); // Will return number 123 but leave it still in the queue +int number = intQueue.head(); // Will return number 123 but leave it still in the queue int number = intQueue.dequeue(); // Will return number 123 and remove it from the queue ``` @@ -73,14 +73,14 @@ You can use also the following functions to get more queue properties: ```C++ bool state = intQueue.isEmpty(); // Returns true if the queue is empty, false otherwise bool state = intQueue.isFull(); // Returns true if the queue is full, false otherwise -unsigned int n = intQueue.item_count(); // Returns the number of items currently on the queue -unsigned int n = intQueue.item_size(); // Returns the size of the item being stored (bytes) -unsigned int n = intQueue.max_queue_size(); // Returns the maximum possible size of the queue (items)* -unsigned int n = intQueue.max_memory_size(); // Returns the maximum possible size of the queue (bytes)* +unsigned int n = intQueue.itemCount(); // Returns the number of items currently on the queue +unsigned int n = intQueue.itemSize(); // Returns the size of the item being stored (bytes) +unsigned int n = intQueue.maxQueueSize(); // Returns the maximum possible size of the queue (items)* +unsigned int n = intQueue.maxMemorySize(); // Returns the maximum possible size of the queue (bytes)* ``` ## Notes Note that while the Queue class cleans up the nodes in memory after destructor or dequeue is called, it keeps a copy of the item being queued. So for example if you are queuing pointers, you will need to keep track of the memory behind them. -*For example if you create a queue of *int* on an ESP8266, where each *int* has a size of 4 bytes and you specify the queue sizes to be up to 10 items and 10 bytes on the constructor, actually the real values will be 2 items and 8 bytes. These will be the values returned by *max_queue_size()* and *max_memory_size()\*. +*For example if you create a queue of *int* on an ESP8266, where each *int* has a size of 4 bytes and you specify the queue sizes to be up to 10 items and 10 bytes on the constructor, actually the real values will be 2 items and 8 bytes. These will be the values returned by *maxQueueSize()* and *maxMemorySize()\*. diff --git a/Testing/TAG b/Testing/TAG new file mode 100644 index 0000000..885e850 --- /dev/null +++ b/Testing/TAG @@ -0,0 +1,3 @@ +20200527-1234 +Experimental +Experimental diff --git a/examples/intQueueItemsSize/intQueueItemsSize.ino b/examples/intQueueItemsSize/intQueueItemsSize.ino index 38d5dfa..7a9179e 100644 --- a/examples/intQueueItemsSize/intQueueItemsSize.ino +++ b/examples/intQueueItemsSize/intQueueItemsSize.ino @@ -1,13 +1,13 @@ /* - Author: Vasco Baptista - email: vascojdb@gmail.com + Author: Vasco Baptista + email: vascojdb@gmail.com - An example of using Einar Arnason's queue - In this example we create a queue of int's - limited by the maximum amount of items - - Usage and further info: - https://github.com/EinarArnason/ArduinoQueue + An example of using Einar Arnason's queue + In this example we create a queue of int's + limited by the maximum amount of items + + Usage and further info: + https://github.com/EinarArnason/ArduinoQueue */ #include "Queue.h" @@ -18,56 +18,55 @@ ArduinoQueue intQueue(QUEUE_SIZE_ITEMS); void printQueueStats() { - Serial.println(""); - Serial.printf("Size of each element: %u bytes\r\n", intQueue.item_size()); - Serial.printf("Items in queue now: %u items\r\n", intQueue.item_count()); - Serial.printf("Queue actual max items: %u items\r\n", intQueue.max_queue_size()); - Serial.printf("Queue actual max memory: %u bytes\r\n", intQueue.max_memory_size()); - Serial.println(""); + Serial.println(""); + Serial.printf("Size of each element: %u bytes\r\n", intQueue.item_size()); + Serial.printf("Items in queue now: %u items\r\n", intQueue.item_count()); + Serial.printf("Queue actual max items: %u items\r\n", + intQueue.maxQueueSize()); + Serial.printf("Queue actual max memory: %u bytes\r\n", + intQueue.maxMemorySize()); + Serial.println(""); } void setup() { - Serial.begin(115200); - Serial.println(""); - Serial.println("========== Queue example =========="); - Serial.printf("Desired max item size: %u items\r\n", QUEUE_SIZE_ITEMS); - Serial.println("==================================="); + Serial.begin(115200); + Serial.println(""); + Serial.println("========== Queue example =========="); + Serial.printf("Desired max item size: %u items\r\n", QUEUE_SIZE_ITEMS); + Serial.println("==================================="); } void loop() { - printQueueStats(); - - // Add elements: (add more than the queue size for demo purposes) - for(int n=1; n intQueue(QUEUE_SIZE_ITEMS, QUEUE_SIZE_BYTES); void printQueueStats() { - Serial.println(""); - Serial.printf("Size of each element: %u bytes\r\n", intQueue.item_size()); - Serial.printf("Items in queue now: %u items\r\n", intQueue.item_count()); - Serial.printf("Queue actual max items: %u items\r\n", intQueue.max_queue_size()); - Serial.printf("Queue actual max memory: %u bytes\r\n", intQueue.max_memory_size()); - Serial.println(""); + Serial.println(""); + Serial.printf("Size of each element: %u bytes\r\n", intQueue.itemSize()); + Serial.printf("Items in queue now: %u items\r\n", intQueue.itemCount()); + Serial.printf("Queue actual max items: %u items\r\n", + intQueue.maxQueueSize()); + Serial.printf("Queue actual max memory: %u bytes\r\n", + intQueue.maxMemorySize()); + Serial.println(""); } void setup() { - Serial.begin(115200); - Serial.println(""); - Serial.println("========== Queue example =========="); - Serial.printf("Desired max item size: %u items\r\n", QUEUE_SIZE_ITEMS); - Serial.printf("Desired max queue size: %u bytes\r\n", QUEUE_SIZE_BYTES); - Serial.println("==================================="); + Serial.begin(115200); + Serial.println(""); + Serial.println("========== Queue example =========="); + Serial.printf("Desired max item size: %u items\r\n", QUEUE_SIZE_ITEMS); + Serial.printf("Desired max queue size: %u bytes\r\n", QUEUE_SIZE_BYTES); + Serial.println("==================================="); } void loop() { - printQueueStats(); - - // Add elements: (add more than the queue size for demo purposes) - for(int n=1; n maintainer=Einar Arnason sentence=Queue Library diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0600749..9667f95 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.11.0) -project(test_ArduinoQueue VERSION 1.2.0) +project(test_ArduinoQueue VERSION 1.2.2) include(FetchContent) diff --git a/test/test_IntQueue.cpp b/test/test_IntQueue.cpp index d2f1b23..8f9295b 100644 --- a/test/test_IntQueue.cpp +++ b/test/test_IntQueue.cpp @@ -2,6 +2,7 @@ #define CATCH_CONFIG_MAIN #include + #include TEST_CASE("Queue is empty", "[single-file]") { @@ -13,4 +14,19 @@ TEST_CASE("List has one element", "[single-file]") { ArduinoQueue ints; ints.enqueue(1); REQUIRE(ints.isEmpty() == false); +} + +TEST_CASE("Concistency with multiple items", "[single-file]") { + ArduinoQueue ints; + for (int i = 0; i < 1000; ++i) { + ints.enqueue(i); + } + + REQUIRE(ints.isEmpty() == false); + REQUIRE(ints.getHead() == 0); + REQUIRE(ints.getTail() == 999); + + for (int i = 0; i < 1000; i++) { + REQUIRE(ints.dequeue() == i); + } } \ No newline at end of file