mojoshader_common.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 16 Apr 2013 00:52:22 -0400
changeset 1126 91c22d2de774
parent 1116 0ef3d106dab9
child 1140 fad7ed946c06
permissions -rw-r--r--
Let "#if ((0) + (1) < 2)" understand that '+' isn't a unary operation.
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
{
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    65
    HashItem *item = *iter;
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    66
    if (item == NULL)
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    67
        item = table->table[calc_hash(table, key)];
965
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
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    69
        item = item->next;
965
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    70
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    71
    while (item != NULL)
965
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    72
    {
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    73
        if (table->keymatch(key, item->key, table->data))
965
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    74
        {
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    75
            *_value = item->value;
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    76
            *iter = item;
965
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
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    79
        item = item->next;
965
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
1065
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    88
int hash_iter_keys(const HashTable *table, const void **_key, void **iter)
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    89
{
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    90
    HashItem *item = *iter;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    91
    int idx = 0;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    92
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    93
    if (item != NULL)
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    94
    {
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    95
        const HashItem *orig = item;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    96
        item = item->next;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    97
        if (item == NULL)
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    98
            idx = calc_hash(table, orig->key) + 1;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
    99
    } // if
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   100
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   101
    while (!item && (idx < table->table_len))
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   102
        item = table->table[idx++];  // skip empty buckets...
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   103
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   104
    if (item == NULL)  // no more matches?
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   105
    {
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   106
        *_key = NULL;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   107
        *iter = NULL;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   108
        return 0;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   109
    } // if
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   110
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   111
    *_key = item->key;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   112
    *iter = item;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   113
    return 1;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   114
} // hash_iter_keys
965
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
   115
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   116
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
   117
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   118
    HashItem *item = NULL;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   119
    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
   120
    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
   121
        return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   122
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   123
    // !!! 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
   124
    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
   125
    if (item == NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   126
        return -1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   127
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   128
    item->key = key;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   129
    item->value = value;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   130
    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
   131
    table->table[hash] = item;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   132
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   133
    return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   134
} // hash_insert
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   135
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   136
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
   137
              const HashTable_KeyMatchFn keymatchfn,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   138
              const HashTable_NukeFn nukefn,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   139
              const int stackable,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   140
              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
   141
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   142
    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
   143
    const uint32 alloc_len = sizeof (HashItem *) * initial_table_size;
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   144
    HashTable *table = (HashTable *) m(sizeof (HashTable), d);
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   145
    if (table == NULL)
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   146
        return NULL;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   147
    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
   148
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   149
    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
   150
    if (table->table == NULL)
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   151
    {
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   152
        f(table, d);
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   153
        return NULL;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   154
    } // if
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   155
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   156
    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
   157
    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
   158
    table->stackable = stackable;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   159
    table->data = data;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   160
    table->hash = hashfn;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   161
    table->keymatch = keymatchfn;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   162
    table->nuke = nukefn;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   163
    table->m = m;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   164
    table->f = f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   165
    table->d = d;
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   166
    return table;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   167
} // hash_create
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   168
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   169
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
   170
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   171
    uint32 i;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   172
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   173
    MOJOSHADER_free f = table->f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   174
    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
   175
    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
   176
    {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   177
        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
   178
        while (item != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   179
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   180
            HashItem *next = item->next;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   181
            table->nuke(item->key, item->value, data);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   182
            f(item, d);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   183
            item = next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   184
        } // while
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
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   187
    f(table->table, d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   188
    f(table, d);
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   189
} // hash_destroy
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   190
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   191
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
   192
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   193
    HashItem *item = NULL;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   194
    HashItem *prev = NULL;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   195
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   196
    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
   197
    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
   198
    {
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   199
        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
   200
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   201
            if (prev != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   202
                prev->next = item->next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   203
            else
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   204
                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
   205
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   206
            table->nuke(item->key, item->value, data);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   207
            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
   208
            return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   209
        } // if
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   210
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   211
        prev = item;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   212
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   213
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   214
    return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   215
} // hash_remove
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   216
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   217
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   218
// 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
   219
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
   220
{
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   221
    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
   222
    while (len--)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   223
        hash = ((hash << 5) + hash) ^ *(str++);
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   224
    return hash;
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   225
} // hash_string_djbxor
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   226
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   227
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
   228
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   229
    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
   230
} // hash_string
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   231
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   232
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
   233
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   234
    (void) data;
870
f9e20269c20b make compile on MSVC, and fix stringmap_insert
Aras Pranckevicius <aras@unity3d.com>
parents: 860
diff changeset
   235
    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
   236
} // hash_hash_string
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   237
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   238
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
   239
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   240
    (void) data;
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   241
    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
   242
} // hash_keymatch_string
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   243
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   244
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   245
// string -> string map...
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   246
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   247
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
   248
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   249
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
   250
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   251
    StringMap *smap = (StringMap *) d;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   252
    smap->f((void *) key, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   253
    smap->f((void *) val, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   254
} // stringmap_nuke
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   255
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   256
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
   257
                            MOJOSHADER_free f, void *d)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   258
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   259
    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
   260
    StringMap *smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   261
    smap = hash_create(0,hash_hash_string,hash_keymatch_string,nuke,0,m,f,d);
1111
7530b37979b8 Some static analysis fixes from Clang 4.0.
Ryan C. Gordon <icculus@icculus.org>
parents: 1080
diff changeset
   262
    if (smap != NULL)
7530b37979b8 Some static analysis fixes from Clang 4.0.
Ryan C. Gordon <icculus@icculus.org>
parents: 1080
diff changeset
   263
        smap->data = smap;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   264
    return smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   265
} // stringmap_create
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   266
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   267
void stringmap_destroy(StringMap *smap)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   268
{
963
5a8f7ef13735 Removed return statement from void function.
Ryan C. Gordon <icculus@icculus.org>
parents: 956
diff changeset
   269
    hash_destroy(smap);
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   270
} // stringmap_destroy
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_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
   273
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   274
    assert(key != NULL);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   275
    if (smap->nuke == stringmap_nuke_noop)  // no copy?
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   276
        return hash_insert(smap, key, value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   277
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   278
    int rc = -1;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   279
    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
   280
    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
   281
    int failed = ( (!k) || ((!v) && (value)) );
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   282
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   283
    if (!failed)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   284
    {
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   285
        strcpy(k, key);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   286
        if (value != NULL)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   287
            strcpy(v, value);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   288
        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
   289
    } // if
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   290
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   291
    if (failed)
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   292
    {
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   293
        smap->f(k, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   294
        smap->f(v, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   295
    } // if
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   296
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   297
    return rc;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   298
} // stringmap_insert
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   299
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   300
int stringmap_remove(StringMap *smap, const char *key)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   301
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   302
    return hash_remove(smap, key);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   303
} // stringmap_remove
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   304
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   305
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
   306
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   307
    const void *value = NULL;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   308
    const int retval = hash_find(smap, key, &value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   309
    *_value = (const char *) value;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   310
    return retval;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   311
} // stringmap_find
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   312
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   313
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   314
// 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
   315
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   316
typedef struct StringBucket
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   317
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   318
    char *string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   319
    struct StringBucket *next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   320
} StringBucket;
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
struct StringCache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   323
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   324
    StringBucket **hashtable;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   325
    uint32 table_size;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   326
    MOJOSHADER_malloc m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   327
    MOJOSHADER_free f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   328
    void *d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   329
};
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   330
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   331
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   332
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
   333
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   334
    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
   335
} // stringcache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   336
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   337
static const char *stringcache_len_internal(StringCache *cache,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   338
                                            const char *str,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   339
                                            const unsigned int len,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   340
                                            const int addmissing)
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   341
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   342
    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
   343
    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
   344
    StringBucket *prev = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   345
    while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   346
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   347
        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
   348
        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
   349
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   350
            // 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
   351
            if (prev != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   352
            {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   353
                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
   354
                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
   355
                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
   356
                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
   357
            } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   358
            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
   359
        } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   360
        prev = bucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   361
        bucket = bucket->next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   362
    } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   363
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   364
    // no match!
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   365
    if (!addmissing)
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   366
        return NULL;
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   367
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   368
    // add to the table.
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   369
    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
   370
    if (bucket == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   371
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   372
    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
   373
    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
   374
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   375
        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
   376
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   377
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   378
    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
   379
    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
   380
    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
   381
    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
   382
    return bucket->string;
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   383
} // stringcache_len_internal
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   384
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   385
const char *stringcache_len(StringCache *cache, const char *str,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   386
                            const unsigned int len)
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   387
{
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   388
    return stringcache_len_internal(cache, str, len, 1);
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   389
} // stringcache_len
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   390
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   391
int stringcache_iscached(StringCache *cache, const char *str)
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   392
{
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   393
    return (stringcache_len_internal(cache, str, strlen(str), 0) != NULL);
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   394
} // stringcache_iscached
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   395
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   396
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
   397
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   398
    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
   399
    char *ptr = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   400
    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
   401
    va_list ap;
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
    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
   404
    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
   405
    va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   406
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   407
    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
   408
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   409
        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
   410
        if (ptr == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   411
            return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   412
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   413
        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
   414
        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
   415
        va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   416
    } // if
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
    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
   419
    if (ptr != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   420
        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
   421
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   422
    return retval;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   423
} // stringcache_fmt
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
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
   426
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   427
    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
   428
    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
   429
    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
   430
    if (!cache)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   431
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   432
    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
   433
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   434
    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
   435
    if (!cache->hashtable)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   436
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   437
        f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   438
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   439
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   440
    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
   441
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   442
    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
   443
    cache->m = m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   444
    cache->f = f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   445
    cache->d = d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   446
    return cache;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   447
} // stringcache_create
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   448
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   449
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
   450
{
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   451
    if (cache == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   452
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   453
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   454
    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
   455
    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
   456
    size_t i;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   457
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   458
    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
   459
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   460
        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
   461
        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
   462
        while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   463
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   464
            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
   465
            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
   466
            f(bucket, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   467
            bucket = next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   468
        } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   469
    } // for
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   470
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   471
    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
   472
    f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   473
} // stringcache_destroy
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   474
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   475
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   476
// 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
   477
//  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
   478
typedef struct ErrorItem
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   479
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   480
    MOJOSHADER_error error;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   481
    struct ErrorItem *next;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   482
} ErrorItem;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   483
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   484
struct ErrorList
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   485
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   486
    ErrorItem head;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   487
    ErrorItem *tail;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   488
    int count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   489
    MOJOSHADER_malloc m;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   490
    MOJOSHADER_free f;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   491
    void *d;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   492
};
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   493
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   494
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
   495
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   496
    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
   497
    if (retval != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   498
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   499
        memset(retval, '\0', sizeof (ErrorList));
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   500
        retval->tail = &retval->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   501
        retval->m = m;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   502
        retval->f = f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   503
        retval->d = d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   504
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   505
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   506
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   507
} // errorlist_create
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   508
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
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
   511
                  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
   512
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   513
    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
   514
} // errorlist_add
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   515
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   516
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   517
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
   518
                      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
   519
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   520
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   521
    va_start(ap, fmt);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   522
    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
   523
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   524
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   525
} // errorlist_add_fmt
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
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   528
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
   529
                     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
   530
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   531
    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
   532
    if (error == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   533
        return 0;
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
    char *fname = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   536
    if (_fname != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   537
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   538
        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
   539
        if (fname == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   540
        {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   541
            list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   542
            return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   543
        } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   544
        strcpy(fname, _fname);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   545
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   546
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   547
    char scratch[128];
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   548
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   549
    va_copy(ap, va);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   550
    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
   551
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   552
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   553
    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
   554
    if (failstr == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   555
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   556
        list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   557
        list->f(fname, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   558
        return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   559
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   560
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   561
    // 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
   562
    //  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
   563
    //  run of vsnprintf().
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   564
    if (len < sizeof (scratch))
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   565
        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
   566
    else
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
        va_copy(ap, va);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   569
        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
   570
        va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   571
    } // else
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   572
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   573
    error->error.error = failstr;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   574
    error->error.filename = fname;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   575
    error->error.error_position = errpos;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   576
    error->next = NULL;
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
    list->tail->next = error;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   579
    list->tail = error;
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
    list->count++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   582
    return 1;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   583
} // errorlist_add_va
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   584
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   585
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   586
int errorlist_count(ErrorList *list)
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   587
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   588
    return list->count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   589
} // errorlist_count
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   590
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   591
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   592
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
   593
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   594
    if (list->count == 0)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   595
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   596
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   597
    int total = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   598
    MOJOSHADER_error *retval = (MOJOSHADER_error *)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   599
            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
   600
    if (retval == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   601
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   602
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   603
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   604
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   605
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   606
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   607
        // reuse the string allocations
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   608
        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
   609
        list->f(item, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   610
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   611
        total++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   612
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   613
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   614
    assert(total == list->count);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   615
    list->count = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   616
    list->head.next = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   617
    list->tail = &list->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   618
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   619
} // errorlist_flatten
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   620
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   621
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   622
void errorlist_destroy(ErrorList *list)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   623
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   624
    if (list == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   625
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   626
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   627
    MOJOSHADER_free f = list->f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   628
    void *d = list->d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   629
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   630
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   631
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   632
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   633
        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
   634
        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
   635
        f(item, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   636
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   637
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   638
    f(list, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   639
} // errorlist_destroy
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   640
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   641
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   642
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
   643
{
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
   644
    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
   645
    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
   646
    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
   647
} BufferBlock;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   648
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   649
struct Buffer
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   650
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   651
    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
   652
    BufferBlock *head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   653
    BufferBlock *tail;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   654
    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
   655
    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
   656
    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
   657
    void *d;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   658
};
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   659
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   660
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
   661
                      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
   662
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   663
    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
   664
    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
   665
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   666
        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
   667
        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
   668
        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
   669
        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
   670
        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
   671
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   672
    return buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   673
} // buffer_create
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   674
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   675
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
   676
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   677
    // 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
   678
    //  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
   679
    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
   680
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   681
    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
   682
        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
   683
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   684
    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
   685
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   686
        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
   687
        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
   688
        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
   689
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   690
            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
   691
            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
   692
            assert(buffer->tail->bytes <= blocksize);
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   693
            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
   694
        } // 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
   695
    } // 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
   696
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   697
    // 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
   698
    //  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
   699
    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
   700
    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
   701
    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
   702
    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
   703
        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
   704
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   705
    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
   706
    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
   707
    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
   708
    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
   709
        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
   710
    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
   711
        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
   712
    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
   713
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   714
    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
   715
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   716
    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
   717
} // 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
   718
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   719
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
   720
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   721
    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
   722
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   723
    // 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
   724
    //  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
   725
    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
   726
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   727
    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
   728
        return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   729
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   730
    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
   731
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   732
        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
   733
        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
   734
        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
   735
        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
   736
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   737
            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
   738
            len -= cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   739
            data += cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   740
            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
   741
            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
   742
            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
   743
        } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   744
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   745
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   746
    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
   747
    {
1113
570cae807859 Fixed logic error.
Ryan C. Gordon <icculus@icculus.org>
parents: 1111
diff changeset
   748
        assert((!buffer->tail) || (buffer->tail->bytes >= blocksize));
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   749
        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
   750
        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
   751
        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
   752
        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
   753
            return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   754
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
   755
        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
   756
        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
   757
        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
   758
        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
   759
            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
   760
        else
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   761
            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
   762
        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
   763
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   764
        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
   765
        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
   766
    } // if
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
    return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   769
} // buffer_append
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
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
   772
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   773
    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
   774
    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
   775
    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
   776
    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
   777
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   778
} // 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
   779
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   780
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
   781
{
1080
b92bdbf78621 M4X4 opcode can actually overflow some string buffers.
Ryan C. Gordon <icculus@icculus.org>
parents: 1065
diff changeset
   782
    char scratch[256];
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   783
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   784
    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
   785
    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
   786
    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
   787
    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
   788
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   789
    // 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
   790
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   791
    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
   792
        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
   793
    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
   794
        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
   795
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   796
    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
   797
    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
   798
        return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   799
    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
   800
    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
   801
    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
   802
    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
   803
    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
   804
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   805
} // 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
   806
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 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
   808
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   809
    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
   810
} // buffer_size
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   811
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   812
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
   813
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   814
    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
   815
    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
   816
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   817
        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
   818
        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
   819
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   820
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   821
    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
   822
    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
   823
} // buffer_empty
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   824
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   825
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
   826
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   827
    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
   828
    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
   829
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   830
    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
   831
    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
   832
    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
   833
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   834
        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
   835
        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
   836
        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
   837
        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
   838
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   839
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   840
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   841
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   842
    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
   843
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   844
    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
   845
    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
   846
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   847
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   848
} // buffer_flatten
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   849
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   850
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
   851
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   852
    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
   853
    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
   854
    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
   855
    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
   856
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   857
        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
   858
        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
   859
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   860
        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
   861
            first = buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   862
        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
   863
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   864
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   865
    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
   866
    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
   867
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   868
        *_len = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   869
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   870
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   871
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   872
    *_len = len;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   873
    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
   874
    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
   875
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   876
        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
   877
        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
   878
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   879
        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
   880
        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
   881
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   882
            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
   883
            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
   884
            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
   885
            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
   886
            item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   887
        } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   888
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   889
        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
   890
        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
   891
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   892
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   893
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   894
    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
   895
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   896
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   897
} // buffer_merge
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   898
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   899
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
   900
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   901
    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
   902
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   903
        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
   904
        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
   905
        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
   906
        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
   907
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   908
} // buffer_destroy
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   909
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
   910
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
   911
{
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 (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
   913
        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
   914
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
    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
   916
    {
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
        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
   918
        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
   919
        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
   920
            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
   921
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
        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
   923
            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
   924
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
        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
   926
        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
   927
        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
   928
    } // 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
   929
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
    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
   931
} // 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
   932
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
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
   934
                    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
   935
{
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
    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
   937
        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
   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
    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
   940
        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
   941
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
    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
   943
        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
   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
    // 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
   946
    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
   947
    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
   948
    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
   949
    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
   950
    {
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
        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
   952
        {
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
            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
   954
            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
   955
            {
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
                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
   957
                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
   958
            } // 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
   959
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   960
            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
   961
            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
   962
        } // 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
   963
    } // 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
   964
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   965
    // 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
   966
    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
   967
    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
   968
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   969
    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
   970
    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
   971
    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
   972
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   973
        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
   974
        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
   975
        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
   976
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   977
            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
   978
            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
   979
                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
   980
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   981
            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
   982
            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
   983
            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
   984
            {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   985
                // 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
   986
                // 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
   987
                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
   988
                    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
   989
            } // 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
   990
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   991
            // 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
   992
            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
   993
        } // 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
   994
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   995
        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
   996
        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
   997
        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
   998
            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
   999
    } // 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
  1000
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1001
    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
  1002
} // 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
  1003
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
  1004
// 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
  1005