diff --git a/.cache/clangd/index/p_buffer.h.9A92E5E417D76D1D.idx b/.cache/clangd/index/p_buffer.h.9A92E5E417D76D1D.idx new file mode 100644 index 0000000..89b71f8 Binary files /dev/null and b/.cache/clangd/index/p_buffer.h.9A92E5E417D76D1D.idx differ diff --git a/.cache/clangd/index/p_queue.h.8C2CF32F4831B384.idx b/.cache/clangd/index/p_queue.h.8C2CF32F4831B384.idx new file mode 100644 index 0000000..871723e Binary files /dev/null and b/.cache/clangd/index/p_queue.h.8C2CF32F4831B384.idx differ diff --git a/.cache/clangd/index/p_queue_example.c.43EE21D32765822A.idx b/.cache/clangd/index/p_queue_example.c.43EE21D32765822A.idx new file mode 100644 index 0000000..f8f1c76 Binary files /dev/null and b/.cache/clangd/index/p_queue_example.c.43EE21D32765822A.idx differ diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..311ee05 --- /dev/null +++ b/.clang-format @@ -0,0 +1,178 @@ +--- +Language: Cpp +# BasedOnStyle: Microsoft +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +#DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Always +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/.dir-locals.el b/.dir-locals.el deleted file mode 100644 index 33388b3..0000000 --- a/.dir-locals.el +++ /dev/null @@ -1,6 +0,0 @@ -((c-mode . ((lsp-clients-clangd-args . ("--compile-commands-dir=build/" - "--pch-storage=memory" - "--background-index" - "-j=4" - )) - ))) diff --git a/CircularBuffer/p_cbuffer.c b/CircularBuffer/p_cbuffer.c deleted file mode 100644 index b7b6b31..0000000 --- a/CircularBuffer/p_cbuffer.c +++ /dev/null @@ -1,77 +0,0 @@ -#include - -// Error handler used for debugging only - -// Circular Buffer Prototypes -- Double -static PB_CB_STATUS p_cb_double_push(p_cb_double *cbuffer, double value); -static PB_CB_STATUS p_cb_double_empty(p_cb_double *cbuffer); - -// Circular Buffer Definitions -- double -PB_CB_STATUS p_cb_double_init(p_cb_double *circ_buffer, double *buff, uint32_t max_length) -{ - PB_CB_STATUS ret = PB_CB_GOOD; - do - { - // Make sure the buffer isn't bad (null) - if (!buff) - { - ret = PB_CB_NULL_BUFFER; - break; - } - - // Make sure the max buffer is a useable size - if (max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) - { - ret = PB_CB_BAD_BUFFER_SIZE; - break; - } - circ_buffer->buffer = buff; - circ_buffer->max_len = (uint16_t)max_length; - circ_buffer->head = 0; - circ_buffer->push = p_cb_double_push; - circ_buffer->empty = p_cb_double_empty; - circ_buffer->empty(circ_buffer); - } while (0); - - return ret; -} - -PB_CB_STATUS p_cb_double_push(p_cb_double *cbuffer, double value) -{ - PB_CB_STATUS ret = PB_CB_GOOD; - - if (!cbuffer) - { - ret = PB_CB_NULL_CBUFFER; - } - else - { - cbuffer->buffer[cbuffer->head] = value; - cbuffer->head = (cbuffer->head + 1) % cbuffer->max_len; - } - - return ret; -} -PB_CB_STATUS p_cb_double_empty(p_cb_double *cbuffer) -{ - PB_CB_STATUS ret = PB_CB_GOOD; - do - { - if (!cbuffer) - { - ret = PB_CB_NULL_CBUFFER; - break; - } - - if (!cbuffer->buffer) - { - ret = PB_CB_NULL_BUFFER; - break; - } - memset(cbuffer->buffer, 0, sizeof(double) * cbuffer->max_len); - cbuffer->head = 0; - cbuffer->b_empty = true; - cbuffer->b_filled = false; - } while (0); - return ret; -} diff --git a/CircularBuffer/p_cbuffer.h b/CircularBuffer/p_cbuffer.h deleted file mode 100644 index 41ba807..0000000 --- a/CircularBuffer/p_cbuffer.h +++ /dev/null @@ -1,64 +0,0 @@ -// Resource/Inspiration: https://embedjournal.com/implementing-circular-buffer-embedded-c/ - -/* - Penguin's Circular Buffer -- a simple floating queue designed for low memory usage (mainly for embedded) - - This is a ring buffer with limited capabilities. It is meant as a container for moving data. - Normally included features such as checks to see if the buffer is full or empty have been omitted - because this type of buffer is being implemented mainly for sensor data usage. Data is almost never read - individually, and even if it is, it isn't meant to be cleared on read. It is a simple moving buffer that - automatically writes over old data for the purpose of keeping track of the most up to date data. - - Notes: - - Initialization is mandatory using p_cb__init. - - If a circular buffer is not initialized, you will run into a LOT of hard-to-debug problems. Just initialize it. - - By default, all cb types should be defined as disabled. This is to save on size. Enable the ones you want to use. - - Behavior: - - Oldest data is overwritten - - popping of data isn't implemented. If this feature is required, use a ring buffer. - - Acronyms: - - p: penguin - - pb: penguin buffer - - cb: circular buffer - - uX, where X is bit size: unsigned X bit integer - - iX, where X is bit size: signed X bit integer -*/ - -#ifndef _PCIRCULARBUFFER_H_ -#define _PCIRCULARBUFFER_H_ - -#include -#include - -typedef enum PB_CB_STATUS -{ - PB_CB_GOOD = 0, - PB_CB_BAD = 1, - PB_CB_BAD_BUFFER_SIZE = 2, - PB_CB_NULL_BUFFER = 3, - PB_CB_NULL_CBUFFER = 4 -} PB_CB_STATUS; - -#if PB_CB_DOUBLE -typedef struct p_cb_double -{ - double *buffer; - uint16_t head; - uint16_t max_len; - // Signifies the buffer being filled at least once. - // Useful for initializing sensor data - bool b_filled; - // Signifies the buffer being empty - // Useful for knowing if data is being received - bool b_empty; - - PB_CB_STATUS (*push)(struct p_cb_double *cbuffer, double value); - PB_CB_STATUS (*empty)(struct p_cb_double *cbuffer); -} p_cb_double; - -PB_CB_STATUS p_cb_double_init(p_cb_double *circ_buffer, double *buff, uint32_t max_length); -#endif - -#endif diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..272ffd6 --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +CC=gcc + +CFLAGS=\ +-Wall \ +-std=gnu11 \ + +ifdef $(DEBUG) + CFLAGS+=\ + -DDEBUG\ + -ffunctions-sections\ + -O3\ + -g3 +endif + + +MK_DIR=mkdir -p + +.PHONY: clean examples tests + +all: examples + +clean: + rm -rf bin + + +examples: clean + $(MK_DIR) bin/ + $(CC) $(CFLAGS) -I. ./examples/p_queue_example.c -o ./bin/p_queue_example + $(CC) $(CFLAGS) -I. ./examples/p_cbuffer_example.c -o ./bin/p_cbuffer_example + + + diff --git a/bin/p_cbuffer_example b/bin/p_cbuffer_example new file mode 100644 index 0000000..cb6fcaa Binary files /dev/null and b/bin/p_cbuffer_example differ diff --git a/bin/p_queue_example b/bin/p_queue_example new file mode 100644 index 0000000..aaffed6 Binary files /dev/null and b/bin/p_queue_example differ diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..7872854 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,16 @@ +[ + { + "arguments": [ + "gcc", + "-c", + "-Wall", + "-std=gnu11", + "-I.", + "-o", + "./bin/p_queue_example", + "examples/p_queue_example.c" + ], + "directory": "/storage/Shared/Projects/PenguinBuffers", + "file": "examples/p_queue_example.c" + } +] \ No newline at end of file diff --git a/examples/p_cbuffer_example.c b/examples/p_cbuffer_example.c new file mode 100644 index 0000000..b480145 --- /dev/null +++ b/examples/p_cbuffer_example.c @@ -0,0 +1,90 @@ +/* + (WORK IN PROGRESS) + Penguin's Circular Buffer Example -- Turning a noisy bell curve into a less + noisy bell curve + + Here's an example of using the circular buffer library for sensor data: + + Let's say I have a sensor that gives me temperature at 1khz (using ideals so + it is exactly 1khz) If this sensor was only giving me raw analog data, I + might want to do some processing on these values so that I can make sure the + values are as clean as possible. The more samples we have, the closer we are + to the actual value. The faster we gather samples, the closer we get to + representing our data in realtime. + + Using the sample rate, I can decide on a sampling window (in seconds) and an + OSR (Oversampling Rate). The larger the buffer size, the more memory I need, + so it is useful to find a happy medium between a large buffer and clean + values. + + A sampling window is the window of time in which we can accept values for an + average value. Depending on your application, a sampling window may need to + be extremely small or maybe not so small. A rocket going extremely fast using + some sensor for real time controls will want an extremely small sampling + window as well as a lot of measurements for both clean, near noiseless data + and as close to realtime data as possible. + + The sampling windows is usually an engineering requirement given that can + match the sampling rate of the sensor with the following: sampling window (in + seconds) = 1 / frequency Here, the OSR is simply 1. + + So at 1khz sample rate, let's say I decide I only need a 0.125 second sample + window and I want to clean up some noisy data. We can now use this equation: + OSR = frequency * sample window (in seconds) + + All of these have ignored real world slowdowns like the time it takes to do + math on lower end hardware, interrupts slightly delaying the math, etc + Without wanting to do some hard analysis on whatever hardware we're using, I + usually take my frequency and half it to ensure timing requirements are met, + like so: + + OSR = frequency / 2 * sample window + + Please note: In applications that require real real-time data, this is not a + good way of doing things. + +*/ + +#include "p_cbuffer.h" + +DEFINE_CBUFFER(int); +#define CBUFFER_SIZE (6) + +void display(cbuffer_int_t* cbuffer) +{ + printf("Cbuffer:\n"); + for (int ind = 0; ind < cbuffer->msize; ind++) + { + printf("[%d]: %d\n", ind, cbuffer->buffer[ind]); + } + printf("\n"); +} + +int main(int argc, char** argv) +{ + cbuffer_int_t cbuffer; + int data[CBUFFER_SIZE]; + + cbuffer_int_init(&cbuffer, data, CBUFFER_SIZE); + cbuffer.push(&cbuffer, 1); + cbuffer.push(&cbuffer, 2); + cbuffer.push(&cbuffer, 3); + cbuffer.push(&cbuffer, 4); + cbuffer.push(&cbuffer, 5); + printf("Is cbuffer filled? %s\n", + cbuffer.is_filled(&cbuffer) ? "Yes" : "No"); + cbuffer.push(&cbuffer, 6); + printf("Is cbuffer filled? %s\n", + cbuffer.is_filled(&cbuffer) ? "Yes" : "No"); + display(&cbuffer); + cbuffer.push(&cbuffer, 7); + display(&cbuffer); + printf("Emptying cbuffer...\n"); + printf("Is cbuffer filled? %s\n", + cbuffer.is_filled(&cbuffer) ? "Yes" : "No"); + cbuffer.empty(&cbuffer); + cbuffer.push(&cbuffer, 8); + display(&cbuffer); + printf("Is cbuffer filled? %s\n", + cbuffer.is_filled(&cbuffer) ? "Yes" : "No"); +} diff --git a/Queue/queue.c b/examples/p_queue_example.c similarity index 83% rename from Queue/queue.c rename to examples/p_queue_example.c index d7c4791..9c547a7 100644 --- a/Queue/queue.c +++ b/examples/p_queue_example.c @@ -1,8 +1,11 @@ -#include "queue.h" +#include "p_queue.h" -QUEUE(int, 4); +DEFINE_QUEUE(int); + +#define SIZE_QUEUE (256) queue_int_t queue; +int buffer[SIZE_QUEUE]; void display(queue_int_t* queue) { @@ -24,7 +27,7 @@ void display(queue_int_t* queue) int main(int argv, char** argc) { - queue_int_init(&queue); + queue_int_init(&queue, buffer, SIZE_QUEUE); // queue.enqueue(&queue, 10); queue.empty(&queue); diff --git a/CircularBuffer/build/Makefile b/old_cbuffer_Makefile similarity index 100% rename from CircularBuffer/build/Makefile rename to old_cbuffer_Makefile diff --git a/p_buffer.h b/p_buffer.h new file mode 100644 index 0000000..592ca58 --- /dev/null +++ b/p_buffer.h @@ -0,0 +1,22 @@ +#ifndef __PBUFFER_H__ +#define __PBUFFER_H__ + +#define MAX_QUEUE_SIZE (512) +#define MAX_CBUFFER_SIZE (512) + +#include +#include +#include + +typedef enum PB_STATUS +{ + PB_GOOD = 0, + PB_BAD = 1, + PB_BAD_BUFFER_SIZE = 2, + PB_NULL_BUFFER = 3, + PB_NULL_DATA = 4, + PB_EMPTY_QUEUE = 5, + PB_FULL_QUEUE = 6 +} PB_STATUS; + +#endif diff --git a/p_cbuffer.h b/p_cbuffer.h new file mode 100644 index 0000000..7b0afed --- /dev/null +++ b/p_cbuffer.h @@ -0,0 +1,133 @@ +// Resource/Inspiration: +// https://embedjournal.com/implementing-circular-buffer-embedded-c/ + +/* + Penguin's Circular Buffer -- a simple floating queue designed for low memory + usage (mainly for embedded) + + This is a ring buffer with limited capabilities. It is meant as a container + for moving data. Normally included features such as checks to see if the + buffer is full or empty have been omitted because this type of buffer is + being implemented mainly for sensor data usage. Data is almost never read + individually, and even if it is, it isn't meant to be cleared on read. It is + a simple moving buffer that automatically writes over old data for the + purpose of keeping track of the most up to date data. + + Notes: + - Initialization is mandatory using p_cb__init. + - If a circular buffer is not initialized, you will run into a LOT of + hard-to-debug problems. Just initialize it. + - By default, all cb types should be defined as disabled. This is to save + on size. Enable the ones you want to use. + + Behavior: + - Oldest data is overwritten + - popping of data isn't implemented. If this feature is required, use a + ring buffer. + + Acronyms: + - p: penguin + - pb: penguin buffer + - cb: circular buffer + - uX, where X is bit size: unsigned X bit integer + - iX, where X is bit size: signed X bit integer +*/ + +#ifndef _PCIRCULARBUFFER_H_ +#define _PCIRCULARBUFFER_H_ + +#include "p_buffer.h" + +#define DEFINE_CBUFFER(type) \ + typedef struct cbuffer_##type##_t \ + { \ + type* buffer; \ + int head; \ + int csize; \ + int msize; \ + \ + PB_STATUS (*push)(struct cbuffer_##type##_t * cbuffer, type value); \ + PB_STATUS (*empty)(struct cbuffer_##type##_t * cbuffer); \ + PB_STATUS (*is_filled)(struct cbuffer_##type##_t * cbuffer); \ + } cbuffer_##type##_t; \ + \ + PB_STATUS cbuffer_##type##_is_filled(cbuffer_##type##_t* cbuffer) \ + { \ + return (cbuffer->csize == cbuffer->msize); \ + } \ + \ + PB_STATUS cbuffer_##type##_push(cbuffer_##type##_t* cbuffer, type value) \ + { \ + PB_STATUS ret = PB_GOOD; \ + \ + if (!cbuffer) \ + { \ + ret = PB_NULL_BUFFER; \ + } \ + else \ + { \ + cbuffer->csize = \ + (cbuffer->csize >= cbuffer->msize ? cbuffer->msize \ + : cbuffer->csize + 1); \ + cbuffer->buffer[cbuffer->head] = value; \ + cbuffer->head = (cbuffer->head + 1) % cbuffer->msize; \ + } \ + \ + return ret; \ + } \ + PB_STATUS cbuffer_##type##_empty(cbuffer_##type##_t* cbuffer) \ + { \ + PB_STATUS ret = PB_GOOD; \ + do \ + { \ + if (!cbuffer) \ + { \ + ret = PB_NULL_BUFFER; \ + break; \ + } \ + \ + if (!cbuffer->buffer) \ + { \ + ret = PB_NULL_DATA; \ + break; \ + } \ + memset(cbuffer->buffer, 0, sizeof(type) * cbuffer->msize); \ + cbuffer->head = 0; \ + cbuffer->csize = 0; \ + } while (0); \ + return ret; \ + } \ + \ + PB_STATUS cbuffer_##type##_init(cbuffer_##type##_t* circ_buffer, \ + type* buff, int total_length) \ + { \ + PB_STATUS ret = PB_GOOD; \ + do \ + { \ + if (!buff) \ + { \ + ret = PB_NULL_DATA; \ + break; \ + } \ + \ + if (total_length > MAX_CBUFFER_SIZE || total_length <= 0) \ + { \ + ret = PB_BAD_BUFFER_SIZE; \ + break; \ + } \ + memset(circ_buffer, 0, sizeof(cbuffer_##type##_t)); \ + memset(buff, 0, sizeof(type) * total_length); \ + circ_buffer->buffer = buff; \ + circ_buffer->msize = total_length; \ + circ_buffer->csize = 0; \ + circ_buffer->head = 0; \ + circ_buffer->push = cbuffer_##type##_push; \ + circ_buffer->empty = cbuffer_##type##_empty; \ + circ_buffer->is_filled = cbuffer_##type##_is_filled; \ + circ_buffer->empty(circ_buffer); \ + } while (0); \ + \ + return ret; \ + } + +#endif diff --git a/Queue/queue.h b/p_queue.h similarity index 89% rename from Queue/queue.h rename to p_queue.h index 4976972..b726a3a 100644 --- a/Queue/queue.h +++ b/p_queue.h @@ -1,31 +1,16 @@ #ifndef __QUEUE_H__ #define __QUEUE_H__ -#include -#include -#include - -#define MAX_QUEUE_SIZE (512) - -typedef enum PB_STATUS -{ - PB_GOOD = 0, - PB_BAD = 1, - PB_BAD_BUFFER_SIZE = 2, - PB_NULL_BUFFER = 3, - PB_NULL_DATA = 4, - PB_EMPTY_QUEUE = 5, - PB_FULL_QUEUE = 6 -} PB_STATUS; +#include "p_buffer.h" // This macro defines a queue type. It doesn't make a queue for you. // See below for an example on how to make a queue. // Creates a type of queue_${type}_t of size ${size}. // the size will be fixed for all instances of that type unfortunately. -#define QUEUE(type, size) \ +#define DEFINE_QUEUE(type) \ typedef struct queue_##type##_t \ { \ - int data[size]; \ + type* data; \ int head; \ int tail; \ int msize; \ @@ -88,7 +73,8 @@ typedef enum PB_STATUS } \ return ret; \ } \ - PB_STATUS queue_##type##_init(queue_##type##_t* queue) \ + PB_STATUS queue_##type##_init(queue_##type##_t* queue, type* buffer, \ + int total_length) \ { \ PB_STATUS ret = PB_GOOD; \ do \ @@ -99,13 +85,16 @@ typedef enum PB_STATUS break; \ } \ \ - if (size > MAX_QUEUE_SIZE || size <= 0) \ + if (total_length > MAX_QUEUE_SIZE || total_length <= 0) \ { \ ret = PB_BAD_BUFFER_SIZE; \ break; \ } \ } while (0); \ - queue->msize = size; \ + memset(queue, 0, sizeof(queue_##type##_t)); \ + memset(buffer, 0, sizeof(type) * total_length); \ + queue->data = buffer; \ + queue->msize = total_length; \ queue->head = -1; \ queue->tail = -1; \ queue->csize = 0; \ @@ -116,10 +105,15 @@ typedef enum PB_STATUS return ret; \ } -// Example: -// QUEUE(int, 4); -// queue_int_t queue; -// // in .c -// queue_int_init(&queue); +/* + Example: + DEFINE_QUEUE(int); + // in .c + queue_int_t queue; + const int SIZE_QUEUE = 256; + int buffer[SIZE_QUEUE]; + queue_int_init(&queue, buffer, SIZE_QUEUE); + queue_int_enqueue(&queue, 12); +*/ #endif diff --git a/p_queue_example b/p_queue_example new file mode 100644 index 0000000..aaffed6 Binary files /dev/null and b/p_queue_example differ