mojoshader_common.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 20 Oct 2011 12:08:12 -0400
changeset 1059 9655c606b39d
parent 965 6284deccb61e
child 1064 d3f0f4cf84f2
permissions -rw-r--r--
Fixed must-copy version of stringmap_insert(). Thanks to Sam Lantinga for pointing out the bug.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     1
#define __MOJOSHADER_INTERNAL__ 1
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     2
#include "mojoshader_internal.h"
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     3
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     4
typedef struct HashItem
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     5
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     6
    const void *key;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     7
    const void *value;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     8
    struct HashItem *next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     9
} HashItem;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    10
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    11
struct HashTable
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    12
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    13
    HashItem **table;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    14
    uint32 table_len;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    15
    int stackable;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    16
    void *data;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    17
    HashTable_HashFn hash;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    18
    HashTable_KeyMatchFn keymatch;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    19
    HashTable_NukeFn nuke;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    20
    MOJOSHADER_malloc m;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    21
    MOJOSHADER_free f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    22
    void *d;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    23
};
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    24
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    25
static inline uint32 calc_hash(const HashTable *table, const void *key)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    26
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    27
    return table->hash(key, table->data) & (table->table_len-1);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    28
} // calc_hash
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    29
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    30
int hash_find(const HashTable *table, const void *key, const void **_value)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    31
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    32
    HashItem *i;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    33
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    34
    const uint32 hash = calc_hash(table, key);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    35
    HashItem *prev = NULL;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    36
    for (i = table->table[hash]; i != NULL; i = i->next)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    37
    {
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    38
        if (table->keymatch(key, i->key, data))
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    39
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    40
            if (_value != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    41
                *_value = i->value;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    42
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    43
            // Matched! Move to the front of list for faster lookup next time.
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    44
            //  (stackable tables have to remain in the same order, though!)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    45
            if ((!table->stackable) && (prev != NULL))
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    46
            {
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    47
                assert(prev->next == i);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    48
                prev->next = i->next;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    49
                i->next = table->table[hash];
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    50
                table->table[hash] = i;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    51
            } // if
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    52
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    53
            return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    54
        } // if
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    55
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    56
        prev = i;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    57
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    58
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    59
    return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    60
} // hash_find
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    61
965
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    62
int hash_iter(const HashTable *table, const void *key,
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    63
              const void **_value, void **iter)
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    64
{
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    65
    HashItem *i = *iter;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    66
    if (i == NULL)
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    67
        i = table->table[calc_hash(table, key)];
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    68
    else
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    69
        i = i->next;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    70
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    71
    while (i != NULL)
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    72
    {
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    73
        if (table->keymatch(key, i->key, table->data))
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    74
        {
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    75
            *_value = i->value;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    76
            *iter = i;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    77
            return 1;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    78
        } // if
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    79
        i = i->next;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    80
    } // while
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    81
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    82
    // no more matches.
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    83
    *_value = NULL;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    84
    *iter = NULL;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    85
    return 0;
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    86
} // hash_iter
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    87
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    88
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    89
int hash_insert(HashTable *table, const void *key, const void *value)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    90
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    91
    HashItem *item = NULL;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    92
    const uint32 hash = calc_hash(table, key);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    93
    if ( (!table->stackable) && (hash_find(table, key, NULL)) )
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    94
        return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    95
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    96
    // !!! FIXME: grow and rehash table if it gets too saturated.
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    97
    item = (HashItem *) table->m(sizeof (HashItem), table->d);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    98
    if (item == NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    99
        return -1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   100
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   101
    item->key = key;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   102
    item->value = value;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   103
    item->next = table->table[hash];
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   104
    table->table[hash] = item;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   105
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   106
    return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   107
} // hash_insert
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   108
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   109
HashTable *hash_create(void *data, const HashTable_HashFn hashfn,
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   110
              const HashTable_KeyMatchFn keymatchfn,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   111
              const HashTable_NukeFn nukefn,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   112
              const int stackable,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   113
              MOJOSHADER_malloc m, MOJOSHADER_free f, void *d)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   114
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   115
    const uint32 initial_table_size = 256;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   116
    const uint32 alloc_len = sizeof (HashItem *) * initial_table_size;
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   117
    HashTable *table = (HashTable *) m(sizeof (HashTable), d);
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   118
    if (table == NULL)
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   119
        return NULL;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   120
    memset(table, '\0', sizeof (HashTable));
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   121
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   122
    table->table = (HashItem **) m(alloc_len, d);
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   123
    if (table->table == NULL)
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   124
    {
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   125
        f(table, d);
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   126
        return NULL;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   127
    } // if
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   128
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   129
    memset(table->table, '\0', alloc_len);
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   130
    table->table_len = initial_table_size;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   131
    table->stackable = stackable;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   132
    table->data = data;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   133
    table->hash = hashfn;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   134
    table->keymatch = keymatchfn;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   135
    table->nuke = nukefn;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   136
    table->m = m;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   137
    table->f = f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   138
    table->d = d;
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   139
    return table;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   140
} // hash_create
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   141
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   142
void hash_destroy(HashTable *table)
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   143
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   144
    uint32 i;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   145
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   146
    MOJOSHADER_free f = table->f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   147
    void *d = table->d;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   148
    for (i = 0; i < table->table_len; i++)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   149
    {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   150
        HashItem *item = table->table[i];
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   151
        while (item != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   152
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   153
            HashItem *next = item->next;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   154
            table->nuke(item->key, item->value, data);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   155
            f(item, d);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   156
            item = next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   157
        } // while
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   158
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   159
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   160
    f(table->table, d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   161
    f(table, d);
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   162
} // hash_destroy
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   163
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   164
int hash_remove(HashTable *table, const void *key)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   165
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   166
    HashItem *item = NULL;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   167
    HashItem *prev = NULL;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   168
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   169
    const uint32 hash = calc_hash(table, key);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   170
    for (item = table->table[hash]; item != NULL; item = item->next)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   171
    {
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   172
        if (table->keymatch(key, item->key, data))
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   173
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   174
            if (prev != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   175
                prev->next = item->next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   176
            else
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   177
                table->table[hash] = item->next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   178
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   179
            table->nuke(item->key, item->value, data);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   180
            table->f(item, table->d);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   181
            return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   182
        } // if
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   183
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   184
        prev = item;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   185
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   186
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   187
    return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   188
} // hash_remove
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   189
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   190
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   191
// this is djb's xor hashing function.
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   192
static inline uint32 hash_string_djbxor(const char *str, size_t len)
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   193
{
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   194
    register uint32 hash = 5381;
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   195
    while (len--)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   196
        hash = ((hash << 5) + hash) ^ *(str++);
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   197
    return hash;
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   198
} // hash_string_djbxor
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   199
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   200
static inline uint32 hash_string(const char *str, size_t len)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   201
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   202
    return hash_string_djbxor(str, len);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   203
} // hash_string
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   204
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   205
uint32 hash_hash_string(const void *sym, void *data)
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   206
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   207
    (void) data;
870
f9e20269c20b make compile on MSVC, and fix stringmap_insert
Aras Pranckevicius <aras@unity3d.com>
parents: 860
diff changeset
   208
    return hash_string((const char*) sym, strlen((const char *) sym));
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   209
} // hash_hash_string
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   210
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   211
int hash_keymatch_string(const void *a, const void *b, void *data)
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   212
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   213
    (void) data;
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   214
    return (strcmp((const char *) a, (const char *) b) == 0);
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   215
} // hash_keymatch_string
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   216
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   217
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   218
// string -> string map...
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   219
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   220
static void stringmap_nuke_noop(const void *key, const void *val, void *d) {}
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   221
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   222
static void stringmap_nuke(const void *key, const void *val, void *d)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   223
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   224
    StringMap *smap = (StringMap *) d;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   225
    smap->f((void *) key, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   226
    smap->f((void *) val, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   227
} // stringmap_nuke
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   228
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   229
StringMap *stringmap_create(const int copy, MOJOSHADER_malloc m,
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   230
                            MOJOSHADER_free f, void *d)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   231
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   232
    HashTable_NukeFn nuke = copy ? stringmap_nuke : stringmap_nuke_noop;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   233
    StringMap *smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   234
    smap = hash_create(0,hash_hash_string,hash_keymatch_string,nuke,0,m,f,d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   235
    smap->data = smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   236
    return smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   237
} // stringmap_create
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   238
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   239
void stringmap_destroy(StringMap *smap)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   240
{
963
5a8f7ef13735 Removed return statement from void function.
Ryan C. Gordon <icculus@icculus.org>
parents: 956
diff changeset
   241
    hash_destroy(smap);
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   242
} // stringmap_destroy
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   243
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   244
int stringmap_insert(StringMap *smap, const char *key, const char *value)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   245
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   246
    assert(key != NULL);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   247
    if (smap->nuke == stringmap_nuke_noop)  // no copy?
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   248
        return hash_insert(smap, key, value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   249
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   250
    int rc = -1;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   251
    char *k = (char *) smap->m(strlen(key) + 1, smap->d);
870
f9e20269c20b make compile on MSVC, and fix stringmap_insert
Aras Pranckevicius <aras@unity3d.com>
parents: 860
diff changeset
   252
    char *v = (char *) (value ? smap->m(strlen(value) + 1, smap->d) : NULL);
1059
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   253
    int failed = ( (!k) || ((!v) && (value)) );
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   254
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   255
    if (!failed)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   256
    {
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   257
        strcpy(k, key);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   258
        if (value != NULL)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   259
            strcpy(v, value);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   260
        failed = ((rc = hash_insert(smap, k, v)) <= 0);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   261
    } // if
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   262
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   263
    if (failed)
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   264
    {
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   265
        smap->f(k, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   266
        smap->f(v, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   267
    } // if
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   268
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   269
    return rc;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   270
} // stringmap_insert
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   271
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   272
int stringmap_remove(StringMap *smap, const char *key)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   273
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   274
    return hash_remove(smap, key);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   275
} // stringmap_remove
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   276
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   277
int stringmap_find(const StringMap *smap, const char *key, const char **_value)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   278
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   279
    const void *value = NULL;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   280
    const int retval = hash_find(smap, key, &value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   281
    *_value = (const char *) value;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   282
    return retval;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   283
} // stringmap_find
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   284
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   285
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   286
// The string cache...   !!! FIXME: use StringMap internally for this.
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   287
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   288
typedef struct StringBucket
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   289
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   290
    char *string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   291
    struct StringBucket *next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   292
} StringBucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   293
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   294
struct StringCache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   295
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   296
    StringBucket **hashtable;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   297
    uint32 table_size;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   298
    MOJOSHADER_malloc m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   299
    MOJOSHADER_free f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   300
    void *d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   301
};
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   302
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   303
const char *stringcache(StringCache *cache, const char *str)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   304
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   305
    return stringcache_len(cache, str, strlen(str));
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   306
} // stringcache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   307
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   308
const char *stringcache_len(StringCache *cache, const char *str,
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   309
                             const unsigned int len)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   310
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   311
    const uint8 hash = hash_string(str, len) & (cache->table_size-1);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   312
    StringBucket *bucket = cache->hashtable[hash];
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   313
    StringBucket *prev = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   314
    while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   315
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   316
        const char *bstr = bucket->string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   317
        if ((strncmp(bstr, str, len) == 0) && (bstr[len] == 0))
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   318
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   319
            // Matched! Move this to the front of the list.
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   320
            if (prev != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   321
            {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   322
                assert(prev->next == bucket);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   323
                prev->next = bucket->next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   324
                bucket->next = cache->hashtable[hash];
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   325
                cache->hashtable[hash] = bucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   326
            } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   327
            return bstr; // already cached
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   328
        } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   329
        prev = bucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   330
        bucket = bucket->next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   331
    } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   332
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   333
    // no match, add to the table.
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   334
    bucket = (StringBucket *) cache->m(sizeof (StringBucket), cache->d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   335
    if (bucket == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   336
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   337
    bucket->string = (char *) cache->m(len + 1, cache->d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   338
    if (bucket->string == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   339
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   340
        cache->f(bucket, cache->d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   341
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   342
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   343
    memcpy(bucket->string, str, len);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   344
    bucket->string[len] = '\0';
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   345
    bucket->next = cache->hashtable[hash];
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   346
    cache->hashtable[hash] = bucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   347
    return bucket->string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   348
} // stringcache_len
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   349
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   350
const char *stringcache_fmt(StringCache *cache, const char *fmt, ...)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   351
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   352
    char buf[128];  // use the stack if reasonable.
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   353
    char *ptr = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   354
    int len = 0;  // number of chars, NOT counting null-terminator!
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   355
    va_list ap;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   356
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   357
    va_start(ap, fmt);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   358
    len = vsnprintf(buf, sizeof (buf), fmt, ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   359
    va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   360
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   361
    if (len > sizeof (buf))
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   362
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   363
        ptr = (char *) cache->m(len, cache->d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   364
        if (ptr == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   365
            return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   366
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   367
        va_start(ap, fmt);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   368
        vsnprintf(ptr, len, fmt, ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   369
        va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   370
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   371
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   372
    const char *retval = stringcache_len(cache, ptr ? ptr : buf, len);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   373
    if (ptr != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   374
        cache->f(ptr, cache->d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   375
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   376
    return retval;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   377
} // stringcache_fmt
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   378
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   379
StringCache *stringcache_create(MOJOSHADER_malloc m, MOJOSHADER_free f, void *d)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   380
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   381
    const uint32 initial_table_size = 256;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   382
    const size_t tablelen = sizeof (StringBucket *) * initial_table_size;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   383
    StringCache *cache = (StringCache *) m(sizeof (StringCache), d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   384
    if (!cache)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   385
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   386
    memset(cache, '\0', sizeof (StringCache));
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   387
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   388
    cache->hashtable = (StringBucket **) m(tablelen, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   389
    if (!cache->hashtable)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   390
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   391
        f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   392
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   393
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   394
    memset(cache->hashtable, '\0', tablelen);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   395
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   396
    cache->table_size = initial_table_size;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   397
    cache->m = m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   398
    cache->f = f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   399
    cache->d = d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   400
    return cache;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   401
} // stringcache_create
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   402
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   403
void stringcache_destroy(StringCache *cache)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   404
{
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   405
    if (cache == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   406
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   407
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   408
    MOJOSHADER_free f = cache->f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   409
    void *d = cache->d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   410
    size_t i;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   411
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   412
    for (i = 0; i < cache->table_size; i++)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   413
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   414
        StringBucket *bucket = cache->hashtable[i];
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   415
        cache->hashtable[i] = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   416
        while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   417
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   418
            StringBucket *next = bucket->next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   419
            f(bucket->string, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   420
            f(bucket, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   421
            bucket = next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   422
        } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   423
    } // for
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   424
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   425
    f(cache->hashtable, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   426
    f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   427
} // stringcache_destroy
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   428
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   429
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   430
// We chain errors as a linked list with a head/tail for easy appending.
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   431
//  These get flattened before passing to the application.
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   432
typedef struct ErrorItem
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   433
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   434
    MOJOSHADER_error error;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   435
    struct ErrorItem *next;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   436
} ErrorItem;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   437
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   438
struct ErrorList
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   439
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   440
    ErrorItem head;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   441
    ErrorItem *tail;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   442
    int count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   443
    MOJOSHADER_malloc m;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   444
    MOJOSHADER_free f;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   445
    void *d;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   446
};
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   447
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   448
ErrorList *errorlist_create(MOJOSHADER_malloc m, MOJOSHADER_free f, void *d)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   449
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   450
    ErrorList *retval = (ErrorList *) m(sizeof (ErrorList), d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   451
    if (retval != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   452
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   453
        memset(retval, '\0', sizeof (ErrorList));
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   454
        retval->tail = &retval->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   455
        retval->m = m;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   456
        retval->f = f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   457
        retval->d = d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   458
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   459
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   460
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   461
} // errorlist_create
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   462
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   463
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   464
int errorlist_add(ErrorList *list, const char *fname,
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   465
                  const int errpos, const char *str)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   466
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   467
    return errorlist_add_fmt(list, fname, errpos, "%s", str);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   468
} // errorlist_add
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   469
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   470
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   471
int errorlist_add_fmt(ErrorList *list, const char *fname,
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   472
                      const int errpos, const char *fmt, ...)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   473
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   474
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   475
    va_start(ap, fmt);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   476
    const int retval = errorlist_add_va(list, fname, errpos, fmt, ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   477
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   478
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   479
} // errorlist_add_fmt
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   480
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   481
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   482
int errorlist_add_va(ErrorList *list, const char *_fname,
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   483
                     const int errpos, const char *fmt, va_list va)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   484
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   485
    ErrorItem *error = (ErrorItem *) list->m(sizeof (ErrorItem), list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   486
    if (error == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   487
        return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   488
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   489
    char *fname = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   490
    if (_fname != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   491
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   492
        fname = (char *) list->m(strlen(_fname) + 1, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   493
        if (fname == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   494
        {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   495
            list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   496
            return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   497
        } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   498
        strcpy(fname, _fname);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   499
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   500
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   501
    char scratch[128];
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   502
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   503
    va_copy(ap, va);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   504
    const int len = vsnprintf(scratch, sizeof (scratch), fmt, ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   505
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   506
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   507
    char *failstr = (char *) list->m(len + 1, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   508
    if (failstr == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   509
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   510
        list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   511
        list->f(fname, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   512
        return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   513
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   514
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   515
    // If we overflowed our scratch buffer, that's okay. We were going to
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   516
    //  allocate anyhow...the scratch buffer just lets us avoid a second
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   517
    //  run of vsnprintf().
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   518
    if (len < sizeof (scratch))
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   519
        strcpy(failstr, scratch);  // copy it over.
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   520
    else
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   521
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   522
        va_copy(ap, va);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   523
        vsnprintf(failstr, len + 1, fmt, ap);  // rebuild it.
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   524
        va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   525
    } // else
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   526
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   527
    error->error.error = failstr;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   528
    error->error.filename = fname;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   529
    error->error.error_position = errpos;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   530
    error->next = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   531
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   532
    list->tail->next = error;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   533
    list->tail = error;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   534
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   535
    list->count++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   536
    return 1;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   537
} // errorlist_add_va
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   538
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   539
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   540
int errorlist_count(ErrorList *list)
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   541
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   542
    return list->count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   543
} // errorlist_count
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   544
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   545
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   546
MOJOSHADER_error *errorlist_flatten(ErrorList *list)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   547
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   548
    if (list->count == 0)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   549
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   550
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   551
    int total = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   552
    MOJOSHADER_error *retval = (MOJOSHADER_error *)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   553
            list->m(sizeof (MOJOSHADER_error) * list->count, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   554
    if (retval == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   555
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   556
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   557
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   558
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   559
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   560
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   561
        // reuse the string allocations
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   562
        memcpy(&retval[total], &item->error, sizeof (MOJOSHADER_error));
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   563
        list->f(item, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   564
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   565
        total++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   566
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   567
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   568
    assert(total == list->count);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   569
    list->count = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   570
    list->head.next = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   571
    list->tail = &list->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   572
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   573
} // errorlist_flatten
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   574
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   575
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   576
void errorlist_destroy(ErrorList *list)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   577
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   578
    if (list == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   579
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   580
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   581
    MOJOSHADER_free f = list->f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   582
    void *d = list->d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   583
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   584
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   585
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   586
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   587
        f((void *) item->error.error, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   588
        f((void *) item->error.filename, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   589
        f(item, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   590
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   591
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   592
    f(list, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   593
} // errorlist_destroy
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   594
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   595
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   596
typedef struct BufferBlock
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   597
{
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   598
    uint8 *data;
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   599
    size_t bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   600
    struct BufferBlock *next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   601
} BufferBlock;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   602
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   603
struct Buffer
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   604
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   605
    size_t total_bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   606
    BufferBlock *head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   607
    BufferBlock *tail;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   608
    size_t block_size;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   609
    MOJOSHADER_malloc m;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   610
    MOJOSHADER_free f;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   611
    void *d;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   612
};
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   613
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   614
Buffer *buffer_create(size_t blksz, MOJOSHADER_malloc m,
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   615
                      MOJOSHADER_free f, void *d)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   616
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   617
    Buffer *buffer = (Buffer *) m(sizeof (Buffer), d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   618
    if (buffer != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   619
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   620
        memset(buffer, '\0', sizeof (Buffer));
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   621
        buffer->block_size = blksz;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   622
        buffer->m = m;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   623
        buffer->f = f;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   624
        buffer->d = d;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   625
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   626
    return buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   627
} // buffer_create
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   628
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   629
char *buffer_reserve(Buffer *buffer, const size_t len)
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   630
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   631
    // note that we make the blocks bigger than blocksize when we have enough
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   632
    //  data to overfill a fresh block, to reduce allocations.
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   633
    const size_t blocksize = buffer->block_size;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   634
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   635
    if (len == 0)
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   636
        return NULL;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   637
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   638
    if (buffer->tail != NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   639
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   640
        const size_t tailbytes = buffer->tail->bytes;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   641
        const size_t avail = (tailbytes >= blocksize) ? 0 : blocksize - tailbytes;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   642
        if (len <= avail)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   643
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   644
            buffer->tail->bytes += len;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   645
            buffer->total_bytes += len;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   646
            assert(buffer->tail->bytes <= blocksize);
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   647
            return (char *) buffer->tail->data + tailbytes;
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   648
        } // if
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   649
    } // if
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   650
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   651
    // need to allocate a new block (even if a previous block wasn't filled,
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   652
    //  so this buffer is contiguous).
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   653
    const size_t bytecount = len > blocksize ? len : blocksize;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   654
    const size_t malloc_len = sizeof (BufferBlock) + bytecount;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   655
    BufferBlock *item = (BufferBlock *) buffer->m(malloc_len, buffer->d);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   656
    if (item == NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   657
        return NULL;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   658
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   659
    item->data = ((uint8 *) item) + sizeof (BufferBlock);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   660
    item->bytes = len;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   661
    item->next = NULL;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   662
    if (buffer->tail != NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   663
        buffer->tail->next = item;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   664
    else
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   665
        buffer->head = item;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   666
    buffer->tail = item;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   667
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   668
    buffer->total_bytes += len;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   669
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   670
    return (char *) item->data;
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   671
} // buffer_reserve
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   672
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   673
int buffer_append(Buffer *buffer, const void *_data, size_t len)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   674
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   675
    const uint8 *data = (const uint8 *) _data;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   676
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   677
    // note that we make the blocks bigger than blocksize when we have enough
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   678
    //  data to overfill a fresh block, to reduce allocations.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   679
    const size_t blocksize = buffer->block_size;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   680
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   681
    if (len == 0)
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   682
        return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   683
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   684
    if (buffer->tail != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   685
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   686
        const size_t tailbytes = buffer->tail->bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   687
        const size_t avail = (tailbytes >= blocksize) ? 0 : blocksize - tailbytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   688
        const size_t cpy = (avail > len) ? len : avail;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   689
        if (cpy > 0)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   690
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   691
            memcpy(buffer->tail->data + tailbytes, data, cpy);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   692
            len -= cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   693
            data += cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   694
            buffer->tail->bytes += cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   695
            buffer->total_bytes += cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   696
            assert(buffer->tail->bytes <= blocksize);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   697
        } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   698
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   699
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   700
    if (len > 0)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   701
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   702
        assert((!buffer->tail) || (buffer->tail->bytes == blocksize));
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   703
        const size_t bytecount = len > blocksize ? len : blocksize;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   704
        const size_t malloc_len = sizeof (BufferBlock) + bytecount;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   705
        BufferBlock *item = (BufferBlock *) buffer->m(malloc_len, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   706
        if (item == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   707
            return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   708
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   709
        item->data = ((uint8 *) item) + sizeof (BufferBlock);
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   710
        item->bytes = len;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   711
        item->next = NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   712
        if (buffer->tail != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   713
            buffer->tail->next = item;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   714
        else
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   715
            buffer->head = item;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   716
        buffer->tail = item;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   717
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   718
        memcpy(item->data, data, len);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   719
        buffer->total_bytes += len;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   720
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   721
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   722
    return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   723
} // buffer_append
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   724
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   725
int buffer_append_fmt(Buffer *buffer, const char *fmt, ...)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   726
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   727
    va_list ap;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   728
    va_start(ap, fmt);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   729
    const int retval = buffer_append_va(buffer, fmt, ap);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   730
    va_end(ap);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   731
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   732
} // buffer_append_fmt
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   733
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   734
int buffer_append_va(Buffer *buffer, const char *fmt, va_list va)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   735
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   736
    char scratch[128];
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   737
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   738
    va_list ap;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   739
    va_copy(ap, va);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   740
    const int len = vsnprintf(scratch, sizeof (scratch), fmt, ap);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   741
    va_end(ap);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   742
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   743
    // If we overflowed our scratch buffer, heap allocate and try again.
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   744
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   745
    if (len == 0)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   746
        return 1;  // nothing to do.
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   747
    else if (len < sizeof (scratch))
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   748
        return buffer_append(buffer, scratch, len);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   749
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   750
    char *buf = (char *) buffer->m(len + 1, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   751
    if (buf == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   752
        return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   753
    va_copy(ap, va);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   754
    vsnprintf(buf, len + 1, fmt, ap);  // rebuild it.
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   755
    va_end(ap);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   756
    const int retval = buffer_append(buffer, scratch, len);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   757
    buffer->f(buf, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   758
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   759
} // buffer_append_va
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   760
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   761
size_t buffer_size(Buffer *buffer)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   762
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   763
    return buffer->total_bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   764
} // buffer_size
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   765
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   766
void buffer_empty(Buffer *buffer)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   767
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   768
    BufferBlock *item = buffer->head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   769
    while (item != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   770
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   771
        BufferBlock *next = item->next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   772
        buffer->f(item, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   773
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   774
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   775
    buffer->head = buffer->tail = NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   776
    buffer->total_bytes = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   777
} // buffer_empty
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   778
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   779
char *buffer_flatten(Buffer *buffer)
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   780
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   781
    char *retval = (char *) buffer->m(buffer->total_bytes + 1, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   782
    if (retval == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   783
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   784
    BufferBlock *item = buffer->head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   785
    char *ptr = retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   786
    while (item != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   787
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   788
        BufferBlock *next = item->next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   789
        memcpy(ptr, item->data, item->bytes);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   790
        ptr += item->bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   791
        buffer->f(item, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   792
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   793
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   794
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   795
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   796
    assert(ptr == (retval + buffer->total_bytes));
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   797
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   798
    buffer->head = buffer->tail = NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   799
    buffer->total_bytes = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   800
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   801
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   802
} // buffer_flatten
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   803
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   804
char *buffer_merge(Buffer **buffers, const size_t n, size_t *_len)
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   805
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   806
    Buffer *first = NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   807
    size_t len = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   808
    size_t i;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   809
    for (i = 0; i < n; i++)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   810
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   811
        Buffer *buffer = buffers[i];
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   812
        if (buffer == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   813
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   814
        if (first == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   815
            first = buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   816
        len += buffer->total_bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   817
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   818
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   819
    char *retval = (char *) (first ? first->m(len + 1, first->d) : NULL);
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   820
    if (retval == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   821
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   822
        *_len = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   823
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   824
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   825
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   826
    *_len = len;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   827
    char *ptr = retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   828
    for (i = 0; i < n; i++)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   829
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   830
        Buffer *buffer = buffers[i];
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   831
        if (buffer == NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   832
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   833
        BufferBlock *item = buffer->head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   834
        while (item != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   835
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   836
            BufferBlock *next = item->next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   837
            memcpy(ptr, item->data, item->bytes);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   838
            ptr += item->bytes;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   839
            buffer->f(item, buffer->d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   840
            item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   841
        } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   842
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   843
        buffer->head = buffer->tail = NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   844
        buffer->total_bytes = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   845
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   846
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   847
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   848
    assert(ptr == (retval + len));
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   849
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   850
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   851
} // buffer_merge
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   852
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   853
void buffer_destroy(Buffer *buffer)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   854
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   855
    if (buffer != NULL)
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   856
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   857
        MOJOSHADER_free f = buffer->f;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   858
        void *d = buffer->d;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   859
        buffer_empty(buffer);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   860
        f(buffer, d);
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   861
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   862
} // buffer_destroy
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   863
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   864
static int blockscmp(BufferBlock *item, const uint8 *data, size_t len)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   865
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   866
    if (len == 0)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   867
        return 1;  // "match"
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   868
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   869
    while (item != NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   870
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   871
        const size_t itemremain = item->bytes;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   872
        const size_t avail = len < itemremain ? len : itemremain;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   873
        if (memcmp(item->data, data, avail) != 0)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   874
            return 0;  // not a match.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   875
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   876
        if (len == avail)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   877
            return 1;   // complete match!
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   878
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   879
        len -= avail;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   880
        data += avail;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   881
        item = item->next;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   882
    } // while
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   883
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   884
    return 0;  // not a complete match.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   885
} // blockscmp
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   886
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   887
ssize_t buffer_find(Buffer *buffer, const size_t start,
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   888
                    const void *_data, const size_t len)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   889
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   890
    if (len == 0)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   891
        return 0;  // I guess that's right.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   892
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   893
    if (start >= buffer->total_bytes)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   894
        return -1;  // definitely can't match.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   895
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   896
    if (len > (buffer->total_bytes - start))
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   897
        return -1;  // definitely can't match.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   898
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   899
    // Find the start point somewhere in the center of a buffer.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   900
    BufferBlock *item = buffer->head;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   901
    const uint8 *ptr = item->data;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   902
    size_t pos = 0;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   903
    if (start > 0)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   904
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   905
        while (1)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   906
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   907
            assert(item != NULL);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   908
            if ((pos + item->bytes) > start)  // start is in this block.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   909
            {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   910
                ptr = item->data + (start - pos);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   911
                break;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   912
            } // if
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   913
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   914
            pos += item->bytes;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   915
            item = item->next;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   916
        } // while
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   917
    } // if
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   918
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   919
    // okay, we're at the origin of the search.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   920
    assert(item != NULL);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   921
    assert(ptr != NULL);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   922
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   923
    const uint8 *data = (const uint8 *) _data;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   924
    const uint8 first = *data;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   925
    while (item != NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   926
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   927
        const size_t itemremain = item->bytes - ((size_t)(ptr-item->data));
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   928
        ptr = (uint8 *) memchr(ptr, first, itemremain);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   929
        while (ptr != NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   930
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   931
            const size_t retval = pos + ((size_t) (ptr - item->data));
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   932
            if (len == 1)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   933
                return retval;  // we're done, here it is!
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   934
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   935
            const size_t itemremain = item->bytes - ((size_t)(ptr-item->data));
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   936
            const size_t avail = len < itemremain ? len : itemremain;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   937
            if ((avail == 0) || (memcmp(ptr, data, avail) == 0))
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   938
            {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   939
                // okay, we've got a (sub)string match! Move to the next block.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   940
                // check all blocks until we get a complete match or a failure.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   941
                if (blockscmp(item->next, data+avail, len-avail))
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   942
                    return (ssize_t) retval;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   943
            } // if
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   944
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   945
            // try again, further in this block.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   946
            ptr = (uint8 *) memchr(ptr + 1, first, itemremain - 1);
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   947
        } // while
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   948
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   949
        pos += item->bytes;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   950
        item = item->next;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   951
        if (item != NULL)
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   952
            ptr = item->data;
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   953
    } // while
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   954
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   955
    return -1;  // no match found.
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   956
} // buffer_find
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   957
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   958
// end of mojoshader_common.c ...
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   959