diff --git a/src/client.h b/src/client.h
index 6ecad1a..6224bf6 100644
--- a/src/client.h
+++ b/src/client.h
@@ -49,31 +49,118 @@ struct Client {
     bool is_pid_set;
 };
 
+/**
+ * Client functions
+ */
+
+/**
+ * Converts the position of `c` to a `XWindowChanges` structure.
+ */
 XWindowChanges wm_client_to_xwchanges(Client *c);
+
+/**
+ * Returns the client associated with `w`.
+ * Returns NULL if it could not find the client.
+ */
 Client* wm_client_find(Wm* wm, Window w);
+
+/**
+ * Initializes a new Client.
+ */
 Client* wm_client_create(Wm *wm, Window w);
+
 void wm_client_handle_window_types(Wm *wm, Client *c, XMapRequestEvent e);
+
+/**
+ * Unmaps `c->window` and `c->frame`.
+ */
 void wm_client_hide(Wm *wm, Client *c);
+
+/**
+ * Maps `c->window` and `c->frame`.
+ */
 void wm_client_show(Wm* wm, Client *c);
+
+/**
+ * Focuses `c`.
+ */
 void wm_client_focus(Wm* wm, Client *c);
+
+/**
+ * Focuses the client in the direction `dir`, relative to the current focused
+ * client.
+ */
 void wm_client_focus_dir(Wm* wm, Client *c, int dir);
+
+/**
+ * Swaps the client in the direction `dir`, relative to the current focused
+ * client.
+ */
 void wm_client_swap_dir(Wm* wm, Client *c, int dir);
+
+/**
+ * Frees `c`, and its dynamically allocated fields.
+ */
 void wm_client_free(Wm *wm, Client *c);
+
+/**
+ * Destroys the window and frame associated with `c`, frees `c`, and recalculates
+ * the layout.
+ */
 void wm_client_kill(Wm *wm, Client *c);
 
+/**
+ * Sets the window property with the atom of `name`, with the value `data`.
+ */
 void wm_client_set_atom(Wm *wm, Client *c, const char *name, const unsigned char *data,
                         Atom type, int nelements);
+
+/**
+ * Reads the window poperty with the atom of `name`, and returns the value
+ * in `atom_ret`, and returns the number of read items in `nitems_ret`.
+ */
 Atom wm_client_get_atom(Wm *wm, Client *c, const char *name, unsigned char **atom_ret,
                         unsigned long *nitems_ret);
 
+
+/**
+ * Finds the client in the direction `dir` relative to `c`.
+ */
 Client* wm_client_get_dir_rel_c(Client *c, int dir);
+
+/**
+ * Returns the currently focused client.
+ */
 Client* wm_client_get_focused(Wm* wm);
+
+/**
+ * Draws border for client `c`.
+ */
 void wm_client_border(Wm* wm, Client *c);
+
+/**
+ * Draws focused border for client `c`.
+ */
 void wm_client_border_focused(Wm* wm, Client *c);
+
+/**
+ * Draws borders for all clients in `m`.
+ */
 void wm_monitor_clients_border(Wm* wm, Monitor *m);
+
+/**
+ * Returns true if `c` is focused, false if `c` is not focused.
+ */
 bool wm_client_is_focused(Wm* wm, Client *c);
 
+/**
+ * Draws server-side decorations for `c`.
+ */
 void wm_client_draw_frame(Wm *wm, Client *c);
+
+/**
+ * Draws server-side decorations for all clients in `m`.
+ */
 void wm_monitor_draw_all_clients_frame(Wm* wm, Monitor *m);
 
 #endif
diff --git a/src/util.c b/src/util.c
index 58a1a69..fc7a185 100644
--- a/src/util.c
+++ b/src/util.c
@@ -225,10 +225,8 @@ UIntArray* wm_nonempty_workspaces_to_strptrarray(Wm *wm)
     return ret;
 }
 
-json_object* wm_state_to_json_object(Wm *wm, const char *prefixstr)
+json_object* wm_state_to_json_object(Wm *wm)
 {
-    assert(prefixstr);
-
     json_object *ret = json_object_new_object();
 
     UIntArray *ws_str = wm_nonempty_workspaces_to_strptrarray(wm);
@@ -503,14 +501,6 @@ UIntArray* wm_treenode_all_keyroots_index(TreeNode *node)
     return ret;
 }
 
-bool wm_nodes_are_equal(TreeNode *node1, TreeNode *node2)
-{
-    if (node1->type != node2->type)
-        return false;
-
-    return true;
-}
-
 // https://github.com/timtadh/zhang-shasha
 void wm_treedist(TreeNode *tree1, TreeNode *tree2, size_t i, size_t j,
                  UIntArray *dists, TreeEditDistanceCosts costs)
@@ -987,16 +977,6 @@ void wm_tree_to_DOT(TreeNode *root, const char *filename)
     wm_nodearray_free(all_nodes);
 }
 
-int wm_get_node_index(TreeNode *parent, unsigned int node_id)
-{
-    for (size_t i = 0; i < parent->children->size; i++) {
-        if (node_id == parent->children->nodes[i]->id)
-            return i;
-    }
-
-    return -1;
-}
-
 void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node)
 {
     DEBUG_PRINT("%s\n", __func__);
diff --git a/src/util.h b/src/util.h
index 9db6904..55c2a90 100644
--- a/src/util.h
+++ b/src/util.h
@@ -77,76 +77,308 @@ typedef struct {
     UpdateCostFunction update_cost_function;
 } TreeEditDistanceCosts;
 
+/**
+ * Functions for NodeArray operations
+ */
+
+/**
+ * Initializes a new NodeArray.
+ */
 NodeArray* wm_nodearray_new();
-void wm_nodearray_set(NodeArray *arr, size_t index, uint64_t value);
+
+/**
+ * Adds `node` to the end of `arr`. If the capacity is lower than the
+ * new size, it resizes the array.
+ */
 void wm_nodearray_push(NodeArray *arr, TreeNode *node);
+
+/**
+ * Removes the last element, and returns it in `ret`.
+ */
 bool wm_nodearray_pop(NodeArray *arr, TreeNode **ret);
+
+/**
+ * Removes the first element, and returns it in `ret`.
+ */
 bool wm_nodearray_pop_front(NodeArray *arr, TreeNode **ret);
+
+/**
+ * Removes all elements from `arr`, and sets its size to 0.
+ */
 void wm_nodearray_clear(NodeArray *arr);
+
+/**
+ * Removes the element at the provided index. Returns true on success, false
+ * on failure.
+ */
 bool wm_nodearray_remove(NodeArray *arr, size_t index);
+
+/**
+ * Frees the array.
+ */
 void wm_nodearray_free(NodeArray *arr);
-TreeNode* wm_nodearray_at(NodeArray *arr, size_t index);
 
+/**
+ * Functions for TreeNode operations
+ */
+
+/**
+ * Initializes a new TreeNode.
+ */
 TreeNode* wm_treenode_new(NodeType type, TreeNode *parent);
-void wm_treenode_free(TreeNode *node);
-bool wm_treenode_is_empty(TreeNode *node);
-void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2);
-void wm_treenode_recalculate_space(TreeNode *node);
-void wm_treenode_swap(TreeNode *root, TreeNode *node1, TreeNode* node2);
-void wm_treenode_add_child(TreeNode *node, TreeNode *child);
-TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client);
-void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node);
-int wm_get_node_index(TreeNode *parent, unsigned int node_id);
 
+/**
+ * Frees `node`, and the `children` NodeArray field.
+ */
+void wm_treenode_free(TreeNode *node);
+
+/**
+ * Returns true if `node` has no children.
+ */
+bool wm_treenode_is_empty(TreeNode *node);
+
+/**
+ * Splits the available space between `ret1` and `ret2`, based on `node->type`.
+ */
+void wm_treenode_split_space(TreeNode *node, Rect *ret1, Rect *ret2);
+
+/**
+ * Asserts `node->children->size == 2`, and calls split_space on first and second
+ * child.
+ */
+void wm_treenode_recalculate_space(TreeNode *node);
+
+/**
+ * Swaps the clients of the `node1` and `node2`.
+ */
+void wm_treenode_swap(TreeNode *root, TreeNode *node1, TreeNode* node2);
+
+/**
+ * Pushes child to `node->children`, and sets `child->parent` to node.
+ */
+void wm_treenode_add_child(TreeNode *node, TreeNode *child);
+
+/**
+ * Finds `client` in `root`, removes and frees the node associated with it,
+ * and recalculates layout.
+ */
+TreeNode* wm_treenode_remove_client(Wm *wm, TreeNode *root, Client *client);
+
+/**
+ * Finds `node` in `root`, removes and frees it, and recalculates layout.
+ */
+void wm_treenode_remove_node(Wm *wm, TreeNode *root, TreeNode *node);
+
+/**
+ * Converts `tree` to DOT file format.
+ * Use `dot <filename> -Tsvg > output.svg` to convert the DOT file to svg.
+ */
 void wm_tree_to_DOT(TreeNode *root, const char *filename);
+
+/**
+ * Converts `type` to a string, and writes it to `buf`.
+ */
 void wm_node_type_to_str(NodeType type, char *buf, size_t bufsize);
+
+/**
+ * Finds non empty workspaces, and converts them to JSON strings.
+ * Return value: `UIntArray<WmWorkspaceToStrRet*>`
+ */
 UIntArray* wm_nonempty_workspaces_to_strptrarray(Wm *wm);
+
+/**
+ * Converts a string to NodeType.
+ */
 NodeType wm_node_type_from_str(char *buf, size_t bufsize);
+
+/**
+ * Converts `node` to a JSON string.
+ */
 char* wm_treenode_to_str(TreeNode *node);
+
+/**
+ * Converts `node` to a JSON string, and if DEBUG is defined, prints it to stderr.
+ */
 void wm_treenode_print(TreeNode *node);
+
+/**
+ * Parses a `json_object` to a TreeNode.
+ */
 TreeNode* wm_json_obj_to_treenode(struct json_object *jobj);
 
+
+/**
+ * Functions for UIntArray operations
+ * UIntArray can be used as a generic pointer container, if
+ * `_Static_assert(sizeof(uint64_t) == sizeof(<pointer_type>), "")`.
+ */
+
+/**
+ * Initializes a new UIntArray.
+ */
 UIntArray* wm_uintarray_new();
+
+/**
+ * Asserts `index < arr->size`, and returns `arr->elements[index]`.
+ */
 uint64_t wm_uintarray_at(UIntArray *arr, size_t index);
-void wm_uintarray_set(UIntArray *arr, size_t index, uint64_t value);
+
+/**
+ * Adds `node` to the end of `arr`. If the capacity is lower than the
+ * new size, it resizes the array.
+ */
 void wm_uintarray_push(UIntArray *arr, uint64_t element);
+
+/**
+ * Removes the last element, and returns it in `ret`.
+ */
 bool wm_uintarray_pop(UIntArray *arr, uint64_t *ret);
+
+/**
+ * Removes the first element, and returns it in `ret`.
+ */
 bool wm_uintarray_pop_front(UIntArray *arr, uint64_t *ret);
+
+/**
+ * Removes the element at the provided index. Returns true on success, false
+ * on failure.
+ */
 bool wm_uintarray_remove(UIntArray *arr, size_t index);
+
+/**
+ * Frees the array.
+ */
 void wm_uintarray_free(UIntArray *arr);
+
+/**
+ * Returns ((uint64_t**)arr->elements)[i][j].
+ */
 uint64_t wm_uintarray_2d_index(UIntArray *arr, size_t i, size_t j);
 
+/**
+ * TreeNode utility functions
+ */
+
+/**
+ * Find the node associated with the currently focused client, and returns it.
+ * Returns NULL if no client is focused.
+ */
 TreeNode* wm_treenode_ptr_find_focused_client_node(TreeNode *root);
+
+/**
+ * Find the node associated with `client`, and returns it.
+ * Returns NULL if it could not find `client`.
+ */
 TreeNode* wm_treenode_ptr_find_client_node(TreeNode *root, Client *client);
+
+/**
+ * Returns all `NODE_CLIENT` type descendant nodes of `root`.
+ */
 NodeArray* wm_treenode_find_client_nodes(TreeNode *root);
+
+/**
+ * Returns the sibling node of `node`.
+ * Returns NULL on error.
+ */
 TreeNode* wm_treenode_split_get_sibling(TreeNode *node);
+
+/**
+ * Returns descendant nodes of `root`.
+ */
 NodeArray* wm_all_nodes_to_array(TreeNode *root);
-json_object* wm_state_to_json_object(Wm *wm, const char *prefixstr);
+
+/**
+ * Converts all non empty workspace trees to a `json_object`.
+ */
+json_object* wm_state_to_json_object(Wm *wm);
+
+/**
+ * Writes current state encoded as JSON to logfile.
+ * If logfile exists, and is not empty, appends the state to the JSON object in
+ * logfile.
+ */
 void wm_log_state(Wm *wm, const char *prefixstr, const char* logfile);
 
-TreeNode* wm_treenode_lmd(TreeNode *node);
-NodeArray* wm_treenode_all_lmds(TreeNode *node);
-UIntArray* wm_treenode_all_lmds_index(TreeNode *node);
-NodeArray* wm_postorder_traversal(TreeNode *tree);
-bool wm_is_treenode_keyroot(TreeNode *node, NodeArray *postorder);
-NodeArray* wm_treenode_all_keyroots(TreeNode *node);
-UIntArray* wm_treenode_all_keyroots_index(TreeNode *node);
-bool wm_nodes_are_equal(TreeNode *node1, TreeNode *node2);
 
+/**
+ * Utility functions for tree edit distance
+ */
+
+/**
+ * Returns the leftmost descendant of `node`.
+ */
+TreeNode* wm_treenode_lmd(TreeNode *node);
+
+/**
+ * Returns all leftmost descendants of `node`.
+ */
+NodeArray* wm_treenode_all_lmds(TreeNode *node);
+
+/**
+ * Returns all leftmost descendants of `node`, as indexes of a postorder
+ * traversal array.
+ */
+UIntArray* wm_treenode_all_lmds_index(TreeNode *node);
+
+/**
+ * Returns all nodes of `tree`, in postorder traversal order.
+ */
+NodeArray* wm_postorder_traversal(TreeNode *tree);
+
+/**
+ * Returns true of `node` is a keyroot.
+ * LR_keyroots(T) = {k | there exists no k’ > k such that l(k)= l(k’)}.
+ * l = leftmost descendant
+ */
+bool wm_is_treenode_keyroot(TreeNode *node, NodeArray *postorder);
+
+/**
+ * Returns all keyroots of `node`.
+ */
+NodeArray* wm_treenode_all_keyroots(TreeNode *node);
+
+/**
+ * Returns all keyroots of `node`, as indexes of a postorder traversal array.
+ */
+UIntArray* wm_treenode_all_keyroots_index(TreeNode *node);
+
+
+/**
+ * Calculates the distance of the subtrees of `tree1` and `tree2`, at indexes
+ * `i` and `j`.
+ */
 void wm_treedist(TreeNode *tree1, TreeNode *tree2, size_t i, size_t j,
                  UIntArray *dists, TreeEditDistanceCosts costs);
 
+/**
+ * Calculates the distance of `tree1` and `tree2` using the edit costs `costs`.
+ */
 size_t wm_tree_edit_distance(TreeNode *tree1, TreeNode *tree2, TreeEditDistanceCosts costs);
 
+/**
+ * Creates the logfile at the provided path.
+ */
 void wm_logfile_init(const char *path);
 
-/* UIntArray<LogEntry*> */
+/**
+ * Frees all dynamically allocated fields of the array elements, and frees the
+ * array.
+ * Type of `entries`: UIntArray<LogEntry*>
+ */
 void wm_logentries_free(UIntArray *entries);
 
-/* UIntArray<LogEntry*> */
+/**
+ * Parses the JSON objects in the file at path `filename`, and populates a LogEntry*
+ * array with the parsed values.
+ * Return type: UIntArray<LogEntry*>
+ */
 UIntArray* wm_read_log(const char* filename);
 
-/* UIntArray<LogEntry*> */
+/**
+ * Calculates the tree edit distance of `log_entries[i]` and `curr_tree`.
+ * Stores the distance in `log_entries[i]->workspaces[j]->tree->distance`.
+ * Type of `log_entries`: UIntArray<LogEntry*>
+ */
 void wm_logentries_calculate_distances(UIntArray *log_entries, TreeNode *curr_tree,
                                        UpdateCostFunction update_cost_function);