/*
 * Utility functions.
 *
 * Copyright 2003 Dimitrie O. Paun
 * Copyright 2003 Ferenc Wagner
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>
#include <windef.h>
#include <winbase.h>

#include "winetest.h"

HANDLE logfile = 0;

void *heap_alloc (size_t len)
{
    void *p = HeapAlloc(GetProcessHeap(), 0, len);

    if (!p) report (R_FATAL, "Out of memory.");
    return p;
}

void *heap_realloc (void *op, size_t len)
{
    void *p = HeapReAlloc(GetProcessHeap(), 0, op, len);

    if (len && !p) report (R_FATAL, "Out of memory.");
    return p;
}

char *heap_strdup( const char *str )
{
    int len = lstrlen(str) + 1;
    char* res = HeapAlloc(GetProcessHeap(), 0, len);
    if (!res) report (R_FATAL, "Out of memory.");
    memcpy(res, str, len);
    return res;
}

void heap_free (void *op)
{
    HeapFree(GetProcessHeap(), 0, op);
}

static char *vstrfmtmake (size_t *lenp, const char *fmt, va_list ap)
{
    size_t size = 1000;
    char *p, *q;
    int n;

    p = HeapAlloc(GetProcessHeap(), 0, size);
    if (!p) return NULL;
    while (1) {
        n = vsnprintf (p, size, fmt, ap);
        if (n < 0) size *= 2;   /* Windows */
        else if ((unsigned)n >= size) size = n+1; /* glibc */
        else break;
        q = HeapReAlloc(GetProcessHeap(), 0, p, size);
        if (!q) {
          heap_free (p);
          return NULL;
       }
       p = q;
    }
    if (lenp) *lenp = n;
    return p;
}

char *vstrmake (size_t *lenp, va_list ap)
{
    const char *fmt;

    fmt = va_arg (ap, const char*);
    return vstrfmtmake (lenp, fmt, ap);
}

char *strmake (size_t *lenp, ...)
{
    va_list ap;
    char *p;

    va_start (ap, lenp);
    p = vstrmake (lenp, ap);
    if (!p) report (R_FATAL, "Out of memory.");
    va_end (ap);
    return p;
}

void xprintf (const char *fmt, ...)
{
    va_list ap;
    size_t size;
    DWORD written;
    char *buffer, *head;

    va_start (ap, fmt);
    buffer = vstrfmtmake (&size, fmt, ap);
    head = buffer;
    va_end (ap);
    while (size) {
        if (!WriteFile( logfile, head, size, &written, NULL ))
            report (R_FATAL, "Can't write logs: %u", GetLastError());
        head += written;
        size -= written;
    }
    heap_free (buffer);
}

int
goodtagchar (char c)
{
    return (('a'<=c && c<='z') ||
            ('A'<=c && c<='Z') ||
            ('0'<=c && c<='9') ||
            c=='-' || c=='.');
}

const char *
findbadtagchar (const char *tag)
{
    while (*tag)
        if (goodtagchar (*tag)) tag++;
        else return tag;
    return NULL;
}
