project_files/frontlib/util/buffer.c
author Wuzzy <Wuzzy2@mail.ru>
Fri, 27 Oct 2017 05:03:58 +0200
changeset 12782 389453e1e09e
parent 10017 de822cd3df3a
permissions -rw-r--r--
ACF7: Fix possible Lua error spam in intro sequence This was caused by a race of onGearDelete vs AnimationSetup. If AnimationSetup came first, it uses old values from the natives table. The solution is to force the code to guarantee that AnimationSetup always coms after deleting gears in the natives table.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10017
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     1
/*
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     2
 * Hedgewars, a free turn based strategy game
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     3
 * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     4
 *
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     5
 * This program is free software; you can redistribute it and/or
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     6
 * modify it under the terms of the GNU General Public License
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     7
 * as published by the Free Software Foundation; either version 2
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     8
 * of the License, or (at your option) any later version.
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
     9
 *
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    10
 * This program is distributed in the hope that it will be useful,
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    13
 * GNU General Public License for more details.
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    14
 *
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    15
 * You should have received a copy of the GNU General Public License
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    16
 * along with this program; if not, write to the Free Software
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    18
 */
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    19
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    20
#include "buffer.h"
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    21
#include "logging.h"
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    22
#include "util.h"
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    23
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    24
#include <stdlib.h>
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    25
#include <limits.h>
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    26
#include <string.h>
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    27
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    28
#define MIN_VECTOR_CAPACITY 16
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    29
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    30
struct _flib_vector {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    31
    void *data;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    32
    size_t size;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    33
    size_t capacity;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    34
};
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    35
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    36
flib_vector *flib_vector_create() {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    37
    flib_vector *result = NULL;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    38
    flib_vector *tmpVector = flib_calloc(1, sizeof(flib_vector));
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    39
    if(tmpVector) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    40
        tmpVector->data = flib_malloc(MIN_VECTOR_CAPACITY);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    41
        if(tmpVector->data) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    42
            tmpVector->size = 0;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    43
            tmpVector->capacity = MIN_VECTOR_CAPACITY;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    44
            result = tmpVector;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    45
            tmpVector = NULL;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    46
        }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    47
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    48
    flib_vector_destroy(tmpVector);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    49
    return result;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    50
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    51
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    52
void flib_vector_destroy(flib_vector *vec) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    53
    if(vec) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    54
        free(vec->data);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    55
        free(vec);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    56
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    57
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    58
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    59
static int setCapacity(flib_vector *vec, size_t newCapacity) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    60
    if(newCapacity == vec->capacity) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    61
        return 0;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    62
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    63
    void *newData = realloc(vec->data, newCapacity);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    64
    if(newData) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    65
        vec->data = newData;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    66
        vec->capacity = newCapacity;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    67
        return 0;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    68
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    69
        return -1;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    70
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    71
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    72
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    73
static int allocateExtraCapacity(flib_vector *vec, size_t extraCapacity) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    74
    if(extraCapacity <= SIZE_MAX - vec->capacity) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    75
        return setCapacity(vec, vec->capacity + extraCapacity);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    76
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    77
        return -1;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    78
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    79
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    80
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    81
int flib_vector_resize(flib_vector *vec, size_t newSize) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    82
    if(log_badargs_if(vec==NULL)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    83
        return -1;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    84
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    85
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    86
    if(vec->capacity < newSize) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    87
        // Resize exponentially for constant amortized time,
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    88
        // But at least by as much as we need of course
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    89
        size_t extraCapacity = (vec->capacity)/2;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    90
        size_t minExtraCapacity = newSize - vec->capacity;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    91
        if(extraCapacity < minExtraCapacity) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    92
            extraCapacity = minExtraCapacity;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    93
        }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    94
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    95
        if(allocateExtraCapacity(vec, extraCapacity)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    96
            allocateExtraCapacity(vec, minExtraCapacity);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    97
        }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    98
    } else if(vec->capacity/2 > newSize) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
    99
        size_t newCapacity = newSize+newSize/4;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   100
        if(newCapacity < MIN_VECTOR_CAPACITY) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   101
            newCapacity = MIN_VECTOR_CAPACITY;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   102
        }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   103
        setCapacity(vec, newCapacity);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   104
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   105
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   106
    if(vec->capacity >= newSize) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   107
        vec->size = newSize;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   108
        return 0;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   109
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   110
        return -1;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   111
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   112
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   113
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   114
int flib_vector_append(flib_vector *vec, const void *data, size_t len) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   115
    if(!log_badargs_if2(vec==NULL, data==NULL && len>0)
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   116
            && !log_oom_if(len > SIZE_MAX-vec->size)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   117
        size_t oldSize = vec->size;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   118
        if(!log_oom_if(flib_vector_resize(vec, vec->size+len))) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   119
            memmove(((uint8_t*)vec->data) + oldSize, data, len);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   120
            return 0;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   121
        }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   122
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   123
    return -1;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   124
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   125
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   126
int flib_vector_appendf(flib_vector *vec, const char *fmt, ...) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   127
    int result = -1;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   128
    if(!log_badargs_if2(vec==NULL, fmt==NULL)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   129
        va_list argp;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   130
        va_start(argp, fmt);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   131
        char *formatted = flib_vasprintf(fmt, argp);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   132
        va_end(argp);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   133
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   134
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   135
        if(formatted) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   136
            size_t len = strlen(formatted);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   137
            result = flib_vector_append(vec, formatted, len);
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   138
        }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   139
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   140
    return result;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   141
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   142
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   143
flib_buffer flib_vector_as_buffer(flib_vector *vec) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   144
    if(log_badargs_if(vec==NULL)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   145
        flib_buffer result = {NULL, 0};
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   146
        return result;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   147
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   148
        flib_buffer result = {vec->data, vec->size};
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   149
        return result;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   150
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   151
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   152
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   153
flib_constbuffer flib_vector_as_constbuffer(flib_vector *vec) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   154
    if(log_badargs_if(vec==NULL)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   155
        flib_constbuffer result = {NULL, 0};
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   156
        return result;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   157
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   158
        flib_constbuffer result = {vec->data, vec->size};
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   159
        return result;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   160
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   161
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   162
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   163
void *flib_vector_data(flib_vector *vec) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   164
    if(log_badargs_if(vec==NULL)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   165
        return NULL;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   166
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   167
        return vec->data;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   168
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   169
}
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   170
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   171
size_t flib_vector_size(flib_vector *vec) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   172
    if(log_badargs_if(vec==NULL)) {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   173
        return 0;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   174
    } else {
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   175
        return vec->size;
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   176
    }
de822cd3df3a fixwhitespace and dos2unix
koda
parents: 7316
diff changeset
   177
}