/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
//
// util.c
//
// common functions
//
// Copyright (c) 1995-96 Jim Nelson.  Permission to distribute
// granted by the author.  No warranties are made on the fitness of this
// source code.
//
*/

#include "defs.h"

/*
//
// generic, global utility functions
//
*/

/*
// returns the markup type flag ... either the closing or opening delimiter
// in the markup can be passed in
*/
uint MarkupType(char delim)
{
    uint markupType;

    markupType = 0;

    if((delim == HTML_OPEN_MARKUP) || (delim == HTML_CLOSE_MARKUP))
    {
        markupType |= MARKUP_TYPE_HTML;
    }

    if((delim == htpOpenMarkup) || (delim == htpCloseMarkup))
    {
        markupType |= MARKUP_TYPE_HTP;
    }

    return markupType;
}

#ifndef HAVE_PIPE

/*
// temporary file name generator
*/
BOOL CreateTempFilename(char *tempfilename, uint size)
{
    static char *tempDir;
    char *tmpName;

    assert(tempfilename != NULL);

    /* find a preferred temporary directory if not found already */
    if(tempDir == NULL)
    {
        if((tempDir = getenv("TEMP")) == NULL)
        {
            if((tempDir = getenv("TMP")) == NULL)
            {
                tempDir = DIR_CURRENT_STRING;
            }
        }
    }

    /* get a temporary filename */
    if((tmpName = tempnam(tempDir, (char *) PROGRAM_NAME)) != NULL)
    {
        /* copy the filename to the callers buffer */
        StringCopy(tempfilename, tmpName, size);

        /* free the tempnam buffer and return success */
        free(tmpName);

        return TRUE;
    }

    return FALSE;
}
#endif


#if 0

/*
// extract directory from a filename, if present
*/

char *GetFileDirectory(const char *filename, char *directory, uint size)
{
    const char *filePtr;
    uint len;

    *directory = NUL;

    len = strlen(filename);
    if(len == 0)
    {
        return directory;
    }

    filePtr = filename + len - 1;
    while(filePtr != filename)
    {
        if(*filePtr == DIR_DELIMITER)
        {
            return StringCopy(directory, filename, (len <= size) ? len : size);
        }

        filePtr--;
        len--;
    }

    return directory;
}   

#endif

/*
// ParseFilename
//
// Returns a pointer to the filename in a full pathname
*/
const char *FindFilename(const char *pathname)
{
    const char *filePtr;
    uint len;

    assert(pathname != NULL);
    if(pathname == NULL)
    {
        return NULL;
    }

    len = strlen(pathname);
    if(len == 0)
    {
        return pathname;
    }

    filePtr = pathname + len - 1;
    while(filePtr != pathname)
    {
        if(strchr(ALL_FILESYSTEM_DELIMITERS, *filePtr) != NULL)
        {
            /* found the first delimiter, return pointer to character just */
            /* past this one */
            /* if pathname ended in a delimiter, then this will return a */
            /* pointer to NUL, which is acceptable */
            return filePtr + 1;
        }

        filePtr--;
    }

    return pathname;
}

/*
// safe strncpy() wrapper (suggested by joseph.dandrea@att.com) ... strncpy()
// by itself has some ugly problems, and strcpy() is simply dangerous.
// Joseph recommended a macro, but I'm sticking to the bulkier solution of
// using a function
*/
char *StringCopy(char *dest, const char *src, uint size)
{
    assert(dest != NULL);
    assert(src != NULL);

    strncpy(dest, src, size);
    dest[size - 1] = NUL;

    return dest;
}

/*
// re-entrant string tokenizer ... used because option.c requires simultaneous
// uses of strtok(), and the standard version just dont cut it
*/
char *StringFirstToken(FIND_TOKEN *findToken, char *string, const char *tokens)
{
    char *ptr;

    assert(string != NULL);
    assert(findToken != NULL);

    findToken->tokens = tokens;
    findToken->lastChar = string + strlen(string);
    findToken->nextStart = findToken->lastChar;

    if(tokens == NULL)
    {
        return string;
    }

    if((ptr = strpbrk(string, tokens)) != NULL)
    {
        *ptr = NUL;
        findToken->nextStart = ptr;
    }

    return string;
}

char *StringNextToken(FIND_TOKEN *findToken)
{
    char *ptr;
    char *start;

    assert(findToken != NULL);
    assert(findToken->lastChar != NULL);

    ptr = findToken->nextStart;

    /* check if this is the end of the original string */
    if(ptr == findToken->lastChar)
    {
        return NULL;
    }

    /* nextStart points to NUL left by last search, skip past it */
    ptr++;
    start = ptr;

    /* keep going */
    if((ptr = strpbrk(ptr, findToken->tokens)) != NULL)
    {
        *ptr = NUL;
        findToken->nextStart = ptr;
    }
    else
    {
        findToken->nextStart = findToken->lastChar;
    }

    return start;
}

/*
// Wrapper function to (a) allocate memory for the duplicated string and
// (b) copy the source string into the new memory location.  Caller is
// responsible to free the string eventually.
*/
char *DuplicateString(const char *src)
{
    char *new;
    uint size;

    assert(src != NULL);

    size = strlen(src) + 1;

    /* allocate memory for the duplicate string */
    if((new = AllocMemory(size)) == NULL)
    {
        return NULL;
    }

    /* copy the string */
    return memcpy(new, src, size);
}

/*
// Like DuplicateString, but only duplicate a sub string of length len.
// The substring is NUL terminated.
*/
char *DuplicateSubString(const char *src, int len)
{
    char *new;
    uint size;

    assert(src != NULL && len <= strlen(src));

    size = len + 1;

    /* allocate memory for the duplicate string */
    if((new = AllocMemory(size)) == NULL)
    {
        return NULL;
    }

    /* copy the string */
    memcpy(new, src, len);
    new[len] = 0;
    return new;
}

/*
// converts directory delimiters for any pathname into one supporting the
// delimiters used by the present filesystem ... it is encumbent on the
// caller to free() the string returned once finished
*/
char *ConvertDirDelimiter(const char *pathname)
{
    char *newPathname;
    char *strptr;

    if(pathname == NULL)
    {
        return NULL;
    }

    /* duplicate the pathname for conversion */
    if((newPathname = DuplicateString(pathname)) == NULL)
    {
        return NULL;
    }

    /* walk the string, looking for delimiters belonging to other filesystems */
    /* replace with native filesystems delimiter */
    strptr = newPathname;
    while(*strptr != NUL)
    {
        if(strchr(OTHER_FILESYSTEM_DELIMITER, *strptr) != NULL)
        {
            *strptr = DIR_DELIMITER;
        }
        strptr++;
    }

    return newPathname;
}

/*
// uses stat() to check for file existance ... maybe not the best way?
*/
BOOL FileExists(const char *pathname)
{
    struct stat dummy;

    return (stat(pathname, &dummy) == 0) ? TRUE : FALSE;
}

#ifndef HAVE_STPCPY
char *stpcpy(char *d, const char *s) {
    do {
        *d++ = *s;
    } while (*s++);
    return d-1;
}
#endif
