summaryrefslogtreecommitdiff
path: root/dmagick/Utils.d
blob: e8cef216fd6446f7f60c2e65d9a72278b8bc21c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * A collection of helper functions used in DMagick.
 *
 * Copyright: Mike Wey 2011
 * License:   To be determined
 * Authors:   Mike Wey
 */

module dmagick.Utils;

import std.math;

import dmagick.c.memory;
import dmagick.c.magickString;
import dmagick.c.magickType;

/**
 * Copy a string into a static array used
 * by ImageMagick for some atributes.
 */
private void copyString(ref char[MaxTextExtent] dest, string source)
{
	if ( source.length < MaxTextExtent )
		throw new Exception("text is to long"); //TODO: a proper exception.

	dest[0 .. source.length] = source;
	dest[source.length] = '\0';
}

/**
 * Our implementation of ImageMagick's CloneString.
 *
 * We use this since using CloneString forces us to
 * append a \0 to the end of the string, and the realocation
 * whould be wastefull if we are just going to copy it
 */
private void copyString(ref char* dest, string source)
{
	if ( source is null )
	{
		if ( dest !is null )
			DestroyString(dest);
		return;
	}

	if ( ~source.length < MaxTextExtent )
		throw new Exception("UnableToAcquireString"); //TODO: a proper exception.

	if ( dest is null )
		dest = cast(char*)AcquireQuantumMemory(source.length+MaxTextExtent, dest.sizeof);
	else
		dest = cast(char*)ResizeQuantumMemory(dest, source.length+MaxTextExtent, dest.sizeof);

	if ( dest is null )
		throw new Exception("UnableToAcquireString"); //TODO: a proper exception.

	if ( source.length > 0 )
		dest[0 .. source.length] = source;

	dest[source.length] = '\0';
}

real degreesToRadians(real deg)
{
	return deg*PI/180;
}

struct RefCounted(alias pred, T)
	if ( !is(T == class) && is(typeof(pred(cast(T*)null)) == T*) )
{
	T* payload;

	private bool isInitialized;
	private size_t* refcount;

	alias payload this;

	this(T* payload)
	{
		this.payload = payload;

		refcount  = new size_t;
		*refcount = 1;

		isInitialized = true;
	}

	this(this)
	{
		if ( isInitialized )
			(*refcount)++;
	}

	~this()
	{
		(*refcount)--;

		if ( *refcount == 0 )
			payload = pred(payload);
	}

	@property size_t refCount()
	{
		return *refcount;
	}
}

unittest
{
	int x = 10;
	int y = 20;

	alias RefCounted!( (int* t){ x = 20; return t; }, int ) IntRef;

	auto a = IntRef(&x);
	assert( a.refCount == 1 );
	auto b = a;
	assert( a.refCount == 2 );

	b = IntRef(&y);
	assert( a.refCount == 1 );
	assert( b.refCount == 1 );
	a = b;
	assert( b.refCount == 2 );
	assert( x == 20 );
}