/*
 *      fhist - file history and comparison tools
 *      Copyright (C) 2000, 2002, 2008, 2010 Peter Miller
 *
 *      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 3 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, see
 *      <http://www.gnu.org/licenses/>.
 */

#include <common/ac/stdlib.h>
#include <libexplain/strdup.h>

#include <common/error.h> /* for assert */
#include <common/mprintf.h>
#include <common/output/private.h>
#include <common/str.h>
#include <common/trace.h>


void
output_delete(output_ty *fp)
{
        trace(("output_delete(fp = %08lX)\n{\ntype is output_%s\n",
                (long)fp, fp->vptr->typename));
        if (fp->vptr->destructor)
                fp->vptr->destructor(fp);
        free(fp);
        trace(("}\n"));
}


#ifdef output_filename
#undef output_filename
#endif

const char *
output_filename(output_ty *fp)
{
        const char      *result;

        trace(("output_filename(fp = %08lX)\n{\ntype is output_%s\n",
                (long)fp, fp->vptr->typename));
        assert(fp->vptr->filename);
        result = fp->vptr->filename(fp);
        trace(("return \"%s\"\n", result));
        trace(("}\n"));
        return result;
}


#ifdef output_ftell
#undef output_ftell
#endif

long
output_ftell(output_ty *fp)
{
        long            result;

        trace(("output_ftell(fp = %08lX)\n{\ntype is output_%s\n",
                (long)fp, fp->vptr->typename));
        assert(fp->vptr->ftell);
        result = fp->vptr->ftell(fp);
        trace(("return %ld;\n", result));
        trace(("}\n"));
        return result;
}


#ifdef output_fputc
#undef output_fputc
#endif

void
output_fputc(output_ty *fp, int c)
{
        trace(("output_fputc(fp = %08lX, c = %d)\n{\ntype is output_%s\n",
                (long)fp, c, fp->vptr->typename));
        assert(fp->vptr->fputc);
        fp->vptr->fputc(fp, c);
        trace(("}\n"));
}


#ifdef output_fputs
#undef output_fputs
#endif

void
output_fputs(output_ty *fp, const char *s)
{
        trace(("output_fputs(fp = %08lX, s = \"%s\")\n{\ntype is output_%s\n",
                (long)fp, s, fp->vptr->typename));
        assert(fp->vptr->fputs);
        fp->vptr->fputs(fp, s);
        trace(("}\n"));
}


#ifdef output_write
#undef output_write
#endif

void
output_write(output_ty *fp, const void *data, size_t len)
{
        trace(("output_write(fp = %08lX, data = %08lX, len = %ld)\n\
{\ntype is output_%s\n", (long)fp, (long)data, (long)len, fp->vptr->typename));
        assert(fp->vptr->write);
        fp->vptr->write(fp, data, len);
        trace(("}\n"));
}


#ifdef output_flush
#undef output_flush
#endif

void
output_flush(output_ty *fp)
{
        trace(("output_flusg(fp = %08lX)\n{\ntype is output_%s\n",
                (long)fp, fp->vptr->typename));
        assert(fp->vptr->flush);
        fp->vptr->flush(fp);
        trace(("}\n"));
}


void
output_fprintf(output_ty *fp, const char *fmt, ...)
{
        va_list         ap;

        va_start(ap, fmt);
        output_vfprintf(fp, fmt, ap);
        va_end(ap);
}


void
output_vfprintf(output_ty *fp, const char *fmt, va_list ap)
{
        char            *tmp;

        tmp = explain_strdup_or_die(vmprintf(fmt, ap));
        assert(fp->vptr->fputs);
        fp->vptr->fputs(fp, tmp);
        free(tmp);
}


void
output_put_str(output_ty *fp, string_ty *s)
{
        if (!s || !s->str_length)
                return;
        output_write(fp, s->str_text, s->str_length);
}
