/*
    (c) 1995-2001 by Wilhelm Noeker (wnoeker@t-online.de)

    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

 */

/*========================================================================*\
 |  File: cookio.c                                     Date: 17 Feb 2001  |
 *------------------------------------------------------------------------*
 |      Generalised I/O for cookies, supporting various file formats.     |
 |                                                                        |
\*========================================================================*/

#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "cookio.h"


#define LBUFSIZE 4000
char line[LBUFSIZE];            /* large enough to hold the longest line */
char cbuf[CBUFSIZE];            /* large enough to hold one complete cookie */


/*
 * Read a cookie from the given input file, store it in a static
 * buffer and return a pointer to it, or NULL at end of file.
 * The size information variables (about strlen, lines, longest line)
 * are optional, passing NULL is allowed.
 * Note: No matter what mode we are in, the string result *never* has
 * a trailing EOL character.
 */
char *read_cookie( FILE *fp, int fmt, long *psize, long *plines, long *pmaxline )
    {
    long cbuflen, lines, w, width;
    int delimlen;
    char *delim = "%%";

    switch( fmt )
        {
        case FMT_WORDS:
            if( fscanf( fp, "%s", cbuf ) != 1 )
                return NULL;
            cbuflen = strlen( cbuf );
            width = cbuflen;
            lines = 1;
            goto done;
        case FMT_LINES:
            if( fgets( cbuf, sizeof( cbuf ), fp ) == NULL )
                return NULL;
            cbuflen = strlen( cbuf );
            width = cbuflen - 1;
            lines = 1;
            goto done;
        case FMT_PERCENT:
            delim = "%";
            break;
        }
    delimlen = strlen( delim );

    strcpy( cbuf, "" );
    cbuflen = lines = width = 0;
    while( fgets( line, sizeof( line ), fp ) )
        {
        if( strncmp( line, delim, delimlen ) == 0 )
            goto done;          /* "end of cookie"-marker */
        else                    /* add a line to the current cookie */
            {
            w = strlen( line );
            if( (cbuflen += w) >= sizeof( cbuf ) )
                {
                printf( "\ncookie too big (>%ld chars) \n", (long) sizeof( cbuf ) );
                exit( 20 );
                }
            strcat( cbuf, line );
            lines++;
            if( w-1 > width )
                width = w-1;    /* "\n" doesn't count for width */
            }
        }
    /* Found EOF. */
    if( cbuflen == 0 )
        return NULL;
done:
    if( cbuf[ cbuflen-1 ] == '\n' )
        cbuf[ --cbuflen ] = '\0';
    if( psize != NULL )
        *psize = cbuflen;
    if( plines != NULL )
        *plines = lines;
    if( pmaxline != NULL )
        *pmaxline = width;
    return cbuf;
    }


/*
 * Write a cookie to the output file. Returns non-zero if successful.
 */
int write_cookie( char *cookie, FILE *fp, int fmt )
    {
    char *fmts = "%s\n%%%%\n";
    int len;
    static int linew = 0;

    switch( fmt )
        {
        case FMT_WORDS:
            fmts = "%s ";
            len = strlen( cookie );
            if( len + linew > 75 )
                {
                fmts = "\n%s ";
                linew = 0;
                }
            linew += len + 1;
            break;
        case FMT_LINES:
            fmts = "%s\n";
            break;
        case FMT_PERCENT:
            fmts = "%s\n%%\n";
            break;
        }
    return (fprintf( fp, fmts, cookie ) > 0) ? 1 : 0;
    }


/*
 * Print a short plaintext description of a cookie format.
 */
void print_fmtinfo( int fmt )
    {
    switch( fmt )
        {
        case FMT_WORDS:
            printf( "each word is a cookie\n" );
            break;
        case FMT_LINES:
            printf( "each line is a cookie\n" );
            break;
        case FMT_PERCENT:
            printf( "cookies are separated by lines of '%%'\n" );
            break;
        default:
            printf( "cookies are separated by lines of '%%%%'\n" );
        }
    }
