1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | internal AST_Parameters* parseParameters(Tokenizer* tokenizer) { TemporaryPoolScope tempPool; // NOTE(Jake): Same as TemporaryPool in HH but immediately uses a g_allocator variable and resets when it goes out of scope // Nobody would have more than 255 parameters in a function surely. Array<Token> parameters(255, tempPool); Array<Token> values(255, tempPool); for (s32 parameterCount = 0;;++parameterCount) { Token left = getToken(tokenizer); if (left.type == TOKEN_PAREN_CLOSE) { break; } if (!requireToken(left, TOKEN_IDENTIFIER)) { return NULL; } if (!requireToken(tokenizer, TOKEN_EQUAL)) { return NULL; } Token right = getToken(tokenizer); if (!(right.type == TOKEN_IDENTIFIER || right.type == TOKEN_STRING)) { lexError(right, "Parameter %d is invalid. Expected identifier or string, instead got '%*.*s'", parameterCount, right.length, right.length, right.data); return NULL; } parameters.push(left); values.push(right); } if (parameters.used == 0) { return NULL; } AST_Parameters* ast = pushStructCurrent(AST_Parameters); ast->type = AST_PARAMETERS; ast->values = pushArrayStructCurrent(Token, values.used); ast->parameters = pushArrayStructCurrent(Token, parameters.used); for(s32 i = 0; i < values.used; ++i) { ast->values[i] = values.data[i]; ast->parameters[i] = values.data[i]; } return ast; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | StringLinkedList getFilesRecursive(String directory, Error* error) { wchar_t szBaseDir[MAX_PATH]; mbstowcs(szBaseDir, directory.data, MAX_PATH); const u32 directoryLimit = 100; wchar_t szDirectories[directoryLimit][MAX_PATH+10]; u32 directories = 0; u32 files = 0; StringCchCopy(szDirectories[directories++], MAX_PATH, szBaseDir); StringLinkedList list = {}; while (directories > 0) { --directories; wchar_t currentDirectory[MAX_PATH]; StringCchCopy(currentDirectory, MAX_PATH, szDirectories[directories]); wchar_t currentDirectoryWSearch[MAX_PATH]; StringCchCopy(currentDirectoryWSearch, MAX_PATH, currentDirectory); StringCchCat(currentDirectoryWSearch, MAX_PATH, TEXT("\\*")); WIN32_FIND_DATA ffd; HANDLE hFind = FindFirstFile(currentDirectoryWSearch, &ffd); DWORD dLastError = GetLastError(); if (hFind == INVALID_HANDLE_VALUE || dLastError == ERROR_FILE_NOT_FOUND) { if (error) { if (dLastError == ERROR_FILE_NOT_FOUND) { error->errorCode = DIRECTORY_NO_FILES; } else { error->errorCode = DIRECTORY_INVALID_DIR; } } StringLinkedList list_null = {}; return list_null; } do { if (wcscmp(ffd.cFileName, TEXT(".")) != 0 && wcscmp(ffd.cFileName, TEXT("..")) != 0) { if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // Push this directory to be searched next iteration. StringCchCopy(szDirectories[directories], MAX_PATH, currentDirectory); StringCchCat(szDirectories[directories], MAX_PATH, TEXT("\\")); StringCchCat(szDirectories[directories], MAX_PATH, ffd.cFileName); ++directories; } else { wchar_t filepath[MAX_PATH]; // todo(Jake): Check if .fel file StringCchCopy(filepath, ArrayCount(filepath), currentDirectory); StringCchCat(filepath, ArrayCount(filepath), TEXT("\\")); StringCchCat(filepath, ArrayCount(filepath), ffd.cFileName); String string = WcharToUTF8String(filepath); list.add(string); ++files; } } } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); } return list; inline String WcharToUTF8String(LPCWSTR string) { String result = {}; u32 stringLength = wcslen(string); result.length = WideCharToMultiByte(CP_UTF8, 0, string, stringLength, NULL, 0, NULL, NULL); result.data = (char*)pushSizeCurrent(result.length + 1); WideCharToMultiByte(CP_UTF8, 0, string, stringLength, result.data, result.length, NULL, NULL); return result; } |
1 2 3 4 5 6 | struct Bucket { Item* items; u32 count; Bucket* next; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | Bucket* Collect() { Bucket* result = Allocate(sizeof(Bucket)); const u32 MaxItemsPerBucket = 1024; Bucket* current = result; current->items = Allocate(MaxItemsPerBucket * sizeof(Item)) current->count = 0; current->next = 0; while (...more files...) { if (current->count == MaxItemsPerBucket) { Bucket* next = Allocate(sizeof(Bucket)); next->items = Allocate(MaxItemsPerBucket * sizeof(Item)) next->count = 0; next->next = 0; current->next = next; current = next; } Item* item = current->items[current->count++]; item->name = ...; item->whatever = ...; } return result; } |
1 2 3 4 5 6 7 8 9 10 11 12 | ProcessItems(Bucket* bucket) { while (bucket) { for (u32 i=0; i<bucket->count; i++) { Item* item = bucket->items + i; ... do something with item ... } bucket = bucket->next; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #define MAX_PARAMETER_COUNT 32 internal AST_Parameters* parseParameters(Tokenizer* tokenizer) { Array<Token>* parameters = NULL; Array<Token>* values = NULL; for (s32 parameterCount = 0;;++parameterCount) { Token left = getToken(tokenizer); if (left.type == TOKEN_PAREN_CLOSE) { break; } else if (left.type == TOKEN_COMMA) { // Get identifier left = getToken(tokenizer); } if (!requireToken(left, TOKEN_IDENTIFIER)) { return NULL; } if (!requireToken(tokenizer, TOKEN_EQUAL)) { return NULL; } Token right = getToken(tokenizer); if (!(right.type == TOKEN_IDENTIFIER || right.type == TOKEN_STRING)) { lexError(right, "Parameter %d is invalid. Expected identifier or string, instead got '%*.*s'", parameterCount, right.length, right.length, right.data); return NULL; } if (parameters == NULL && values == NULL) { parameters = Array<Token>::create(MAX_PARAMETER_COUNT); values = Array<Token>::create(MAX_PARAMETER_COUNT); } if (parameters->used == parameters->size) { lexError(right, "Maximum allowed parameters for function or component is %d.", MAX_PARAMETER_COUNT); return NULL; } parameters->push(left); values->push(right); } if (parameters == NULL || values == NULL) { return NULL; } AST_Parameters* ast = pushStructCurrent(AST_Parameters); ast->type = AST_PARAMETERS; ast->values = values; ast->parameters = parameters; return ast; } #undef MAX_PARAMETER_COUNT |