/* ----------------------------------------------------------------------- *
 *
 *   Copyright 2008 rPath, Inc. - All Rights Reserved
 *
 *   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, Inc., 51 Franklin St, Fifth Floor,
 *   Boston MA 02110-1301, USA; either version 2 of the License, or
 *   (at your option) any later version; incorporated herein by reference.
 *
 * ----------------------------------------------------------------------- */

/*
 * le.h
 *
 * Write unaligned littleendian data
 */

#ifndef LE_H
#define LE_H

#include <inttypes.h>

#if defined(__386__) || defined(__i386__) || defined(__x86_64__)

/* Littleendian architecture, unaligned accesses permitted */

static inline uint16_t rdle16(const uint16_t *p)
{
	return *p;
}

static inline uint32_t rdle32(const uint32_t *p)
{
	return *p;
}

static inline uint64_t rdle64(const uint64_t *p)
{
	return *p;
}

static inline void wrle16(uint16_t v, uint16_t *p)
{
	*p = v;
}

static inline void wrle32(uint32_t v, uint32_t *p)
{
	*p = v;
}

static inline void wrle64(uint64_t v, uint64_t *p)
{
	*p = v;
}

#else

static inline uint16_t rdle16(const uint16_t *p)
{
	const uint8_t *_p = (const uint8_t *)p;
	uint16_t _v;

	_v  = (uint16_t)_p[0];
	_v += (uint16_t)_p[1] << 8;

	return _v;
}

static inline uint32_t rdle32(const uint32_t *p)
{
	const uint8_t *_p = (const uint8_t *)p;
	uint32_t _v;

	_v  = (uint32_t)_p[0];
	_v += (uint32_t)_p[1] << 8;
	_v += (uint32_t)_p[2] << 16;
	_v += (uint32_t)_p[3] << 24;

	return _v;
}

static inline uint64_t rdle64(const uint64_t *p)
{
	const uint8_t *_p = (const uint8_t *)p;
	uint64_t _v;

	_v  = (uint64_t)_p[0];
	_v += (uint64_t)_p[1] << 8;
	_v += (uint64_t)_p[2] << 16;
	_v += (uint64_t)_p[3] << 24;
	_v += (uint64_t)_p[4] << 32;
	_v += (uint64_t)_p[5] << 40;
	_v += (uint64_t)_p[6] << 48;
	_v += (uint64_t)_p[7] << 56;

	return _v;
}

static inline void wrle16(uint16_t v, uint16_t *p)
{
	uint8_t *_p = (uint8_t *)p;

	_p[0] = v;
	_p[1] = v >> 8;
}

static inline void wrle32(uint32_t v, uint32_t *p)
{
	uint8_t *_p = (uint8_t *)p;

	_p[0] = v;
	_p[1] = v >> 8;
	_p[2] = v >> 16;
	_p[3] = v >> 24;
}

static inline void wrle64(uint64_t v, uint64_t *p)
{
	uint8_t *_p = (uint8_t *)p;

	_p[0] = v;
	_p[1] = v >> 8;
	_p[2] = v >> 16;
	_p[3] = v >> 24;
	_p[4] = v >> 32;
	_p[5] = v >> 40;
	_p[6] = v >> 48;
	_p[7] = v >> 56;
}

#endif

#endif /* LE_H */
