mojoshader_common.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 18 Apr 2012 00:19:32 -0400
changeset 1095 bc3d2c6e06cf
parent 1080 b92bdbf78621
child 1111 7530b37979b8
permissions -rw-r--r--
glsl: Implemented most of the missing srcmods. Reread the GLSL spec, and it turns out that "vec3(x,y,z) - 3.0" is legal syntactic sugar: the compiler knows to subtract 3.0 from each of the three components in that vec3. This made this simpler than having to tapdance to generate correct constant vectors ourselves, and it's easier to read.
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);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   262
    smap->data = smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   263
    return smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   264
} // stringmap_create
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   265
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   266
void stringmap_destroy(StringMap *smap)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   267
{
963
5a8f7ef13735 Removed return statement from void function.
Ryan C. Gordon <icculus@icculus.org>
parents: 956
diff changeset
   268
    hash_destroy(smap);
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   269
} // stringmap_destroy
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   270
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   271
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
   272
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   273
    assert(key != NULL);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   274
    if (smap->nuke == stringmap_nuke_noop)  // no copy?
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   275
        return hash_insert(smap, key, value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   276
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   277
    int rc = -1;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   278
    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
   279
    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
   280
    int failed = ( (!k) || ((!v) && (value)) );
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   281
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   282
    if (!failed)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   283
    {
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   284
        strcpy(k, key);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   285
        if (value != NULL)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   286
            strcpy(v, value);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   287
        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
   288
    } // if
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   289
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   290
    if (failed)
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   291
    {
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   292
        smap->f(k, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   293
        smap->f(v, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   294
    } // if
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   295
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   296
    return rc;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   297
} // stringmap_insert
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   298
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   299
int stringmap_remove(StringMap *smap, const char *key)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   300
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   301
    return hash_remove(smap, key);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   302
} // stringmap_remove
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   303
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   304
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
   305
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   306
    const void *value = NULL;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   307
    const int retval = hash_find(smap, key, &value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   308
    *_value = (const char *) value;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   309
    return retval;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   310
} // stringmap_find
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   311
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
// 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
   314
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   315
typedef struct StringBucket
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   316
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   317
    char *string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   318
    struct StringBucket *next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   319
} StringBucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   320
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   321
struct StringCache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   322
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   323
    StringBucket **hashtable;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   324
    uint32 table_size;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   325
    MOJOSHADER_malloc m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   326
    MOJOSHADER_free f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   327
    void *d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   328
};
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
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
   331
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   332
    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
   333
} // stringcache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   334
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   335
const char *stringcache_len(StringCache *cache, const char *str,
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   336
                             const unsigned int len)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   337
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   338
    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
   339
    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
   340
    StringBucket *prev = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   341
    while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   342
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   343
        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
   344
        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
   345
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   346
            // 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
   347
            if (prev != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   348
            {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   349
                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
   350
                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
   351
                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
   352
                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
   353
            } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   354
            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
   355
        } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   356
        prev = bucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   357
        bucket = bucket->next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   358
    } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   359
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   360
    // no match, add to the table.
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   361
    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
   362
    if (bucket == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   363
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   364
    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
   365
    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
   366
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   367
        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
   368
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   369
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   370
    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
   371
    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
   372
    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
   373
    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
   374
    return bucket->string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   375
} // stringcache_len
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   376
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   377
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
   378
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   379
    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
   380
    char *ptr = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   381
    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
   382
    va_list ap;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   383
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   384
    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
   385
    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
   386
    va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   387
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   388
    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
   389
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   390
        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
   391
        if (ptr == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   392
            return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   393
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   394
        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
   395
        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
   396
        va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   397
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   398
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   399
    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
   400
    if (ptr != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   401
        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
   402
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   403
    return retval;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   404
} // stringcache_fmt
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   405
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   406
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
   407
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   408
    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
   409
    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
   410
    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
   411
    if (!cache)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   412
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   413
    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
   414
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   415
    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
   416
    if (!cache->hashtable)
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
        f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   419
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   420
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   421
    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
   422
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   423
    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
   424
    cache->m = m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   425
    cache->f = f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   426
    cache->d = d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   427
    return cache;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   428
} // stringcache_create
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   429
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   430
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
   431
{
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   432
    if (cache == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   433
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   434
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   435
    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
   436
    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
   437
    size_t i;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   438
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   439
    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
   440
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   441
        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
   442
        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
   443
        while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   444
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   445
            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
   446
            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
   447
            f(bucket, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   448
            bucket = next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   449
        } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   450
    } // for
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   451
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   452
    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
   453
    f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   454
} // stringcache_destroy
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   455
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   456
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   457
// 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
   458
//  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
   459
typedef struct ErrorItem
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   460
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   461
    MOJOSHADER_error error;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   462
    struct ErrorItem *next;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   463
} ErrorItem;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   464
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   465
struct ErrorList
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   466
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   467
    ErrorItem head;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   468
    ErrorItem *tail;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   469
    int count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   470
    MOJOSHADER_malloc m;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   471
    MOJOSHADER_free f;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   472
    void *d;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   473
};
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   474
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   475
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
   476
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   477
    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
   478
    if (retval != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   479
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   480
        memset(retval, '\0', sizeof (ErrorList));
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   481
        retval->tail = &retval->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   482
        retval->m = m;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   483
        retval->f = f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   484
        retval->d = d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   485
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   486
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   487
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   488
} // errorlist_create
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   489
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   490
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   491
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
   492
                  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
   493
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   494
    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
   495
} // errorlist_add
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   496
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   497
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   498
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
   499
                      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
   500
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   501
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   502
    va_start(ap, fmt);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   503
    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
   504
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   505
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   506
} // errorlist_add_fmt
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   507
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
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
   510
                     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
   511
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   512
    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
   513
    if (error == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   514
        return 0;
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
    char *fname = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   517
    if (_fname != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   518
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   519
        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
   520
        if (fname == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   521
        {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   522
            list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   523
            return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   524
        } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   525
        strcpy(fname, _fname);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   526
    } // if
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
    char scratch[128];
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   529
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   530
    va_copy(ap, va);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   531
    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
   532
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   533
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   534
    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
   535
    if (failstr == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   536
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   537
        list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   538
        list->f(fname, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   539
        return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   540
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   541
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   542
    // 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
   543
    //  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
   544
    //  run of vsnprintf().
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   545
    if (len < sizeof (scratch))
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   546
        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
   547
    else
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   548
    {
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
        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
   551
        va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   552
    } // else
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   553
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   554
    error->error.error = failstr;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   555
    error->error.filename = fname;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   556
    error->error.error_position = errpos;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   557
    error->next = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   558
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   559
    list->tail->next = error;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   560
    list->tail = error;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   561
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   562
    list->count++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   563
    return 1;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   564
} // errorlist_add_va
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   565
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   566
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   567
int errorlist_count(ErrorList *list)
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   568
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   569
    return list->count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   570
} // errorlist_count
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   571
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   572
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   573
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
   574
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   575
    if (list->count == 0)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   576
        return 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
    int total = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   579
    MOJOSHADER_error *retval = (MOJOSHADER_error *)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   580
            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
   581
    if (retval == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   582
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   583
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   584
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   585
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   586
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   587
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   588
        // reuse the string allocations
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   589
        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
   590
        list->f(item, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   591
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   592
        total++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   593
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   594
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   595
    assert(total == list->count);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   596
    list->count = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   597
    list->head.next = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   598
    list->tail = &list->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   599
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   600
} // errorlist_flatten
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   601
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
void errorlist_destroy(ErrorList *list)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   604
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   605
    if (list == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   606
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   607
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   608
    MOJOSHADER_free f = list->f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   609
    void *d = list->d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   610
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   611
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   612
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   613
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   614
        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
   615
        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
   616
        f(item, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   617
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   618
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   619
    f(list, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   620
} // errorlist_destroy
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
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   623
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
   624
{
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
   625
    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
   626
    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
   627
    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
   628
} BufferBlock;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   629
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   630
struct Buffer
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   631
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   632
    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
   633
    BufferBlock *head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   634
    BufferBlock *tail;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   635
    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
   636
    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
   637
    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
   638
    void *d;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   639
};
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   640
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   641
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
   642
                      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
   643
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   644
    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
   645
    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
   646
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   647
        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
   648
        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
   649
        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
   650
        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
   651
        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
   652
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   653
    return buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   654
} // buffer_create
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   655
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   656
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
   657
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   658
    // 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
   659
    //  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
   660
    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
   661
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   662
    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
   663
        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
   664
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   665
    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
   666
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   667
        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
   668
        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
   669
        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
   670
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   671
            buffer->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
   672
            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
   673
            assert(buffer->tail->bytes <= blocksize);
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   674
            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
   675
        } // 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
   676
    } // 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
   677
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   678
    // 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
   679
    //  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
   680
    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
   681
    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
   682
    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
   683
    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
   684
        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
   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
    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
   687
    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
   688
    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
   689
    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
   690
        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
   691
    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
   692
        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
   693
    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
   694
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
    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
   696
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   697
    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
   698
} // 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
   699
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
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
   701
{
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
    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
   703
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
    // 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
   705
    //  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
   706
    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
   707
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 (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
   709
        return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   710
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   711
    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
   712
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   713
        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
   714
        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
   715
        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
   716
        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
   717
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   718
            memcpy(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
   719
            len -= cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   720
            data += cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   721
            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
   722
            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
   723
            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
   724
        } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   725
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   726
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   727
    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
   728
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   729
        assert((!buffer->tail) || (buffer->tail->bytes == blocksize));
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   730
        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
   731
        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
   732
        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
   733
        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
   734
            return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   735
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
   736
        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
   737
        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
   738
        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
   739
        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
   740
            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
   741
        else
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   742
            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
   743
        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
   744
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   745
        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
   746
        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
   747
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   748
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   749
    return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   750
} // buffer_append
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   751
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   752
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
   753
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   754
    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
   755
    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
   756
    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
   757
    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
   758
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   759
} // buffer_append_fmt
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   760
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   761
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
   762
{
1080
b92bdbf78621 M4X4 opcode can actually overflow some string buffers.
Ryan C. Gordon <icculus@icculus.org>
parents: 1065
diff changeset
   763
    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
   764
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   765
    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
   766
    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
   767
    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
   768
    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
   769
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   770
    // 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
   771
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   772
    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
   773
        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
   774
    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
   775
        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
   776
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   777
    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
   778
    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
   779
        return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   780
    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
   781
    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
   782
    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
   783
    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
   784
    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
   785
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   786
} // 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
   787
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   788
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
   789
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   790
    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
   791
} // buffer_size
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   792
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   793
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
   794
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   795
    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
   796
    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
   797
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   798
        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
   799
        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
   800
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   801
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   802
    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
   803
    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
   804
} // buffer_empty
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   805
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   806
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
   807
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   808
    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
   809
    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
   810
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   811
    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
   812
    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
   813
    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
   814
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   815
        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
   816
        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
   817
        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
   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
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   822
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   823
    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
   824
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   825
    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
   826
    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
   827
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   828
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   829
} // buffer_flatten
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   830
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   831
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
   832
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   833
    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
   834
    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
   835
    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
   836
    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
   837
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   838
        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
   839
        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
   840
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   841
        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
   842
            first = buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   843
        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
   844
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   845
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   846
    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
   847
    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
   848
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   849
        *_len = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   850
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   851
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   852
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   853
    *_len = len;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   854
    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
   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
        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
   861
        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
   862
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   863
            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
   864
            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
   865
            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
   866
            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
   867
            item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   868
        } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   869
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   870
        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
   871
        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
   872
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   873
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   874
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   875
    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
   876
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   877
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   878
} // buffer_merge
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   879
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   880
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
   881
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   882
    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
   883
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   884
        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
   885
        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
   886
        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
   887
        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
   888
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   889
} // buffer_destroy
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   890
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
   891
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
   892
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   893
    if (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
   894
        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
   895
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   896
    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
   897
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   898
        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
   899
        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
   900
        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
   901
            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
   902
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   903
        if (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
   904
            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
   905
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   906
        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
   907
        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
   908
        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
   909
    } // 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
   910
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
    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
   912
} // 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
   913
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   914
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
   915
                    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
   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
    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
   918
        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
   919
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
    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
   921
        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
   922
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   923
    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
   924
        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
   925
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
    // 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
   927
    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
   928
    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
   929
    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
   930
    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
   931
    {
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
        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
   933
        {
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
            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
   935
            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
   936
            {
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
                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
   938
                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
   939
            } // 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
   940
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
            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
   942
            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
   943
        } // 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
   944
    } // 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
   945
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
    // 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
   947
    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
   948
    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
   949
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
    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
   951
    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
   952
    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
   953
    {
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
        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
   955
        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
   956
        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
   957
        {
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
            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
   959
            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
   960
                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
   961
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
            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
   963
            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
   964
            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
   965
            {
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
                // 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
   967
                // 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
   968
                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
   969
                    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
   970
            } // 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
   971
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
            // 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
   973
            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
   974
        } // 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
   975
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
        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
   977
        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
   978
        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
   979
            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
   980
    } // 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
   981
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
    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
   983
} // 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
   984
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   985
// 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
   986