gettimeofday: port recent C++ fix to Emacs
[gnulib.git] / lib / gl_array_list.c
index d75bf0a..af5f891 100644 (file)
@@ -1,5 +1,5 @@
 /* Sequential list data type implemented by an array.
-   Copyright (C) 2006-2008 Free Software Foundation, Inc.
+   Copyright (C) 2006-2013 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2006.
 
    This program is free software: you can redistribute it and/or modify
@@ -24,8 +24,6 @@
 /* Get memcpy.  */
 #include <string.h>
 
-#include "xalloc.h"
-
 /* Checked size_t computations.  */
 #include "xsize.h"
 
@@ -52,13 +50,17 @@ struct gl_list_impl
 #define NODE_TO_INDEX(node) ((uintptr_t)(node) - 1)
 
 static gl_list_t
-gl_array_create_empty (gl_list_implementation_t implementation,
-                       gl_listelement_equals_fn equals_fn,
-                       gl_listelement_hashcode_fn hashcode_fn,
-                       gl_listelement_dispose_fn dispose_fn,
-                       bool allow_duplicates)
+gl_array_nx_create_empty (gl_list_implementation_t implementation,
+                          gl_listelement_equals_fn equals_fn,
+                          gl_listelement_hashcode_fn hashcode_fn,
+                          gl_listelement_dispose_fn dispose_fn,
+                          bool allow_duplicates)
 {
-  struct gl_list_impl *list = XMALLOC (struct gl_list_impl);
+  struct gl_list_impl *list =
+    (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
+
+  if (list == NULL)
+    return NULL;
 
   list->base.vtable = implementation;
   list->base.equals_fn = equals_fn;
@@ -73,14 +75,18 @@ gl_array_create_empty (gl_list_implementation_t implementation,
 }
 
 static gl_list_t
-gl_array_create (gl_list_implementation_t implementation,
-                 gl_listelement_equals_fn equals_fn,
-                 gl_listelement_hashcode_fn hashcode_fn,
-                 gl_listelement_dispose_fn dispose_fn,
-                 bool allow_duplicates,
-                 size_t count, const void **contents)
+gl_array_nx_create (gl_list_implementation_t implementation,
+                    gl_listelement_equals_fn equals_fn,
+                    gl_listelement_hashcode_fn hashcode_fn,
+                    gl_listelement_dispose_fn dispose_fn,
+                    bool allow_duplicates,
+                    size_t count, const void **contents)
 {
-  struct gl_list_impl *list = XMALLOC (struct gl_list_impl);
+  struct gl_list_impl *list =
+    (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl));
+
+  if (list == NULL)
+    return NULL;
 
   list->base.vtable = implementation;
   list->base.equals_fn = equals_fn;
@@ -89,7 +95,11 @@ gl_array_create (gl_list_implementation_t implementation,
   list->base.allow_duplicates = allow_duplicates;
   if (count > 0)
     {
-      list->elements = XNMALLOC (count, const void *);
+      if (size_overflow_p (xtimes (count, sizeof (const void *))))
+        goto fail;
+      list->elements = (const void **) malloc (count * sizeof (const void *));
+      if (list->elements == NULL)
+        goto fail;
       memcpy (list->elements, contents, count * sizeof (const void *));
     }
   else
@@ -98,6 +108,10 @@ gl_array_create (gl_list_implementation_t implementation,
   list->allocated = count;
 
   return list;
+
+ fail:
+  free (list);
+  return NULL;
 }
 
 static size_t
@@ -116,14 +130,16 @@ gl_array_node_value (gl_list_t list, gl_list_node_t node)
   return list->elements[index];
 }
 
-static void
-gl_array_node_set_value (gl_list_t list, gl_list_node_t node, const void *elt)
+static int
+gl_array_node_nx_set_value (gl_list_t list, gl_list_node_t node,
+                            const void *elt)
 {
   uintptr_t index = NODE_TO_INDEX (node);
   if (!(index < list->count))
     /* Invalid argument.  */
     abort ();
   list->elements[index] = elt;
+  return 0;
 }
 
 static gl_list_node_t
@@ -165,7 +181,7 @@ gl_array_get_at (gl_list_t list, size_t position)
 }
 
 static gl_list_node_t
-gl_array_set_at (gl_list_t list, size_t position, const void *elt)
+gl_array_nx_set_at (gl_list_t list, size_t position, const void *elt)
 {
   size_t count = list->count;
 
@@ -227,8 +243,9 @@ gl_array_search_from_to (gl_list_t list, size_t start_index, size_t end_index,
   return INDEX_TO_NODE (index);
 }
 
-/* Ensure that list->allocated > list->count.  */
-static void
+/* Ensure that list->allocated > list->count.
+   Return 0 upon success, -1 upon out-of-memory.  */
+static int
 grow (gl_list_t list)
 {
   size_t new_allocated;
@@ -240,24 +257,26 @@ grow (gl_list_t list)
   memory_size = xtimes (new_allocated, sizeof (const void *));
   if (size_overflow_p (memory_size))
     /* Overflow, would lead to out of memory.  */
-    xalloc_die ();
-  memory = (const void **) xrealloc (list->elements, memory_size);
+    return -1;
+  memory = (const void **) realloc (list->elements, memory_size);
   if (memory == NULL)
     /* Out of memory.  */
-    xalloc_die ();
+    return -1;
   list->elements = memory;
   list->allocated = new_allocated;
+  return 0;
 }
 
 static gl_list_node_t
-gl_array_add_first (gl_list_t list, const void *elt)
+gl_array_nx_add_first (gl_list_t list, const void *elt)
 {
   size_t count = list->count;
   const void **elements;
   size_t i;
 
   if (count == list->allocated)
-    grow (list);
+    if (grow (list) < 0)
+      return NULL;
   elements = list->elements;
   for (i = count; i > 0; i--)
     elements[i] = elements[i - 1];
@@ -267,19 +286,20 @@ gl_array_add_first (gl_list_t list, const void *elt)
 }
 
 static gl_list_node_t
-gl_array_add_last (gl_list_t list, const void *elt)
+gl_array_nx_add_last (gl_list_t list, const void *elt)
 {
   size_t count = list->count;
 
   if (count == list->allocated)
-    grow (list);
+    if (grow (list) < 0)
+      return NULL;
   list->elements[count] = elt;
   list->count = count + 1;
   return INDEX_TO_NODE (count);
 }
 
 static gl_list_node_t
-gl_array_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
+gl_array_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
 {
   size_t count = list->count;
   uintptr_t index = NODE_TO_INDEX (node);
@@ -292,7 +312,8 @@ gl_array_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
     abort ();
   position = index;
   if (count == list->allocated)
-    grow (list);
+    if (grow (list) < 0)
+      return NULL;
   elements = list->elements;
   for (i = count; i > position; i--)
     elements[i] = elements[i - 1];
@@ -302,7 +323,7 @@ gl_array_add_before (gl_list_t list, gl_list_node_t node, const void *elt)
 }
 
 static gl_list_node_t
-gl_array_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
+gl_array_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
 {
   size_t count = list->count;
   uintptr_t index = NODE_TO_INDEX (node);
@@ -315,7 +336,8 @@ gl_array_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
     abort ();
   position = index + 1;
   if (count == list->allocated)
-    grow (list);
+    if (grow (list) < 0)
+      return NULL;
   elements = list->elements;
   for (i = count; i > position; i--)
     elements[i] = elements[i - 1];
@@ -325,7 +347,7 @@ gl_array_add_after (gl_list_t list, gl_list_node_t node, const void *elt)
 }
 
 static gl_list_node_t
-gl_array_add_at (gl_list_t list, size_t position, const void *elt)
+gl_array_nx_add_at (gl_list_t list, size_t position, const void *elt)
 {
   size_t count = list->count;
   const void **elements;
@@ -335,7 +357,8 @@ gl_array_add_at (gl_list_t list, size_t position, const void *elt)
     /* Invalid argument.  */
     abort ();
   if (count == list->allocated)
-    grow (list);
+    if (grow (list) < 0)
+      return NULL;
   elements = list->elements;
   for (i = count; i > position; i--)
     elements[i] = elements[i - 1];
@@ -583,8 +606,8 @@ gl_array_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar,
 }
 
 static gl_list_node_t
-gl_array_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar,
-                         const void *elt)
+gl_array_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar,
+                            const void *elt)
 {
   size_t count = list->count;
   size_t low = 0;
@@ -607,7 +630,7 @@ gl_array_sortedlist_add (gl_list_t list, gl_listelement_compar_fn compar,
           break;
         }
     }
-  return gl_array_add_at (list, low, elt);
+  return gl_array_nx_add_at (list, low, elt);
 }
 
 static bool
@@ -624,22 +647,22 @@ gl_array_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar,
 
 const struct gl_list_implementation gl_array_list_implementation =
   {
-    gl_array_create_empty,
-    gl_array_create,
+    gl_array_nx_create_empty,
+    gl_array_nx_create,
     gl_array_size,
     gl_array_node_value,
-    gl_array_node_set_value,
+    gl_array_node_nx_set_value,
     gl_array_next_node,
     gl_array_previous_node,
     gl_array_get_at,
-    gl_array_set_at,
+    gl_array_nx_set_at,
     gl_array_search_from_to,
     gl_array_indexof_from_to,
-    gl_array_add_first,
-    gl_array_add_last,
-    gl_array_add_before,
-    gl_array_add_after,
-    gl_array_add_at,
+    gl_array_nx_add_first,
+    gl_array_nx_add_last,
+    gl_array_nx_add_before,
+    gl_array_nx_add_after,
+    gl_array_nx_add_at,
     gl_array_remove_node,
     gl_array_remove_at,
     gl_array_remove,
@@ -652,6 +675,6 @@ const struct gl_list_implementation gl_array_list_implementation =
     gl_array_sortedlist_search_from_to,
     gl_array_sortedlist_indexof,
     gl_array_sortedlist_indexof_from_to,
-    gl_array_sortedlist_add,
+    gl_array_sortedlist_nx_add,
     gl_array_sortedlist_remove
   };