//
//      tardy - a tar post-processor
//      Copyright (C) 1993-1999, 2001, 2002, 2008, 2009, 2011 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 <libtardy/ac/stddef.h>
#include <libtardy/ac/stdio.h>
#include <libtardy/ac/string.h>

#include <libtardy/main.h>


//
//  NAME
//      strerror - string for error number
//
//  SYNOPSIS
//      char *strerror(int errnum);
//
//  DESCRIPTION
//      The strerror function maps the error number in errnum to an error
//      message string.
//
//  RETURNS
//      The strerror function returns a pointer to the string, the contents of
//      which are implementation-defined.  The array pointed to shall not be
//      modified by the program, but may be overwritten by a subsequent call to
//      the strerror function.
//
//  CAVEAT
//      Unknown errors will be rendered in the form "Error %d", where %d will
//      be replaced by a decimal representation of the error number.
//

#ifndef HAVE_STRERROR

char *
strerror(in n)
{
    extern int sys_nerr;
    if (n < 1 || n > sys_nerr)
    {
        static char buffer[16];
        snprintf(buffer, sizeof(buffer), "Error %d", n);
        return buffer;
    }
    extern char *sys_errlist[];
    return sys_errlist[n];
}

#endif // HAVE_STRERROR
#ifndef HAVE_STRVERSCMP

int
strverscmp(const char *lhs, const char *rhs)
{
    return strcmp(lhs, rhs);
}

#endif // HAVE_STRVERSCMP
#ifndef HAVE_MEMMEM

void *
memmem(const void *haystack_v, size_t haystack_size, const void *needle_v,
    size_t needle_size)
{
    if (!haystack_size)
        return 0;
    if (!needle_size)
        return (void *)haystack_v;
    if (needle_size > haystack_size)
        return 0;
    if (needle_size == haystack_size)
    {
        if (0 == memcmp(haystack_v, needle_v, needle_size))
            return (void *)haystack_v;
        return 0;
    }
    const unsigned char *needle = (const unsigned char *)needle_v;
    if (needle_size == 1)
        return memchr(haystack_v, needle[0], haystack_size);
    const unsigned char *haystack = (const unsigned char *)haystack_v;
    const unsigned char *haystack_end =
        haystack + haystack_size - needle_size + 1;
    while (haystack < haystack_end)
    {
        const unsigned char *first =
            memchr(haystack, needle[0], haystack_end - haystack);
        if (!first)
            break;
        if (0 == memcmp(first + 1, needle + 1, needle_size - 1))
            return (void *)first;
        haystack = first + 1;
    }
    return 0;
}

#endif
