mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 23:32:09 +00:00
Add a set of macros for dynamic arrays
Includes docs and test cases.
This commit is contained in:
parent
e37aba364a
commit
0cb04dc490
3 changed files with 520 additions and 2 deletions
301
include/QF/darray.h
Normal file
301
include/QF/darray.h
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
/*
|
||||||
|
darray.h
|
||||||
|
|
||||||
|
Dynamic arrays
|
||||||
|
|
||||||
|
Copyright (C) 2020 Bill Currie <bill@taniwha.org>
|
||||||
|
|
||||||
|
Author: Bill Currie <bill@taniwha.org>
|
||||||
|
Date: 2020/02/17
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __pr_type_h
|
||||||
|
#define __pr_type_h
|
||||||
|
|
||||||
|
/** \defgroup darray Dynamic Arrays
|
||||||
|
\ingroup utils
|
||||||
|
|
||||||
|
Dynamic array container object
|
||||||
|
*/
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/** The structure defs for a dynamic array with elements of the given type.
|
||||||
|
|
||||||
|
This is just the defs of a struct delcaration: it is useless on its own.
|
||||||
|
The intended usage is something like:
|
||||||
|
|
||||||
|
typedef struct dynamic_array_s DARRAY_TYPE(int) dynamic_array_t;
|
||||||
|
|
||||||
|
This allows full flexibility in just how the actual type is used.
|
||||||
|
|
||||||
|
The \a size field is the number of elements currently in the array, and
|
||||||
|
the \a maxSize field is the number of elements the array can hold without
|
||||||
|
being resized.
|
||||||
|
|
||||||
|
The \a grow field specifies the number of elements by which \a maxSize is
|
||||||
|
to grow when the array needs to be resized. Setting this to 0 prevents
|
||||||
|
resizing and any attempt to do so is a fatal error.
|
||||||
|
|
||||||
|
\param ele_type The type to use for the element array, which is accessed
|
||||||
|
by the \a a field.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_TYPE(ele_type) \
|
||||||
|
{ \
|
||||||
|
size_t size; \
|
||||||
|
size_t maxSize; \
|
||||||
|
size_t grow; \
|
||||||
|
ele_type *a; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clear the array.
|
||||||
|
|
||||||
|
If the array can grow, its backing will be freed and maxSize and a reset,
|
||||||
|
otherwise maxSize and a are left untouched.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_CLEAR(array) \
|
||||||
|
do { \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
free (ar->a); \
|
||||||
|
ar->size = 0; \
|
||||||
|
if (ar->grow) { \
|
||||||
|
ar->maxSize = 0; \
|
||||||
|
ar->a = 0; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/** Set the size of the array.
|
||||||
|
|
||||||
|
If the new size is greater than maxSize, and the array can grow (grow is
|
||||||
|
non-zero), then maxSize will be increased to the smallest multiple of grow
|
||||||
|
greater than or equal to size (ie, maxSize >= size, maxSize % grow == 0).
|
||||||
|
|
||||||
|
Attempting to increase maxSize on an array that cannot grow is an error:
|
||||||
|
it is assumed that the array struct does not own the backing memory.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\param newSize The new size of the array: newly opened slots are
|
||||||
|
uninitialized, but old slots retain their values.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_RESIZE(array, newSize) \
|
||||||
|
do { \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
size_t ns = (newSize); \
|
||||||
|
if (__builtin_expect (ns > ar->maxSize, 0)) { \
|
||||||
|
if (__builtin_expect (!ar->grow, 0)) { \
|
||||||
|
Sys_Error ("Attempt to grow fixed-size darray: %s:%d", \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
ar->maxSize = ar->grow * ((ns + ar->grow - 1) / ar->grow); \
|
||||||
|
ar->a = realloc (ar->a, ar->maxSize * sizeof (*ar->a)); \
|
||||||
|
if (__builtin_expect (!ar->a, 0)) { \
|
||||||
|
Sys_Error ("failed to realloc darray: %s:%d", \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
ar->size = ns; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/** Append a value to the end of the array.
|
||||||
|
|
||||||
|
The array is grown by one and the value written to the newly opened slot.
|
||||||
|
|
||||||
|
If the new array size is greater than maxSize and the array can be grown,
|
||||||
|
the array backing will be resized to the next multiple of grow.
|
||||||
|
|
||||||
|
Attempting to grow an array that cannot grow is an error: it is assumed
|
||||||
|
that the array struct does not own the backing memory.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\param value The value to be appended to the array. Must be of a type
|
||||||
|
compatible with that used for creating the array struct.
|
||||||
|
\return The appended value: can be assigned to another compatible
|
||||||
|
value.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_APPEND(array, value) \
|
||||||
|
({ \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
__auto_type ob = (value); \
|
||||||
|
size_t sz = ar->size; \
|
||||||
|
DARRAY_RESIZE (ar, ar->size + 1); \
|
||||||
|
ar->a[sz] = ob; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** Open a hole in the array for bulk copying of data.
|
||||||
|
|
||||||
|
The array is grown by the requested size, opening a hole at the specified
|
||||||
|
index. Values beyond the index are copied to just after the newly opened
|
||||||
|
hole.
|
||||||
|
|
||||||
|
If the new array size is greater than maxSize and the array can be grown,
|
||||||
|
the array backing will be resized to the next multiple of grow.
|
||||||
|
|
||||||
|
Attempting to grow an array that cannot grow is an error: it is assumed
|
||||||
|
that the array struct does not own the backing memory.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\param index The index at which the hole will begin.
|
||||||
|
\param space The sized of the hole to be opened, in array elements.
|
||||||
|
\return The *address* of the newly opened hole: can be passed to
|
||||||
|
memcpy and friends.
|
||||||
|
|
||||||
|
memcpy (DARRAY_OPEN_AT(array, index, size), data,
|
||||||
|
size * sizeof (*data));
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_OPEN_AT(array, index, space) \
|
||||||
|
({ \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
size_t po = (index); \
|
||||||
|
size_t sp = (space); \
|
||||||
|
if (__builtin_expect (po > ar->size, 0)) { \
|
||||||
|
Sys_Error ("Attempt to insert elements outside darray: " \
|
||||||
|
"%s:%d", __FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
DARRAY_RESIZE (ar, ar->size + sp); \
|
||||||
|
memmove (&ar->a[po + sp], &ar->a[po], \
|
||||||
|
(ar->size - po) * sizeof (*ar->a)); \
|
||||||
|
&ar->a[po]; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** Insert a value into the array at the specified index.
|
||||||
|
|
||||||
|
The array is grown by one at the specified index and the value written
|
||||||
|
to the newly opened slot. Values beyond the index are copied to just
|
||||||
|
after the newly opened slot.
|
||||||
|
|
||||||
|
If the new array size is greater than maxSize and the array can be grown,
|
||||||
|
the array backing will be resized to the next multiple of grow.
|
||||||
|
|
||||||
|
Attempting to grow an array that cannot grow is an error: it is assumed
|
||||||
|
that the array struct does not own the backing memory.
|
||||||
|
|
||||||
|
Attempting to insert a value beyond one past the end of the array is an
|
||||||
|
error (inserting at index = size is valid).
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\param value The value to be inserted into the array. Must be of a type
|
||||||
|
compatible with that used for creating the array struct.
|
||||||
|
\param index The index at which the value will be inserted
|
||||||
|
\return The inserted value: can be assigned to another compatible
|
||||||
|
value.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_INSERT_AT(array, value, index) \
|
||||||
|
({ \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
__auto_type ob = (value); \
|
||||||
|
*DARRAY_OPEN_AT (ar, index, 1) = ob; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** Close a segment of an array.
|
||||||
|
|
||||||
|
The values beyond the segment are copied to the beginning of the segment
|
||||||
|
and the array size reduced by the size of the segment. All but the first
|
||||||
|
one of the values previously in the segment are lost and gone forever.
|
||||||
|
|
||||||
|
Attempting to close a segment that extends outside the array is an error.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\param index The index of the beginning of the segment.
|
||||||
|
\param count The number of values in the segment.
|
||||||
|
\return The single value at the beginning of the segment: can be
|
||||||
|
assigned to another compatible value.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_CLOSE_AT(array, index, count) \
|
||||||
|
({ \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
size_t po = (index); \
|
||||||
|
size_t co = (count); \
|
||||||
|
if (__builtin_expect (po + co > ar->size \
|
||||||
|
|| po >= ar->size, 0)) { \
|
||||||
|
Sys_Error ("Attempt to remove elements outside darray: " \
|
||||||
|
"%s:%d", __FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
__auto_type ob = ar->a[po]; \
|
||||||
|
memmove (&ar->a[po], &ar->a[po + co], \
|
||||||
|
(ar->size - po - co) * sizeof (ob)); \
|
||||||
|
ar->size -= co; \
|
||||||
|
ob; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** Remove a value from an array at the specified index.
|
||||||
|
|
||||||
|
The values beyond the index are moved down to fill the hole left by the
|
||||||
|
single value and the array size reduced by one.
|
||||||
|
|
||||||
|
Attempting to remove a value from beyond the array is an error.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\param index The index of the value to be removed.
|
||||||
|
\return The removed value: can be assigned to another compatible
|
||||||
|
value.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_REMOVE_AT(array, index) \
|
||||||
|
({ \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
DARRAY_CLOSE_AT (ar, index, 1); \
|
||||||
|
})
|
||||||
|
|
||||||
|
/** Remove (pop) a value from the end of an array.
|
||||||
|
|
||||||
|
The size of the array size reduced by one.
|
||||||
|
|
||||||
|
Attempting to remove a value from an empty array is an error.
|
||||||
|
|
||||||
|
\param array *Address* of the array to be modified (ie, pointer to the
|
||||||
|
array struct instance, not the instance itself: use & for
|
||||||
|
static instances of the array struct).
|
||||||
|
\return The removed value: can be assigned to another compatible
|
||||||
|
value.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
#define DARRAY_REMOVE(array) \
|
||||||
|
({ \
|
||||||
|
__auto_type ar = (array); \
|
||||||
|
DARRAY_CLOSE_AT (ar, ar->size - 1, 1); \
|
||||||
|
})
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
|
#endif//__pr_type_h
|
|
@ -3,8 +3,8 @@ AUTOMAKE_OPTIONS= foreign
|
||||||
AM_CPPFLAGS= -I$(top_srcdir)/include
|
AM_CPPFLAGS= -I$(top_srcdir)/include
|
||||||
|
|
||||||
check_PROGRAMS= \
|
check_PROGRAMS= \
|
||||||
test-bary test-cs test-dq test-half test-mat3 test-mat4 test-plist \
|
test-bary test-cs test-darray test-dq test-half test-mat3 test-mat4 \
|
||||||
test-qfs test-quat test-seb test-seg test-set test-vrect
|
test-plist test-qfs test-quat test-seb test-seg test-set test-vrect
|
||||||
|
|
||||||
test_bary_SOURCES=test-bary.c
|
test_bary_SOURCES=test-bary.c
|
||||||
test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
test_bary_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||||
|
@ -14,6 +14,10 @@ test_cs_SOURCES=test-cs.c
|
||||||
test_cs_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
test_cs_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||||
test_cs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
test_cs_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||||
|
|
||||||
|
test_darray_SOURCES=test-darray.c
|
||||||
|
test_darray_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||||
|
test_darray_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||||
|
|
||||||
test_dq_SOURCES=test-dq.c
|
test_dq_SOURCES=test-dq.c
|
||||||
test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
test_dq_LDADD=$(top_builddir)/libs/util/libQFutil.la
|
||||||
test_dq_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
test_dq_DEPENDENCIES=$(top_builddir)/libs/util/libQFutil.la
|
||||||
|
|
213
libs/util/test/test-darray.c
Normal file
213
libs/util/test/test-darray.c
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
#define remove remove_renamed
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "QF/darray.h"
|
||||||
|
#include "QF/sys.h"
|
||||||
|
#undef remove
|
||||||
|
|
||||||
|
typedef int (*test_func) (int a, int b);
|
||||||
|
typedef struct intarray_s DARRAY_TYPE(int) intarray_t;
|
||||||
|
|
||||||
|
intarray_t intarray = {0, 0, 16, 0};
|
||||||
|
|
||||||
|
static int
|
||||||
|
append (int val, int b)
|
||||||
|
{
|
||||||
|
return DARRAY_APPEND (&intarray, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_size (int a, int b)
|
||||||
|
{
|
||||||
|
return intarray.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_maxSize (int a, int b)
|
||||||
|
{
|
||||||
|
return intarray.maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_grow (int a, int b)
|
||||||
|
{
|
||||||
|
return intarray.grow;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_maxSizeGrowth (int a, int b)
|
||||||
|
{
|
||||||
|
return intarray.maxSize % intarray.grow;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_array (int a, int b)
|
||||||
|
{
|
||||||
|
return !!intarray.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_value (int index, int b)
|
||||||
|
{
|
||||||
|
if ((size_t) index >= intarray.size) {
|
||||||
|
Sys_Error ("indexing beyond array");
|
||||||
|
}
|
||||||
|
return intarray.a[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
insert_at (int val, int pos)
|
||||||
|
{
|
||||||
|
return DARRAY_INSERT_AT (&intarray, val, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_at (int pos, int size)
|
||||||
|
{
|
||||||
|
return DARRAY_OPEN_AT (&intarray, pos, size) - intarray.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char text[] = "Aloy is an awesome huntress.";
|
||||||
|
static int
|
||||||
|
open_at2 (int pos, int size)
|
||||||
|
{
|
||||||
|
memcpy(DARRAY_OPEN_AT (&intarray, pos, size), text, size * sizeof (int));
|
||||||
|
return strcmp((char*) (intarray.a + pos), text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
remove_at (int pos, int b)
|
||||||
|
{
|
||||||
|
return DARRAY_REMOVE_AT (&intarray, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
remove (int pos, int b)
|
||||||
|
{
|
||||||
|
return DARRAY_REMOVE (&intarray);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
close_at (int pos, int size)
|
||||||
|
{
|
||||||
|
return DARRAY_CLOSE_AT (&intarray, pos, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
clear (int a, int b)
|
||||||
|
{
|
||||||
|
DARRAY_CLEAR (&intarray);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
resize (int size, int b)
|
||||||
|
{
|
||||||
|
DARRAY_RESIZE (&intarray, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct {
|
||||||
|
test_func test;
|
||||||
|
int param1, param2;
|
||||||
|
int test_expect;
|
||||||
|
} tests[] = {
|
||||||
|
{check_size, 0, 0, 0}, // confirm array empty but can grow
|
||||||
|
{check_maxSize, 0, 0, 0},
|
||||||
|
{check_grow, 0, 0, 16},
|
||||||
|
{check_array, 0, 0, 0},
|
||||||
|
{append, 5, 0, 5}, // test first append to emtpty array
|
||||||
|
{check_size, 0, 0, 1},
|
||||||
|
{check_maxSizeGrowth, 0, 0, 0},
|
||||||
|
{check_maxSize, 0, 0, 16},
|
||||||
|
{check_array, 0, 0, 1},
|
||||||
|
{check_value, 0, 0, 5},
|
||||||
|
{append, 42, 0, 42}, // test a second append
|
||||||
|
{check_size, 0, 0, 2},
|
||||||
|
{check_maxSize, 0, 0, 16},
|
||||||
|
{check_value, 0, 0, 5},
|
||||||
|
{check_value, 1, 0, 42},
|
||||||
|
{insert_at, 69, 1, 69}, // test insertions
|
||||||
|
{insert_at, 96, 0, 96},
|
||||||
|
{check_size, 0, 0, 4},
|
||||||
|
{check_maxSize, 0, 0, 16},
|
||||||
|
{check_value, 0, 0, 96},
|
||||||
|
{check_value, 1, 0, 5},
|
||||||
|
{check_value, 2, 0, 69},
|
||||||
|
{check_value, 3, 0, 42},
|
||||||
|
{open_at, 2, 14, 2}, // test opening a large hole
|
||||||
|
{check_maxSizeGrowth, 0, 0, 0},
|
||||||
|
{check_maxSize, 0, 0, 32},
|
||||||
|
{check_size, 0, 0, 18},
|
||||||
|
{check_value, 0, 0, 96},
|
||||||
|
{check_value, 1, 0, 5},
|
||||||
|
{check_value, 16, 0, 69},
|
||||||
|
{check_value, 17, 0, 42},
|
||||||
|
{close_at, 1, 15, 5}, // test block removal
|
||||||
|
{check_maxSize, 0, 0, 32},
|
||||||
|
{check_size, 0, 0, 3},
|
||||||
|
{check_value, 0, 0, 96},
|
||||||
|
{check_value, 1, 0, 69},
|
||||||
|
{check_value, 2, 0, 42},
|
||||||
|
{remove, 0, 0, 42}, // test "pop"
|
||||||
|
{check_maxSize, 0, 0, 32},
|
||||||
|
{check_size, 0, 0, 2},
|
||||||
|
{check_value, 0, 0, 96},
|
||||||
|
{check_value, 1, 0, 69},
|
||||||
|
{remove_at, 0, 0, 96}, // test remove at
|
||||||
|
{check_maxSize, 0, 0, 32},
|
||||||
|
{check_size, 0, 0, 1},
|
||||||
|
{check_value, 0, 0, 69},
|
||||||
|
{insert_at, 71, 1, 71}, // test insertion at end
|
||||||
|
{resize, 48, 0, 0}, // test resize bigger
|
||||||
|
{check_maxSizeGrowth, 0, 0, 0},
|
||||||
|
{check_maxSize, 0, 0, 48},
|
||||||
|
{check_size, 0, 0, 48},
|
||||||
|
{check_value, 0, 0, 69},
|
||||||
|
{check_value, 1, 0, 71},
|
||||||
|
{resize, 24, 0, 0}, // test resize smaller
|
||||||
|
{check_maxSizeGrowth, 0, 0, 0},
|
||||||
|
{check_maxSize, 0, 0, 48},
|
||||||
|
{check_size, 0, 0, 24},
|
||||||
|
{check_value, 0, 0, 69},
|
||||||
|
{check_value, 1, 0, 71},
|
||||||
|
{open_at2, 1, (sizeof (text) + sizeof (int) - 1) / sizeof (int), 0},
|
||||||
|
{check_value, 0, 0, 69},
|
||||||
|
{check_value, 1, 0, 0x796f6c41},
|
||||||
|
{check_value, 9, 0, 71},
|
||||||
|
{clear, 0, 0, 0}, // test clearing
|
||||||
|
{check_size, 0, 0, 0},
|
||||||
|
{check_maxSize, 0, 0, 0},
|
||||||
|
{check_array, 0, 0, 0},
|
||||||
|
};
|
||||||
|
#define num_tests (sizeof (tests) / sizeof (tests[0]))
|
||||||
|
int test_start_line = __LINE__ - num_tests - 2;
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_tests; i++) {
|
||||||
|
if (tests[i].test) {
|
||||||
|
int test_res;
|
||||||
|
test_res = tests[i].test (tests[i].param1, tests[i].param2);
|
||||||
|
if (test_res != tests[i].test_expect) {
|
||||||
|
res |= 1;
|
||||||
|
printf ("test %d (line %d) failed\n", (int) i,
|
||||||
|
(int) i + test_start_line);
|
||||||
|
printf ("expect: %d\n", tests[i].test_expect);
|
||||||
|
printf ("got : %d\n", test_res);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
Loading…
Reference in a new issue