memory.h 3.06 KB
/**
 * \file
 *
 * \author	Georg Hopp
 *
 * \copyright
 * Copyright © 2014 Georg Hopp
 *
 * 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/>.
 */

#ifndef __TR_MEMORY_H__
#define __TR_MEMORY_H__

#define TR_MEM_FREE(seg)	(TR_free((void **)&(seg)))

#include <stdlib.h>      // for NULL definition
#include <sys/types.h>

struct memSegment
{
	size_t   ref_count;
	size_t   size;
	int      idx;
	void   * ptr;

	struct memSegment * next;
};

/**
 * I found this at stanford.edu:
 * https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
 *
 * Really cool way of dealing with this. The oneat stanford.edu is slightly
 * different as ist deals only with 32bit values. I need a 64bit version
 * because on a 64bit system size_t is also 64bit and thus it is possible
 * to allocate that much amount of memory theoretically.
 */
inline
int
TR_bitwidth(size_t value)
{
	static const char LogTable256[256] = {
		-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
		LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
		LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
	};
#undef LT

	int             r;          // r will be lg(v)
	register size_t t1, t2, t3; // temporaries

	if (sizeof(value) == 8 && (t3 = value >> 32)) {
		if ((t2 = t3 >> 16)) {
			r = (t1 = t2 >> 8) ? 56 + LogTable256[t1] : 48 + LogTable256[t2];
		} else {
			r = (t1 = t3 >> 8) ? 40 + LogTable256[t1] : 32 + LogTable256[t3];
		}
	} else {
		if ((t2 = value >> 16)) {
			r = (t1 = t2 >> 8) ? 24 + LogTable256[t1] : 16 + LogTable256[t2];
		} else {
			r = (t1 = value >> 8) ? 8 + LogTable256[t1] : LogTable256[value];
		}
	}

	return r;
}

inline
struct memSegment *
_getMemInfo(void * mem)
{
	if (NULL == mem) {
		return 0;
	}

	return (struct memSegment *)(mem - sizeof(struct memSegment));
}

inline
size_t
TR_getSize(void * mem)
{
	struct memSegment * segment =
		(struct memSegment *)(mem - sizeof(struct memSegment));

	return segment ? segment->size : 0;
}

inline
size_t
TR_getUsableSize(void * mem)
{
	size_t size = TR_getSize(mem);

	return size ? size - sizeof(struct memSegment) : 0;
}

inline
int
TR_getIdx(void * mem)
{
	struct memSegment * segment =
		(struct memSegment *)(mem - sizeof(struct memSegment));

	return segment ? segment->idx : -1;
}

void   * TR_malloc(size_t);
void   * TR_calloc(size_t, size_t);
void   * TR_reference(void *);
void     TR_free(void **);
void     TR_cleanup();

char *   TR_strdup(const char *);

#endif // __TR_MEMORY_H__

// vim: set ts=4 sw=4: