Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2004:
[Freeciv-Dev] Re: (PR#8683) remove specvec?
Home

[Freeciv-Dev] Re: (PR#8683) remove specvec?

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] Re: (PR#8683) remove specvec?
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 6 May 2004 17:29:11 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8683 >

After discussion with Vasco, I think specvec should stay but become a 
wrapper for an array.  To wit:

- It should not be a wrapper for athing but should use its own 
implementation.  This sounds like a big deal but it's not: only 8 
additional lines of code are required, and the implementation is faster. 
  The difference here is that specvecs have constant, known size whereas 
athings must have their size given on initialization.  See the attached 
patch.

- Users should be allowed to access the array directly.  The functions 
are therefore just a convenient way to resize the data.  Why call 
foo_vector_get(v, 5) when you can just have v->vec[5]?  It would be nice 
to access the data as v[5] but this would require some very ugly "magic".

- Eventually astring and athing should be replaced by specvecs.  These 
are just special-cases of convenient resizable arrays.

jason

Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.115
diff -u -r1.115 player.h
--- common/player.h     23 Apr 2004 22:58:06 -0000      1.115
+++ common/player.h     7 May 2004 00:28:03 -0000
@@ -219,6 +219,9 @@
   bool debug;
 };
 
+#define SPECVEC_TAG player
+#include "specvec.h"
+
 void player_init(struct player *plr);
 struct player *find_player_by_name(const char *name);
 struct player *find_player_by_name_prefix(const char *name,
Index: utility/specvec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/specvec.h,v
retrieving revision 1.4
diff -u -r1.4 specvec.h
--- utility/specvec.h   6 May 2004 22:57:36 -0000       1.4
+++ utility/specvec.h   7 May 2004 00:28:03 -0000
@@ -13,8 +13,7 @@
 
 /* specvectors: "specific vectors".
    
-   This file is used to implement type-checked vectors (variable size arrays).
-   (Or, maybe, what you end up doing when you don't use C++ ?)
+   This file is used to implement resizable arrays.
    
    Before including this file, you must define the following:
      SPECVEC_TAG - this tag will be used to form names for functions etc.
@@ -34,10 +33,6 @@
       void foo_vector_copy(struct foo_vector *to, struct foo_vector *from);
       void foo_vector_free(struct foo_vector *tthis);
 
-   Also, in a single .c file, you should include specvec_c.h,
-   with the same SPECVEC_TAG and SPECVEC_TYPE defined, to
-   provide the function implementations.
-
    Note this is not protected against multiple inclusions; this is
    so that you can have multiple different specvectors.  For each
    specvector, this file should be included _once_, inside a .h file
@@ -47,7 +42,7 @@
 #include <assert.h>
 #include <string.h>            /* for memcpy */
 
-#include "astring.h"
+#include "mem.h"
 
 #ifndef SPECVEC_TAG
 #error Must define a SPECVEC_TAG to use this header
@@ -64,7 +59,8 @@
 #define SPECVEC_FOO(suffix) SPECVEC_PASTE(SPECVEC_TAG, suffix)
 
 SPECVEC_VECTOR {
-  struct athing vector;
+  size_t size, size_alloc;
+  SPECVEC_TYPE *vec;
 };
 
 #ifndef SPECVEC_TAG
@@ -84,44 +80,50 @@
 
 static inline void SPECVEC_FOO(_vector_init) (SPECVEC_VECTOR *tthis)
 {
-  ath_init(&tthis->vector, sizeof(SPECVEC_TYPE));
+  tthis->vec = NULL;
+  tthis->size = tthis->size_alloc = 0;
 }
 
 static inline void SPECVEC_FOO(_vector_reserve) (SPECVEC_VECTOR *tthis, int n)
 {
-  ath_minnum(&tthis->vector, n);
+  if (n > tthis->size_alloc) {
+    int new_size = MAX(n, tthis->size_alloc * 2);
+
+    tthis->vec = fc_realloc(tthis->vec, new_size * sizeof(*tthis->vec));
+    tthis->size_alloc = new_size;
+  }
+  tthis->size = n;
 }
 
 static inline size_t SPECVEC_FOO(_vector_size) (SPECVEC_VECTOR *tthis)
 {
-  return tthis->vector.n;
+  return tthis->size;
 }
 
 static inline SPECVEC_TYPE *SPECVEC_FOO(_vector_get) (SPECVEC_VECTOR *tthis, 
int index)
 {
-  assert(index>=0 && index<tthis->vector.n);
-
-  return ((SPECVEC_TYPE *)ath_get(&tthis->vector, index));
+  if (index < 0 || index >= tthis->size) {
+    assert(index >= 0 && index < tthis->size);
+    return NULL;
+  } else {
+    return tthis->vec + index;
+  }
 }
 
-/* You must _init "*to" before using this function */
+/* "to" need not be initialized but cannot contain other data. */
 static inline void SPECVEC_FOO(_vector_copy) (SPECVEC_VECTOR *to, 
SPECVEC_VECTOR *from)
 {
-  int i;
-  size_t size = SPECVEC_FOO(_vector_size) (from);
-
-  SPECVEC_FOO(_vector_reserve) (to, size);
-
-  for (i = 0; i < size; i++) {
-    memcpy(SPECVEC_FOO(_vector_get) (to, i), 
-           SPECVEC_FOO(_vector_get) (from, i),
-           sizeof(SPECVEC_TYPE));
-  }
+  SPECVEC_FOO(_vector_init) (to);
+  SPECVEC_FOO(_vector_reserve) (to, from->size);
+  memcpy(to->vec, from->vec, from->size * sizeof(*to->vec));
 }
 
 static inline void SPECVEC_FOO(_vector_free) (SPECVEC_VECTOR *tthis)
 {
-  ath_free(&tthis->vector);
+  if (tthis->vec) {
+    free(tthis->vec);
+  }
+  SPECVEC_FOO(_vector_init)(tthis);
 }
 
 #undef SPECVEC_TAG

[Prev in Thread] Current Thread [Next in Thread]