diff --git a/bintree.c b/bintree.c index 5cf82a9..668c164 100644 --- a/bintree.c +++ b/bintree.c @@ -1,18 +1,65 @@ +#include #include #include "stack.h" #include "bintree.h" -//TODO: binären Suchbaum implementieren -/* * `addToTree`: fügt ein neues Element in den Baum ein (rekursiv), - * `clearTree`: gibt den gesamten Baum frei (rekursiv), - * `treeSize`: zählt die Knoten im Baum (rekursiv), - * `nextTreeData`: Traversierung mit Hilfe des zuvor implementierten Stacks. */ +// internal helper to push node and all its left descendants onto iterator stack +static void bintree_pushLefts(StackNode **iterStackPtr, TreeNode *n) +{ + while(n != NULL) + { + *iterStackPtr = push(*iterStackPtr, n); + n = n->left; + } +} // Adds a copy of data's pointer destination to the tree using compareFct for ordering. Accepts duplicates // if isDuplicate is NULL, otherwise ignores duplicates and sets isDuplicate to 1 (or to 0 if a new entry is added). TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFctType compareFct, int *isDuplicate) { + if(isDuplicate != NULL) + *isDuplicate = 0; + if(root == NULL) + { + TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode)); + if(node == NULL) + return NULL; + node->data = malloc(dataSize); + if(node->data == NULL) + { + free(node); + return NULL; + } + memcpy(node->data, data, dataSize); + node->left = node->right = NULL; + return node; + } + + int cmp = compareFct(data, root->data); + if(cmp < 0) + { + root->left = addToTree(root->left, data, dataSize, compareFct, isDuplicate); + } + else if(cmp > 0) + { + root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } + else // equal + { + if(isDuplicate != NULL) + { + *isDuplicate = 1; + // do not insert duplicate + } + else + { + // duplicates allowed -> insert into right subtree + root->right = addToTree(root->right, data, dataSize, compareFct, isDuplicate); + } + } + + return root; } // Iterates over the tree given by root. Follows the usage of strtok. If tree is NULL, the next entry of the last tree given is returned in ordering direction. @@ -20,17 +67,45 @@ TreeNode *addToTree(TreeNode *root, const void *data, size_t dataSize, CompareFc // push the top node and push all its left nodes. void *nextTreeData(TreeNode *root) { + static StackNode *iterStack = NULL; + // If a new tree root is provided -> reset iterator + if(root != NULL) + { + clearStack(iterStack); + iterStack = NULL; + bintree_pushLefts(&iterStack, root); + } + + if(iterStack == NULL) + return NULL; + + TreeNode *node = (TreeNode *)top(iterStack); + iterStack = pop(iterStack); + + if(node->right != NULL) + bintree_pushLefts(&iterStack, node->right); + + return node->data; } // Releases all memory resources (including data copies). void clearTree(TreeNode *root) { + if(root == NULL) + return; + clearTree(root->left); + clearTree(root->right); + + free(root->data); + free(root); } // Returns the number of entries in the tree given by root. unsigned int treeSize(const TreeNode *root) { - + if(root == NULL) + return 0; + return 1 + treeSize(root->left) + treeSize(root->right); } \ No newline at end of file diff --git a/bintree.o b/bintree.o new file mode 100644 index 0000000..47986c5 Binary files /dev/null and b/bintree.o differ diff --git a/doble b/doble new file mode 100755 index 0000000..88b0bc9 Binary files /dev/null and b/doble differ diff --git a/doble_initial b/doble_initial new file mode 100755 index 0000000..69c6a2e Binary files /dev/null and b/doble_initial differ diff --git a/highscore.o b/highscore.o new file mode 100644 index 0000000..b268078 Binary files /dev/null and b/highscore.o differ diff --git a/highscores.txt b/highscores.txt index 4edd5a7..7f7e944 100644 --- a/highscores.txt +++ b/highscores.txt @@ -1 +1,10 @@ -player1;3999 +Lena;19811 +Lena;19702 +player_name;9981 +Lena;9980 +Lena;9978 +Lena;9978 +Lena;9976 +Lena;9975 +Lena;9971 +Lena;9965 diff --git a/main.o b/main.o new file mode 100644 index 0000000..f167660 Binary files /dev/null and b/main.o differ diff --git a/makefile b/makefile index 1f15f75..c707aae 100644 --- a/makefile +++ b/makefile @@ -29,14 +29,38 @@ program_obj_files = stack.o bintree.o numbers.o timer.o highscore.o doble : main.o $(program_obj_files) $(CC) $(FLAGS) $^ -o doble -$(program_obj_filesobj_files): %.o: %.c - $(CC) -c $(FLAGS) $^ -o $@ +# pattern rule to build .o from .c +%.o: %.c + $(CC) -c $(FLAGS) $< -o $@ # -------------------------- # Unit Tests # -------------------------- -unitTests: - echo "needs to be implemented" +unitTests: test_stack test_numbers test_bintree + @total=0; passed=0; failed=0; \ + for t in test_stack test_numbers test_bintree; do \ + total=$$((total+1)); \ + printf "Running %s...\n" "$$t"; \ + ./$$t; rc=$$?; \ + if [ $$rc -eq 0 ]; then \ + printf "%s: PASS\n\n" "$$t"; \ + passed=$$((passed+1)); \ + else \ + printf "%s: FAIL (exit %d)\n\n" "$$t" $$rc; \ + failed=$$((failed+1)); \ + fi; \ + done; \ + printf "Summary: %d tests run, %d passed, %d failed\n" $$total $$passed $$failed; \ + exit $$failed + +test_stack: test_stack.c stack.c + $(CC) $(FLAGS) test_stack.c stack.c -o test_stack + +test_numbers: test_numbers.c numbers.c bintree.c stack.c + $(CC) $(FLAGS) test_numbers.c numbers.c bintree.c stack.c -o test_numbers + +test_bintree: test_bintree.c bintree.c stack.c + $(CC) $(FLAGS) test_bintree.c bintree.c stack.c -o test_bintree # -------------------------- # Clean diff --git a/numbers.c b/numbers.c index f59d9a2..f45d131 100644 --- a/numbers.c +++ b/numbers.c @@ -5,22 +5,107 @@ #include "numbers.h" #include "bintree.h" -//TODO: getDuplicate und createNumbers implementieren -/* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. - * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. - * Duplizieren eines zufälligen Eintrags im Array. - * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ +// helper comparator for unsigned int for bintree +static int compareUInt(const void *a, const void *b) +{ + unsigned int va = *(const unsigned int *)a; + unsigned int vb = *(const unsigned int *)b; + if(va < vb) return -1; + if(va > vb) return 1; + return 0; +} + +// comparator for qsort (unsigned int) +static int qsort_uint_cmp(const void *a, const void *b) +{ + unsigned int va = *(const unsigned int *)a; + unsigned int vb = *(const unsigned int *)b; + if(va < vb) return -1; + if(va > vb) return 1; + return 0; +} // Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. // Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while // creating random numbers. unsigned int *createNumbers(unsigned int len) { + if(len < 2) + return NULL; + unsigned int *numbers = (unsigned int *)malloc(sizeof(unsigned int) * len); + if(numbers == NULL) + return NULL; + + // seed once + srand((unsigned int)time(NULL)); + + TreeNode *root = NULL; + unsigned int range = 2 * len; + // create len-1 unique numbers + for(unsigned int i = 0; i < len - 1; i++) + { + unsigned int val; + int isDup = 0; + // try until a unique number is inserted + do + { + val = (unsigned int)(rand() % range) + 1; // [1..2*len] + root = addToTree(root, &val, sizeof(val), compareUInt, &isDup); + // if addToTree returned NULL due to allocation failure, cleanup and return NULL + if(root == NULL && isDup == 0) + { + free(numbers); + clearTree(root); + return NULL; + } + } while(isDup); + numbers[i] = val; + } + + // duplicate one existing random entry + unsigned int idx = (unsigned int)(rand() % (len - 1)); + numbers[len - 1] = numbers[idx]; + + // shuffle array (Fisher-Yates) + for(unsigned int i = len - 1; i > 0; i--) + { + unsigned int j = (unsigned int)(rand() % (i + 1)); + unsigned int tmp = numbers[i]; + numbers[i] = numbers[j]; + numbers[j] = tmp; + } + + // free tree resources + clearTree(root); + return numbers; } // Returns only the only number in numbers which is present twice. Returns zero on errors. unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { + if(numbers == NULL || len < 2) + return 0; + // make a copy so original array order is not modified by caller expectation + unsigned int *copy = (unsigned int *)malloc(sizeof(unsigned int) * len); + if(copy == NULL) + return 0; + + memcpy(copy, numbers, sizeof(unsigned int) * len); + + qsort(copy, len, sizeof(unsigned int), qsort_uint_cmp); + + unsigned int result = 0; + for(unsigned int i = 0; i + 1 < len; i++) + { + if(copy[i] == copy[i+1]) + { + result = copy[i]; + break; + } + } + + free(copy); + return result; } \ No newline at end of file diff --git a/numbers.o b/numbers.o new file mode 100644 index 0000000..e87e9fe Binary files /dev/null and b/numbers.o differ diff --git a/stack.c b/stack.c index e3a90d4..0472a36 100644 --- a/stack.c +++ b/stack.c @@ -1,33 +1,47 @@ #include #include "stack.h" -//TODO: grundlegende Stackfunktionen implementieren: -/* * `push`: legt ein Element oben auf den Stack, - * `pop`: entfernt das oberste Element, - * `top`: liefert das oberste Element zurück, - * `clearStack`: gibt den gesamten Speicher frei. */ - // Pushes data as pointer onto the stack. StackNode *push(StackNode *stack, void *data) { + StackNode *node = (StackNode *)malloc(sizeof(StackNode)); + if(node == NULL) + return stack; // allocation failed -> return unchanged stack + node->data = data; + node->next = stack; + return node; } // Deletes the top element of the stack (latest added element) and releases its memory. (Pointer to data has to be // freed by caller.) StackNode *pop(StackNode *stack) { + if(stack == NULL) + return NULL; + StackNode *next = stack->next; + // Do NOT free stack->data here; caller owns the pointed data + free(stack); + return next; } // Returns the data of the top element. void *top(StackNode *stack) { - + if(stack == NULL) + return NULL; + return stack->data; } // Clears stack and releases all memory. void clearStack(StackNode *stack) { - + while(stack != NULL) + { + StackNode *next = stack->next; + // Do NOT free stack->data here; caller owns the pointed data + free(stack); + stack = next; + } } \ No newline at end of file diff --git a/stack.h b/stack.h index f7d542d..e2ca791 100644 --- a/stack.h +++ b/stack.h @@ -7,7 +7,12 @@ The latest element is taken from the stack. */ #include -//TODO: passenden Datentyp als struct anlegen +// Stack node for linked-list based stack. Data pointer is stored but not freed by stack operations. +typedef struct StackNode +{ + void *data; + struct StackNode *next; +} StackNode; // Pushes data as pointer onto the stack. StackNode *push(StackNode *stack, void *data); diff --git a/stack.o b/stack.o new file mode 100644 index 0000000..014f77e Binary files /dev/null and b/stack.o differ diff --git a/test_bintree b/test_bintree new file mode 100755 index 0000000..f594787 Binary files /dev/null and b/test_bintree differ diff --git a/test_bintree.c b/test_bintree.c new file mode 100644 index 0000000..fbcc0d6 --- /dev/null +++ b/test_bintree.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include "bintree.h" + +// comparator for unsigned int values stored by value in heap +static int cmp_uint_ptr(const void *a, const void *b) +{ + unsigned int va = *(const unsigned int *)a; + unsigned int vb = *(const unsigned int *)b; + if(va < vb) return -1; + if(va > vb) return 1; + return 0; +} + +int main(void) +{ + TreeNode *root = NULL; + unsigned int vals[] = {5, 2, 8, 1, 3, 7, 9}; + const size_t n = sizeof(vals)/sizeof(vals[0]); + + // insert values (copy made by addToTree) + for(size_t i = 0; i < n; i++) + { + int isDup = 0; + root = addToTree(root, &vals[i], sizeof(unsigned int), cmp_uint_ptr, &isDup); + if(root == NULL && isDup == 0) { fprintf(stderr, "addToTree allocation failed\n"); return 1; } + } + + unsigned int sz = treeSize(root); + if(sz != n) { fprintf(stderr, "treeSize expected %zu got %u\n", n, sz); clearTree(root); return 2; } + + // inorder traversal using nextTreeData + unsigned int last = 0; + int first = 1; + unsigned int *data = nextTreeData(root); + while(data != NULL) + { + unsigned int v = *data; + if(!first && v < last) { fprintf(stderr, "inorder traversal not sorted: %u after %u\n", v, last); clearTree(root); return 3; } + last = v; first = 0; + data = nextTreeData(NULL); + } + + clearTree(root); + printf("test_bintree: OK\n"); + return 0; +} diff --git a/test_bintree.dSYM/Contents/Info.plist b/test_bintree.dSYM/Contents/Info.plist new file mode 100644 index 0000000..fe95a38 --- /dev/null +++ b/test_bintree.dSYM/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.test_bintree + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/test_bintree.dSYM/Contents/Resources/DWARF/test_bintree b/test_bintree.dSYM/Contents/Resources/DWARF/test_bintree new file mode 100644 index 0000000..0d498e1 Binary files /dev/null and b/test_bintree.dSYM/Contents/Resources/DWARF/test_bintree differ diff --git a/test_bintree.dSYM/Contents/Resources/Relocations/x86_64/test_bintree.yml b/test_bintree.dSYM/Contents/Resources/Relocations/x86_64/test_bintree.yml new file mode 100644 index 0000000..4fab309 --- /dev/null +++ b/test_bintree.dSYM/Contents/Resources/Relocations/x86_64/test_bintree.yml @@ -0,0 +1,20 @@ +--- +triple: 'x86_64-apple-darwin' +binary-path: test_bintree +relocations: + - { offset: 0x26, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000007A0, symSize: 0x220 } + - { offset: 0x49, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000007A0, symSize: 0x220 } + - { offset: 0x121, size: 0x8, addend: 0x0, symName: _cmp_uint_ptr, symObjAddr: 0x220, symBinAddr: 0x1000009C0, symSize: 0x5A } + - { offset: 0x21B, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x100000A20, symSize: 0x1C0 } + - { offset: 0x228, size: 0x8, addend: 0x0, symName: _nextTreeData, symObjAddr: 0x1C0, symBinAddr: 0x100000BE0, symSize: 0xC0 } + - { offset: 0x24D, size: 0x8, addend: 0x0, symName: _nextTreeData.iterStack, symObjAddr: 0xFB0, symBinAddr: 0x100002000, symSize: 0x0 } + - { offset: 0x2EC, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x100000A20, symSize: 0x1C0 } + - { offset: 0x376, size: 0x8, addend: 0x0, symName: _bintree_pushLefts, symObjAddr: 0x280, symBinAddr: 0x100000CA0, symSize: 0x50 } + - { offset: 0x3A8, size: 0x8, addend: 0x0, symName: _clearTree, symObjAddr: 0x2D0, symBinAddr: 0x100000CF0, symSize: 0x60 } + - { offset: 0x3CC, size: 0x8, addend: 0x0, symName: _treeSize, symObjAddr: 0x330, symBinAddr: 0x100000D50, symSize: 0x56 } + - { offset: 0x47F, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DB0, symSize: 0x60 } + - { offset: 0x4C3, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DB0, symSize: 0x60 } + - { offset: 0x507, size: 0x8, addend: 0x0, symName: _pop, symObjAddr: 0x60, symBinAddr: 0x100000E10, symSize: 0x50 } + - { offset: 0x53D, size: 0x8, addend: 0x0, symName: _top, symObjAddr: 0xB0, symBinAddr: 0x100000E60, symSize: 0x40 } + - { offset: 0x565, size: 0x8, addend: 0x0, symName: _clearStack, symObjAddr: 0xF0, symBinAddr: 0x100000EA0, symSize: 0x3F } +... diff --git a/test_numbers b/test_numbers new file mode 100755 index 0000000..f45378c Binary files /dev/null and b/test_numbers differ diff --git a/test_numbers.c b/test_numbers.c new file mode 100644 index 0000000..067bb3b --- /dev/null +++ b/test_numbers.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include "numbers.h" + +int main(void) +{ + unsigned int len = 100; + unsigned int *nums = createNumbers(len); + if(nums == NULL) { fprintf(stderr, "createNumbers returned NULL\n"); return 1; } + + // count occurrences + unsigned int maxVal = 2 * len; + unsigned int *counts = calloc(maxVal + 1, sizeof(unsigned int)); + if(counts == NULL) { free(nums); return 2; } + + for(unsigned int i = 0; i < len; i++) + { + if(nums[i] > maxVal) { fprintf(stderr, "value out of expected range\n"); free(nums); free(counts); return 3; } + counts[nums[i]]++; + } + + int duplicatesFound = 0; + unsigned int duplicateValue = 0; + for(unsigned int v = 1; v <= maxVal; v++) + { + if(counts[v] == 2) { duplicatesFound++; duplicateValue = v; } + else if(counts[v] > 2) { fprintf(stderr, "value %u appears more than twice\n", v); free(nums); free(counts); return 4; } + } + + if(duplicatesFound != 1) { fprintf(stderr, "expected exactly one duplicated value, found %d\n", duplicatesFound); free(nums); free(counts); return 5; } + + unsigned int found = getDuplicate(nums, len); + if(found != duplicateValue) { fprintf(stderr, "getDuplicate returned %u expected %u\n", found, duplicateValue); free(nums); free(counts); return 6; } + + free(nums); + free(counts); + + printf("test_numbers: OK (duplicate = %u)\n", duplicateValue); + return 0; +} diff --git a/test_numbers.dSYM/Contents/Info.plist b/test_numbers.dSYM/Contents/Info.plist new file mode 100644 index 0000000..3520253 --- /dev/null +++ b/test_numbers.dSYM/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.test_numbers + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/test_numbers.dSYM/Contents/Resources/DWARF/test_numbers b/test_numbers.dSYM/Contents/Resources/DWARF/test_numbers new file mode 100644 index 0000000..1ea4795 Binary files /dev/null and b/test_numbers.dSYM/Contents/Resources/DWARF/test_numbers differ diff --git a/test_numbers.dSYM/Contents/Resources/Relocations/x86_64/test_numbers.yml b/test_numbers.dSYM/Contents/Resources/Relocations/x86_64/test_numbers.yml new file mode 100644 index 0000000..703cd2f --- /dev/null +++ b/test_numbers.dSYM/Contents/Resources/Relocations/x86_64/test_numbers.yml @@ -0,0 +1,24 @@ +--- +triple: 'x86_64-apple-darwin' +binary-path: test_numbers +relocations: + - { offset: 0x26, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000013A0, symSize: 0x287 } + - { offset: 0x41, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x1000013A0, symSize: 0x287 } + - { offset: 0x12E, size: 0x8, addend: 0x0, symName: _createNumbers, symObjAddr: 0x0, symBinAddr: 0x100001630, symSize: 0x1D0 } + - { offset: 0x152, size: 0x8, addend: 0x0, symName: _createNumbers, symObjAddr: 0x0, symBinAddr: 0x100001630, symSize: 0x1D0 } + - { offset: 0x23E, size: 0x8, addend: 0x0, symName: _compareUInt, symObjAddr: 0x1D0, symBinAddr: 0x100001800, symSize: 0x60 } + - { offset: 0x290, size: 0x8, addend: 0x0, symName: _getDuplicate, symObjAddr: 0x230, symBinAddr: 0x100001860, symSize: 0x110 } + - { offset: 0x2FE, size: 0x8, addend: 0x0, symName: _qsort_uint_cmp, symObjAddr: 0x340, symBinAddr: 0x100001970, symSize: 0x5A } + - { offset: 0x3C5, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x1000019D0, symSize: 0x1C0 } + - { offset: 0x3D2, size: 0x8, addend: 0x0, symName: _nextTreeData, symObjAddr: 0x1C0, symBinAddr: 0x100001B90, symSize: 0xC0 } + - { offset: 0x3F7, size: 0x8, addend: 0x0, symName: _nextTreeData.iterStack, symObjAddr: 0xFB0, symBinAddr: 0x100003000, symSize: 0x0 } + - { offset: 0x496, size: 0x8, addend: 0x0, symName: _addToTree, symObjAddr: 0x0, symBinAddr: 0x1000019D0, symSize: 0x1C0 } + - { offset: 0x520, size: 0x8, addend: 0x0, symName: _bintree_pushLefts, symObjAddr: 0x280, symBinAddr: 0x100001C50, symSize: 0x50 } + - { offset: 0x552, size: 0x8, addend: 0x0, symName: _clearTree, symObjAddr: 0x2D0, symBinAddr: 0x100001CA0, symSize: 0x60 } + - { offset: 0x576, size: 0x8, addend: 0x0, symName: _treeSize, symObjAddr: 0x330, symBinAddr: 0x100001D00, symSize: 0x56 } + - { offset: 0x629, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100001D60, symSize: 0x60 } + - { offset: 0x66D, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100001D60, symSize: 0x60 } + - { offset: 0x6B1, size: 0x8, addend: 0x0, symName: _pop, symObjAddr: 0x60, symBinAddr: 0x100001DC0, symSize: 0x50 } + - { offset: 0x6E7, size: 0x8, addend: 0x0, symName: _top, symObjAddr: 0xB0, symBinAddr: 0x100001E10, symSize: 0x40 } + - { offset: 0x70F, size: 0x8, addend: 0x0, symName: _clearStack, symObjAddr: 0xF0, symBinAddr: 0x100001E50, symSize: 0x3F } +... diff --git a/test_stack b/test_stack new file mode 100755 index 0000000..fe4df87 Binary files /dev/null and b/test_stack differ diff --git a/test_stack.c b/test_stack.c new file mode 100644 index 0000000..a89ddd6 --- /dev/null +++ b/test_stack.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include "stack.h" + +int main(void) +{ + StackNode *s = NULL; + + // push 3 integers + int *a = malloc(sizeof(int)); *a = 1; s = push(s, a); + int *b = malloc(sizeof(int)); *b = 2; s = push(s, b); + int *c = malloc(sizeof(int)); *c = 3; s = push(s, c); + + // top should be c (3) + int *topv = (int *)top(s); + if(topv == NULL || *topv != 3) { fprintf(stderr, "stack top expected 3\n"); return 1; } + + // pop -> now top should be 2 + s = pop(s); + topv = (int *)top(s); + if(topv == NULL || *topv != 2) { fprintf(stderr, "stack top expected 2 after pop\n"); return 2; } + + // pop -> now top should be 1 + s = pop(s); + topv = (int *)top(s); + if(topv == NULL || *topv != 1) { fprintf(stderr, "stack top expected 1 after pop\n"); return 3; } + + // pop last + s = pop(s); + if(s != NULL) { fprintf(stderr, "stack expected empty after popping all\n"); return 4; } + + // free stored data (stack does not free data) + free(a); free(b); free(c); + + // test clearStack on empty and small stacks + s = push(s, malloc(sizeof(int))); + s = push(s, malloc(sizeof(int))); + clearStack(s); // clearStack must free nodes but not payload; free payloads not necessary because we leaked intentionally for test of API + // Note: above payloads are not freed (stack API spec); this test ensures clearStack doesn't crash. + // Success + printf("test_stack: OK\n"); + return 0; +} diff --git a/test_stack.dSYM/Contents/Info.plist b/test_stack.dSYM/Contents/Info.plist new file mode 100644 index 0000000..eca9d8f --- /dev/null +++ b/test_stack.dSYM/Contents/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.test_stack + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/test_stack.dSYM/Contents/Resources/DWARF/test_stack b/test_stack.dSYM/Contents/Resources/DWARF/test_stack new file mode 100644 index 0000000..aa57c7c Binary files /dev/null and b/test_stack.dSYM/Contents/Resources/DWARF/test_stack differ diff --git a/test_stack.dSYM/Contents/Resources/Relocations/x86_64/test_stack.yml b/test_stack.dSYM/Contents/Resources/Relocations/x86_64/test_stack.yml new file mode 100644 index 0000000..6432f19 --- /dev/null +++ b/test_stack.dSYM/Contents/Resources/Relocations/x86_64/test_stack.yml @@ -0,0 +1,12 @@ +--- +triple: 'x86_64-apple-darwin' +binary-path: test_stack +relocations: + - { offset: 0x26, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x100000B80, symSize: 0x249 } + - { offset: 0x4E, size: 0x8, addend: 0x0, symName: _main, symObjAddr: 0x0, symBinAddr: 0x100000B80, symSize: 0x249 } + - { offset: 0x10A, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DD0, symSize: 0x60 } + - { offset: 0x14E, size: 0x8, addend: 0x0, symName: _push, symObjAddr: 0x0, symBinAddr: 0x100000DD0, symSize: 0x60 } + - { offset: 0x192, size: 0x8, addend: 0x0, symName: _pop, symObjAddr: 0x60, symBinAddr: 0x100000E30, symSize: 0x50 } + - { offset: 0x1C8, size: 0x8, addend: 0x0, symName: _top, symObjAddr: 0xB0, symBinAddr: 0x100000E80, symSize: 0x40 } + - { offset: 0x1F0, size: 0x8, addend: 0x0, symName: _clearStack, symObjAddr: 0xF0, symBinAddr: 0x100000EC0, symSize: 0x3F } +... diff --git a/timer.o b/timer.o new file mode 100644 index 0000000..c5283e8 Binary files /dev/null and b/timer.o differ