.


CircFile.c
/* CircFile.c */
/* Copyright(c) 1991-2006 by Motion Engineering, Inc.  All rights reserved.
 *
 * This software  contains proprietary and  confidential information  of
 * Motion Engineering Inc., and its suppliers.  Except as may be set forth
 * in the license agreement under which  this software is supplied, use,
 * disclosure, or  reproduction is prohibited without the prior express
 * written consent of Motion Engineering, Inc.
 */

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

#ifndef TRUE
    #define TRUE    (1)
#endif
#ifndef FALSE
    #define FALSE   (0)
#endif

#define IS_TRUE(x)  ((x)!=FALSE)
#define IS_FALSE(x) ((x)==FALSE)

#define LINE_HEADER_LENGTH  (8)
#define MAX_LINE_COUNT      (499999)
#define MAX_LINE_VAL        (1000000)

typedef struct CircFile
{
    FILE*   cFile;
    long    lineLength;
    long    lineCount;
    long    currentLine;
    long    writeLine;

    long    writable;
    long    eof;
} CircFile;

CircFile* circFileOpenForWrite(const char* name, long lineLength, long lineCount)
{
    CircFile* file;

    if ((lineLength < 2) || (lineCount < 1) || (lineCount > MAX_LINE_COUNT))
    {
        return NULL;
    }

    file = (CircFile*) malloc(sizeof(CircFile));

    if (file != NULL)
    {
        file->cFile = fopen(name, "wb");
        if (file->cFile == NULL)
        {
            free(file);
            file = NULL;
        }
    }
    if (file != NULL)
    {
        file->lineLength = lineLength+LINE_HEADER_LENGTH+1;
        file->lineCount = lineCount;
        file->currentLine = 0;
        file->writeLine = 0;
        file->writable = TRUE;
        file->eof = FALSE;
    }

    return file;
}

CircFile* circFileOpenForRead(const char* name)
{
    CircFile* file = (CircFile*) malloc(sizeof(CircFile));

    if (file != NULL)
    {
        file->cFile = fopen(name, "rb");
        if (file->cFile == NULL)
        {
            free(file);
            file = NULL;
        }
    }
    if (file != NULL)
    {
        long    fileLength;

        file->writable = FALSE;

        fseek(file->cFile, 0, SEEK_END);

        fileLength = ftell(file->cFile);

        if (fileLength == 0)
        {
            file->lineLength = 0;
            file->lineCount = 0;
        }
        else
        {
            long    lineA, lineB, lineC, idA, idB, idC, difLineAB, difLineBC, difLineAC;

            fseek(file->cFile, 0, SEEK_SET);
            while(fgetc(file->cFile)!='\n');

            file->lineLength = ftell(file->cFile);
            file->lineCount = fileLength/file->lineLength;

            fseek(file->cFile, 0, SEEK_SET);
            fscanf(file->cFile, "%06d", &idA);
            lineA = 0;

            fseek(file->cFile, (file->lineCount/2)*file->lineLength, SEEK_SET);
            fscanf(file->cFile, "%06d", &idB);
            lineB = file->lineCount/2;

            fseek(file->cFile, (file->lineCount-1)*file->lineLength, SEEK_SET);
            fscanf(file->cFile, "%06d", &idC);
            lineC = file->lineCount-1;

            difLineAC = idC-idA;
            if (difLineAC > MAX_LINE_COUNT) {difLineAC -= MAX_LINE_VAL;}
            if (difLineAC < -MAX_LINE_COUNT) {difLineAC += MAX_LINE_VAL;}

            if ((difLineAC > 0) || (file->lineCount == 1))
            {
                file->writeLine = 0;
            }
            else
            {
                for(;;)
                {
                    difLineAB = idB-idA;
                    if (difLineAB > MAX_LINE_COUNT) {difLineAB -= MAX_LINE_VAL;}
                    if (difLineAB < -MAX_LINE_COUNT) {difLineAB += MAX_LINE_VAL;}

                    difLineBC = idC-idB;
                    if (difLineBC > MAX_LINE_COUNT) {difLineBC -= MAX_LINE_VAL;}
                    if (difLineBC < -MAX_LINE_COUNT) {difLineBC += MAX_LINE_VAL;}

                    if (difLineAB < 0)
                    {
                        if (lineB == lineA + 1)
                        {
                            file->writeLine = lineB;
                            break;
                        }
                        idC = idB;
                        lineC = lineB;
                    }
                    else if (difLineBC < 0)
                    {
                        if (lineC == lineB + 1)
                        {
                            file->writeLine = lineC;
                            break;
                        }
                        idA = idB;
                        lineA = lineB;
                    }
                    else
                    {
                        file->writeLine = -1;
                        break;
                    }
                    lineB = (lineA + lineC)/2;
                    fseek(file->cFile, lineB*file->lineLength, SEEK_SET);
                    fscanf(file->cFile, "%06d", &idB);
                }
            }
        }
        fseek(file->cFile, file->writeLine*file->lineLength + LINE_HEADER_LENGTH, SEEK_SET);
        file->currentLine = 0;
        file->eof = FALSE;
    }
    return file;
}

void circFileClose(CircFile* file)
{
    if (file != NULL)
    {
        if (IS_TRUE(file->writable))
        {
            long    position;

            position = ftell(file->cFile) % file->lineLength;

            if (position > 0)
            {
                while (position < file->lineLength-1)
                {
                    fputc(' ', file->cFile);
                    ++position;
                }
                fputc('\n', file->cFile);
            }
        }
        fclose(file->cFile);
        free(file);
    }
}

long circFileLineLength(CircFile* file)
{
    if (file != NULL)
    {
        return file->lineLength - LINE_HEADER_LENGTH - 1;
    }
    return -1;
}

long circFileLineCount(CircFile* file)
{
    if (file != NULL)
    {
        return file->lineCount;
    }
    return -1;
}

long circFileSize(CircFile* file)
{
    if (file != NULL)
    {
        return (file->lineLength - LINE_HEADER_LENGTH)*file->lineCount;
    }
    return -1;
}

/* Used internally -- don't need error checking */
long _circFileSizeAbs(CircFile* file)
{
    return file->lineLength*file->lineCount;
}

/* Used internally -- don't need error checking */
long _circFilePositionOffset(CircFile* file)
{
    return file->lineLength*file->writeLine;
}

/* Used internally -- don't need error checking */
long _circFileTellAbs(CircFile* file)
{
    long position = ftell(file->cFile) - file->writeLine*file->lineLength;

    if (position<0)
    {
        position += file->lineCount*file->lineLength;
    }

    return position;
}

/* Used internally -- don't need error checking */
long _circFileTellFromAbs(CircFile* file, long absPosition)
{
    return absPosition - LINE_HEADER_LENGTH*(1 + absPosition/file->lineLength);
}

/* Used internally -- don't need error checking */
long _circFileTellToAbs(CircFile* file, long position)
{
    return position + LINE_HEADER_LENGTH*(1 + position/(circFileLineLength(file)+1));
}

long circFileTell(CircFile* file)
{
    if (file != NULL)
    {
        long absPosition = _circFileTellAbs(file);

        return _circFileTellFromAbs(file, absPosition);
    }
    return -1;
}

long circFileTellLine(CircFile* file)
{
    if (file != NULL)
    {
        return circFileTell(file)/(circFileLineLength(file)+1);
    }
    return -1;
}

int circFileEof(CircFile* file)
{
    if (file != NULL)
    {
        if (feof(file->cFile) || (file->lineLength == 0) || (file->lineCount == 0))
        {
            return TRUE;
        }
        return ((int) file->eof);
    }
    return -1;
}

char* circFileGets(CircFile* file, char* buffer, int length)
{
    if (file != NULL)
    {
        if (IS_TRUE(file->eof))
        {
            buffer[0]='\0';
        }
        else
        {
            fgets(buffer, length, file->cFile);

            if ((ftell(file->cFile) % file->lineLength) == 0)
            {
                ++file->currentLine;
                if (file->currentLine == file->lineCount)
                {
                    file->eof = TRUE;
                    file->currentLine;
                }
                file->currentLine %= file->lineCount;
                fseek(file->cFile, ((file->writeLine+file->currentLine)%file->lineCount)*file->lineLength + LINE_HEADER_LENGTH, SEEK_SET);
            }
        }
    }
    else
    {
        buffer[0]='\0';
    }
    return buffer;
}

int circFileGetc(CircFile* file)
{
    if (file != NULL)
    {
        int c;

        long position;

        if (IS_TRUE(file->eof))
        {
            return EOF;
        }

        position = ftell(file->cFile);

        c = fgetc(file->cFile);
        if (ftell(file->cFile)%file->lineLength == 0)
        {
            ++file->currentLine;
            if (file->currentLine == file->lineCount)
            {
                file->eof = TRUE;
                file->currentLine;
            }
            fseek(file->cFile, ((file->writeLine+file->currentLine)%file->lineCount)*file->lineLength + LINE_HEADER_LENGTH, SEEK_SET);
        }

        return c;
    }
    return EOF;
}

int circFileSeek(CircFile* file, long count, int seek)
{
    if (file != NULL)
    {
        int     returnValue;

        long    position;

        if (seek == SEEK_CUR)
        {
            count += circFileTell(file);
        }
        else if (seek == SEEK_END)
        {
            count += circFileSize(file);
        }
        else if (seek != SEEK_SET)
        {
            return -1;  /* Error */
        }

        if ((count < 0) || (count > circFileSize(file)))
        {
            return -1;  /* Error */
        }
        else if (count == circFileSize(file))
        {
            file->eof = TRUE;
        }
        else
        {
            file->eof = FALSE;
        }

        position = (_circFilePositionOffset(file) + _circFileTellToAbs(file, count)) %
            _circFileSizeAbs(file);

        returnValue = fseek(file->cFile, position, SEEK_SET);

        file->currentLine = (position/file->lineLength)-(file->writeLine);
        if (file->currentLine < 0)
        {
            file->currentLine += file->lineCount;
        }

        return returnValue;
    }
    return -1;
}

int circFileSeekLine(CircFile* file, long lineCount, int seek)
{
    if (file != NULL)
    {
        int     returnValue;

        long    position;

        if (seek == SEEK_CUR)
        {
            lineCount += circFileTellLine(file);
        }
        else if (seek == SEEK_END)
        {
            lineCount += file->lineCount;
        }
        else if (seek != SEEK_SET)
        {
            return -1;  /* Error */
        }

        if ((lineCount < 0) || (lineCount > file->lineCount))
        {
            return -1;  /* Error */
        }
        else if (lineCount == file->lineCount)
        {
            file->eof = TRUE;
        }
        else
        {
            file->eof = FALSE;
        }

        file->currentLine = lineCount;

        position = (_circFilePositionOffset(file) + _circFileTellToAbs(file, (circFileLineLength(file)+1)*lineCount)) %
            _circFileSizeAbs(file);

        returnValue = fseek(file->cFile, position, SEEK_SET);

        return returnValue;
    }
    return -1;
}

void circFileWrite(CircFile* file, const char* buffer)
{
    if (file != NULL)
    {
        long    position;

        if (IS_FALSE(file->writable))
        {
            return;
        }

        if (*buffer == '\0')
        {
            return;
        }

        position = ftell(file->cFile) % file->lineLength;

        if (position == 0)
        {
            fprintf(file->cFile, "%06d: ", file->writeLine % 10000000);
            position = LINE_HEADER_LENGTH;
        }

        while (*buffer != '\0')
        {
            while ((position < file->lineLength-1) && (*buffer != '\0') && (*buffer != '\n'))
            {
                fputc(*buffer, file->cFile);
                ++buffer;
                ++position;
            }
            if (*buffer != '\0')
            {
                if (*buffer == '\n')
                {
                    while (position < file->lineLength-1)
                    {
                        fputc(' ', file->cFile);
                        ++position;
                    }
                    ++buffer;
                }
                fputc('\n', file->cFile);

                ++file->currentLine;
                ++file->writeLine;
                position = LINE_HEADER_LENGTH;
                if (file->currentLine >= file->lineCount)
                {
                    fseek(file->cFile, 0, SEEK_SET);
                    file->currentLine = 0;
                }
                if (*buffer != '\0')
                {
                    fprintf(file->cFile, "%06d: ", file->writeLine % 10000000);
                }
            }
        }
    }
}

void circFilePrint(CircFile* file, const char* format, ...)
{
    va_list marker;

    va_start( marker, format );     /* Initialize variable arguments. */

    if (file != NULL)
    {
        if (IS_FALSE(file->writable))
        {
            return;
        }
        else
        {
            char    buffer[4096];   // TODO: Change this to a dynamically allocated buffer */

            _vsnprintf(buffer, 4096, format, marker);

            circFileWrite(file, buffer);
        }
    }
}

void circFileWriteLine(CircFile* file, const char* buffer)
{
    if (file != NULL)
    {
        long    position;

        if (IS_FALSE(file->writable))
        {
            return;
        }

        position = ftell(file->cFile) % file->lineLength;

        if (position > 0)
        {
            while (position < file->lineLength-1)
            {
                fputc(' ', file->cFile);
                ++position;
            }
            fputc('\n', file->cFile);

            ++file->currentLine;
            ++file->writeLine;
            position = LINE_HEADER_LENGTH;
            if (file->currentLine >= file->lineCount)
            {
                fseek(file->cFile, 0, SEEK_SET);
                file->currentLine = 0;
            }
        }

        fprintf(file->cFile, "%06d: ", file->writeLine % 10000000);

        while ((position < file->lineLength-1) && (*buffer != '\0') && (*buffer != '\n'))
        {
            fputc(*buffer, file->cFile);
            ++buffer;
            ++position;
        }
        while (position < file->lineLength-1)
        {
            fputc(' ', file->cFile);
            ++position;
        }
        fputc('\n', file->cFile);

        ++file->currentLine;
        ++file->writeLine;
        if (file->currentLine >= file->lineCount)
        {
            fseek(file->cFile, 0, SEEK_SET);
            file->currentLine = 0;
        }
    }
}

void circFilePrintLine(CircFile* file, const char* format, ...)
{
    va_list marker;

    va_start( marker, format );     /* Initialize variable arguments. */

    if (file != NULL)
    {
        long    index = 0;
        char*   buffer;

        buffer = (char*) malloc(file->lineLength);

        if (IS_FALSE(file->writable))
        {
            return;
        }

        if (buffer != NULL)
        {
            index = _vsnprintf(buffer, file->lineLength-1, format, marker);

            if (index = -1)
            {
                index = file->lineLength-1;
            }
            buffer[index]='\0';

            circFileWriteLine(file, buffer);
            free(buffer);
        }
    }
}
       Legal Notice  |  Tech Email  |  Feedback
      
Copyright ©
2001-2021 Motion Engineering