1
/*===========================================================================
2
Copyright (C) 1987-2009 European Southern Observatory (ESO)
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; either version 2 of
7
the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public
15
License along with this program; if not, write to the Free
16
Software Foundation, Inc., 675 Massachusetts Ave, Cambridge,
19
Correspondence concerning ESO-MIDAS should be addressed as follows:
20
Internet e-mail: midas@eso.org
21
Postal address: European Southern Observatory
22
Data Management Division
23
Karl-Schwarzschild-Strasse 2
24
D 85748 Garching bei Muenchen
26
===========================================================================*/
28
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
30
.IDENTIFICATION buffer.c
31
.AUTHOR Francois Ochsenbein [ESO-IPG]
33
.KEYWORDS Buffer / Stack Management
36
These routines allow the management of buffers defined
37
as the following BUFFER structure:
40
\item {\tt char *buf} is the address of the buffer in memory
41
\item {\tt int allocated} is the number of bytes allocated to buf
42
\item {\tt int used} is the present number of bytes used in this
44
\item {\tt int increment} is the number of bytes for automatic expansions
45
\item {\tt offset} is an integer, \eg
46
to perform some searches. It is used for stacking and unstacking.
49
.VERSION 1.0 03-Feb-1987: Creation
50
.VERSION 1.1 20-May-1987: Removed bug in mm_set
51
.VERSION 2.0 20-Apr-1988: Changed function names, added stacking facilities.
52
.VERSION 2.1 01-Jun-1988: Added mm_zloc (retrieve a zero item),
53
mm_zindex (retrieve non-zero item)
54
mm_zfree (free the index)
55
.VERSION 2.2 07-Nov-1988: Removed bug in mm_bunst
56
.VERSION 2.3 07-Jun-1991: Be sure an EOS is appended in mm_bapp
59
----------------------------------------------------------------------------*/
61
#define DEBUG 0 /* For debugging purposes */
64
#define PM_LEVEL LEVEL_STR
67
#define PASCAL_DEF 0 /* Don't include pascalisation ... */
69
#include <midas_def.h> /* Standard Definitions */
70
#include <stesodef.h> /* Standard Definitions */
74
extern int mm_free(), eh_put1(), eh_ed_i();
78
#define FINISH goto FIN
80
/*==========================================================================*/
81
BUFFER *mm_bopen(size, incr)
83
.PURPOSE Allocation of a buffer of a given size
84
.RETURNS Address of allocated buffer, or NULL address if failed,
85
.REMARKS If incr is zero, the buffer cannot be automatically expanded.
87
int size; /* IN: The required size (bytes) */
88
int incr; /* IN: The increment size for expansion (bytes) */
94
if (size < 0) size = 0;
95
b = MEM_GET(BUFFER,1);
96
b->buf = NULL_PTR(char);
99
b->increment = (incr > 0 ? incr : 0);
103
b->buf = MEM_GET(char, b->allocated);
108
/*==========================================================================*/
111
.PURPOSE Free a BUFFER structure --- but ONLY the buffer!
115
BUFFER *b; /* IN: The buffer to free */
122
b->buf = NULL_PTR(char);
131
/*==========================================================================*/
134
.PURPOSE Expansion of a buffer
135
.RETURNS OK (1)/ NOK(0)
136
.REMARKS Size of zero implies "use increment"
138
BUFFER *b; /* IN: The Buffer to Expand */
139
int size; /* IN: The required new size (bytes) */
142
int new_size, status;
146
new_size = (size > 0 ? size : b->allocated + b->increment);
148
p = MEM_EXP(char, b->buf, new_size);
149
if (p) b->allocated = new_size, b->buf = p, status = OK;
155
/*==========================================================================*/
156
char *mm_bst(b, record, len)
158
.PURPOSE Stack a record into buffer --- The buffer is
159
expanded if necessary
160
.RETURNS Address of stacked record / NULL if error
161
.REMARKS Save offset of previous stacked values.
163
BUFFER *b; /* IN: The buffer to free */
164
char *record; /* IN: record to append */
165
int len; /* IN: Length of record */
171
a = mm_ball(b, len + sizeof(int));
173
{ a += oscopy(a, (char *)(&(b->offset)), sizeof(int));
174
b->offset = a - b->buf;
175
oscopy(a, record, len);
181
/*==========================================================================*/
184
.PURPOSE Unstack a record from buffer.
185
.RETURNS Address of record / NULL
188
BUFFER *b; /* IN: The buffer to free */
194
if (b->used <= 0) p = NULL_PTR(char);
196
{ b->used = b->offset - sizeof(int);
197
oscopy((char *)(&(b->offset)), b->buf + b->used, sizeof(int));
198
if (b->used <= 0) p = NULL_PTR(char);
199
else p = b->buf + b->offset;
205
/*==========================================================================*/
206
char *mm_bapp(b, record, len)
208
.PURPOSE Append a record to a buffer --- The buffer is
209
expanded if necessary
210
.RETURNS Address of stored record / NULL if error
213
BUFFER *b; /* IN: The buffer to free */
214
char *record; /* IN: record to append */
215
int len; /* IN: Length of record */
221
/* Get a pointer in buffer, and then copy string
224
p = mm_ball(b, len+1);
226
oscopy(p, record, len), p[len] = 0;
231
TRACE_ED_STR2("Buffer: ",b->buf, b->used);
237
/*==========================================================================*/
238
char *mm_ball(b, len)
240
.PURPOSE Set a pointer to next available record in buffer.
241
Buffer is expanded if necessary
242
.RETURNS Address of available record / NULL if error
245
BUFFER *b; /* IN: The buffer to free */
246
int len; /* IN: Length of record */
254
TRACE_ED_I("Asks for bytes: ",len);
258
if_not(b) { ERROR("Bad Buffer"); FINISH; }
259
if (len < 0) { ERR_ED_I("Bad Length: ", len); FINISH; }
261
p = (b->buf) + b->used;
262
if (len == 0 ) FINISH;
265
TRACE_ED_I("Already in buffer: ",b->used);
266
TRACE_ED_STR2("Already in buffer: ",b->buf, b->used);
269
ex = b->used + len - b->allocated;
270
if ( ex > 0) /* Doesn't fit. Expand is required */
271
{ if(b->increment) /* Increment is possible */
272
{ ex = (ex+b->increment-1)/b->increment;
273
ex = ex*b->increment + b->allocated;
274
p = (mm_bexp(b, ex) ? b->buf + b->used : NULL_PTR(char));
276
else p = NULL_PTR(char);
281
if(p) b->used += len;
286
/*==========================================================================*/
287
char *mm_zfree(b, index, item_len)
289
.PURPOSE Free the indexed item.
290
.RETURNS Address of freed item / NULL if bad item
293
BUFFER *b; /* IN: The buffer to free */
294
int index; /* IN: Index of item to free */
295
int item_len; /* IN: Size of 1 item */
302
/* Find first the position */
304
o = index * item_len;
305
if ( (o < 0) || (o >= b->used) ) FINISH;
308
oscfill(p, item_len, '\0');
314
/*==========================================================================*/
315
char *mm_zindex(b, index, item_len)
317
.PURPOSE Finds the position of indexed item. Null item is checked.
318
.RETURNS Address of found item / NULL if bad item or is filled
322
BUFFER *b; /* IN: The buffer to free */
323
int index; /* IN: Index of item to free */
324
int item_len; /* IN: Size of 1 item */
331
/* Find first the position */
333
o = index * item_len;
334
if ( (o < 0) || (o >= b->used) ) FINISH;
337
if (oscskip(p, item_len, '\0') == item_len) /* Filled with zeroes... */
344
/*==========================================================================*/
345
char *mm_zloc(b, item_len)
347
.PURPOSE Finds the position for a new (free) item. The found
348
position is filled with zeroes, and b->offset is initialized.
349
.RETURNS Address of found item position / NULL if impossible.
352
BUFFER *b; /* IN: The buffer to free */
353
int item_len; /* IN: Size of 1 item */
358
/* Look first if space remains. If yes, use it */
360
if (b->allocated > b->used)
361
{ b->offset = b->used;
365
/* Find an position with only zeroes */
367
for (b->offset = 0; b->offset < b->used; b->offset += item_len)
368
if (oscskip(b->buf + b->offset, item_len, '\0') == item_len)
371
/* Last possibility: Must expand the buffer...
372
* Remember that b->offset is correctly set to b->used */
374
mm_ball(b, item_len);
376
/* Now, initialize the found item */
379
if (b->offset < b->allocated) /* It's OK... */
380
{ p = b->buf + b->offset;
381
oscfill(p, item_len, '\0');
382
if (b->used <= b->offset) b->used = b->offset + item_len;
385
{ ERROR("Maximum reached.");