/* -*- Mode: C; tab-width: 4 -*-
 *
 * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1.  Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of its
 *     contributors may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "dnssd_ipc.h"

#if defined(_WIN32)

char *win32_strerror(int inErrorCode)
{
    static char buffer[1024];
    DWORD n;
    memset(buffer, 0, sizeof(buffer));
    n = FormatMessageA(
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        (DWORD) inErrorCode,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        buffer,
        sizeof(buffer),
        NULL);
    if (n > 0)
    {
        // Remove any trailing CR's or LF's since some messages have them.
        while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1]))
            buffer[--n] = '\0';
    }
    return buffer;
}

#endif

void put_uint32(const uint32_t l, char **ptr)
{
    (*ptr)[0] = (char)((l >> 24) &  0xFF);
    (*ptr)[1] = (char)((l >> 16) &  0xFF);
    (*ptr)[2] = (char)((l >>  8) &  0xFF);
    (*ptr)[3] = (char)((l      ) &  0xFF);
    *ptr += sizeof(uint32_t);
}

uint32_t get_uint32(const char **ptr, const char *end)
{
    if (!*ptr || *ptr + sizeof(uint32_t) > end)
    {
        *ptr = NULL;
        return(0);
    }
    else
    {
        uint8_t *p = (uint8_t*) *ptr;
        *ptr += sizeof(uint32_t);
        return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3]));
    }
}

void put_uint16(uint16_t s, char **ptr)
{
    (*ptr)[0] = (char)((s >>  8) &  0xFF);
    (*ptr)[1] = (char)((s      ) &  0xFF);
    *ptr += sizeof(uint16_t);
}

uint16_t get_uint16(const char **ptr, const char *end)
{
    if (!*ptr || *ptr + sizeof(uint16_t) > end)
    {
        *ptr = NULL;
        return(0);
    }
    else
    {
        uint8_t *p = (uint8_t*) *ptr;
        *ptr += sizeof(uint16_t);
        return((uint16_t) ((uint16_t)p[0] << 8 | p[1]));
    }
}

int put_string(const char *str, char **ptr)
{
    if (!str) str = "";
    strcpy(*ptr, str);
    *ptr += strlen(str) + 1;
    return 0;
}

int get_string(const char **ptr, const char *const end, char *buffer, int buflen)
{
    if (!*ptr)
    {
        *buffer = 0;
        return(-1);
    }
    else
    {
        char *lim = buffer + buflen;    // Calculate limit
        while (*ptr < end && buffer < lim)
        {
            char c = *buffer++ = *(*ptr)++;
            if (c == 0) return(0);      // Success
        }
        if (buffer == lim) buffer--;
        *buffer = 0;                    // Failed, so terminate string,
        *ptr = NULL;                    // clear pointer,
        return(-1);                     // and return failure indication
    }
}

void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr)
{
    memcpy(*ptr, rdata, rdlen);
    *ptr += rdlen;
}

const char *get_rdata(const char **ptr, const char *end, int rdlen)
{
    if (!*ptr || *ptr + rdlen > end)
    {
        *ptr = NULL;
        return(0);
    }
    else
    {
        const char *rd = *ptr;
        *ptr += rdlen;
        return rd;
    }
}

void ConvertHeaderBytes(ipc_msg_hdr *hdr)
{
    hdr->version   = htonl(hdr->version);
    hdr->datalen   = htonl(hdr->datalen);
    hdr->ipc_flags = htonl(hdr->ipc_flags);
    hdr->op        = htonl(hdr->op );
    hdr->reg_index = htonl(hdr->reg_index);
}
