diff --git a/src/util.c b/src/util.c index 70592c8..1755fed 100644 --- a/src/util.c +++ b/src/util.c @@ -1,13 +1,23 @@ -#include "util.h" -#include "wm.h" +#include +#include +#include +#include #include -#include -#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "client.h" +#include "wm.h" static unsigned int node_id = 0; @@ -124,6 +134,23 @@ void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize) } } +NodeType wm_node_type_from_str(char *buf, size_t bufsize) +{ + char *types[4] = {0}; + types[NODE_CLIENT] = "NODE_CLIENT"; + types[NODE_VERTICAL] = "NODE_VERTICAL"; + types[NODE_HORIZONTAL] = "NODE_HORIZONTAL"; + types[NODE_TAB] = "NODE_TAB"; + + for (size_t i = 0; i < 4; i++) { + if (strncmp(buf, types[i], bufsize) == 0) + return (NodeType)i; + } + + fprintf(stderr, "wm: invalid node type string: %s. exiting\n", buf); + exit(1); +} + char* wm_treenode_to_str(TreeNode *node) { assert(node); @@ -166,9 +193,10 @@ char* wm_treenode_to_str(TreeNode *node) return ret; } -PtrArray wm_nonempty_workspaces_to_strptrarray(Wm *wm) +UIntArray* wm_nonempty_workspaces_to_strptrarray(Wm *wm) { - PtrArray ret = wm_ptrarray_new(); + _Static_assert(sizeof(uint64_t) == sizeof(uint64_t*), "static assert failed"); + UIntArray *ret = wm_uintarray_new(); for (size_t i = 0; i < wm->smon->wscount; i++) { TreeNode *node = wm->smon->workspaces[i].tree; @@ -179,11 +207,11 @@ PtrArray wm_nonempty_workspaces_to_strptrarray(Wm *wm) .ws_index = i, .str = wm_treenode_to_str(wm->smon->workspaces[i].tree) }; - wm_ptrarray_push(&ret, ws_str_with_index); + wm_uintarray_push(ret, (uint64_t)ws_str_with_index); } } - DEBUG_PRINT("%s returning %ld\n", __func__, ret.size); + DEBUG_PRINT("%s returning %ld\n", __func__, ret->size); return ret; } @@ -193,34 +221,83 @@ void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile) RETURN_IF_NULL(prefixstr); RETURN_IF_NULL(logfile); - FILE *fptr = fopen(logfile, "a"); - if (!fptr) { - fprintf(stderr, "wm: could not open log file %s\n", logfile); - return; - } - - PtrArray ws_str = wm_nonempty_workspaces_to_strptrarray(wm); + UIntArray *ws_str = wm_nonempty_workspaces_to_strptrarray(wm); char str[128] = {0}; char prefix[WM_PREFIX_LEN + 32] = {0}; - snprintf(prefix, sizeof(prefix), "%lu_%s", time(NULL), prefixstr); + snprintf(prefix, sizeof(prefix), "%lu:%s", time(NULL), prefixstr); json_object *log_entry_obj = json_object_new_object(); - json_object_object_add(log_entry_obj, prefix, json_object_new_object()); - for (size_t i = 0; i < ws_str.size; i++) { - WmWorkspaceToStrRet *ws_with_index = (WmWorkspaceToStrRet*)ws_str.ptrs[i]; + for (size_t i = 0; i < ws_str->size; i++) { + WmWorkspaceToStrRet *ws_with_index = (WmWorkspaceToStrRet*) + wm_uintarray_at(ws_str, i); + snprintf(str, sizeof(str), "%ld", ws_with_index->ws_index); - json_object_object_add(json_object_object_get(log_entry_obj, prefix), str, json_tokener_parse(ws_with_index->str)); - fprintf(fptr, "%s,\n", json_object_to_json_string_ext(log_entry_obj, JSON_C_TO_STRING_PRETTY)); + json_object_object_add(log_entry_obj, str, json_tokener_parse(ws_with_index->str)); + free(ws_with_index->str); free(ws_with_index); } - json_object_put(log_entry_obj); - fflush(fptr); - fclose(fptr); - wm_ptrarray_free(&ws_str); + int fd = -1; + struct json_object *jobj = NULL; + if (access(logfile, F_OK) != 0) { + fd = creat(logfile, 0644); + + if (fd < 0) { + perror("creat"); + goto ret; + } + + jobj = json_object_new_object(); + } else { + fd = open(logfile, O_RDWR); + + if (fd < 0) { + perror("open"); + goto ret; + } + + jobj = json_object_from_fd(fd); + if (!jobj) { + const char *err = json_util_get_last_err(); + fprintf(stderr, "wm: could not read json: %s\n", err); + // TODO maybe free + goto ret; + } + } + + json_object_object_add(jobj, prefix, log_entry_obj); + + int ret = close(fd); + if (ret < 0) { + perror("close"); + goto ret; + } + + ret = open(logfile, O_TRUNC | O_WRONLY); + + if (ret < 0) { + perror("open"); + goto ret; + } + + json_object_to_fd(fd, jobj, JSON_C_TO_STRING_PRETTY); + + ret = close(fd); + if (ret < 0) { + perror("close"); + goto ret; + } + + // TODO + wm_logentries_free(wm->log_entries); + wm->log_entries = wm_read_log(logfile); + +ret: + json_object_put(jobj); + wm_uintarray_free(ws_str); } TreeNode* wm_treenode_lmd(TreeNode *node) @@ -671,45 +748,54 @@ void wm_nodearray_free(NodeArray *arr) free(arr); } -PtrArray wm_ptrarray_new() +UIntArray* wm_uintarray_new() { - PtrArray arr; + UIntArray *arr = calloc(1, sizeof(UIntArray)); + assert(arr); - arr.capacity = 10; - arr.ptrs = calloc(arr.capacity, sizeof(void*)); - assert(arr.ptrs); - arr.size = 0; + arr->capacity = 10; + arr->elements = calloc(arr->capacity, sizeof(void*)); + assert(arr->elements); + arr->size = 0; return arr; } -void wm_ptrarray_push(PtrArray *arr, void* ptr) +uint64_t wm_uintarray_at(UIntArray *arr, size_t index) +{ + assert(arr); + assert(index < arr->size); + + return arr->elements[index]; +} + +void wm_uintarray_push(UIntArray *arr, uint64_t element) { assert(arr); arr->size++; if (arr->size >= arr->capacity) { - void* temp = calloc(arr->capacity, sizeof(void*)); + void* temp = calloc(arr->capacity, sizeof(uint64_t)); assert(temp); - memcpy(temp, arr->ptrs, arr->capacity * sizeof(void*)); - free(arr->ptrs); + memcpy(temp, arr->elements, arr->capacity * sizeof(uint64_t)); + free(arr->elements); size_t old_capacity = arr->capacity; arr->capacity = old_capacity * 2; - arr->ptrs = calloc(arr->capacity, sizeof(void*)); - assert(arr->ptrs); - memcpy(arr->ptrs, temp, old_capacity * sizeof(void*)); + arr->elements = calloc(arr->capacity, sizeof(uint64_t)); + assert(arr->elements); + memcpy(arr->elements, temp, old_capacity * sizeof(uint64_t)); free(temp); - arr->ptrs[arr->size - 1] = ptr; + arr->elements[arr->size - 1] = element; return; } - arr->ptrs[arr->size - 1] = ptr; + arr->elements[arr->size - 1] = element; } -bool wm_ptrarray_pop(PtrArray *arr, void **ret) +bool wm_uintarray_pop(UIntArray *arr, uint64_t *ret) { DEBUG_PRINT("%s\n", __func__); assert(arr); @@ -718,12 +804,12 @@ bool wm_ptrarray_pop(PtrArray *arr, void **ret) if (arr->size == 0) return false; - *ret = arr->ptrs[arr->size - 1]; + *ret = arr->elements[arr->size - 1]; arr->size--; return true; } -bool wm_ptrarray_pop_front(PtrArray *arr, void **ret) +bool wm_uintarray_pop_front(UIntArray *arr, uint64_t *ret) { assert(arr); assert(ret); @@ -731,14 +817,14 @@ bool wm_ptrarray_pop_front(PtrArray *arr, void **ret) if (arr->size == 0) return false; - *ret = arr->ptrs[0]; + *ret = arr->elements[0]; arr->size--; - memmove(arr->ptrs, arr->ptrs+1, arr->size * sizeof(void*)); + memmove(arr->elements, arr->elements+1, arr->size * sizeof(uint64_t)); return true; } -bool wm_ptrarray_remove(PtrArray *arr, size_t index) +bool wm_uintarray_remove(UIntArray *arr, size_t index) { DEBUG_PRINT("%s\n", __func__); assert(arr); @@ -754,21 +840,32 @@ bool wm_ptrarray_remove(PtrArray *arr, size_t index) return true; } - memmove(arr->ptrs + index, arr->ptrs + index+1, arr->size-1 * sizeof(void*)); + memmove(arr->elements + index, arr->elements + index+1, arr->size-1 * sizeof(uint64_t)); return true; } -void wm_ptrarray_free(PtrArray *arr) +void wm_uintarray_free(UIntArray *arr) { // DEBUG_PRINT("%s\n", __func__); assert(arr); - RETURN_IF_NULL(arr->ptrs); + RETURN_IF_NULL(arr->elements); arr->capacity = 0; arr->size = 0; - free(arr->ptrs); - arr->ptrs = NULL; + free(arr->elements); + arr->elements = NULL; + + free(arr); +} + +uint64_t wm_uintarray_2d_index(UIntArray *arr, size_t i, size_t j) +{ + assert(arr); + + return ((uint64_t**)arr->elements)[i][j]; +} + } TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) @@ -781,14 +878,14 @@ TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) NodeArray *visited = wm_nodearray_new(); wm_nodearray_push(visited, root); - PtrArray queue = wm_ptrarray_new(); + NodeArray *queue = wm_nodearray_new(); - wm_ptrarray_push(&queue, root); + wm_nodearray_push(queue, root); - while (queue.size > 0) { + while (queue->size > 0) { TreeNode *node; - if (!wm_ptrarray_pop_front(&queue, (void**)&node)) + if (!wm_nodearray_pop_front(queue, &node)) goto ret; if (node->type == NODE_CLIENT && node->client && node->client->focused) { @@ -809,14 +906,14 @@ TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root) if (!_visited) { wm_nodearray_push(visited, child_node); - wm_ptrarray_push(&queue, child_node); + wm_nodearray_push(queue, child_node); } } } ret: wm_nodearray_free(visited); - wm_ptrarray_free(&queue); + wm_nodearray_free(queue); return ret; } diff --git a/src/util.h b/src/util.h index 4516f52..1c884d7 100644 --- a/src/util.h +++ b/src/util.h @@ -2,6 +2,7 @@ #define UTIL_H #include +#include #include #include #include @@ -30,10 +31,10 @@ typedef struct { } NodeArray; typedef struct { - void **ptrs; + uint64_t *elements; size_t size; size_t capacity; -} PtrArray; +} UIntArray; typedef struct { int x; @@ -79,15 +80,21 @@ void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node); int wm_get_node_index(TreeNode *parent, unsigned int node_id); void wm_tree_to_DOT(TreeNode *root, const char *filename); void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize); +UIntArray* wm_nonempty_workspaces_to_strptrarray(Wm *wm); +NodeType wm_node_type_from_str(char *buf, size_t bufsize); char* wm_treenode_to_str(TreeNode *node); void wm_treenode_print(TreeNode *node); -PtrArray wm_ptrarray_new(); -void wm_ptrarray_push(PtrArray *arr, void* ptr); -bool wm_ptrarray_pop(PtrArray *arr, void **ret); -bool wm_ptrarray_pop_front(PtrArray *arr, void **ret); -bool wm_ptrarray_remove(PtrArray *arr, size_t index); -void wm_ptrarray_free(PtrArray *arr); +UIntArray* wm_uintarray_new(); +uint64_t wm_uintarray_at(UIntArray *arr, size_t index); +void wm_uintarray_set(UIntArray *arr, size_t index, uint64_t value); +void wm_uintarray_push(UIntArray *arr, uint64_t element); +bool wm_uintarray_pop(UIntArray *arr, uint64_t *ret); +bool wm_uintarray_pop_front(UIntArray *arr, uint64_t *ret); +bool wm_uintarray_remove(UIntArray *arr, size_t index); +void wm_uintarray_free(UIntArray *arr); +uint64_t wm_uintarray_2d_index(UIntArray *arr, size_t i, size_t j); + TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root); TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client); NodeArray* wm_treenode_find_client_nodes(TreeNode *root);