diff --git a/Spring-2023/CS-2124/Assignment-4/.clang-format b/Spring-2023/CS-2124/Assignment-4/.clang-format new file mode 100644 index 0000000..bf3583d --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/.clang-format @@ -0,0 +1,225 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: + Kind: Always + OverEmptyLines: 0 +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakAfterAttributes: Never +BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: 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 +IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock +IndentGotoLabels: true +IndentPPDirectives: None +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertNewlineAtEOF: false +InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +LineEnding: DeriveLF +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +PPIndentWidth: -1 +QualifierAlignment: Leave +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: LexicographicNumeric +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +... + diff --git a/Spring-2023/CS-2124/Assignment-4/.gitignore b/Spring-2023/CS-2124/Assignment-4/.gitignore new file mode 100644 index 0000000..0bea09f --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/.gitignore @@ -0,0 +1,8 @@ +bin +CMakeFiles +Makefile +CMakeCache.txt +cmake_install.cmake +README.pdf +*.tex +.tex-out diff --git a/Spring-2023/CS-2124/Assignment-4/Assignment.pdf b/Spring-2023/CS-2124/Assignment-4/Assignment.pdf new file mode 100644 index 0000000..7e1f043 Binary files /dev/null and b/Spring-2023/CS-2124/Assignment-4/Assignment.pdf differ diff --git a/Spring-2023/CS-2124/Assignment-4/CMakeLists.txt b/Spring-2023/CS-2124/Assignment-4/CMakeLists.txt new file mode 100644 index 0000000..7121d70 --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.25) + +set(SOURCES src/lib/vec.h src/lib/lib.h src/lib/lib.c) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin) + + +project(AssignmentFour LANGUAGES C) + +add_executable(AvlTree src/avl_tree.c ${SOURCES}) +add_executable(HuffHeap src/huffman_heap.c ${SOURCES}) diff --git a/Spring-2023/CS-2124/Assignment-4/README.org b/Spring-2023/CS-2124/Assignment-4/README.org new file mode 100644 index 0000000..7c1484b --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/README.org @@ -0,0 +1,58 @@ +* Assignment 4 + +- ABC123: =zfp106= +- Name: =Price Hiller= +- Course: =CS2124= +- Section: =0C3= +- Semester: =Spring 2024= + +** Source Code +The full source code for this project can be found at +[[https://git.orion-technologies.io/Price/college/src/branch/Development/Spring-2023/CS-2124/Assignment-4]] + +** Running the Programs +1. Install [[https://cmake.org/download/][cmake]] version 3.25 or greater. +2. Ensure you have a recent version of ~make~ at the time of writing. This project successfully + compiles with ~GNU make~ version ~4.4.1~. +3. Go the directory with ~CMakeLists.txt~ and run ~cmake .~ to generate a Makefile. +4. Run ~make all~ to compile all the programs. +5. Go into the newly created ~bin~ directory where all the compiled programs will be output to +6. Programs will be named ~PartOne~, ~PartTwo~, and ~PartThree~ + +** Questions/Prompts with Answers + +*** Part One: Avl Tree (3 points) +- Prompt + - Write a program that will have pre-defined input as numbers (~1,2,3,4,5~) + - Then the program will create a BST of the input and print that out + - Then the program will balance the BST and print out the AVL tree (pre-order) + + _Steps_: + - Create BST (0.5 points) + - Balance the tree (0.5 points) + _Output_: + - Print BST Pre-order (1 point) + - Print Balanced-AVL Pre-order (1 point) +- Output + [[./assets/PartOne/img1.png]] + +*** Part Two: Building Huffman Tree using Heap (2 Points) +- Prompt + - Write code to generate a Huffman Encoding (Variable Bit) using Heap. + - The characters and their frequency can be seen in the output screen shot and in the Tables 1 & 2 + - Despite the different variable bit coding (i.e. Table 1 & Table 2) the total bits are the same + - Include the Table for Total Bits in your PDF file with the output screenshot +- Output + - Table of total bits: + | Char | Code | Freq | Bits = Code * Freq | + |------------|------|------|--------------------| + | a | 100 | 5 | 15 | + | b | 101 | 9 | 27 | + | c | 00 | 12 | 24 | + | d | 01 | 13 | 26 | + | e | 11 | 16 | 32 | + |------------|------|------|--------------------| + | Total Bits | | | 124 | + |------------|------|------|--------------------| + - Screenshot of program running: + [[./assets/PartTwo/img1.png]] diff --git a/Spring-2023/CS-2124/Assignment-4/assets/PartOne/img1.png b/Spring-2023/CS-2124/Assignment-4/assets/PartOne/img1.png new file mode 100644 index 0000000..e627812 Binary files /dev/null and b/Spring-2023/CS-2124/Assignment-4/assets/PartOne/img1.png differ diff --git a/Spring-2023/CS-2124/Assignment-4/assets/PartTwo/img1.png b/Spring-2023/CS-2124/Assignment-4/assets/PartTwo/img1.png new file mode 100644 index 0000000..405e591 Binary files /dev/null and b/Spring-2023/CS-2124/Assignment-4/assets/PartTwo/img1.png differ diff --git a/Spring-2023/CS-2124/Assignment-4/src/avl_tree.c b/Spring-2023/CS-2124/Assignment-4/src/avl_tree.c new file mode 100644 index 0000000..5415486 --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/src/avl_tree.c @@ -0,0 +1,181 @@ +// ==== Intructions ==== +// • Write a program that will have pre defined input as numbers (1,2,3,4,5) +// • Then program will first create a BST of the input and print that out +// • Then the program will balance the BST and print out the AVL tree +// (pre-order) +// +// Steps +// • Create BST (0.5-point) +// • Balance the tree (i.e. AVL tree) (0.5-point) +// Output: +// • Print BST Pre-order (1-point) +// • Print Balanced-AVL Pre-order (1-point) + +#include +#include +#include + +int max(int a, int b) { + int max = (a > b) ? a : b; + return max; +} + +typedef struct BstNode { + int value; + int height; + int balance; + struct BstNode *left; + struct BstNode *right; +} BstNode; + +BstNode *bst_new(int value) { + BstNode *bst = (BstNode *)malloc(sizeof(BstNode)); + bst->value = value; + bst->height = 0; + bst->balance = 0; + bst->left = NULL; + bst->right = NULL; + + return bst; +} +void bst_print_preorder(BstNode *node) { + if (node == NULL) { + return; + } + + printf("%d, ", node->value); + bst_print_preorder(node->left); + bst_print_preorder(node->right); +} + +void bst_dbg(BstNode *node) { + bst_print_preorder(node); + printf("BstNode {\n value: %d,\n height: %d,\n balance: %d\n}\n", + node->value, node->height, node->balance); +} + +BstNode *bst_search(BstNode *node, int value) { + if (node == NULL) { + return NULL; + } + + if (node->value == value) { + return node; + } + + if (value < node->value) { + return bst_search(node->left, value); + } else { + return bst_search(node->right, value); + } +} + +bool bst_contains(BstNode *node, int value) { + return (bst_search(node, value) != NULL); +} + +int bst_height(BstNode *node) { + if (node == NULL) { + return -1; + } + + int left_height = bst_height(node->left); + int right_height = bst_height(node->right); + + return max(left_height, right_height) + 1; +} + +void bst_update(BstNode *node) { + int left_height = bst_height(node->left); + int right_height = bst_height(node->right); + node->height = max(left_height, right_height) + 1; + node->balance = left_height - right_height; +} + +BstNode *avl_right_rotate(BstNode *node) { + BstNode *left_child = node->left; + node->left = left_child->right; + left_child->right = node; + bst_update(node); + bst_update(left_child); + return node; +} + +BstNode *avl_left_rotate(BstNode *node) { + BstNode *right_child = node->right; + node->right = right_child->left; + right_child->left = node; + bst_update(node); + bst_update(right_child); + return right_child; +} + +/** + * @brief Balances a single node according to the AVL algorithm + * + * @param node The node to balance + * @return The balanced node + */ +BstNode *avl_balance_node(BstNode *node) { + if (node->balance == 2) { + if (node->left->balance >= 0) { + node = avl_right_rotate(node); + } else { + node = avl_left_rotate(node->left); + node = avl_right_rotate(node); + } + } else if (node->balance == -2) { + if (node->right->balance <= 0) { + node = avl_left_rotate(node); + } else { + node = avl_right_rotate(node->right); + node = avl_left_rotate(node); + } + } + + return node; +} + +/** + * @brief Insert a value into a Binary Search Tree in place + * + * @param node The given binary search tree to insert into + * @param value The value to insert + * @param balance Whether to balance the insertion with AVL + */ +void bst_insert(BstNode **node, int value, bool balance) { + if (*node == NULL) + *node = bst_new(value); + else if ((*node)->value == value) + // No duplicates allowed in our implementation + return; + else if ((*node)->value > value) + bst_insert(&(*node)->left, value, balance); + else + bst_insert(&(*node)->right, value, balance); + + bst_update(*node); + if (balance) + *node = avl_balance_node(*node); +} + +int main(int argc, char *argv[]) { + printf("Price Hiller, zfp106 (Spring 2024)\n"); + printf("==================================\n"); + printf("Unbalanced BST Pre-Order: "); + BstNode *bst = bst_new(1); + int input[] = {2, 3, 4, 5}; + for (int i = 0; i < sizeof(input)/sizeof(input[0]); i++) { + bst_insert(&bst, input[i], false); + } + bst_print_preorder(bst); + + printf("\nBalanced AVL Tree Pre-Order: "); + BstNode *avl = bst_new(1); + for (int i = 0; i < sizeof(input)/sizeof(input[0]); i++) { + bst_insert(&avl, input[i], true); + } + bst_print_preorder(avl); + printf("\n"); + return EXIT_SUCCESS; +} diff --git a/Spring-2023/CS-2124/Assignment-4/src/huffman_heap.c b/Spring-2023/CS-2124/Assignment-4/src/huffman_heap.c new file mode 100644 index 0000000..a735b05 --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/src/huffman_heap.c @@ -0,0 +1,100 @@ +#include "lib/vec.h" +#include +#include +#include + +typedef struct HuffCode { + char byte; + char *code; + int frequency; +} HuffCode; + +bool huffcode_cmp(HuffCode *first, HuffCode *second) { + int lendiff = strlen(first->code) - strlen(second->code); + if (lendiff == 0) { + int first_code = strtol(first->code, NULL, 2); + int second_code = strtol(second->code, NULL, 2); + return first_code >= second_code; + } else if (lendiff > 0) { + return true; + } else { + return false; + } +} + +DECL_VEC(HuffVec, HuffCode *); + +typedef struct MinHeap { + HuffVec *arr; +} MinHeap; + +int minheap_parent(int i) { return (i - 1) / 2; } + +int minheap_left_child(int i) { return (2 * i + 1); } + +int minheap_right_child(int i) { return (2 * i + 2); } + +HuffCode *minheap_get_min(MinHeap *heap) { return heap->arr->data[0]; } + +MinHeap *minheap_new(HuffVec *arr) { + MinHeap *minheap = (MinHeap *)malloc(sizeof(MinHeap)); + minheap->arr = arr; + return minheap; +} + +void minheap_swap(MinHeap *heap, int idx, int jdx) { + HuffCode *temp = heap->arr->data[idx]; + heap->arr->data[idx] = heap->arr->data[jdx]; + heap->arr->data[jdx] = temp; +} + +void *minheap_insert(MinHeap **_heap, HuffCode *value) { + MinHeap *heap = (*_heap); + int curr = heap->arr->elem_count - 1; + HuffVec_push(heap->arr, value); + while (curr > 0 && huffcode_cmp(heap->arr->data[minheap_parent(curr)], + heap->arr->data[curr])) { + minheap_swap(heap, minheap_parent(curr), curr); + curr = minheap_parent(curr); + } + return heap; +} + +void minheap_print(MinHeap *heap) { + for (int i = 0; i < heap->arr->elem_count; i++) { + HuffCode *huffcode = heap->arr->data[i]; + printf("%c: %s\n", huffcode->byte, huffcode->code); + } +} + +int main() { + printf("Price Hiller, zfp106 (Spring 2024)\n"); + printf("==================================\n"); + + HuffVec arr = HuffVec_new(2); + MinHeap *heap = minheap_new(&arr); + + char chars[] = {'a', 'b', 'c', 'd', 'e'}; + char *codes[] = {"100", "101", "00", "01", "11"}; + int frequencies[] = {5, 9, 12, 13, 16}; + + printf("Huffman Encoding (Variable Bit)\n"); + printf("Char | Freq\n"); + + HuffCode huffs[sizeof(frequencies) / sizeof(frequencies[0])] = {}; + // Two for loops like this to maintain ownership over the huffman codes + for (int i = 0; i < sizeof(frequencies) / sizeof(frequencies[0]); i++) { + HuffCode huff = { + .byte = chars[i], .code = codes[i], .frequency = frequencies[i]}; + huffs[i] = huff; + printf("%c | %d\n", huff.byte, huff.frequency); + } + printf("----------\n"); + + for (int i = 0; i < sizeof(frequencies) / sizeof(frequencies[0]); i++) { + heap = minheap_insert(&heap, &huffs[i]); + } + + minheap_print(heap); + return 0; +} diff --git a/Spring-2023/CS-2124/Assignment-4/src/lib/lib.c b/Spring-2023/CS-2124/Assignment-4/src/lib/lib.c new file mode 100644 index 0000000..34df0d8 --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/src/lib/lib.c @@ -0,0 +1,57 @@ +// Credit to +// https://stackoverflow.com/questions/40159892/using-asprintf-on-windows/49873938#49873938 +// with modifications by me + + +#include /* needed for va_* */ +#include /* needed for vsnprintf */ +#include /* needed for malloc, free */ + +#ifdef _MSC_VER +#include +#else +#include +#endif + +int vscprintf(const char *format, va_list ap) { + va_list ap_copy; + va_copy(ap_copy, ap); + int retval = vsnprintf(NULL, 0, format, ap_copy); + va_end(ap_copy); + return retval; +} + +/* + * asprintf, vasprintf: + * MSVC does not implement these, thus we implement them here + * GNU-C-compatible compilers implement these with the same names, thus we + * don't have to do anything + */ +int vasprintf(char **strp, const char *format, va_list ap) { + int len = vscprintf(format, ap); + if (len == -1) + return -1; + char *str = (char *)malloc((size_t)len + 1); + if (!str) + return -1; + int retval = vsnprintf(str, len + 1, format, ap); + if (retval == -1) { + free(str); + return -1; + } + *strp = str; + return retval; +} + +char* fmtstr(const char *format, ...) { + char *str = NULL; + va_list ap; + va_start(ap, format); + vasprintf(&str, format, ap); + va_end(ap); + return str; +} + +void print_header() { + printf("Price Hiller, zfp106 (Spring 2024)\n"); +} diff --git a/Spring-2023/CS-2124/Assignment-4/src/lib/lib.h b/Spring-2023/CS-2124/Assignment-4/src/lib/lib.h new file mode 100644 index 0000000..a87b90a --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/src/lib/lib.h @@ -0,0 +1,35 @@ +// Credit to +// https://stackoverflow.com/questions/40159892/using-asprintf-on-windows/49873938#49873938 +// with modifications by me + +#ifndef FMTSTR_H +#define FMTSTR_H + +#if defined(__GNUC__) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE /* needed for (v)asprintf, affects '#include ' */ +#endif + +#include /* needed for va_* */ + +/* + * vscprintf: + * MSVC implements this as _vscprintf, thus we just 'symlink' it here + * GNU-C-compatible compilers do not implement this, thus we implement it here + */ +#ifdef _MSC_VER +#define vscprintf _vscprintf +#endif + + +#ifdef _MSC_VER +int vasprintf(char **strp, const char *format, va_list ap); +#endif + +#ifdef __GNUC__ +int vscprintf(const char *format, va_list ap); +#endif + +char* fmtstr(const char *format, ...); +void print_header(); + +#endif diff --git a/Spring-2023/CS-2124/Assignment-4/src/lib/vec.h b/Spring-2023/CS-2124/Assignment-4/src/lib/vec.h new file mode 100644 index 0000000..5494383 --- /dev/null +++ b/Spring-2023/CS-2124/Assignment-4/src/lib/vec.h @@ -0,0 +1,79 @@ +#pragma once +#define VECTOR_LIB +#include +#include + +// This code is pretty bad in all honesty, but I *really* didn't want to play +// the void pointer game. +#define DECL_VEC(type_name, type) \ + typedef struct { \ + size_t elem_count; \ + size_t capacity; \ + type *data; \ + } type_name; \ + \ + type_name type_name##_new(size_t initial_capacity) { \ + initial_capacity = (initial_capacity < 1) ? 1 : initial_capacity; \ + type_name v = {.capacity = initial_capacity, \ + .elem_count = 0, \ + .data = malloc(sizeof(type *) * initial_capacity)}; \ + return v; \ + } \ + \ + bool type_name##_alloc(type_name *v, size_t extra_capacity) { \ + if (extra_capacity == 0) { \ + return false; \ + } \ + \ + int desired_size = v->capacity + extra_capacity; \ + type *newData = realloc(v->data, sizeof(type *) * desired_size); \ + if (newData == NULL) \ + return false; \ + v->data = newData; \ + v->capacity = desired_size; \ + return true; \ + } \ + \ + bool type_name##_ensure_capacity(type_name *v, size_t capacity) { \ + if (v->capacity < capacity) \ + return type_name##_alloc(v, capacity - v->capacity); \ + return true; \ + } \ + \ + void type_name##_push(type_name *v, type item) { \ + type_name##_ensure_capacity(v, v->elem_count + 1); \ + v->data[v->elem_count++] = item; \ + } \ + \ + type *type_name##_get(type_name *v, size_t index) { \ + if (index >= 0 && index < v->elem_count) \ + return &v->data[index]; \ + return NULL; \ + } \ + \ + void type_name##_del(type_name *v, size_t index) { \ + if (index >= 0 && index < v->elem_count) { \ + for (int i = index; (i < v->elem_count - 1); ++i) { \ + v->data[i] = v->data[i + 1]; \ + } \ + v->elem_count--; \ + } \ + } \ + \ + type type_name##_pop(type_name *v) { \ + type popped_value = *type_name##_get(v, v->elem_count - 1); \ + type_name##_del(v, v->elem_count - 1); \ + return popped_value; \ + } \ + \ + type type_name##_first(type_name *v) { \ + type found_value = *type_name##_get(v, 0); \ + type_name##_del(v, 0); \ + return found_value; \ + } \ + \ + type *type_name##_peek(type_name *v) { \ + return type_name##_get(v, v->elem_count - 1); \ + } \ + \ + void type_name##_free(type_name *v) { free(v->data); }