/*
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free
* Software Foundation, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GnuTLS.
*
* The GnuTLS 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 3 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 program. If not, see
*
*/
/* This file contains the functions needed for 64 bit integer support in
* TLS, and functions which ease the access to TLS vectors (data of given size).
*/
#include
#include
#include
#include
/* This function will add one to uint64 x.
* Returns 0 on success, or -1 if the uint64 max limit
* has been reached.
*/
int
_gnutls_uint64pp (uint64 * x)
{
register int i, y = 0;
for (i = 7; i >= 0; i--)
{
y = 0;
if (x->i[i] == 0xff)
{
x->i[i] = 0;
y = 1;
}
else
x->i[i]++;
if (y == 0)
break;
}
if (y != 0)
return -1; /* over 64 bits! WOW */
return 0;
}
/* This function will add one to uint48 x.
* Returns 0 on success, or -1 if the uint48 max limit
* has been reached.
*/
int
_gnutls_uint48pp (uint64 * x)
{
register int i, y = 0;
for (i = 7; i >= 3; i--)
{
y = 0;
if (x->i[i] == 0xff)
{
x->i[i] = 0;
y = 1;
}
else
x->i[i]++;
if (y == 0)
break;
}
if (y != 0)
return -1; /* over 48 bits */
return 0;
}
uint32_t
_gnutls_uint24touint32 (uint24 num)
{
uint32_t ret = 0;
((uint8_t *) & ret)[1] = num.pint[0];
((uint8_t *) & ret)[2] = num.pint[1];
((uint8_t *) & ret)[3] = num.pint[2];
return ret;
}
uint24
_gnutls_uint32touint24 (uint32_t num)
{
uint24 ret;
ret.pint[0] = ((uint8_t *) & num)[1];
ret.pint[1] = ((uint8_t *) & num)[2];
ret.pint[2] = ((uint8_t *) & num)[3];
return ret;
}
/* data should be at least 3 bytes */
uint32_t
_gnutls_read_uint24 (const opaque * data)
{
uint32_t res;
uint24 num;
num.pint[0] = data[0];
num.pint[1] = data[1];
num.pint[2] = data[2];
res = _gnutls_uint24touint32 (num);
#ifndef WORDS_BIGENDIAN
res = bswap_32 (res);
#endif
return res;
}
void
_gnutls_write_uint64 (uint64_t num, opaque * data)
{
#ifndef WORDS_BIGENDIAN
num = bswap_64 (num);
#endif
memcpy(data, &num, 8);
}
void
_gnutls_write_uint24 (uint32_t num, opaque * data)
{
uint24 tmp;
#ifndef WORDS_BIGENDIAN
num = bswap_32 (num);
#endif
tmp = _gnutls_uint32touint24 (num);
data[0] = tmp.pint[0];
data[1] = tmp.pint[1];
data[2] = tmp.pint[2];
}
uint32_t
_gnutls_read_uint32 (const opaque * data)
{
uint32_t res;
memcpy (&res, data, sizeof (uint32_t));
#ifndef WORDS_BIGENDIAN
res = bswap_32 (res);
#endif
return res;
}
void
_gnutls_write_uint32 (uint32_t num, opaque * data)
{
#ifndef WORDS_BIGENDIAN
num = bswap_32 (num);
#endif
memcpy (data, &num, sizeof (uint32_t));
}
uint16_t
_gnutls_read_uint16 (const opaque * data)
{
uint16_t res;
memcpy (&res, data, sizeof (uint16_t));
#ifndef WORDS_BIGENDIAN
res = bswap_16 (res);
#endif
return res;
}
void
_gnutls_write_uint16 (uint16_t num, opaque * data)
{
#ifndef WORDS_BIGENDIAN
num = bswap_16 (num);
#endif
memcpy (data, &num, sizeof (uint16_t));
}
uint32_t
_gnutls_conv_uint32 (uint32_t data)
{
#ifndef WORDS_BIGENDIAN
return bswap_32 (data);
#else
return data;
#endif
}
uint16_t
_gnutls_conv_uint16 (uint16_t data)
{
#ifndef WORDS_BIGENDIAN
return bswap_16 (data);
#else
return data;
#endif
}
uint32_t
_gnutls_uint64touint32 (const uint64 * num)
{
uint32_t ret;
memcpy (&ret, &num->i[4], 4);
#ifndef WORDS_BIGENDIAN
ret = bswap_32 (ret);
#endif
return ret;
}