13 unsigned char iteration
;
16 struct fsample_header
{
19 unsigned char iteration
;
27 struct fsample_header
*header
;
29 CoreHandlerDelFn corehandlerdel
;
32 static fsample_t version
= 1;
34 static void fscorefree(void *arg
) {
35 fsample
*f
= (fsample
*)arg
;
36 munmap(f
->header
, f
->len
);
39 fsample
*fsopen(char *filename
, size_t samples
, CoreHandlerAddFn chafn
, CoreHandlerDelFn chdfn
) {
42 fsample
*f
= (fsample
*)malloc(sizeof(fsample
));
46 f
->len
= samples
* sizeof(struct fsample_p
) + sizeof(struct fsample_header
);
47 f
->fd
= open(filename
, O_RDWR
|O_CREAT
, 0600);
49 if(!lseek(f
->fd
, 0, SEEK_END
))
52 if((f
->fd
== -1) || (lseek(f
->fd
, f
->len
- 1, SEEK_SET
) == -1)) {
63 f
->header
= mmap(NULL
, f
->len
, PROT_READ
|PROT_WRITE
, flags
, f
->fd
, 0);
64 if(f
->header
== MAP_FAILED
) {
70 if(!new && (memcmp(f
->header
->magic
, "FSAMP", sizeof(f
->header
->magic
)) || (version
!= f
->header
->version
))) {
71 munmap(f
->header
, f
->len
);
78 f
->corehandler
= chafn(fscorefree
, f
);
79 f
->corehandlerdel
= chdfn
;
81 f
->corehandler
= NULL
;
82 f
->corehandlerdel
= NULL
;
85 memcpy(f
->header
->magic
, "FSAMP", sizeof(f
->header
->magic
));
86 f
->header
->version
= version
;
88 f
->m
= (struct fsample_p
*)(f
->header
+ 1);
91 if(f
->header
->iteration
== 0)
92 f
->header
->iteration
= 1;
97 void fsclose(fsample
*f
) {
98 munmap(f
->header
, f
->len
);
101 if(f
->corehandlerdel
&& f
->corehandler
)
102 (f
->corehandlerdel
)(f
->corehandler
);
107 static inline unsigned char previteration(fsample
*f
) {
108 unsigned char p
= f
->header
->iteration
- 1;
115 /* doesn't support writing to negative numbers... */
116 inline void fsset(fsample
*f
, fsample_t pos
, fsample_t value
) {
117 fsample_t actualpos
= pos
% f
->samples
;
118 struct fsample_p
*p
= &f
->m
[actualpos
];
120 if(f
->header
->lastpos
> actualpos
) {
121 f
->header
->iteration
++;
122 if(f
->header
->iteration
== 0)
123 f
->header
->iteration
= 1;
126 f
->header
->lastpos
= actualpos
;
128 p
->iteration
= f
->header
->iteration
;
132 static inline fsample_t
mmod(int x
, int y
) {
139 #error Unknown modulo operator function.
143 /* API functions only have access to positive indicies */
144 inline fsample_t
__fsget(fsample
*f
, int pos
, fsample_t
*t
) {
145 struct fsample_p
*p
= &f
->m
[mmod(pos
, f
->samples
)];
147 if(p
->iteration
!= f
->header
->iteration
) {
148 unsigned char prev
= previteration(f
);
150 if(prev
!= p
->iteration
|| (pos
<= f
->header
->lastpos
)) {
151 /*printf("bad: prev: %d p->iteration: %d, pos: %d lastpos: %d\n", prev, p->iteration, pos, f->header->lastpos);*/
160 inline fsample_t
fsget_r(fsample
*f
, fsample_t pos
, fsample_t
*t
) {
161 struct fsample_p
*p
= &f
->m
[mmod(pos
, f
->samples
)];
167 inline fsample_t
fsget(fsample
*f
, fsample_t pos
, fsample_t
*t
) {
168 return __fsget(f
, pos
, t
);
171 int fsadd_m(fsample_m
*f
, char *filename
, size_t freq
, DeriveValueFn derive
, void *tag
) {
172 fsample_m_entry
*p
= &f
->entry
[f
->pos
];
174 p
->f
= fsopen(filename
, f
->samples
/ freq
, f
->chafn
, f
->chdfn
);
185 fsample_m
*fsopen_m(size_t count
, char *filename
, size_t samples
, CoreHandlerAddFn chafn
, CoreHandlerDelFn chdfn
) {
186 fsample_m
*n
= (fsample_m
*)malloc(sizeof(fsample_m
) + (count
+ 1) * sizeof(fsample_m_entry
));
190 n
->samples
= samples
;
195 if(!fsadd_m(n
, filename
, 1, NULL
, 0)) {
203 void fsset_m(fsample_m
*f
, fsample_t pos
, fsample_t value
) {
206 for(i
=0;i
<f
->pos
;i
++) {
209 if((pos
+ 1) % f
->entry
[i
].freq
!= 0)
212 if(f
->entry
[i
].derive
) {
213 v
= (f
->entry
[i
].derive
)(f
, i
, pos
, f
->entry
[i
].tag
);
218 fsset(f
->entry
[i
].f
, pos
/ f
->entry
[i
].freq
, v
);
222 void fsclose_m(fsample_m
*f
) {
225 for(i
=0;i
<f
->pos
;i
++)
226 fsclose(f
->entry
[i
].f
);
230 inline fsample_t
__fsget_m(fsample_m
*f
, int entry
, int pos
, fsample_t
*t
) {
231 return __fsget(f
->entry
[entry
].f
, pos
/ f
->entry
[entry
].freq
, t
);
234 inline fsample_t
fsget_m(fsample_m
*f
, int entry
, fsample_t pos
, fsample_t
*t
) {
235 return fsget(f
->entry
[entry
].f
, pos
/ f
->entry
[entry
].freq
, t
);
238 inline fsample_t
fsget_mr(fsample_m
*f
, int entry
, fsample_t pos
, fsample_t
*t
) {
239 return fsget_r(f
->entry
[entry
].f
, pos
/ f
->entry
[entry
].freq
, t
);
242 fsample_t
fsamean(fsample_m
*f
, int entry
, fsample_t pos
, void *tag
) {
244 long samples
= (long)tag
;
246 int rpos
= pos
/ f
->entry
[0].freq
;
250 for(i
=0;i
<samples
;i
++) {
251 if(__fsget_m(f
, 0, rpos
- i
, &t
)) {
255 /* printf("bad :(\n");*/
265 fsample_t
fsapmean(fsample_m
*f
, int entry
, fsample_t pos
, void *tag
) {
267 long samples
= (long)tag
;
269 int rpos
= pos
/ f
->entry
[entry
- 1].freq
;
273 for(i
=0;i
<=samples
;i
++) {
274 if(__fsget(f
->entry
[entry
- 1].f
, rpos
- i
, &t
)) {
278 /*printf("bad :(\n");*/