utils: small fixes
authorNiki Roo <niki@nikiroo.be>
Thu, 26 May 2022 11:14:43 +0000 (13:14 +0200)
committerNiki Roo <niki@nikiroo.be>
Thu, 26 May 2022 11:14:43 +0000 (13:14 +0200)
src/tests/utils/desktop.c
src/utils/array.c
src/utils/array.h
src/utils/utils.h

index c219d8a46a9a9fde1b9c650c4980a29533fa2d02..8047e1ab93440cff85ef3e7b53b889b78f21e7f3 100644 (file)
@@ -33,11 +33,6 @@ static void teardown() {
        free_desktop(d);
 }
 
-static void reset() {
-       teardown();
-       setup();
-}
-
 START(init)
                if (!d)
                        FAIL("new_desktop returned NULL");
index c5299f0ebb94df31999c853657c2aa9369b18da9..e5bb7eed05eae387a881ab78764fe87773f7b8d6 100644 (file)
@@ -30,7 +30,8 @@ typedef struct {
        void *data;
 } priv_t;
 
-/* make sure we have at least n elements in the buffer, grow if needed */
+/* make sure we have at least n+1 elements in the buffer, grow if needed */
+/* +1 is so we can always end with a NULL value for array_data/convert() */
 static int array_assure(array_t *me, size_t nb_elem);
 
 /* for qsort operations */
@@ -105,7 +106,7 @@ void array_clear(array_t *me) {
 // convert to void * data (free the rest)
 void *array_convert(array_t *me) {
        priv_t *priv = (priv_t *) me->priv;
-       void *data = priv->data;
+       void *data = array_data(me);
        free(priv);
        free(me);
        return data;
@@ -113,6 +114,18 @@ void *array_convert(array_t *me) {
 
 void *array_data(array_t *me) {
        priv_t *priv = (priv_t *) me->priv;
+
+       // Note: this should be impossible
+       if (me->count >= priv->buffer)
+               array_assure(me, me->count + 1);
+
+       // cast to (char *) because we want 'byte' arithmetic
+       void *after_end = (void *) (((char *) priv->data)
+                       + (me->count * priv->elem_size));
+
+       // last item is always NULL
+       memset(after_end, '\0', priv->elem_size);
+
        return priv->data;
 }
 
@@ -133,10 +146,39 @@ void *array_newn(array_t *me, size_t how_many) {
 }
 
 void *array_first(array_t *me) {
+       if (!me->count)
+               return NULL;
+
        priv_t *priv = (priv_t *) me->priv;
        return priv->data;
 }
 
+void *array_last(array_t *me) {
+       if (!me->count)
+               return NULL;
+
+       priv_t *priv = (priv_t *) me->priv;
+       // cast to (char *) because we want 'byte' arithmetic
+       return (void *) (((char *) priv->data) + ((me->count - 1) * priv->elem_size));
+}
+
+void *array_prev(array_t *me, void *ptr) {
+       priv_t *priv = (priv_t *) me->priv;
+
+       // cast to (char *) because we want 'byte' arithmetic
+       char *cptr = (char *) ptr;
+       char *cdata = (char*) priv->data;
+
+       if (cptr) {
+               cptr -= priv->elem_size;
+               if (cptr >= cdata) {
+                       return cptr;
+               }
+       }
+
+       return NULL;
+}
+
 void *array_next(array_t *me, void *ptr) {
        priv_t *priv = (priv_t *) me->priv;
 
@@ -323,7 +365,7 @@ int array_setn(array_t *me, size_t i, void *data, size_t n) {
 static int array_assure(array_t *me, size_t nb_elem) {
        priv_t *priv = (priv_t *) me->priv;
 
-       if (priv->buffer < nb_elem) {
+       if (priv->buffer <= nb_elem) {
                priv->buffer *= 2;
                if (priv->buffer < nb_elem) {
                        priv->buffer = nb_elem;
index 201c2a01623d4f0554d53cbbcd506383ed7f9072..363856268d8ef64e9c447e18ab3b35531c1802ac 100644 (file)
@@ -143,7 +143,7 @@ typedef struct {
 array_t *new_array(size_t elem_size, size_t initial);
 
 /**
- * Create a new array.
+ * Initialise a new array.
  *
  * @param elem_size the size of one element
  * @param initial the initial number of items the buffer can hold (<b>not</b> 0)
@@ -177,12 +177,17 @@ void uninit_array(array_t *me);
 
 /**
  * Clear the array, that is, resets its current size to 0 (buffer unchanged).
+ *
+ * @note if you hold custom structures with owned resources in the array, you
+ * should deallocate them properly before
  */
 void array_clear(array_t *me);
 
 /** 
  * Convert the array to a block of memory where all values are adjacent.
  *
+ * @note an extra NULL value is assured to be present as last element
+ *
  * @return the data (you must later call `free()` on it)
  */
 void *array_convert(array_t *me);
@@ -194,6 +199,8 @@ void *array_convert(array_t *me);
  *
  * Be careful if you change the content (you should not).
  *
+ * @note an extra NULL value is assured to be present as last element
+ *
  * @return the internal storage area
  */
 void *array_data(array_t *me);
@@ -227,10 +234,30 @@ void *array_newn(array_t *me, size_t n);
  * store integers, it will be <tt>(int *)</tt>; if you store strings, it will
  * be <tt>char **</tt>).
  *
- * @return a <i>pointer</i> to the first element
+ * @return a <i>pointer</i> to the first element, or NULL if no elements are
+ *             present
  */
 void *array_first(array_t *me);
 
+/**
+ * Return a pointer to the last element of the array (for instance, if you
+ * store integers, it will be <tt>(int *)</tt>; if you store strings, it will
+ * be <tt>char **</tt>).
+ *
+ * @return a <i>pointer</i> to the last element, or NULL if no elements are
+ *             present
+ */
+void *array_last(array_t *me);
+
+/**
+ * Return the pointer to the previous element, or NULL if it was the first.
+ *
+ * @param ptr a pointer from an array (the array must be valid)
+ *
+ * @return the previous element, or NULL
+ */
+void *array_prev(array_t *me, void *ptr);
+
 /**
  * Return the pointer to the next element, or NULL if it was the last.
  *
@@ -246,6 +273,8 @@ void *array_next(array_t *me, void *ptr);
  *
  * @param i the index of the element to retrieve
  *
+ * @note if the index is out of bounds, you will get invalid data
+ *
  * @return the pointer to the i'th element
  */
 void *array_get(array_t *me, size_t i);
@@ -271,6 +300,15 @@ void *array_pop(array_t *me);
  * Cut the array at the given size and return a pointer to the first element
  * that was removed if any.
  *
+ * @note be careful, the memory pointed to by the element(s) will be reused the
+ *             next time we add an element -- you should not use it after this; in
+ *             short, the return value is mainly so you can call <tt>free</tt> on
+ *             value(s) pointed to by this pointer (<b>not</b> the pointer itself) if
+ *             it is a pointer to memory you own, or use it locally before continuing
+ *             to use the array
+ * @note in case this was not clear, do <b>not</b> call <tt>free</tt> on the
+ *             returned value(s)
+ *
  * @return a pointer to the first removed element, or NULL
  */
 void *array_cut_at(array_t *me, size_t n);
@@ -335,7 +373,8 @@ void array_qsortl(array_t *me, int rev);
 void array_qsortf(array_t *me, int rev);
 
 /**
- * Add an element to the array.
+ * Add an element to the array (will create a new item in the array and copy the
+ * data from the given element in it).
  *
  * @param data the memory position of the element to add
  *
@@ -345,7 +384,8 @@ void array_qsortf(array_t *me, int rev);
 int array_push(array_t *me, void *data);
 
 /**
- * Add multiple elements to the array.
+ * Add multiple elements to the array (will create new items in the array and
+ * copy the data from the given elements in them).
  *
  * @param data the memory position of the elements to add, adjacent to each
  *  other
@@ -382,7 +422,9 @@ int array_copyn(array_t *me, void *target, size_t i, size_t n);
 
 /**
  * Set an element of the array to the given value.
- * Can also append a new elements.
+ * Can also append an element at the end of the array (i.e., <tt>i</tt> can be
+ * the size of the array and this will result in an array with one more
+ * element).
  * Memory will be copied from the given data to the array.
  *
  * @param i the element index
@@ -398,7 +440,9 @@ int array_set(array_t *me, size_t i, void *data);
 
 /**
  * Set elements of the array to the given value.
- * Can also append some of them to the array if no values were present.
+ * Can also append elements at the end of the array (i.e., <tt>i</tt> can be
+ * the size of the array and this will result in an array with <tt>n</tt> more
+ * elements).
  * Memory will be copied from the given data to the array.
  *
  * @param i the element index to start the insertion at
index 90d4a6a7687e1fb692448a8718a381276d811870..ef6a9f58e4a1114fea5f0c88cddaf3f4e5565ac6 100644 (file)
@@ -57,13 +57,14 @@ size_t strnlen(const char *s, size_t maxlen);
 #endif
 #if _POSIX_C_SOURCE < 200809L && _XOPEN_SOURCE < 500
 /**
- * The strndup() function is similar, but copies at most n bytes.
- * If s is longer than n, only n bytes are copied, and a terminating null byte
- * ('\0') is added.
+ * The strdup() function returns a pointer to a new string which is a
+ * duplicate of the string s.  Memory for the new string is obtained with
+ * malloc(3), and can be freed with free(3).
  *
- * @return On success, the strndup() function returns a pointer to the
- *             duplicated string.  It returns NULL if insufficient memory was
- *             available, with errno set to indicate the error
+ *
+ * @return On success, the strdup() function returns a pointer to the duplicated
+ *     string.  It returns NULL if insufficient memory was available, with
+ *     errno set to indicate the error.
  */
 char *strdup(const char *source);
 #endif