mojoshader_common.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 23 Apr 2012 01:53:40 -0400
changeset 1101 3a1384bf9ca1
parent 1080 b92bdbf78621
child 1111 7530b37979b8
permissions -rw-r--r--
Handle implicit declaration of ps_1_1 v# registers.
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