-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrange.h
More file actions
88 lines (73 loc) · 2.06 KB
/
range.h
File metadata and controls
88 lines (73 loc) · 2.06 KB
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
#ifndef _DS_RANGE_H
#define _DS_RANGE_H
/* Range Data Structure (for array indexing)
* Namespace: range
*
* Simple interval [min, max] included.
*
* int std[RANGE_SIZE(-90, 90)];
* Range r = range_init("Degrees", -90, 90, NULL);
*
* std[range_at(-90)] = 0; // first element
* std[range_at(-90)] = 0; // last element
*
*/
#include <stddef.h>
#include <stdbool.h>
#define RANGE_SIZE(start, end) ((size_t)((end) - (start) + 1))
typedef int RangeType;
typedef struct Range Range;
typedef RangeType (*RangeCallback)(Range r, RangeType i);
/* extreme included */
struct Range {
RangeType start;
RangeType end;
RangeCallback clbk;
const char *name;
};
/* Create the range from start to end (both included).
* It stores a callback pointer that will be called in case of index out of
* bound in the auxiliary methods.
* The callback is also called by this function if end <= start.
* The callback can abort the program or return a safe index.
*
* name: an identifier for the user, not used by the methods.
* start, end: can be negative
* clbk: the callback function. It can be NULL.
*/
Range range_init(const char *name, RangeType start, RangeType end, RangeCallback clbk)
{
Range r = {.start = start, .end = end, .clbk = clbk, .name = name};
if (clbk != NULL && end <= start) {
clbk(r, 0);
}
return r;
}
/* Check if the range index is in the boundaries after a change (i++) */
bool range_in(Range r, RangeType i)
{
return (r.start <= i) && (i <= r.end);
}
/* Convert the range index i into the canonical index zero based */
size_t range_at(Range r, RangeType i)
{
if (r.clbk != NULL && !range_in(r, i)){
i = r.clbk(r, i);
}
return i - r.start;
}
/* Convert the canonical index i into the range index */
RangeType range_of(Range r, size_t i)
{
RangeType j = r.start + i;
if (r.clbk != NULL && !range_in(r, j)){
j = r.clbk(r, j);
}
return j;
}
/* Number of element in the range (or in the array indexed by the range) */
size_t range_size(Range r)
{
return RANGE_SIZE(r.start, r.end);
}
#endif