If you have comments or questions concerning this source file, discuss them in the forum.
/*
Copyright (c) 2002 Nicolai Haehnle

See the license.txt for details. If that file was not included in the
source distributions, please email <prefect@rtts.org>
*/
// lib_main.cpp - misc functions

#include "library.h"


/*
==============
SwapShort
==============
*/
short SwapShort(short x)
{
    short s;

    ((byte *)&s)[0] = ((byte *)&x)[1];
    ((byte *)&s)[1] = ((byte *)&x)[0];

    return s;
}

/*
==============
SwapInt
==============
*/
int SwapInt(int x)
{
    int s;

    ((byte *)&s)[0] = ((byte *)&x)[3];
    ((byte *)&s)[1] = ((byte *)&x)[2];
    ((byte *)&s)[2] = ((byte *)&x)[1];
    ((byte *)&s)[3] = ((byte *)&x)[0];

    return s;
}

/*
==============
SwapFloat
==============
*/
float SwapFloat(float x)
{
    float s;

    ((byte *)&s)[0] = ((byte *)&x)[3];
    ((byte *)&s)[1] = ((byte *)&x)[2];
    ((byte *)&s)[2] = ((byte *)&x)[1];
    ((byte *)&s)[3] = ((byte *)&x)[0];

    return s;
}


/*
==============
memnchr

Search the first occurence of a character other than c
==============
*/
void *memnchr(const void *buf, int c, int bytes)
{
    while(bytes--) {
        if (*(byte *)buf != (byte)c)
            return (void *)buf;
        buf = (const char *)buf + 1;
    }
    return 0;
}

/*
==============================================================================

LError IMPLEMENTATION

==============================================================================
*/

/*
==============
LError::LError

Format the error message into the buffer
==============
*/
LError::LError(const char *fmt, ...)
{
    va_list va;

    va_start(va, fmt);
    vsnprintf(m_szMessage, sizeof(m_szMessage), fmt, va);
    va_end(va);

    m_iSeverity = ERR_FATAL;
}

LError::LError(int iSeverity, const char *fmt, ...)
{
    va_list va;

    va_start(va, fmt);
    vsnprintf(m_szMessage, sizeof(m_szMessage), fmt, va);
    va_end(va);

    m_iSeverity = iSeverity;
}

/*
==============================================================================

MISCELLANEOUS LIBRARY FUNCTIONS

==============================================================================
*/

/*
==============
xstrcpy

Buffer overflow safe strcpy
==============
*/
void xstrcpy(char *dest, int size, const char *src)
{
    while(size > 1 && *src) {
        *dest++ = *src++;
        size--;
    }
    *dest = 0;
}

/*
==============
xstrcat

Buffer overflow safe strcat
==============
*/
void xstrcat(char *dest, int size, const char *src)
{
    while(*dest) {
        dest++;
        size--;
    }

    if (size <= 1)
        return;

    while(*src) {
        if (!--size)
            break;
        *dest++ = *src++;
    }

    *dest = 0;
}

/*
==============
L_Tokenize

Destructive tokenizer, splits at whitespaces including newlines.
Tokens can be surrounded by quotation marks.
==============
*/
int L_Tokenize(char **tokv, int max_tokc, char *string)
{
    int tokc = 0;

    while(*string) {
        string += strspn(string, " \t\n");
        if (!*string)
            break;

        if (*string != '"') {
            tokv[tokc++] = string;
            if (tokc >= max_tokc)
                break;

            string += strcspn(string, " \t\n");
        } else {
            tokv[tokc++] = ++string; // skip the '"'
            if (tokc >= max_tokc)
                break;

            string += strcspn(string, "\"");
        }

        if (!*string)
            break;
        *string++ = 0;
    }

    return tokc;
}


/*
==============
BitMaskSect

Perform bitmask intersection.
Returns 0 if the masks don't intersect.
==============
*/
int BitMaskSect(byte *mask0, int w0, int h0, byte *mask1, int w1, int h1,
                int dx, int dy)
{
    int bytes0, bytes1;
    int x0, y0, x1, y1, w, h;
    int x, y;
    byte *p0, *p1;
    byte bit0, bit1;

    // determine the rectangle of intersection
    if (dx >= 0) {
        x0 = dx;
        x1 = 0;
    } else {
        x0 = 0;
        x1 = -dx;
    }

    if (x0 >= w0 || x1 >= w1)
        return 0;

    w = w0 - x0;
    if (w1 - x1 < w)
        w = w1 - x1;

    if (w <= 0)
        return 0;

    if (dy >= 0) {
        y0 = dy;
        y1 = 0;
    } else {
        y0 = 0;
        y1 = -dy;
    }

    if (y0 >= h0 || y1 >= h1)
        return 0;

    h = h0 - y0;
    if (h1 - y1 < h)
        h = h1 - y1;

    if (h <= 0)
        return 0;

    // now trace the masks line by line, bit by bit (should use byteops and
    // shifts for performance.. oh well)
    bytes0 = (w0 + 7) / 8;
    bytes1 = (w1 + 7) / 8;

    for(y = 0; y < h; y++) {
        p0 = mask0 + (y0 + y) * bytes0;
        p0 += x0 >> 3;
        bit0 = 1 << (x0 & 7);

        p1 = mask1 + (y1 + y) * bytes1;
        p1 += x1 >> 3;
        bit1 = 1 << (x1 & 7);

        for(x = 0; x < w; x++) {
            if ((*p0 & bit0) && (*p1 & bit1))
                return 1;

            bit0 <<= 1;
            if (!bit0) {
                p0++;
                bit0 = 1;
            }

            bit1 <<= 1;
            if (!bit1) {
                p1++;
                bit1 = 1;
            }
        }
    }

    return 0;
}