mojoshader_common.c
author Ethan Lee <flibitijibibo@flibitijibibo.com>
Thu, 17 May 2018 13:05:09 -0400
changeset 1187 0687a8d78a54
parent 1180 8abc040525ed
child 1188 25000edc0176
permissions -rw-r--r--
Add COMPILER_SUPPORT CMake flag, do not build effect/compiler files if disabled
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"
1180
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
     3
#include <math.h>
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
     4
1146
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
     5
// Convenience functions for allocators...
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
     6
#if !MOJOSHADER_FORCE_ALLOCATOR
1150
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
     7
void * MOJOSHADERCALL MOJOSHADER_internal_malloc(int bytes, void *d) { return malloc(bytes); }
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
     8
void MOJOSHADERCALL MOJOSHADER_internal_free(void *ptr, void *d) { free(ptr); }
1146
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
     9
#endif
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    10
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    11
MOJOSHADER_error MOJOSHADER_out_of_mem_error = {
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    12
    "Out of memory", NULL, MOJOSHADER_POSITION_NONE
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    13
};
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    14
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    15
MOJOSHADER_parseData MOJOSHADER_out_of_mem_data = {
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    16
    1, &MOJOSHADER_out_of_mem_error, 0, 0, 0, 0,
1170
6e9659bf396f Explicitly initial a bunch of bits of MOJOSHADER_out_of_mem_data.
Ryan C. Gordon <icculus@icculus.org>
parents: 1161
diff changeset
    17
    MOJOSHADER_TYPE_UNKNOWN, 0, 0, 0, 0, 0, 0, 0,
6e9659bf396f Explicitly initial a bunch of bits of MOJOSHADER_out_of_mem_data.
Ryan C. Gordon <icculus@icculus.org>
parents: 1161
diff changeset
    18
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1146
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    19
};
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    20
31337471b909 Moved some simple things into mojoshader_common.c.
Ryan C. Gordon <icculus@icculus.org>
parents: 1141
diff changeset
    21
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    22
typedef struct HashItem
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
    const void *key;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    25
    const void *value;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    26
    struct HashItem *next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    27
} HashItem;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    28
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    29
struct HashTable
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    30
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    31
    HashItem **table;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    32
    uint32 table_len;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    33
    int stackable;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    34
    void *data;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    35
    HashTable_HashFn hash;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    36
    HashTable_KeyMatchFn keymatch;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    37
    HashTable_NukeFn nuke;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    38
    MOJOSHADER_malloc m;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    39
    MOJOSHADER_free f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    40
    void *d;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    41
};
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    42
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    43
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
    44
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    45
    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
    46
} // calc_hash
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    47
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    48
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
    49
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    50
    HashItem *i;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    51
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    52
    const uint32 hash = calc_hash(table, key);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    53
    HashItem *prev = NULL;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    54
    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
    55
    {
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    56
        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
    57
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    58
            if (_value != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    59
                *_value = i->value;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    60
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    61
            // 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
    62
            //  (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
    63
            if ((!table->stackable) && (prev != NULL))
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    64
            {
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    65
                assert(prev->next == i);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    66
                prev->next = i->next;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    67
                i->next = table->table[hash];
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    68
                table->table[hash] = i;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    69
            } // if
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    70
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    71
            return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    72
        } // if
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    73
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
    74
        prev = i;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    75
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    76
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    77
    return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    78
} // hash_find
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
    79
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
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
    81
              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
    82
{
1150
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
    83
    HashItem *item = (HashItem *) *iter;
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    84
    if (item == NULL)
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    85
        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
    86
    else
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    87
        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
    88
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    89
    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
    90
    {
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    91
        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
    92
        {
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    93
            *_value = item->value;
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    94
            *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
    95
            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
    96
        } // if
1064
d3f0f4cf84f2 Minor hash_iter() code cleanup.
Ryan C. Gordon <icculus@icculus.org>
parents: 1059
diff changeset
    97
        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
    98
    } // while
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
    99
6284deccb61e Added hash_iter() function, for iterating all matching entries in a hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents: 963
diff changeset
   100
    // 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
   101
    *_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
   102
    *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
   103
    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
   104
} // 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
   105
1065
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   106
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
   107
{
1150
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
   108
    HashItem *item = (HashItem *) *iter;
1161
6085abb2edaa Fixed up a few Visual Studio warnings, compiling as C++, etc.
Ryan C. Gordon <icculus@icculus.org>
parents: 1153
diff changeset
   109
    uint32 idx = 0;
1065
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
    if (item != NULL)
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   112
    {
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   113
        const HashItem *orig = item;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   114
        item = item->next;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   115
        if (item == NULL)
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   116
            idx = calc_hash(table, orig->key) + 1;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   117
    } // if
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   118
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   119
    while (!item && (idx < table->table_len))
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   120
        item = table->table[idx++];  // skip empty buckets...
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   121
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   122
    if (item == NULL)  // no more matches?
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   123
    {
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   124
        *_key = NULL;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   125
        *iter = NULL;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   126
        return 0;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   127
    } // if
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   128
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   129
    *_key = item->key;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   130
    *iter = item;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   131
    return 1;
bb021d539ec5 Implemented hash_iter_keys().
Ryan C. Gordon <icculus@icculus.org>
parents: 1064
diff changeset
   132
} // 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
   133
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   134
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
   135
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   136
    HashItem *item = NULL;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   137
    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
   138
    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
   139
        return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   140
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   141
    // !!! 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
   142
    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
   143
    if (item == NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   144
        return -1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   145
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   146
    item->key = key;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   147
    item->value = value;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   148
    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
   149
    table->table[hash] = item;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   150
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   151
    return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   152
} // hash_insert
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   153
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   154
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
   155
              const HashTable_KeyMatchFn keymatchfn,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   156
              const HashTable_NukeFn nukefn,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   157
              const int stackable,
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   158
              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
   159
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   160
    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
   161
    const uint32 alloc_len = sizeof (HashItem *) * initial_table_size;
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   162
    HashTable *table = (HashTable *) m(sizeof (HashTable), d);
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   163
    if (table == NULL)
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   164
        return NULL;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   165
    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
   166
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   167
    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
   168
    if (table->table == NULL)
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   169
    {
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   170
        f(table, d);
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   171
        return NULL;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   172
    } // if
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   173
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   174
    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
   175
    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
   176
    table->stackable = stackable;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   177
    table->data = data;
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   178
    table->hash = hashfn;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   179
    table->keymatch = keymatchfn;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   180
    table->nuke = nukefn;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   181
    table->m = m;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   182
    table->f = f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   183
    table->d = d;
735
78c882b8c813 Patched to compile.
Ryan C. Gordon <icculus@icculus.org>
parents: 734
diff changeset
   184
    return table;
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   185
} // hash_create
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   186
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   187
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
   188
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   189
    uint32 i;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   190
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   191
    MOJOSHADER_free f = table->f;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   192
    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
   193
    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
   194
    {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   195
        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
   196
        while (item != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   197
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   198
            HashItem *next = item->next;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   199
            table->nuke(item->key, item->value, data);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   200
            f(item, d);
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   201
            item = next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   202
        } // while
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   203
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   204
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   205
    f(table->table, d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   206
    f(table, d);
733
1b6d68fabe46 Reworked hashtable create/destroy functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 732
diff changeset
   207
} // hash_destroy
732
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   208
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   209
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
   210
{
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   211
    HashItem *item = NULL;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   212
    HashItem *prev = NULL;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   213
    void *data = table->data;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   214
    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
   215
    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
   216
    {
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   217
        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
   218
        {
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   219
            if (prev != NULL)
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   220
                prev->next = item->next;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   221
            else
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   222
                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
   223
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   224
            table->nuke(item->key, item->value, data);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   225
            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
   226
            return 1;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   227
        } // if
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   228
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   229
        prev = item;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   230
    } // for
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   231
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   232
    return 0;
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   233
} // hash_remove
e070fea1f8c7 Added mojoshader_common.c with first shot at generic hashtable.
Ryan C. Gordon <icculus@icculus.org>
parents:
diff changeset
   234
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   235
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   236
// 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
   237
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
   238
{
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   239
    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
   240
    while (len--)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   241
        hash = ((hash << 5) + hash) ^ *(str++);
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   242
    return hash;
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   243
} // hash_string_djbxor
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   244
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   245
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
   246
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   247
    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
   248
} // hash_string
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   249
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   250
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
   251
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   252
    (void) data;
870
f9e20269c20b make compile on MSVC, and fix stringmap_insert
Aras Pranckevicius <aras@unity3d.com>
parents: 860
diff changeset
   253
    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
   254
} // hash_hash_string
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   255
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   256
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
   257
{
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   258
    (void) data;
734
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   259
    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
   260
} // hash_keymatch_string
1f69fc50c79c Added string hash/compare functions.
Ryan C. Gordon <icculus@icculus.org>
parents: 733
diff changeset
   261
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   262
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   263
// string -> string map...
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   264
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   265
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
   266
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   267
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
   268
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   269
    StringMap *smap = (StringMap *) d;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   270
    smap->f((void *) key, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   271
    smap->f((void *) val, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   272
} // stringmap_nuke
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   273
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   274
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
   275
                            MOJOSHADER_free f, void *d)
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
    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
   278
    StringMap *smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   279
    smap = hash_create(0,hash_hash_string,hash_keymatch_string,nuke,0,m,f,d);
1111
7530b37979b8 Some static analysis fixes from Clang 4.0.
Ryan C. Gordon <icculus@icculus.org>
parents: 1080
diff changeset
   280
    if (smap != NULL)
7530b37979b8 Some static analysis fixes from Clang 4.0.
Ryan C. Gordon <icculus@icculus.org>
parents: 1080
diff changeset
   281
        smap->data = smap;
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   282
    return smap;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   283
} // stringmap_create
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   284
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   285
void stringmap_destroy(StringMap *smap)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   286
{
963
5a8f7ef13735 Removed return statement from void function.
Ryan C. Gordon <icculus@icculus.org>
parents: 956
diff changeset
   287
    hash_destroy(smap);
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   288
} // stringmap_destroy
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   289
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   290
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
   291
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   292
    assert(key != NULL);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   293
    if (smap->nuke == stringmap_nuke_noop)  // no copy?
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   294
        return hash_insert(smap, key, value);
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
    int rc = -1;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   297
    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
   298
    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
   299
    int failed = ( (!k) || ((!v) && (value)) );
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   300
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   301
    if (!failed)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   302
    {
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   303
        strcpy(k, key);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   304
        if (value != NULL)
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   305
            strcpy(v, value);
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   306
        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
   307
    } // if
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   308
9655c606b39d Fixed must-copy version of stringmap_insert().
Ryan C. Gordon <icculus@icculus.org>
parents: 965
diff changeset
   309
    if (failed)
859
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   310
    {
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   311
        smap->f(k, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   312
        smap->f(v, smap->d);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   313
    } // if
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   314
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   315
    return rc;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   316
} // stringmap_insert
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   317
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   318
int stringmap_remove(StringMap *smap, const char *key)
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   319
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   320
    return hash_remove(smap, key);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   321
} // stringmap_remove
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   322
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   323
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
   324
{
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   325
    const void *value = NULL;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   326
    const int retval = hash_find(smap, key, &value);
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   327
    *_value = (const char *) value;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   328
    return retval;
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   329
} // stringmap_find
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   330
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   331
824d67791db0 Implemented StringMap, for future use.
Ryan C. Gordon <icculus@icculus.org>
parents: 858
diff changeset
   332
// 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
   333
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   334
typedef struct StringBucket
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   335
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   336
    char *string;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   337
    struct StringBucket *next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   338
} StringBucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   339
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   340
struct StringCache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   341
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   342
    StringBucket **hashtable;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   343
    uint32 table_size;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   344
    MOJOSHADER_malloc m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   345
    MOJOSHADER_free f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   346
    void *d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   347
};
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   348
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   349
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   350
const char *stringcache(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
   351
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   352
    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
   353
} // stringcache
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   354
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   355
static const char *stringcache_len_internal(StringCache *cache,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   356
                                            const char *str,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   357
                                            const unsigned int len,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   358
                                            const int addmissing)
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   359
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   360
    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
   361
    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
   362
    StringBucket *prev = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   363
    while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   364
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   365
        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
   366
        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
   367
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   368
            // 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
   369
            if (prev != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   370
            {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   371
                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
   372
                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
   373
                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
   374
                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
   375
            } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   376
            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
   377
        } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   378
        prev = bucket;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   379
        bucket = bucket->next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   380
    } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   381
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   382
    // no match!
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   383
    if (!addmissing)
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   384
        return NULL;
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   385
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   386
    // add to the table.
1141
77468a2a9165 Reduce malloc pressure in stringcache (thanks, Max!).
Ryan C. Gordon <icculus@icculus.org>
parents: 1140
diff changeset
   387
    bucket = (StringBucket *) cache->m(sizeof (StringBucket) + len + 1, cache->d);
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   388
    if (bucket == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   389
        return NULL;
1141
77468a2a9165 Reduce malloc pressure in stringcache (thanks, Max!).
Ryan C. Gordon <icculus@icculus.org>
parents: 1140
diff changeset
   390
    bucket->string = (char *)(bucket + 1);
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   391
    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
   392
    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
   393
    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
   394
    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
   395
    return bucket->string;
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   396
} // stringcache_len_internal
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   397
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   398
const char *stringcache_len(StringCache *cache, const char *str,
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   399
                            const unsigned int len)
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   400
{
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   401
    return stringcache_len_internal(cache, str, len, 1);
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   402
} // stringcache_len
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   403
1116
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   404
int stringcache_iscached(StringCache *cache, const char *str)
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   405
{
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   406
    return (stringcache_len_internal(cache, str, strlen(str), 0) != NULL);
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   407
} // stringcache_iscached
0ef3d106dab9 Added stringcache_iscached().
Ryan C. Gordon <icculus@icculus.org>
parents: 1113
diff changeset
   408
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   409
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
   410
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   411
    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
   412
    char *ptr = NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   413
    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
   414
    va_list ap;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   415
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   416
    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
   417
    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
   418
    va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   419
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   420
    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
   421
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   422
        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
   423
        if (ptr == NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   424
            return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   425
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   426
        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
   427
        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
   428
        va_end(ap);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   429
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   430
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   431
    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
   432
    if (ptr != NULL)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   433
        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
   434
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   435
    return retval;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   436
} // stringcache_fmt
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   437
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   438
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
   439
{
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   440
    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
   441
    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
   442
    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
   443
    if (!cache)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   444
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   445
    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
   446
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   447
    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
   448
    if (!cache->hashtable)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   449
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   450
        f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   451
        return NULL;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   452
    } // if
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   453
    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
   454
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   455
    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
   456
    cache->m = m;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   457
    cache->f = f;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   458
    cache->d = d;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   459
    return cache;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   460
} // stringcache_create
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   461
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   462
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
   463
{
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   464
    if (cache == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   465
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   466
858
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   467
    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
   468
    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
   469
    size_t i;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   470
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   471
    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
   472
    {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   473
        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
   474
        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
   475
        while (bucket)
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   476
        {
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   477
            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
   478
            f(bucket, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   479
            bucket = next;
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   480
        } // while
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   481
    } // for
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   482
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   483
    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
   484
    f(cache, d);
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   485
} // stringcache_destroy
d51537335896 Formalized the compiler's string cache into a real API.
Ryan C. Gordon <icculus@icculus.org>
parents: 735
diff changeset
   486
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   487
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   488
// 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
   489
//  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
   490
typedef struct ErrorItem
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   491
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   492
    MOJOSHADER_error error;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   493
    struct ErrorItem *next;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   494
} ErrorItem;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   495
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   496
struct ErrorList
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   497
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   498
    ErrorItem head;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   499
    ErrorItem *tail;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   500
    int count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   501
    MOJOSHADER_malloc m;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   502
    MOJOSHADER_free f;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   503
    void *d;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   504
};
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   505
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   506
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
   507
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   508
    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
   509
    if (retval != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   510
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   511
        memset(retval, '\0', sizeof (ErrorList));
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   512
        retval->tail = &retval->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   513
        retval->m = m;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   514
        retval->f = f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   515
        retval->d = d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   516
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   517
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   518
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   519
} // errorlist_create
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   520
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
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
   523
                  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
   524
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   525
    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
   526
} // errorlist_add
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
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   529
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
   530
                      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
   531
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   532
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   533
    va_start(ap, fmt);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   534
    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
   535
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   536
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   537
} // errorlist_add_fmt
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   538
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   539
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   540
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
   541
                     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
   542
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   543
    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
   544
    if (error == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   545
        return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   546
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   547
    char *fname = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   548
    if (_fname != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   549
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   550
        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
   551
        if (fname == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   552
        {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   553
            list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   554
            return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   555
        } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   556
        strcpy(fname, _fname);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   557
    } // if
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
    char scratch[128];
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   560
    va_list ap;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   561
    va_copy(ap, va);
1153
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   562
    int len = vsnprintf(scratch, sizeof (scratch), fmt, ap);
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   563
    va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   564
1153
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   565
    // on some versions of the windows C runtime, vsnprintf() returns -1
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   566
    // if the buffer overflows instead of the length the string would have
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   567
    // been as expected.
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   568
    // In this case we make another copy of va and fetch the length only
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   569
    // with another call to _vscprintf
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   570
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   571
#ifdef _MSC_VER
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   572
    if (len == -1)
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   573
    {
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   574
        va_copy(ap, va);
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   575
        len = _vscprintf(fmt, ap);
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   576
        va_end(ap);
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   577
    }
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   578
#endif
663c9541e21f Deal with quirks of MSVC's vsnprintf() implementation.
Baldur Karlsson <baldur@unity3d.com>
parents: 1150
diff changeset
   579
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   580
    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
   581
    if (failstr == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   582
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   583
        list->f(error, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   584
        list->f(fname, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   585
        return 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   586
    } // if
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   587
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   588
    // 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
   589
    //  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
   590
    //  run of vsnprintf().
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   591
    if (len < sizeof (scratch))
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   592
        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
   593
    else
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
        va_copy(ap, va);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   596
        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
   597
        va_end(ap);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   598
    } // else
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   599
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   600
    error->error.error = failstr;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   601
    error->error.filename = fname;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   602
    error->error.error_position = errpos;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   603
    error->next = NULL;
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
    list->tail->next = error;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   606
    list->tail = error;
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
    list->count++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   609
    return 1;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   610
} // errorlist_add_va
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   611
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   612
945
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   613
int errorlist_count(ErrorList *list)
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   614
{
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   615
    return list->count;
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   616
} // errorlist_count
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   617
f00ea3986db8 Made ErrorList struct opaque to callers.
Ryan C. Gordon <icculus@icculus.org>
parents: 944
diff changeset
   618
939
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   619
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
   620
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   621
    if (list->count == 0)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   622
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   623
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   624
    int total = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   625
    MOJOSHADER_error *retval = (MOJOSHADER_error *)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   626
            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
   627
    if (retval == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   628
        return NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   629
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   630
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   631
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   632
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   633
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   634
        // reuse the string allocations
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   635
        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
   636
        list->f(item, list->d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   637
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   638
        total++;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   639
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   640
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   641
    assert(total == list->count);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   642
    list->count = 0;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   643
    list->head.next = NULL;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   644
    list->tail = &list->head;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   645
    return retval;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   646
} // errorlist_flatten
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   647
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   648
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   649
void errorlist_destroy(ErrorList *list)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   650
{
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   651
    if (list == NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   652
        return;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   653
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   654
    MOJOSHADER_free f = list->f;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   655
    void *d = list->d;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   656
    ErrorItem *item = list->head.next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   657
    while (item != NULL)
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   658
    {
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   659
        ErrorItem *next = item->next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   660
        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
   661
        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
   662
        f(item, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   663
        item = next;
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   664
    } // while
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   665
    f(list, d);
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   666
} // errorlist_destroy
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   667
64cc93ee5a56 Cut-and-paste cleanup: unified the ErrorList functionality.
Ryan C. Gordon <icculus@icculus.org>
parents: 870
diff changeset
   668
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   669
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
   670
{
946
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   671
    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
   672
    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
   673
    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
   674
} BufferBlock;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   675
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   676
struct Buffer
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   677
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   678
    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
   679
    BufferBlock *head;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   680
    BufferBlock *tail;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   681
    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
   682
    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
   683
    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
   684
    void *d;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   685
};
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   686
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   687
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
   688
                      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
   689
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   690
    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
   691
    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
   692
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   693
        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
   694
        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
   695
        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
   696
        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
   697
        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
   698
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   699
    return buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   700
} // buffer_create
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   701
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   702
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
   703
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   704
    // 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
   705
    //  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
   706
    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
   707
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   708
    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
   709
        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
   710
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   711
    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
   712
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   713
        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
   714
        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
   715
        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
   716
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   717
            buffer->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
   718
            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
   719
            assert(buffer->tail->bytes <= blocksize);
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   720
            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
   721
        } // 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
   722
    } // 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
   723
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   724
    // 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
   725
    //  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
   726
    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
   727
    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
   728
    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
   729
    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
   730
        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
   731
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   732
    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
   733
    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
   734
    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
   735
    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
   736
        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
   737
    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
   738
        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
   739
    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
   740
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   741
    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
   742
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   743
    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
   744
} // 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
   745
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   746
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
   747
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   748
    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
   749
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   750
    // 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
   751
    //  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
   752
    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
   753
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   754
    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
   755
        return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   756
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   757
    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
   758
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   759
        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
   760
        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
   761
        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
   762
        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
   763
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   764
            memcpy(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
   765
            len -= cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   766
            data += cpy;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   767
            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
   768
            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
   769
            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
   770
        } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   771
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   772
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   773
    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
   774
    {
1113
570cae807859 Fixed logic error.
Ryan C. Gordon <icculus@icculus.org>
parents: 1111
diff changeset
   775
        assert((!buffer->tail) || (buffer->tail->bytes >= blocksize));
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   776
        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
   777
        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
   778
        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
   779
        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
   780
            return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   781
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
   782
        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
   783
        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
   784
        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
   785
        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
   786
            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
   787
        else
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   788
            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
   789
        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
   790
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   791
        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
   792
        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
   793
    } // if
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
    return 1;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   796
} // buffer_append
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
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
   799
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   800
    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
   801
    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
   802
    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
   803
    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
   804
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   805
} // buffer_append_fmt
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   806
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   807
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
   808
{
1080
b92bdbf78621 M4X4 opcode can actually overflow some string buffers.
Ryan C. Gordon <icculus@icculus.org>
parents: 1065
diff changeset
   809
    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
   810
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   811
    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
   812
    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
   813
    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
   814
    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
   815
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   816
    // 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
   817
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   818
    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
   819
        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
   820
    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
   821
        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
   822
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   823
    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
   824
    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
   825
        return 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   826
    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
   827
    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
   828
    va_end(ap);
1140
fad7ed946c06 Fixed incorrect variable in buffer_append_va (thanks, Max!).
Ryan C. Gordon <icculus@icculus.org>
parents: 1116
diff changeset
   829
    const int retval = buffer_append(buffer, buf, len);
944
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   830
    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
   831
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   832
} // 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
   833
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 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
   835
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   836
    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
   837
} // buffer_size
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   838
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   839
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
   840
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   841
    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
   842
    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
   843
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   844
        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
   845
        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
   846
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   847
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   848
    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
   849
    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
   850
} // buffer_empty
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   851
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   852
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
   853
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   854
    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
   855
    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
   856
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   857
    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
   858
    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
   859
    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
   860
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   861
        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
   862
        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
   863
        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
   864
        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
   865
        item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   866
    } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   867
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   868
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   869
    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
   870
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   871
    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
   872
    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
   873
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   874
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   875
} // buffer_flatten
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   876
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   877
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
   878
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   879
    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
   880
    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
   881
    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
   882
    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
   883
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   884
        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
   885
        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
   886
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   887
        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
   888
            first = buffer;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   889
        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
   890
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   891
956
7888858a6777 Patched to compile on Windows.
Ryan C. Gordon <icculus@icculus.org>
parents: 946
diff changeset
   892
    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
   893
    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
   894
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   895
        *_len = 0;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   896
        return NULL;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   897
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   898
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   899
    *_len = len;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   900
    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
   901
    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
   902
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   903
        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
   904
        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
   905
            continue;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   906
        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
   907
        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
   908
        {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   909
            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
   910
            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
   911
            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
   912
            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
   913
            item = next;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   914
        } // while
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   915
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   916
        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
   917
        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
   918
    } // for
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   919
    *ptr = '\0';
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   920
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   921
    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
   922
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   923
    return retval;
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   924
} // buffer_merge
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   925
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   926
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
   927
{
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   928
    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
   929
    {
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   930
        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
   931
        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
   932
        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
   933
        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
   934
    } // if
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   935
} // buffer_destroy
9f9fa9650772 Paying off more technical debt: unified growable buffers into one place.
Ryan C. Gordon <icculus@icculus.org>
parents: 939
diff changeset
   936
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
   937
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
   938
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   939
    if (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
   940
        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
   941
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   942
    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
   943
    {
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
        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
   945
        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
   946
        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
   947
            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
   948
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   949
        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
   950
            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
   951
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
        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
   953
        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
   954
        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
   955
    } // 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
   956
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
    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
   958
} // 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
   959
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   960
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
   961
                    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
   962
{
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   963
    if (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
   964
        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
   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
    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
   967
        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
   968
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   969
    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
   970
        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
   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
    // 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
   973
    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
   974
    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
   975
    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
   976
    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
   977
    {
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
        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
   979
        {
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
            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
   981
            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
   982
            {
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
                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
   984
                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
   985
            } // 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
   986
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   987
            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
   988
            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
   989
        } // 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
   990
    } // 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
   991
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   992
    // 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
   993
    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
   994
    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
   995
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
   996
    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
   997
    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
   998
    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
   999
    {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1000
        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
  1001
        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
  1002
        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
  1003
        {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1004
            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
  1005
            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
  1006
                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
  1007
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1008
            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
  1009
            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
  1010
            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
  1011
            {
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1012
                // 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
  1013
                // 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
  1014
                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
  1015
                    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
  1016
            } // 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
  1017
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1018
            // 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
  1019
            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
  1020
        } // 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
  1021
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1022
        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
  1023
        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
  1024
        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
  1025
            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
  1026
    } // 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
  1027
16fec3a3f687 Technical debt: cleaned up things in the assembler that should've used Buffer.
Ryan C. Gordon <icculus@icculus.org>
parents: 945
diff changeset
  1028
    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
  1029
} // 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
  1030
1150
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1031
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1032
// Based on SDL_string.c's SDL_PrintFloat function
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1033
size_t MOJOSHADER_printFloat(char *text, size_t maxlen, float arg)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1034
{
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1035
    size_t len;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1036
    size_t left = maxlen;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1037
    char *textstart = text;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1038
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1039
    int precision = 9;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1040
1180
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1041
    if (isnan(arg))
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1042
    {
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1043
        if (left > 3)
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1044
        {
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1045
            snprintf(text, left, "NaN");
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1046
            left -= 3;
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1047
        } // if
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1048
        text += 3;
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1049
    } // if
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1050
    else if (isinf(arg))
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1051
    {
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1052
        if (left > 3)
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1053
        {
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1054
            snprintf(text, left, "inf");
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1055
            left -= 3;
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1056
        } // if
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1057
        text += 3;
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1058
    } // else if
8abc040525ed A bunch of fixes for bugs that that American Fuzzy Lop exposed.
Ryan C. Gordon <icculus@icculus.org>
parents: 1170
diff changeset
  1059
    else if (arg)
1150
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1060
    {
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1061
        /* This isn't especially accurate, but hey, it's easy. :) */
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1062
        unsigned long value;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1063
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1064
        if (arg < 0)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1065
        {
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1066
            if (left > 1)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1067
            {
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1068
                *text = '-';
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1069
                --left;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1070
            } // if
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1071
            ++text;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1072
            arg = -arg;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1073
        } // if
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1074
        value = (unsigned long) arg;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1075
        len = snprintf(text, left, "%lu", value);
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1076
        text += len;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1077
        if (len >= left)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1078
            left = (left < 1) ? left : 1;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1079
        else
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1080
            left -= len;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1081
        arg -= value;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1082
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1083
        int mult = 10;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1084
        if (left > 1)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1085
        {
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1086
            *text = '.';
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1087
            --left;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1088
        } // if
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1089
        ++text;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1090
        while (precision-- > 0)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1091
        {
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1092
            value = (unsigned long) (arg * mult);
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1093
            len = snprintf(text, left, "%lu", value);
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1094
            text += len;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1095
            if (len >= left)
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1096
                left = (left < 1) ? left : 1;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1097
            else
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1098
                left -= len;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1099
            arg -= (double) value / mult;
02c0f0afb39a - Add ability to build MojoShader as a shared library
Ethan Lee <flibitijibibo@flibitijibibo.com>
parents: 1146
diff changeset
  1100
            if (arg < 0) arg = -arg; // Sometimes that bit gets flipped...
<