/src/botlib/l_struct.c
C | 507 lines | 383 code | 18 blank | 106 comment | 107 complexity | 6e0d6a916eab05c634071d427260a53f MD5 | raw file
Possible License(s): GPL-3.0
- /*
- ===========================================================================
- Return to Castle Wolfenstein multiplayer GPL Source Code
- Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
- This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (?RTCW MP Source Code?).
- RTCW MP Source Code 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 3 of the License, or
- (at your option) any later version.
- RTCW MP Source Code 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 RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- /*****************************************************************************
- * name: l_struct.c
- *
- * desc: structure reading / writing
- *
- *
- *****************************************************************************/
- #ifdef BOTLIB
- #include "../game/q_shared.h"
- #include "../game/botlib.h" //for the include of be_interface.h
- #include "l_script.h"
- #include "l_precomp.h"
- #include "l_struct.h"
- #include "l_utils.h"
- #include "be_interface.h"
- #endif //BOTLIB
- #ifdef BSPC
- //include files for usage in the BSP Converter
- #include "../bspc/qbsp.h"
- #include "../bspc/l_log.h"
- #include "../bspc/l_mem.h"
- #include "l_precomp.h"
- #include "l_struct.h"
- #define qtrue true
- #define qfalse false
- #endif //BSPC
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- fielddef_t *FindField( fielddef_t *defs, char *name ) {
- int i;
- for ( i = 0; defs[i].name; i++ )
- {
- if ( !strcmp( defs[i].name, name ) ) {
- return &defs[i];
- }
- } //end for
- return NULL;
- } //end of the function FindField
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- qboolean ReadNumber( source_t *source, fielddef_t *fd, void *p ) {
- token_t token;
- int negative = qfalse;
- long int intval, intmin = 0, intmax = 0;
- double floatval;
- if ( !PC_ExpectAnyToken( source, &token ) ) {
- return 0;
- }
- //check for minus sign
- if ( token.type == TT_PUNCTUATION ) {
- if ( fd->type & FT_UNSIGNED ) {
- SourceError( source, "expected unsigned value, found %s", token.string );
- return 0;
- } //end if
- //if not a minus sign
- if ( strcmp( token.string, "-" ) ) {
- SourceError( source, "unexpected punctuation %s", token.string );
- return 0;
- } //end if
- negative = qtrue;
- //read the number
- if ( !PC_ExpectAnyToken( source, &token ) ) {
- return 0;
- }
- } //end if
- //check if it is a number
- if ( token.type != TT_NUMBER ) {
- SourceError( source, "expected number, found %s", token.string );
- return 0;
- } //end if
- //check for a float value
- if ( token.subtype & TT_FLOAT ) {
- if ( ( fd->type & FT_TYPE ) != FT_FLOAT ) {
- SourceError( source, "unexpected float" );
- return 0;
- } //end if
- floatval = token.floatvalue;
- if ( negative ) {
- floatval = -floatval;
- }
- if ( fd->type & FT_BOUNDED ) {
- if ( floatval < fd->floatmin || floatval > fd->floatmax ) {
- SourceError( source, "float out of range [%f, %f]", fd->floatmin, fd->floatmax );
- return 0;
- } //end if
- } //end if
- *(float *) p = (float) floatval;
- return 1;
- } //end if
- //
- intval = token.intvalue;
- if ( negative ) {
- intval = -intval;
- }
- //check bounds
- if ( ( fd->type & FT_TYPE ) == FT_CHAR ) {
- if ( fd->type & FT_UNSIGNED ) {
- intmin = 0; intmax = 255;
- } else {intmin = -128; intmax = 127;}
- } //end if
- if ( ( fd->type & FT_TYPE ) == FT_INT ) {
- if ( fd->type & FT_UNSIGNED ) {
- intmin = 0; intmax = 65535;
- } else {intmin = -32768; intmax = 32767;}
- } //end else if
- if ( ( fd->type & FT_TYPE ) == FT_CHAR || ( fd->type & FT_TYPE ) == FT_INT ) {
- if ( fd->type & FT_BOUNDED ) {
- intmin = Maximum( intmin, fd->floatmin );
- intmax = Minimum( intmax, fd->floatmax );
- } //end if
- if ( intval < intmin || intval > intmax ) {
- SourceError( source, "value %d out of range [%d, %d]", intval, intmin, intmax );
- return 0;
- } //end if
- } //end if
- else if ( ( fd->type & FT_TYPE ) == FT_FLOAT ) {
- if ( fd->type & FT_BOUNDED ) {
- if ( intval < fd->floatmin || intval > fd->floatmax ) {
- SourceError( source, "value %d out of range [%f, %f]", intval, fd->floatmin, fd->floatmax );
- return 0;
- } //end if
- } //end if
- } //end else if
- //store the value
- if ( ( fd->type & FT_TYPE ) == FT_CHAR ) {
- if ( fd->type & FT_UNSIGNED ) {
- *(unsigned char *) p = (unsigned char) intval;
- } else { *(char *) p = (char) intval;}
- } //end if
- else if ( ( fd->type & FT_TYPE ) == FT_INT ) {
- if ( fd->type & FT_UNSIGNED ) {
- *(unsigned int *) p = (unsigned int) intval;
- } else { *(int *) p = (int) intval;}
- } //end else
- else if ( ( fd->type & FT_TYPE ) == FT_FLOAT ) {
- *(float *) p = (float) intval;
- } //end else
- return 1;
- } //end of the function ReadNumber
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- qboolean ReadChar( source_t *source, fielddef_t *fd, void *p ) {
- token_t token;
- if ( !PC_ExpectAnyToken( source, &token ) ) {
- return 0;
- }
- //take literals into account
- if ( token.type == TT_LITERAL ) {
- StripSingleQuotes( token.string );
- *(char *) p = token.string[0];
- } //end if
- else
- {
- PC_UnreadLastToken( source );
- if ( !ReadNumber( source, fd, p ) ) {
- return 0;
- }
- } //end if
- return 1;
- } //end of the function ReadChar
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- int ReadString( source_t *source, fielddef_t *fd, void *p ) {
- token_t token;
- if ( !PC_ExpectTokenType( source, TT_STRING, 0, &token ) ) {
- return 0;
- }
- //remove the double quotes
- StripDoubleQuotes( token.string );
- //copy the string
- strncpy( (char *) p, token.string, MAX_STRINGFIELD );
- //make sure the string is closed with a zero
- ( (char *)p )[MAX_STRINGFIELD - 1] = '\0';
- //
- return 1;
- } //end of the function ReadString
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- int ReadStructure( source_t *source, structdef_t *def, char *structure ) {
- token_t token;
- fielddef_t *fd;
- void *p;
- int num;
- if ( !PC_ExpectTokenString( source, "{" ) ) {
- return 0;
- }
- while ( 1 )
- {
- if ( !PC_ExpectAnyToken( source, &token ) ) {
- return qfalse;
- }
- //if end of structure
- if ( !strcmp( token.string, "}" ) ) {
- break;
- }
- //find the field with the name
- fd = FindField( def->fields, token.string );
- if ( !fd ) {
- SourceError( source, "unknown structure field %s", token.string );
- return qfalse;
- } //end if
- if ( fd->type & FT_ARRAY ) {
- num = fd->maxarray;
- if ( !PC_ExpectTokenString( source, "{" ) ) {
- return qfalse;
- }
- } //end if
- else
- {
- num = 1;
- } //end else
- p = ( void * )( structure + fd->offset );
- while ( num-- > 0 )
- {
- if ( fd->type & FT_ARRAY ) {
- if ( PC_CheckTokenString( source, "}" ) ) {
- break;
- }
- } //end if
- switch ( fd->type & FT_TYPE )
- {
- case FT_CHAR:
- {
- if ( !ReadChar( source, fd, p ) ) {
- return qfalse;
- }
- p = (char *) p + sizeof( char );
- break;
- } //end case
- case FT_INT:
- {
- if ( !ReadNumber( source, fd, p ) ) {
- return qfalse;
- }
- p = (char *) p + sizeof( int );
- break;
- } //end case
- case FT_FLOAT:
- {
- if ( !ReadNumber( source, fd, p ) ) {
- return qfalse;
- }
- p = (char *) p + sizeof( float );
- break;
- } //end case
- case FT_STRING:
- {
- if ( !ReadString( source, fd, p ) ) {
- return qfalse;
- }
- p = (char *) p + MAX_STRINGFIELD;
- break;
- } //end case
- case FT_STRUCT:
- {
- if ( !fd->substruct ) {
- SourceError( source, "BUG: no sub structure defined" );
- return qfalse;
- } //end if
- ReadStructure( source, fd->substruct, (char *) p );
- p = (char *) p + fd->substruct->size;
- break;
- } //end case
- } //end switch
- if ( fd->type & FT_ARRAY ) {
- if ( !PC_ExpectAnyToken( source, &token ) ) {
- return qfalse;
- }
- if ( !strcmp( token.string, "}" ) ) {
- break;
- }
- if ( strcmp( token.string, "," ) ) {
- SourceError( source, "expected a comma, found %s", token.string );
- return qfalse;
- } //end if
- } //end if
- } //end while
- } //end while
- return qtrue;
- } //end of the function ReadStructure
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- int WriteIndent( FILE *fp, int indent ) {
- while ( indent-- > 0 )
- {
- if ( fprintf( fp, "\t" ) < 0 ) {
- return qfalse;
- }
- } //end while
- return qtrue;
- } //end of the function WriteIndent
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- int WriteFloat( FILE *fp, float value ) {
- char buf[128];
- int l;
- sprintf( buf, "%f", value );
- l = strlen( buf );
- //strip any trailing zeros
- while ( l-- > 1 )
- {
- if ( buf[l] != '0' && buf[l] != '.' ) {
- break;
- }
- if ( buf[l] == '.' ) {
- buf[l] = 0;
- break;
- } //end if
- buf[l] = 0;
- } //end while
- //write the float to file
- if ( fprintf( fp, "%s", buf ) < 0 ) {
- return 0;
- }
- return 1;
- } //end of the function WriteFloat
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- int WriteStructWithIndent( FILE *fp, structdef_t *def, char *structure, int indent ) {
- int i, num;
- void *p;
- fielddef_t *fd;
- if ( !WriteIndent( fp, indent ) ) {
- return qfalse;
- }
- if ( fprintf( fp, "{\r\n" ) < 0 ) {
- return qfalse;
- }
- indent++;
- for ( i = 0; def->fields[i].name; i++ )
- {
- fd = &def->fields[i];
- if ( !WriteIndent( fp, indent ) ) {
- return qfalse;
- }
- if ( fprintf( fp, "%s\t", fd->name ) < 0 ) {
- return qfalse;
- }
- p = ( void * )( structure + fd->offset );
- if ( fd->type & FT_ARRAY ) {
- num = fd->maxarray;
- if ( fprintf( fp, "{" ) < 0 ) {
- return qfalse;
- }
- } //end if
- else
- {
- num = 1;
- } //end else
- while ( num-- > 0 )
- {
- switch ( fd->type & FT_TYPE )
- {
- case FT_CHAR:
- {
- if ( fprintf( fp, "%d", *(char *) p ) < 0 ) {
- return qfalse;
- }
- p = (char *) p + sizeof( char );
- break;
- } //end case
- case FT_INT:
- {
- if ( fprintf( fp, "%d", *(int *) p ) < 0 ) {
- return qfalse;
- }
- p = (char *) p + sizeof( int );
- break;
- } //end case
- case FT_FLOAT:
- {
- if ( !WriteFloat( fp, *(float *)p ) ) {
- return qfalse;
- }
- p = (char *) p + sizeof( float );
- break;
- } //end case
- case FT_STRING:
- {
- if ( fprintf( fp, "\"%s\"", (char *) p ) < 0 ) {
- return qfalse;
- }
- p = (char *) p + MAX_STRINGFIELD;
- break;
- } //end case
- case FT_STRUCT:
- {
- if ( !WriteStructWithIndent( fp, fd->substruct, structure, indent ) ) {
- return qfalse;
- }
- p = (char *) p + fd->substruct->size;
- break;
- } //end case
- } //end switch
- if ( fd->type & FT_ARRAY ) {
- if ( num > 0 ) {
- if ( fprintf( fp, "," ) < 0 ) {
- return qfalse;
- }
- } //end if
- else
- {
- if ( fprintf( fp, "}" ) < 0 ) {
- return qfalse;
- }
- } //end else
- } //end if
- } //end while
- if ( fprintf( fp, "\r\n" ) < 0 ) {
- return qfalse;
- }
- } //end for
- indent--;
- if ( !WriteIndent( fp, indent ) ) {
- return qfalse;
- }
- if ( fprintf( fp, "}\r\n" ) < 0 ) {
- return qfalse;
- }
- return qtrue;
- } //end of the function WriteStructWithIndent
- //===========================================================================
- //
- // Parameter: -
- // Returns: -
- // Changes Globals: -
- //===========================================================================
- int WriteStructure( FILE *fp, structdef_t *def, char *structure ) {
- return WriteStructWithIndent( fp, def, structure, 0 );
- } //end of the function WriteStructure