From 8f970d170a91399cc072d9b7f37f14538aee067c Mon Sep 17 00:00:00 2001 From: Nick Van Doorn Date: Sun, 19 Aug 2018 21:33:20 -0700 Subject: Initial commit --- .clang-format | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 3 +- Makefile | 9 ++++++ example.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ functional.c | 50 +++++++++++++++++++++++++++++++ functional.h | 32 ++++++++++++++++++++ readme.md | 0 7 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 .clang-format create mode 100644 Makefile create mode 100644 example.c create mode 100644 functional.c create mode 100644 functional.h create mode 100644 readme.md diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..b360796 --- /dev/null +++ b/.clang-format @@ -0,0 +1,90 @@ +--- +Language: Cpp +# BasedOnStyle: Chromium +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: true +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: true +BinPackArguments: true +BinPackParameters: false +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^<.*\.h>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IndentCaseLabels: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 8 +UseTab: Never +... + diff --git a/.gitignore b/.gitignore index b8d81fd..7efa141 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.o +*.o +*.dSYM diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bab241f --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +CC = gcc +CFLAGS = -Wall -g + +example: example.c functional.c + $(CC) $(CFLAGS) -o example.o example.c functional.c && ./example.o + +.PHONY: format +format: + clang-format -i -style=file *.{c,h} diff --git a/example.c b/example.c new file mode 100644 index 0000000..f5d44b5 --- /dev/null +++ b/example.c @@ -0,0 +1,95 @@ +#include "functional.h" +#define MAX_STR_SIZE 400 + +typedef struct { + unsigned int age; + char* name; +} Person; + +bool shouldIncludePerson(FunctionalArgs* args) { + const char* toExclude = args->ctxp; + Person* first = args->arr; + Person* p = &first[args->i]; + return p->age > 30 && strcmp(toExclude, p->name); +} + +void* derefPerson(int i, void* arr) { + Person* p = arr; + return (void*)&p[i]; +} + +int stringifyPerson(Person* p, char* out, size_t n) { + return snprintf(out, n, "Person %s is %d years of age, yo\n", p->name, + p->age); +} + +void printPerson(Person* p) { + char personStr[MAX_STR_SIZE]; + stringifyPerson(p, personStr, MAX_STR_SIZE); + printf("%s", personStr); +} + +void shiftPersonLeft(FunctionalArgs* args) { + Person* people = args->arr; + for (int i = args->i; i < args->n - 1; i++) { + people[i] = people[i + 1]; + } + args->n--; +} + +void mapPersonToAge(FunctionalArgs* args) { + int* storage = args->storage; + Person* people = args->arr; + storage[args->i] = people[args->i].age; +} + +void copyPerson(FunctionalArgs* args) { + Person* src = args->arr; + Person* dest = args->storage; + dest[args->i - args->offset] = src[args->i]; +} + +void mapExample(Functional* f) { + func_map(f); + for (int i = 0; i < f->args.n; i++) { + int* ages = f->args.storage; + printf("age[%d] = %d\n", i, ages[i]); + } +} + +void filterExample(Functional* f) { + func_filter(f); + for (int i = 0; i < f->args.n; i++) { + Person* people = f->args.storage; + printPerson(&people[i]); + } +} + +void findExample(Functional* f) { + Person* olderAndNotHarry = func_find(f); + printPerson(olderAndNotHarry); +} + +int main() { + Person people[] = {{.age = 19, .name = "Alex"}, + {.age = 42, .name = "Jenna"}, + {.age = 55, .name = "Tom"}}; + int ages[3]; + Person filteredPeople[3]; + Functional func = { + .args = {.i = 0, + .n = 3, + .arr = (void*)people, + .ctxp = (void*)"Harry", + .storage = filteredPeople}, + .filter = shouldIncludePerson, + .map = copyPerson, + .derefInput = derefPerson, + }; + findExample(&func); + filterExample(&func); + func.args.storage = ages; + func.map = mapPersonToAge; + func.args.n = 3; + mapExample(&func); +} diff --git a/functional.c b/functional.c new file mode 100644 index 0000000..c1577bd --- /dev/null +++ b/functional.c @@ -0,0 +1,50 @@ +#include "functional.h" + +void func_map(Functional* f) { + f->args.i = 0; + f->args.offset = 0; + while (f->args.i < f->args.n) { + f->map(&f->args); + f->args.i++; + } +} + +void func_filterGeneric(Functional* f, + void (*shiftLeft)(FunctionalArgs* args)) { + bool shouldMutate = shiftLeft != NULL; + int nInCollection = 0; + for (f->args.i = 0; f->args.i < f->args.n; f->args.i++) { + bool shouldInclude = f->filter(&f->args); + if (shouldInclude) { + f->args.offset = f->args.i - nInCollection; + if (!shouldMutate) { + f->map(&f->args); + } + nInCollection++; + } else { + if (shouldMutate) { + shiftLeft(&f->args); + } + } + } + f->args.n = nInCollection; +} + +void func_filter(Functional* f) { + func_filterGeneric(f, NULL); +} + +void func_filterMutate(Functional* f, void (*shiftLeft)(FunctionalArgs* args)) { + func_filterGeneric(f, shiftLeft); +} + +void* func_find(Functional* f) { + f->args.i = 0; + while (f->args.i < f->args.n) { + if (f->filter(&f->args)) { + return f->derefInput(f->args.i, f->args.arr); + } + f->args.i++; + } + return NULL; +} diff --git a/functional.h b/functional.h new file mode 100644 index 0000000..fe7a869 --- /dev/null +++ b/functional.h @@ -0,0 +1,32 @@ +#ifndef FUNCTIONAL_H +#define FUNCTIONAL_H + +#include +#include +#include +#include + +typedef struct { + int i; + int offset; + int n; + void* arr; + void* ctxp; + void* storage; +} FunctionalArgs; + +typedef struct { + bool (*filter)(FunctionalArgs* args); + void (*map)(FunctionalArgs* args); + void* (*derefInput)(int i, void* j); // callback used to deference arr[i] + void (*shiftLeft)(FunctionalArgs* f); + FunctionalArgs args; +} Functional; + +void func_map(Functional* f); + +void func_filter(Functional* f); + +void* func_find(Functional* f); + +#endif diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3