]> git.sur5r.net Git - cc65/blobdiff - src/common/strpool.c
Make much more usage of dynamic strings (StrBufs) instead of char* and
[cc65] / src / common / strpool.c
index 6416c24a71516215611fe3f167a18a7b7748ebb6..4bb19fcddb5ebf748317be67eadf8e496e3d342f 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2003      Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 2003-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -35,7 +35,7 @@
 
 /* A string pool is used to store identifiers and other strings. Each string
  * stored in the pool has a unique id, which may be used to access the string
- * in the pool. Identical strings are only stored once in the pool and have
+ * in the pool. Identical strings are stored only once in the pool and have
  * identical ids. This means that instead of comparing strings, just the
  * string pool ids must be compared.
  */
@@ -64,8 +64,7 @@ struct StringPoolEntry {
     StringPoolEntry*    Next;   /* Pointer to next entry in hash chain */
     unsigned            Hash;   /* Full hash value */
     unsigned            Id;     /* The numeric string id */
-    unsigned            Len;    /* Length of the string (excluding terminator) */
-    char                S[1];   /* The string itself */
+    StrBuf              Buf;    /* The string itself */
 };
 
 
@@ -76,21 +75,21 @@ struct StringPoolEntry {
 
 
 
-static StringPoolEntry* NewStringPoolEntry (const char* S, unsigned Hash, unsigned Id)
+static StringPoolEntry* NewStringPoolEntry (const StrBuf* S, unsigned Hash, unsigned Id)
 /* Create a new string pool entry and return it. */
 {
-    /* Get the length of the string */
-    unsigned Len = strlen (S);
-
     /* Allocate memory */
-    StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry) + Len);
+    StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry));
 
     /* Initialize the fields */
     E->Next = 0;
     E->Hash = Hash;
     E->Id   = Id;
-    E->Len  = Len;
-    memcpy (E->S, S, Len+1);
+    E->Buf  = AUTO_STRBUF_INITIALIZER;
+    SB_Copy (&E->Buf, S);
+
+    /* Always zero terminate the string */
+    SB_Terminate (&E->Buf);
 
     /* Return the new entry */
     return E;
@@ -129,7 +128,15 @@ void DoneStringPool (StringPool* P)
 
     /* Free all entries and clear the entry collection */
     for (I = 0; I < CollCount (&P->Entries); ++I) {
-        xfree (CollAtUnchecked (&P->Entries, I));
+
+        /* Get a pointer to the entry */
+        StringPoolEntry* E = CollAtUnchecked (&P->Entries, I);
+
+        /* Free string buffer memory */
+        SB_Done (&E->Buf);
+
+        /* Free the memory for the entry itself */
+        xfree (E);
     }
     CollDeleteAll (&P->Entries);
 
@@ -165,25 +172,26 @@ void FreeStringPool (StringPool* P)
 
 
 
-const char* SP_Get (const StringPool* P, unsigned Index)
+const StrBuf* SP_Get (const StringPool* P, unsigned Index)
 /* Return a string from the pool. Index must exist, otherwise FAIL is called. */
 {
     /* Get the collection entry */
     const StringPoolEntry* E = CollConstAt (&P->Entries, Index);
 
     /* Return the string from the entry */
-    return E->S;
+    return &E->Buf;
 }
 
 
 
-unsigned SP_Add (StringPool* P, const char* S)
-/* Add a string to the buffer and return the index. If the string does already
- * exist in the pool, SP_Add will just return the index of the existing string.
+unsigned SP_Add (StringPool* P, const StrBuf* S)
+/* Add a string buffer to the buffer and return the index. If the string does
+ * already exist in the pool, SP_AddBuf will just return the index of the
+ * existing string.
  */
 {
     /* Calculate the string hash */
-    unsigned Hash = HashStr (S);
+    unsigned Hash = HashBuf (S);
 
     /* Calculate the reduced string hash */
     unsigned RHash = Hash % (sizeof (P->Tab)/sizeof (P->Tab[0]));
@@ -191,7 +199,7 @@ unsigned SP_Add (StringPool* P, const char* S)
     /* Search for an existing entry */
     StringPoolEntry* E = P->Tab[RHash];
     while (E) {
-        if (E->Hash == Hash && strcmp (E->S, S) == 0) {
+        if (E->Hash == Hash && SB_Compare (&E->Buf, S) == 0) {
             /* Found, return the id of the existing string */
             return E->Id;
         }
@@ -208,8 +216,8 @@ unsigned SP_Add (StringPool* P, const char* S)
     E->Next = P->Tab[RHash];
     P->Tab[RHash] = E;
 
-    /* Add up the string size (plus terminator) */
-    P->TotalSize += E->Len + 1;
+    /* Add up the string size */
+    P->TotalSize += SB_GetLen (&E->Buf);
 
     /* Return the id of the entry */
     return E->Id;
@@ -217,3 +225,22 @@ unsigned SP_Add (StringPool* P, const char* S)
 
 
 
+unsigned SP_AddStr (StringPool* P, const char* S)
+/* Add a string to the buffer and return the index. If the string does already
+ * exist in the pool, SP_Add will just return the index of the existing string.
+ */
+{
+    unsigned Id;
+
+    /* First make a string buffer, then add it. This is some overhead, but the
+     * routine will probably go.
+     */
+    StrBuf Buf;
+    Id = SP_Add (P, SB_InitFromString (&Buf, S));
+
+    /* Return the id of the new entry */
+    return Id;
+}
+
+
+