Browse Source

2006-10-30 Marcus Brinkmann <marcus@g10code.de>

	* configure.ac (VERSION_MAJOR, VERSION_MINOR): New variable
	definitions.
	* src/gpgsm.h: Fix syntax error.
	* src/table.c, src/table.h: Rewritten.
	* src/slots.c: Reorganized and rewritten to use the new table
	interface.  Include gpgsm.h.
	* src/p11-signinit.c, src/p11-sign.c, src/p11-getslotlist.c,
	src/p11-getsessioninfo.c, src/p11-getmechanismlist.c,
	src/p11-getattributevalue.c, src/p11-findobjectsinit.c,
	src/p11-findobjectsfinal.c, src/p11-findobjects.c,
	src/p11-closesession.c: Adjust callers.
Marcus Brinkmann 18 years ago
parent
commit
1330318afa

+ 14 - 0
ChangeLog

@@ -1,3 +1,17 @@
+2006-10-30  Marcus Brinkmann  <marcus@g10code.de>
+
+	* configure.ac (VERSION_MAJOR, VERSION_MINOR): New variable
+	definitions.
+	* src/gpgsm.h: Fix syntax error.
+	* src/table.c, src/table.h: Rewritten.
+	* src/slots.c: Reorganized and rewritten to use the new table
+	interface.  Include gpgsm.h.
+	* src/p11-signinit.c, src/p11-sign.c, src/p11-getslotlist.c,
+	src/p11-getsessioninfo.c, src/p11-getmechanismlist.c,
+	src/p11-getattributevalue.c, src/p11-findobjectsinit.c,
+	src/p11-findobjectsfinal.c, src/p11-findobjects.c,
+	src/p11-closesession.c: Adjust callers.
+
 2006-10-26  Marcus Brinkmann  <marcus@g10code.de>
 
 	* src/settings.h: Require VERSION_MAJOR and VERSION_MINOR to be

+ 6 - 0
configure.ac

@@ -34,6 +34,10 @@ LIBSCUTE_LT_CURRENT=0
 LIBSCUTE_LT_AGE=0
 LIBSCUTE_LT_REVISION=0
 
+# Version numbers reported by the PKCS #11 module to its users.
+VERSION_MAJOR=0
+VERSION_MINOR=0
+
 NEED_GPG_ERROR_VERSION=0.7
 NEED_LIBASSUAN_VERSION=0.6.10
 NEED_GPGSM_VERSION=1.9.6
@@ -85,6 +89,8 @@ AC_SUBST(PACKAGE)
 AC_SUBST(VERSION)
 AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package])
 AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package])
+AC_DEFINE_UNQUOTED(VERSION_MAJOR, $VERSION_MAJOR, [Major version number])
+AC_DEFINE_UNQUOTED(VERSION_MINOR, $VERSION_MINOR, [Minor version number])
 
 # Don't default to build static libs.
 AC_DISABLE_STATIC

+ 5 - 4
src/gpgsm.h

@@ -42,9 +42,10 @@
    Returns allocated attributes for the certificate object in ATTRP
    and ATTR_COUNTP, and for the private key object in PRV_ATTRP
    and PRV_ATTR_COUNTP.  */
-gpg_error_t
-scute_gpgsm_get_cert (char *grip,
-		      CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp,
-		      CK_ATTRIBUTE_PTR *prv_attrp, CK_ULONG *prv_attr_countp)
+gpg_error_t scute_gpgsm_get_cert (char *grip,
+				  CK_ATTRIBUTE_PTR *attrp,
+				  CK_ULONG *attr_countp,
+				  CK_ATTRIBUTE_PTR *prv_attrp,
+				  CK_ULONG *prv_attr_countp);
 
 #endif	/* GPGSM_H */

+ 3 - 2
src/p11-closesession.c

@@ -45,16 +45,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
 
   err = scute_global_lock ();
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
-  err = slot_close_session (slot, hSession);
+  err = slot_close_session (slot, session);
 
  out:
   scute_global_unlock ();

+ 4 - 3
src/p11-findobjects.c

@@ -52,6 +52,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
   CK_RV err = CKR_OK;
   CK_ULONG count;
   slot_iterator_t slot;
+  session_iterator_t session;
   object_iterator_t *oids;
   int oids_len;
 
@@ -62,11 +63,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
-  err = session_get_search_result (slot, hSession, &oids, &oids_len);
+  err = session_get_search_result (slot, session, &oids, &oids_len);
   assert (!err);
 
   count = MIN (ulMaxObjectCount, oids_len);
@@ -74,7 +75,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)
 
   oids_len = oids_len - count;
   memmove (oids, oids + count, sizeof (CK_OBJECT_HANDLE) * oids_len);
-  err = session_set_search_result (slot, hSession, oids, oids_len);
+  err = session_set_search_result (slot, session, oids, oids_len);
   assert (!err);
 
   *pulObjectCount = count;

+ 3 - 2
src/p11-findobjectsfinal.c

@@ -47,16 +47,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
 
   err = scute_global_lock ();
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
-  err = session_set_search_result (slot, hSession, NULL, 0);
+  err = session_set_search_result (slot, session, NULL, 0);
 
  out:
   scute_global_unlock ();

+ 4 - 6
src/p11-findobjectsinit.c

@@ -50,6 +50,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
   object_iterator_t object;
   object_iterator_t *search_result;
   int search_result_len = 0;
@@ -61,7 +62,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
@@ -77,7 +78,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
     }
   search_result_len = 0;
 
-  err = objects_iterate_begin (slot, &object);
+  err = objects_iterate_first (slot, &object);
   if (err)
     {
       free (search_result);
@@ -124,16 +125,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)
 	}
     }
 
-  /* Always call this after an iteration.  */
-  objects_iterate_end (slot, &object);
-
   if (err)
     {
       free (search_result);
       goto out;
     }
 
-  err = session_set_search_result (slot, hSession, search_result,
+  err = session_set_search_result (slot, session, search_result,
 				   search_result_len);
 
  out:

+ 2 - 1
src/p11-getattributevalue.c

@@ -48,6 +48,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
   CK_ATTRIBUTE_PTR attr;
   CK_ULONG attr_count;
 
@@ -58,7 +59,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 

+ 1 - 4
src/p11-getmechanismlist.c

@@ -63,7 +63,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)
   /* Leave LEFT positive for the whole search when only counting.  */
   left = pMechanismList ? *pulCount : 1;
   *pulCount = 0;
-  err = mechanisms_iterate_begin (slot, &mechanism);
+  err = mechanisms_iterate_first (slot, &mechanism);
   if (err)
     goto out;
 
@@ -79,9 +79,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)
       err = mechanisms_iterate_next (slot, &mechanism);
     }
 
-  /* Always call this after an iteration.  */
-  mechanisms_iterate_end (slot, &mechanism);
-
   if (err)
     goto out;
 

+ 4 - 3
src/p11-getsessioninfo.c

@@ -47,6 +47,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
   bool rw;
 
   if (pInfo == NULL_PTR)
@@ -56,7 +57,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
@@ -66,11 +67,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)
 
   /* We have to re-lookup the session handle, as it might just have
      become invalid.  */
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
-  rw = session_get_rw (slot, hSession);
+  rw = session_get_rw (slot, session);
   switch (slot_get_status (slot))
     {
     case SLOT_LOGIN_PUBLIC:

+ 1 - 4
src/p11-getslotlist.c

@@ -64,7 +64,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)
   /* Leave LEFT positive for the whole search when only counting.  */
   left = pSlotList ? *pulCount : 1;
   *pulCount = 0;
-  err = slots_iterate_begin (&slot);
+  err = slots_iterate_first (&slot);
   if (err)
     goto out;
 
@@ -83,9 +83,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)
       err = slots_iterate_next (&slot);
     }
 
-  /* Always call this after an iteration.  */
-  slots_iterate_end (&slot);
-
   if (err)
     goto out;
 

+ 3 - 2
src/p11-sign.c

@@ -46,6 +46,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
 
   if (pData == NULL_PTR || pulSignatureLen == NULL_PTR)
     return CKR_ARGUMENTS_BAD;
@@ -54,12 +55,12 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
   /* FIXME: Who cares if they called sign init correctly.  */
-  err = session_sign (slot, hSession, pData, ulDataLen,
+  err = session_sign (slot, session, pData, ulDataLen,
 		      pSignature, pulSignatureLen);
 
  out:

+ 3 - 2
src/p11-signinit.c

@@ -46,6 +46,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)
 {
   CK_RV err = CKR_OK;
   slot_iterator_t slot;
+  session_iterator_t session;
 
   if (pMechanism == NULL_PTR || pMechanism->mechanism != CKM_RSA_PKCS)
     return CKR_ARGUMENTS_BAD;
@@ -57,11 +58,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)
   if (err)
     return err;
 
-  err = slots_lookup_session (hSession, &slot);
+  err = slots_lookup_session (hSession, &slot, &session);
   if (err)
     goto out;
 
-  err = session_set_signing_key (slot, hSession, hKey);
+  err = session_set_signing_key (slot, session, hKey);
 
  out:
   scute_global_unlock ();

File diff suppressed because it is too large
+ 333 - 324
src/slots.c


+ 6 - 15
src/slots.h

@@ -56,7 +56,7 @@ typedef int mechanism_iterator_t;
 typedef CK_OBJECT_HANDLE object_iterator_t;
 
 /* A session pointer.  */
-typedef CK_SESSION_HANDLE session_iterator_t;
+typedef int session_iterator_t;
 
 
 /* Initialize the slot list.  */
@@ -76,14 +76,11 @@ CK_RV slots_update_slot (slot_iterator_t id);
 
 /* Begin iterating over the list of slots.  If succeeds, will be
    followed up by a slot_iterate_end.  */
-CK_RV slots_iterate_begin (slot_iterator_t *slot);
+CK_RV slots_iterate_first (slot_iterator_t *slot);
 
 /* Continue iterating over the list of slots.  */
 CK_RV slots_iterate_next (slot_iterator_t *slot);
 
-/* Continue iterating over the list of slots.  */
-CK_RV slots_iterate_end (slot_iterator_t *slot);
-
 /* Return true iff the previous slot was the last one.  */
 bool slots_iterate_last (slot_iterator_t *slot);
 
@@ -125,17 +122,13 @@ CK_SLOT_ID slot_get_id (slot_iterator_t slot);
 
 /* Begin iterating over the list of mechanisms.  If succeeds, will be
    followed up by a slot_iterate_end.  */
-CK_RV mechanisms_iterate_begin (slot_iterator_t id,
+CK_RV mechanisms_iterate_first (slot_iterator_t id,
 				mechanism_iterator_t *mechanism);
 
 /* Continue iterating over the list of mechanisms.  */
 CK_RV mechanisms_iterate_next (slot_iterator_t id,
 			       mechanism_iterator_t *mechanism);
 
-/* Stop iterating over the list of mechanisms.  */
-CK_RV mechanisms_iterate_end (slot_iterator_t id,
-			      mechanism_iterator_t *mechanism);
-
 /* Return true iff the previous slot was the last one.  */
 bool mechanisms_iterate_last (slot_iterator_t id,
 			      mechanism_iterator_t *mechanisms);
@@ -160,7 +153,8 @@ CK_RV slot_create_session (slot_iterator_t id, session_iterator_t *session,
 			   bool rw);
 
 /* Look up session.  */
-CK_RV slots_lookup_session (session_iterator_t sid, slot_iterator_t *id);
+CK_RV slots_lookup_session (CK_SESSION_HANDLE sid, slot_iterator_t *id,
+			    session_iterator_t *session_id);
 
 /* Close the session.  */
 CK_RV slot_close_session (slot_iterator_t id, session_iterator_t sid);
@@ -179,14 +173,11 @@ slot_login_t slot_get_status (slot_iterator_t id);
 
 /* Begin iterating over the list of objects.  If succeeds, will be
    followed up by a slot_iterate_end.  */
-CK_RV objects_iterate_begin (slot_iterator_t id, object_iterator_t *object);
+CK_RV objects_iterate_first (slot_iterator_t id, object_iterator_t *object);
 
 /* Continue iterating over the list of objects.  */
 CK_RV objects_iterate_next (slot_iterator_t id, object_iterator_t *object);
 
-/* Stop iterating over the list of objects.  */
-CK_RV objects_iterate_end (slot_iterator_t id, object_iterator_t *object);
-
 /* Return true iff the previous slot was the last one.  */
 bool objects_iterate_last (slot_iterator_t id, object_iterator_t *object);
 

+ 238 - 26
src/table.c

@@ -1,5 +1,5 @@
-/* table.c - Table abstraction implementation.
-   Copyright (C) 2004, 2006 Marcus Brinkmann
+/* table.c - Indexed table implementation.
+   Copyright (C) 2006 g10 Code GmbH
 
    This file is part of Scute[1].
 
@@ -34,60 +34,172 @@
 #include <config.h>
 #endif
 
+#include <stdlib.h>
 #include <assert.h>
-#include <string.h>
+
+#include <gpg-error.h>
 
 #include "table.h"
 
+/* Indices are 1 based externally, but 0 based internally.  */
+#define INDEX_COPY_IN(idx) ((idx) - 1)
+#define INDEX_COPY_OUT(idx) ((idx) + 1)
+
+/* End of table marker.  */
+#define INDEX_EOT (-1)
+
 
-/* Initialize the table TABLE.  */
-error_t
-hurd_table_init (hurd_table_t table, unsigned int entry_size)
+/* This is an indexed list implementation.  It only supports storing
+   and retrieving pointers.  One would like to support arbitrary data
+   types inline, but this is not possible in a portable manner,
+   because of aliasing and alignment restrictions.
+
+   Note that this implementation is only fast if the lists are very
+   short.  */
+
+struct scute_table
+{
+  /* The user data pointers.  */
+  void **data;
+
+  /* The size of DATA.  */
+  int size;
+
+  /* The number of used entries in DATA.  */
+  int used;
+
+  /* The index of the lowest entry that is unused.  */
+  unsigned int first_free;
+
+  /* The index after the highest entry that is used.  */
+  unsigned int last_used;
+
+  /* The allocator and deallocator callback.  */
+  scute_table_alloc_cb_t alloc;
+  scute_table_dealloc_cb_t dealloc;
+};
+
+
+/* Some support functions for iteration.  */
+
+/* Return the first element in TABLE.  */
+static int
+index_first (scute_table_t table)
+{
+  int index = 0;
+
+  while (index < table->last_used && table->data[index] == NULL)
+    index++;
+
+  if (index == table->last_used)
+    return INDEX_EOT;
+
+  return index;
+}
+
+
+/* Return the element following INDEX, or the end-of-list marker if
+   INDEX is the last element on the list.  */
+static int
+index_next (scute_table_t table, int index)
 {
-  assert (sizeof (entry_size) >= sizeof (void *));
+  index++;
 
-  *table = (struct hurd_table) HURD_TABLE_INITIALIZER (entry_size);
+  while (index < table->last_used && table->data[index] == NULL)
+    index++;
+
+  if (index >= table->last_used)
+    index = INDEX_EOT;
+
+  return index;
+}
+
+
+/* TABLE interface implementation.  */
+
+/* Create a new table and return it in TABLE_R.  */
+gpg_error_t
+scute_table_create (scute_table_t *table_r,
+				scute_table_alloc_cb_t alloc,
+				scute_table_dealloc_cb_t dealloc)
+{
+  scute_table_t table;
+
+  table = malloc (sizeof (*table));
+  if (!table)
+    return gpg_error_from_syserror ();
+
+  table->data = NULL;
+  table->size = 0;
+  table->used = 0;
+  table->first_free = 0;
+  table->last_used = 0;
+  table->alloc = alloc;
+  table->dealloc = dealloc;
+
+  *table_r = table;
   return 0;
 }
 
 
-/* Destroy the table TABLE.  */
+/* Destroy the indexed list TABLE.  The user has to make sure that the
+   existing entries are not needed anymore before calling this
+   function.  */
 void
-hurd_table_destroy (hurd_table_t table)
+scute_table_destroy (scute_table_t table)
 {
+  int idx = 0;
+
+  if (table == NULL)
+    return;
+
+  for (idx = 0; idx < table->last_used; idx++)
+    if (table->data[idx] != NULL)
+      (*table->dealloc) (table->data[idx]);
+
   if (table->data)
     free (table->data);
+  free (table);
 }
 
-
+
 /* The initial table size.  */
 #define TABLE_START_SIZE	4
 
-/* Add the table element DATA to the table TABLE.  The index for this
-   element is returned in R_IDX.  Note that the data is added by
-   copying ENTRY_SIZE bytes into the table (the ENTRY_SIZE parameter
-   was provided at table initialization time).  */
-error_t
-hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx)
+/* Allocate a new table entry with a free index.  Returns the index
+   pointing to the new list entry in INDEX_R.  This calls the
+   allocator on the new entry before returning.  Also returns the
+   table entry in *DATA_R if this is not NULL.  */
+gpg_error_t
+scute_table_alloc (scute_table_t table, int *index_r, void **data_r,
+		   void *hook)
 {
+  gpg_error_t err;
   unsigned int idx;
+  void *data;
 
   if (table->used == table->size)
     {
       unsigned int size_new = table->size ? 2 * table->size : TABLE_START_SIZE;
       void *data_new;
 
-      data_new = realloc (table->data, size_new * table->entry_size);
+      data_new = realloc (table->data, size_new * sizeof (*(table->data)));
       if (!data_new)
-	return errno;
+	return gpg_error_from_syserror ();
 
       table->first_free = table->size;
       table->data = data_new;
       table->size = size_new;
     }
 
-  for (idx = table->first_free; idx < table->init_size; idx++)
-    if (_HURD_TABLE_ENTRY_LOOKUP (table, idx) == HURD_TABLE_EMPTY)
+  /* We may needlessly have increased the table size if this fails,
+     but that is not a problem.  */
+  err = (*table->alloc) (&data, hook);
+  if (err)
+    return err;
+
+  for (idx = table->first_free; idx < table->last_used; idx++)
+    if (table->data[idx] == NULL)
       break;
 
   /* The following setting for FIRST_FREE is safe, because if this was
@@ -96,14 +208,114 @@ hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx)
      the meantime.  */
   table->first_free = idx + 1;
 
-  if (idx == table->init_size)
-    table->init_size++;
   if (idx == table->last_used)
     table->last_used++;
 
-  memcpy (HURD_TABLE_LOOKUP (table, idx), data, table->entry_size);
+  table->data[idx] = data;
   table->used++;
-  *r_idx = idx;
+
+  *index_r = INDEX_COPY_OUT (idx);
+  if (data_r != NULL)
+    *data_r = data;
+
   return 0;
 }
- 
+
+
+/* Deallocate the list entry index.  Afterwards, INDEX points to the
+   following entry.  This calls the deallocator on the entry before
+   returning.  */
+void
+scute_table_dealloc (scute_table_t table, int *index)
+{
+  int idx = INDEX_COPY_IN (*index);
+  void *data = NULL;
+
+  if (idx == INDEX_EOT)
+    return NULL;
+
+  assert (idx >= 0 && idx < table->last_used);
+  assert (table->data[idx] != NULL);
+
+  data = table->data[idx];
+  table->data[idx] = NULL;
+
+  table->used--;
+
+  if (idx < table->first_free)
+    table->first_free = idx;
+
+  /* Update TABLE->last_used if necessary.  */
+  if (idx + 1 == table->last_used)
+    while (table->last_used > 0)
+      {
+	if (table->data[table->last_used - 1] != NULL)
+	  break;
+	table->last_used--;
+      }
+
+  *index = INDEX_COPY_OUT (index_next (table, idx));
+
+  (*table->dealloc) (data);
+}
+
+
+/* Return the iterator for the beginning of the list TABLE.  */
+int
+scute_table_first (scute_table_t table)
+{
+  if (table->used)
+    {
+      if (table->data[0] != NULL)
+	return INDEX_COPY_OUT (0);
+      else
+	return INDEX_COPY_OUT (index_first (table));
+    }
+
+  return 0;
+}
+
+
+/* Return the index following INDEX.  If INDEX is the last element in
+   the list, return 0.  */
+int
+scute_table_next (scute_table_t table, int index)
+{
+  int idx = INDEX_COPY_IN (index);
+
+  if (idx == INDEX_EOT)
+    return 0;
+
+  idx = index_next (table, idx);
+  return INDEX_COPY_OUT (idx);
+}
+
+
+/* Return true iff INDEX is the end-of-list marker.  */
+bool
+scute_table_last (scute_table_t table, int index)
+{
+  return INDEX_COPY_IN (index) == INDEX_EOT;
+}
+
+
+/* Return the user data associated with INDEX.  Return NULL if INDEX
+   is not valid.  */
+void *
+scute_table_data (scute_table_t table, int index)
+{
+  int idx = INDEX_COPY_IN (index);
+
+  if (idx >= 0 && idx < table->last_used)
+    return table->data[idx];
+
+  return NULL;
+}
+
+
+/* Return the number of entries in the table TABLE.  */
+int
+scute_table_used (scute_table_t table)
+{
+  return table->used;
+}

+ 45 - 181
src/table.h

@@ -1,5 +1,5 @@
-/* table.h - Table abstraction interface.
-   Copyright (C) 2004, 2006 Marcus Brinkmann
+/* table.h - Iterative table interface.
+   Copyright (C) 2006 g10 Code GmbH
 
    This file is part of Scute[1].
 
@@ -30,200 +30,64 @@
    not obligated to do so.  If you do not wish to do so, delete this
    exception statement from your version.  */
 
-#ifndef _HURD_TABLE_H
-#define _HURD_TABLE_H	1
+#ifndef TABLE_H
+#define TABLE_H	1
 
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
+#include <stdbool.h>
 
-
-/* The hurd_table data type is a fancy array.  At initialization time,
-   you have to provide the size ENTRY_SIZE of each table entry.  When
-   you enter an element, you get an index number in return.  This
-   index can be used for fast lookup of table elements.  You access
-   the table elements through pointers to the beginning of the each
-   block of ENTRY_SIZE bytes.
-
-   Embedded at the beginning of the ENTRY_SIZE bytes in each slot is a
-   void pointer.  You can use this void pointer freely for your own
-   purpose with the following restriction: In a used table entry, it
-   must never be NULL.  NULL at the beginning of a table entry
-   indicates an unused (free) table entry.
-
-   The table will grow (and eventually shrink, not yet implemented)
-   automatically.  New elements are always allocated from the
-   beginning of the table.  This means that when a new element is
-   added, the free slot with the lowest index is always used.  This
-   makes slot usage predictable and attempts to prevent fragmentation
-   and sparse usage.
-
-   Note that tables, unlike hashes, can not be reorganized, because
-   the index is not stable under reorganization.
-
-   Of all operations supported, only lookup is immediate.  Entering
-   new elements is usually fast, too, unless the first free slot is
-   unknown and has to be searched for, or there are no more free slots
-   and the table has to be enlarged.
-
-   Iterating over the used elements of the table is always
-   of the order of the table size.
-
-   In the future, removing an element can also shrink the table.  In
-   order to be able to do this, the implementation keeps track of the
-   last used slot.  For this reason, the remove operation is sometimes
-   not immediate.  */
-
-
-/* Because the first element in each table entry is a pointer, the
-   table entry should be naturally aligned.  */
-#define _HURD_TABLE_ALIGN(x) \
-  (((x) + sizeof (void *) - 1) & ~(sizeof (void *) - 1))
-
-
-/* The value used for empty table entries.  */
-#define HURD_TABLE_EMPTY	(NULL)
-
-struct hurd_table
-{
-  /* The size of one entry.  Must at least be sizeof (void *).  At the
-     beginning of each entry, a void * should be present that is
-     HURD_TABLE_EMPTY for unused elements and something else for used
-     table elements.  */
-  unsigned int entry_size;
-
-  /* The number of allocated table entries.  */
-  unsigned int size;
-
-  /* The number of table entries that are initialized.  */
-  unsigned int init_size;
-
-  /* The number of used table entries.  */
-  unsigned int used;
-
-  /* The index of the lowest entry that is unused.  */
-  unsigned int first_free;
-
-  /* The index after the highest entry that is used.  */
-  unsigned int last_used;
-
-  /* The table data.  */
-  char *data;
-};
-typedef struct hurd_table *hurd_table_t;
-
-
-#define HURD_TABLE_INITIALIZER(size_of_one)				\
-  { .entry_size = _HURD_TABLE_ALIGN (size_of_one), .size = 0,		\
-    .init_size = 0, .used = 0, .first_free = 0, .last_used = 0,		\
-    .data = NULL }
-
-/* Fast accessor without range check.  */
-#define HURD_TABLE_LOOKUP(table, idx)					\
-  ((void *) (&(table)->data[(idx) * (table)->entry_size]))
-
-/* For bound checks.  */
-#define HURD_TABLE_EXTENT(table)					\
-  ((table)->last_used)
-
-/* For bound checks.  */
-#define HURD_TABLE_USED(table)						\
-  ((table)->used)
-
-/* This is an lvalue for the pointer embedded in the table entry.  */
-#define _HURD_TABLE_ENTRY(entry)	(*(void **) (entry))
-
-#define _HURD_TABLE_ENTRY_LOOKUP(table, idx)				\
-  _HURD_TABLE_ENTRY (HURD_TABLE_LOOKUP (table, idx))
+#include <gpg-error.h>
 
 
-/* Initialize the table TABLE.  */
-error_t hurd_table_init (hurd_table_t table, unsigned int entry_size);
-
-
-/* Destroy the table TABLE.  */
-void hurd_table_destroy (hurd_table_t table);
+/* The indexed list type.  */
+struct scute_table;
+typedef struct scute_table *scute_table_t;
 
 
-/* Add the table element DATA to the table TABLE.  The index for this
-   element is returned in R_IDX.  Note that the data is added by
-   copying ENTRY_SIZE bytes into the table (the ENTRY_SIZE parameter
-   was provided at table initialization time).  */
-error_t hurd_table_enter (hurd_table_t table, void *data, unsigned int *r_idx);
+/* TABLE interface.  */
 
+/* A table entry allocator function callback.  Should return the new
+   table entry in DATA_R.  */
+typedef gpg_error_t (*scute_table_alloc_cb_t) (void **data_r, void *hook);
 
-/* Lookup the table element with the index IDX in the table TABLE.  If
-   there is no element with this index, return NULL.  Otherwise a
-   pointer to the table entry is returned.  */
-static inline void *
-hurd_table_lookup (hurd_table_t table, unsigned int idx)
-{
-  void *result;
+/* A table entry deallocator function callback.  */
+typedef void (*scute_table_dealloc_cb_t) (void *data);
 
-  if (idx >= table->init_size)
-    return NULL;
+/* Allocate a new table and return it in TABLE_R.  */
+gpg_error_t scute_table_create (scute_table_t *table_r,
+				scute_table_alloc_cb_t alloc,
+				scute_table_dealloc_cb_t dealloc);
 
-  result = HURD_TABLE_LOOKUP (table, idx);
-  if (_HURD_TABLE_ENTRY (result) == HURD_TABLE_EMPTY)
-    return NULL;
+/* Destroy the indexed list TABLE.  This also calls the deallocator on
+   all entries.  */
+void scute_table_destroy (scute_table_t table);
 
-  return result;
-}
+/* Allocate a new table entry with a free index.  Returns the index
+   pointing to the new list entry in INDEX_R.  This calls the
+   allocator on the new entry before returning.  Also returns the
+   table entry in *DATA_R if this is not NULL.  */
+gpg_error_t scute_table_alloc (scute_table_t table, int *index_r,
+			       void **data_r, void *hook);
 
+/* Deallocate the list entry index.  Afterwards, INDEX points to the
+   following entry.  This calls the deallocator on the entry before
+   returning.  */
+void scute_table_dealloc (scute_table_t table, int *index);
 
-/* Remove the table element with the index IDX from the table
-   TABLE.  */
-static inline void
-hurd_table_remove (hurd_table_t table, unsigned int idx)
-{
-  void *entry;
+/* Return the index for the beginning of the list TABLE.  */
+int scute_table_first (scute_table_t table);
 
-  assert (idx < table->init_size);
+/* Return the index following INDEX.  If INDEX is the last element in
+   the list, return 0.  */
+int scute_table_next (scute_table_t table, int index);
 
-  entry = HURD_TABLE_LOOKUP (table, idx);
-  assert (_HURD_TABLE_ENTRY (entry) != HURD_TABLE_EMPTY);
+/* Return true iff INDEX is the end-of-list marker.  */
+bool scute_table_last (scute_table_t table, int index);
 
-  _HURD_TABLE_ENTRY (entry) = HURD_TABLE_EMPTY;
+/* Return the user data associated with INDEX.  Return NULL if INDEX is
+   the end-of-list marker.  */
+void *scute_table_data (scute_table_t table, int index);
 
-  if (idx < table->first_free)
-    table->first_free = idx;
+/* Return the number of entries in the table TABLE.  */
+int scute_table_used (scute_table_t table);
 
-  if (idx + 1 == table->last_used)
-    while (table->last_used > 0)
-      {
-	if (_HURD_TABLE_ENTRY_LOOKUP (table, table->last_used - 1)
-	    != HURD_TABLE_EMPTY)
-	  break;
-	table->last_used--;
-      }
-
-  table->used--;
-}
-
-
-/* Iterate over all elements in the table.  You use this macro
-   with a block, for example like this:
-
-     error_t err;
-     HURD_TABLE_ITERATE (table, idx)
-       {
-         err = foo (idx);
-         if (err)
-           break;
-       }
-     if (err)
-       cleanup_and_return ();
-
-   Or even like this:
-
-     HURD_TABLE_ITERATE (ht, idx)
-       foo (idx);
-
-   The block will be run for every used element in the table.  Because
-   IDX is already a verified valid table index, you can lookup the
-   table entry with the fast macro HURD_TABLE_LOOKUP.  */
-#define HURD_TABLE_ITERATE(table, idx)					\
-  for (unsigned int idx = 0; idx < (table)->last_used; idx++)		\
-    if (_HURD_TABLE_ENTRY_LOOKUP ((table), (idx)) != HURD_TABLE_EMPTY)
-
-#endif	/* _HURD_TABLE_H */
+#endif	/* !TABLE_H */

Some files were not shown because too many files changed in this diff