shithub: choc

ref: e98e86a672d7f1548c57a1b3351b1aacb60d9e03
dir: /src/deh_io.c/

View raw version
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// $Id: deh_io.c 153 2005-10-02 23:49:01Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
// 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 the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
// $Log$
// Revision 1.1  2005/10/02 23:49:01  fraggle
// The beginnings of dehacked support
//
//
//-----------------------------------------------------------------------------
//
// Dehacked I/O code (does all reads from dehacked files)
//
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "z_zone.h"

#include "deh_defs.h"
#include "deh_io.h"

struct deh_context_s
{
    FILE *stream;
    char *readbuffer;
    int readbuffer_size;
};

// Open a dehacked file for reading
// Returns NULL if open failed

deh_context_t *DEH_OpenFile(char *filename)
{
    FILE *fstream;
    deh_context_t *context;
    
    fstream = fopen(filename, "r");

    if (fstream == NULL)
        return NULL;

    context = Z_Malloc(sizeof(*context), PU_STATIC, NULL);
    context->stream = fstream;
    
    // Initial read buffer size of 128 bytes

    context->readbuffer_size = 128;
    context->readbuffer = Z_Malloc(context->readbuffer_size, PU_STATIC, NULL);

    return context;
}

// Close dehacked file

void DEH_CloseFile(deh_context_t *context)
{
    fclose(context->stream);
    Z_Free(context->readbuffer);
    Z_Free(context);
}

// Reads a single character from a dehacked file

int DEH_GetChar(deh_context_t *context)
{
    int result;
   
    // Read characters, but ignore carriage returns
    // Essentially this is a DOS->Unix conversion

    do 
    {
        if (feof(context->stream))
        {
            // end of file

            result = -1;
        }
        else
        {
            result = fgetc(context->stream);
        }

    } while (result == '\r');

    return result;
}

// Increase the read buffer size

static void IncreaseReadBuffer(deh_context_t *context)
{
    char *newbuffer;
    int newbuffer_size;

    newbuffer_size = context->readbuffer_size * 2;
    newbuffer = Z_Malloc(newbuffer_size, PU_STATIC, NULL);

    memcpy(newbuffer, context->readbuffer, context->readbuffer_size);

    Z_Free(context->readbuffer);

    context->readbuffer = newbuffer;
    context->readbuffer_size = newbuffer_size;
}

// Read a whole line

char *DEH_ReadLine(deh_context_t *context)
{
    char *p;
    int c;
    int pos;

    for (pos=0; ; ++pos)
    {
        c = DEH_GetChar(context);

        if (c < 0)
        {
            // end of file

            return NULL;
        }

        // cope with lines of any length: increase the buffer size

        if (pos >= context->readbuffer_size)
        {
            IncreaseReadBuffer(context);
        }

        if (c == '\n')
        {
            // end of line: a full line has been read

            context->readbuffer[pos] = '\0';
            break;
        }
        else
        {
            context->readbuffer[pos] = (char) c;
        }
    }
    
    return context->readbuffer;
}