aoutil

ちょっとしたユーティリティマクロやテンプレート関数

#ifndef AOUTIL_H_INCLUDED
#define AOUTIL_H_INCLUDED

#ifdef __cplusplus
extern "C"  {
#endif //__cplusplus

#define RAD2DEG(rad)		((rad) * 0.00872664625997165)
#define DEG2RAD(deg)		((deg) * 114.591559026165)

#define SAFE_DELETE(p)		{ delete (p); (p)=0;}
#define SAFE_DELETE_AR(p)	{ delete[] (p); (p)=0; }

#define nARRAY(a)			( sizeof(a)/sizeof(a[0]) )

/*
   20.8:
   ビットの集合や配列はどうやって実装すればいいのか。

	A:

	charやintの配列を使う。マクロを使って、しかるべきインデックス にある望みのビットにアクセスできるようにする。以下にcharの配列 を使った簡単なマクロの例を紹介する。
*/

#include <limits.h>             /* for CHAR_BIT */

#define BITMASK(b) (1 << ((b) % CHAR_BIT))
#define BITSLOT(b) ((b) / CHAR_BIT)
#define BITSET(a, b) ((a)[BITSLOT(b)] |= BITMASK(b))
#define BITTEST(a, b) ((a)[BITSLOT(b)] & BITMASK(b))

#define dputs(N) printf("%s = \"%s\"\n", #N, N);
#define dputi(N) printf("%s = %d\n", #N, N);
#define dputf(N) printf("%s = %f\n", #N, N);

#ifdef __cplusplus
}
#endif //__cplusplus

#ifdef __cplusplus

template< typename T >
T clamp(T min, T val, T max)
{
	if ( val < min )
		return min;
	if ( val > max )
		return max;
	return val;
}

template< typename T >
void swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}

template< typename T >
T min(T& a, T& b)
{
	if ( a < b )
		return a;
	else
		return b;
}

template< typename T >
T max(T& a, T& b)
{
	if ( a > b )
		return a;
	else
		return b;
}

inline int isLittleEndian()
{
	int x = 1;
	if(*(char *)&x == 1)
		return 1;
	else
		return 0;
}

#endif //__cplusplus

#endif   /* AOUTIL_H_INCLUDED */

readlines.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

long getFileSize(const char* filename)
{
	long sz = 0;

	FILE* fp = fopen(filename, "rb"); 
	if (fp == NULL)
		return 0;

	fseek(fp, 0, SEEK_END); 
	sz = ftell(fp); 
	fclose(fp);

	return sz;
}

// ・0バイトは0行とみなす
// ・Unixのテキストファイルの定義と違い、改行で終わっていなくても1行とみなす
int getLineCount(char* buf, int len)
{
	int i;
	int c = 0;
	int inLine = 0;

	if (buf == NULL)
		return 0;

	for (i=0; i<len; i++)
	{
		if (buf[i] == (char)'\n')
		{
			c++;
			inLine = 0;
		}
		else
		{
			inLine = 1;
		}
	}

	if (inLine)
		c++;

	return c;
}

// ・0バイトは長さ0の文字列を返す
char* readFileAsString(const char* filename, long* outLen)
{
	char* buf = NULL;
	long size = 0;

	FILE* fp = fopen(filename, "rb");
	if (fp == NULL)
		return NULL;

	size = getFileSize(filename); 
	buf = (char*)malloc(size + 1);

	fread(buf, size, 1, fp);
	buf[size] = '\0';

	if (outLen)
		*outLen = size;

	fclose(fp);

	return buf;
}

// 0バイトはNULLを返し、outLineCountを0にする
char** readLines(const char* filename, int* outLineCount)
{
	int i;
	char** list = NULL;
	char* buf = NULL;
	long len = 0;
	int lineCount = 0;
	int lineIdx = 0;

	buf = readFileAsString(filename, &len);
	if (buf == NULL)
		return NULL;

	lineCount = getLineCount(buf, len);
	if (lineCount == 0)
	{
		*outLineCount = 0;
		return NULL;
	}

	list = (char**)malloc(sizeof(char*) * lineCount);

	list[0] = buf;
	for (i=0; i<len; i++)
	{
		if (buf[i] == (char)'\n')
		{
			buf[i] = '\0';

			lineIdx++;
			if (lineIdx < lineCount)
				list[lineIdx] = &buf[i + 1];
		}
	}

	if (outLineCount)
		*outLineCount = lineCount;

	return list;
}

vector.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef void* VectorType;
typedef struct _Vector {
    long capacity;
    long count;
    VectorType* data;
} Vector;

Vector* Vector_new(int initialCapacity)
{
    if (initialCapacity <= 0)
        return NULL;

    Vector* p = malloc(sizeof(Vector));
    p->capacity = initialCapacity;
    p->count = 0;
    p->data = malloc(sizeof(VectorType) * p->capacity);
    return p;
}

VectorType Vector_get(Vector* self, int i)
{
    return self->data[i];
}

long Vector_count(Vector* self)
{
    return self->count;
}

void Vector_push(Vector* self, VectorType d)
{
    VectorType tmp;
    if (self->count + 1 > self->capacity)
    {
        tmp = realloc(self->data, sizeof(VectorType) * self->capacity * 2);
        if (tmp == NULL)
            return;
        self->capacity *= 2;
        self->data = tmp;
    }
    self->data[self->count] = d;
    self->count += 1;
}

void Vector_delete(Vector* self)
{
    free(self);
}