nkeynes@185 | 1 | /**
|
nkeynes@185 | 2 | * $Id: testdata.c,v 1.1 2006-07-11 01:35:23 nkeynes Exp $
|
nkeynes@185 | 3 | *
|
nkeynes@185 | 4 | * Test data loader.
|
nkeynes@185 | 5 | *
|
nkeynes@185 | 6 | * Copyright (c) 2006 Nathan Keynes.
|
nkeynes@185 | 7 | *
|
nkeynes@185 | 8 | * This program is free software; you can redistribute it and/or modify
|
nkeynes@185 | 9 | * it under the terms of the GNU General Public License as published by
|
nkeynes@185 | 10 | * the Free Software Foundation; either version 2 of the License, or
|
nkeynes@185 | 11 | * (at your option) any later version.
|
nkeynes@185 | 12 | *
|
nkeynes@185 | 13 | * This program is distributed in the hope that it will be useful,
|
nkeynes@185 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nkeynes@185 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nkeynes@185 | 16 | * GNU General Public License for more details.
|
nkeynes@185 | 17 | */
|
nkeynes@185 | 18 |
|
nkeynes@185 | 19 | #include <stdlib.h>
|
nkeynes@185 | 20 | #include <string.h>
|
nkeynes@185 | 21 | #include <ctype.h>
|
nkeynes@185 | 22 | #include <math.h>
|
nkeynes@185 | 23 | #include "testdata.h"
|
nkeynes@185 | 24 |
|
nkeynes@185 | 25 | #define DEFAULT_SIZE 1024
|
nkeynes@185 | 26 |
|
nkeynes@185 | 27 | /* get the next 32-byte aligned address that is no less than x */
|
nkeynes@185 | 28 | #define ALIGN_32(x) ((char *)((((unsigned int)(x))+0x1F)&0xFFFFFFE0))
|
nkeynes@185 | 29 |
|
nkeynes@185 | 30 | void free_test_dataset( test_data_t tests )
|
nkeynes@185 | 31 | {
|
nkeynes@185 | 32 | test_data_t next;
|
nkeynes@185 | 33 |
|
nkeynes@185 | 34 | do {
|
nkeynes@185 | 35 | next = tests->next;
|
nkeynes@185 | 36 | free(tests);
|
nkeynes@185 | 37 | tests = next;
|
nkeynes@185 | 38 | } while( next != NULL );
|
nkeynes@185 | 39 | }
|
nkeynes@185 | 40 |
|
nkeynes@185 | 41 | test_data_block_t get_test_data( test_data_t data, char *name )
|
nkeynes@185 | 42 | {
|
nkeynes@185 | 43 | int i;
|
nkeynes@185 | 44 | for( i=0; i<MAX_DATA_BLOCKS; i++ ) {
|
nkeynes@185 | 45 | if( data->item[i].name != NULL &&
|
nkeynes@185 | 46 | strcmp(name, data->item[i].name) == 0 ) {
|
nkeynes@185 | 47 | return &data->item[i];
|
nkeynes@185 | 48 | }
|
nkeynes@185 | 49 | }
|
nkeynes@185 | 50 | return NULL;
|
nkeynes@185 | 51 | }
|
nkeynes@185 | 52 |
|
nkeynes@185 | 53 | void dump_test_dataset( FILE *f, test_data_t dataset )
|
nkeynes@185 | 54 | {
|
nkeynes@185 | 55 | test_data_t test = dataset;
|
nkeynes@185 | 56 | int i;
|
nkeynes@185 | 57 | while( test != NULL ) {
|
nkeynes@185 | 58 | fprintf( f, "Test: %s\n", test->test_name );
|
nkeynes@185 | 59 | for( i=0; i<MAX_DATA_BLOCKS; i++ ) {
|
nkeynes@185 | 60 | if( test->item[i].name != NULL ) {
|
nkeynes@185 | 61 | fprintf( f, "Block: %s, %d bytes\n", test->item[i].name, test->item[i].length );
|
nkeynes@185 | 62 | fwrite_dump( f, test->item[i].data, test->item[i].length );
|
nkeynes@185 | 63 | }
|
nkeynes@185 | 64 | }
|
nkeynes@185 | 65 | test = test->next;
|
nkeynes@185 | 66 | }
|
nkeynes@185 | 67 | }
|
nkeynes@185 | 68 |
|
nkeynes@185 | 69 | int test_block_compare( test_data_block_t block, char *result, int result_length )
|
nkeynes@185 | 70 | {
|
nkeynes@185 | 71 | if( block->length != result_length )
|
nkeynes@185 | 72 | return -1;
|
nkeynes@185 | 73 | return memcmp( block->data, result, block->length );
|
nkeynes@185 | 74 | }
|
nkeynes@185 | 75 |
|
nkeynes@185 | 76 |
|
nkeynes@185 | 77 | /**
|
nkeynes@185 | 78 | * Load a batch of test data from the given IO stream.
|
nkeynes@185 | 79 | */
|
nkeynes@185 | 80 | test_data_t load_test_dataset( FILE *f )
|
nkeynes@185 | 81 | {
|
nkeynes@185 | 82 | test_data_t head = NULL;
|
nkeynes@185 | 83 | test_data_t current = NULL;
|
nkeynes@185 | 84 | test_data_t last = NULL;
|
nkeynes@185 | 85 | int current_size = 0;
|
nkeynes@185 | 86 | int current_block = -1;
|
nkeynes@185 | 87 | char *current_end = NULL;
|
nkeynes@185 | 88 | char *dataptr = NULL;
|
nkeynes@185 | 89 |
|
nkeynes@185 | 90 | char buf[512];
|
nkeynes@185 | 91 | char *line;
|
nkeynes@185 | 92 | while( fgets(buf, sizeof(buf), f ) != NULL ) {
|
nkeynes@185 | 93 | line = buf;
|
nkeynes@185 | 94 | while( isspace(*line) ) /* Trim leading whitespace */
|
nkeynes@185 | 95 | line++;
|
nkeynes@185 | 96 | if( line[0] == '[' ) { /* New test */
|
nkeynes@185 | 97 | char *test_name = line+1;
|
nkeynes@185 | 98 | char *end = strchr(test_name, ']');
|
nkeynes@185 | 99 | if( end != NULL )
|
nkeynes@185 | 100 | *end = '\0';
|
nkeynes@185 | 101 | current_size = DEFAULT_SIZE;
|
nkeynes@185 | 102 | test_data_t test = calloc(current_size, 1);
|
nkeynes@185 | 103 |
|
nkeynes@185 | 104 | dataptr = (char *)(test+1);
|
nkeynes@185 | 105 | test->next = NULL;
|
nkeynes@185 | 106 | if( head == NULL )
|
nkeynes@185 | 107 | head = test;
|
nkeynes@185 | 108 | if( current != NULL )
|
nkeynes@185 | 109 | current->next = test;
|
nkeynes@185 | 110 | last = current;
|
nkeynes@185 | 111 | current = test;
|
nkeynes@185 | 112 | current_end = ((char *)test) + current_size;
|
nkeynes@185 | 113 | current_block = -1;
|
nkeynes@185 | 114 | strcpy( dataptr, test_name );
|
nkeynes@185 | 115 | test->test_name = dataptr;
|
nkeynes@185 | 116 | dataptr = ALIGN_32(dataptr + strlen(test_name)+1);
|
nkeynes@185 | 117 | } else if( *line == '#' ) { /* Comment */
|
nkeynes@185 | 118 | } else {
|
nkeynes@185 | 119 | char *equals = strrchr( line, '=' );
|
nkeynes@185 | 120 | if( equals != NULL ) {
|
nkeynes@185 | 121 | char *block_name = line;
|
nkeynes@185 | 122 | int len;
|
nkeynes@185 | 123 | *equals-- = '\0';
|
nkeynes@185 | 124 | while( isspace(*equals) )
|
nkeynes@185 | 125 | *equals-- = '\0';
|
nkeynes@185 | 126 | len = strlen(line)+1;
|
nkeynes@185 | 127 | if( dataptr + len > current_end ) {
|
nkeynes@185 | 128 | current_end += current_size;
|
nkeynes@185 | 129 | current_size *= 2;
|
nkeynes@185 | 130 | current = realloc(current, current_size );
|
nkeynes@185 | 131 | if( last != NULL )
|
nkeynes@185 | 132 | last->next = current;
|
nkeynes@185 | 133 | }
|
nkeynes@185 | 134 | current_block++;
|
nkeynes@185 | 135 | strcpy( dataptr, block_name );
|
nkeynes@185 | 136 | current->item[current_block].name = dataptr;
|
nkeynes@185 | 137 | dataptr = ALIGN_32(dataptr+len);
|
nkeynes@185 | 138 | current->item[current_block].data = dataptr;
|
nkeynes@185 | 139 | current->item[current_block].length = 0;
|
nkeynes@185 | 140 | } else {
|
nkeynes@185 | 141 | /* Data */
|
nkeynes@185 | 142 | if( current == NULL || current_block == -1 )
|
nkeynes@185 | 143 | continue;
|
nkeynes@185 | 144 | char *p = strtok(line, "\t\r\n ");
|
nkeynes@185 | 145 | while( p != NULL ) {
|
nkeynes@185 | 146 | if( dataptr + 8 > current_end ) {
|
nkeynes@185 | 147 | current_end += current_size;
|
nkeynes@185 | 148 | current_size *= 2;
|
nkeynes@185 | 149 | current = realloc(current, current_size );
|
nkeynes@185 | 150 | if( last != NULL )
|
nkeynes@185 | 151 | last->next = current;
|
nkeynes@185 | 152 | }
|
nkeynes@185 | 153 | int len = strlen(p);
|
nkeynes@185 | 154 | int datalen = 0;
|
nkeynes@185 | 155 | char *dot = strchr(p, '.');
|
nkeynes@185 | 156 | if( dot != NULL ) { /* FP */
|
nkeynes@185 | 157 | if( p[len-1] == 'L' ) { /* Ending in L */
|
nkeynes@185 | 158 | p[len-1] = '\0';
|
nkeynes@185 | 159 | double d = strtod(p, NULL);
|
nkeynes@185 | 160 | *((double *)dataptr) = d;
|
nkeynes@185 | 161 | datalen = 8;
|
nkeynes@185 | 162 | } else {
|
nkeynes@185 | 163 | float f = (float)strtod(p,NULL);
|
nkeynes@185 | 164 | *((float *)dataptr) = f;
|
nkeynes@185 | 165 | datalen = 4;
|
nkeynes@185 | 166 | }
|
nkeynes@185 | 167 | } else {
|
nkeynes@185 | 168 | unsigned long value = strtoul(p, NULL, 16);
|
nkeynes@185 | 169 | if( len == 8 ) {
|
nkeynes@185 | 170 | *((unsigned int *)dataptr) = value;
|
nkeynes@185 | 171 | datalen = 4;
|
nkeynes@185 | 172 | } else if( len == 4 ) {
|
nkeynes@185 | 173 | *((unsigned short *)dataptr) = value;
|
nkeynes@185 | 174 | datalen = 2;
|
nkeynes@185 | 175 | } else if( len == 2 ) {
|
nkeynes@185 | 176 | *((unsigned char *)dataptr) = value;
|
nkeynes@185 | 177 | datalen = 1;
|
nkeynes@185 | 178 | }
|
nkeynes@185 | 179 | }
|
nkeynes@185 | 180 | dataptr += datalen;
|
nkeynes@185 | 181 | current->item[current_block].length += datalen;
|
nkeynes@185 | 182 | p = strtok(NULL, "\t\r\n ");
|
nkeynes@185 | 183 | }
|
nkeynes@185 | 184 | }
|
nkeynes@185 | 185 | }
|
nkeynes@185 | 186 | }
|
nkeynes@185 | 187 | fclose(f);
|
nkeynes@185 | 188 | return head;
|
nkeynes@185 | 189 | }
|