1 /*
2 library_file.c: functions for file i/o
3 Copyright (C) 2001 CCLRC, Charles Ballard
4
5 This library is free software: you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 version 3, modified in accordance with the provisions of the
8 license to address the requirements of UK law.
9
10 You should have received a copy of the modified GNU Lesser General
11 Public License along with this library. If not, copies may be
12 downloaded from http://www.ccp4.ac.uk/ccp4license.php
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU Lesser General Public License for more details.
18 */
19
20 /** @file library_file.c
21 * Functions for file i/o.
22 * Charles Ballard
23 */
24
25 #include<string.h>
26 #include <limits.h>
27 #include <fcntl.h>
28 #if defined _MSC_VER
29 #include <io.h>
30 #endif
31 #include "library_file.h"
32 #include "ccp4_errno.h"
33 #include "ccp4_file_err.h"
34 /* rcsid[] = "$Id: library_file.c,v 1.26 2012/08/20 12:21:16 gxg60988 Exp $" */
35
36 static uint16 nativeIT = NATIVEIT; /* machine integer type */
37 static uint16 nativeFT = NATIVEFT; /* machine float type */
38
39 static int _item_sizes[] = {
40 (int) sizeof (char), /* 0: bytes */
41 (int) sizeof (short int), /* 1: (integer) half words */
42 (int) sizeof (float), /* 2: reals/words */
43 (int) sizeof (int), /* 3: `short complex' (pairs of half words).
44 NB int rather than 2*short since must fit
45 into fortran integer */
46 (int) 2*sizeof (float), /* 4: complex (pairs of words) */
47 (int) sizeof (int), /* 5: not used */
48 (int) sizeof (int) /* 6: integers */
49 };
50
51 static int (*_read_mode[])(CCP4File *, uint8 *, size_t) = {
52 ccp4_file_readchar,
53 ccp4_file_readshort,
54 ccp4_file_readfloat,
55 ccp4_file_readshortcomp,
56 ccp4_file_readcomp,
57 NULL,
58 ccp4_file_readint
59 };
60
61 static int (*_write_mode[])(CCP4File *, const uint8 *, size_t) = {
62 ccp4_file_writechar,
63 ccp4_file_writeshort,
64 ccp4_file_writefloat,
65 ccp4_file_writeshortcomp,
66 ccp4_file_writecomp,
67 NULL,
68 ccp4_file_writeint
69 };
70
71 /**
72 * vaxF2ieeeF:
73 * @param buffer (float_uint_uchar *) vax order float array
74 * @param size (unsigned int) number of items
75 *
76 * Translation from Vax floating point format to ieee.
77 *
78 */
vaxF2ieeeF(union float_uint_uchar * buffer,const unsigned int size)79 static void vaxF2ieeeF(union float_uint_uchar *buffer, const unsigned int size)
80 {
81 union float_uint_uchar out;
82 unsigned char exp;
83 unsigned int i;
84
85 if ( buffer == NULL || size == 0) return;
86
87 for (i = 0; i < size; i++) {
88 exp = (buffer[i].c[1] << 1) | (buffer[i].c[0] >> 7); /* extract exponent */
89 if (!exp && !buffer[i].c[1]) /* zero value */
90 out.c[0] = out.c[1] = out.c[2] = out.c[3] = 0;
91 else if (exp > 2) { /* normal value */
92 out.c[0] = buffer[i].c[1] - (uint8)1; /* subtracts 2 from exponent */
93 /* copy mantissa, LSB of exponent */
94 out.c[1] = buffer[i].c[0];
95 out.c[2] = buffer[i].c[3];
96 out.c[3] = buffer[i].c[2];
97 } else if (exp) { /* denormalized number */
98 int shft;
99
100 out.c[0] = buffer[i].c[1] & 0x80; /* keep sign, zero exponent */
101 shft = 3 - exp;
102 /* shift original mant by 1 or 2 to get denormalized mant */
103 /* prefix mantissa with '1'b or '01'b as appropriate */
104 out.c[1] = (uint8)((buffer[i].c[0] & 0x7f) >> shft) |
105 (uint8)(0x10 << exp);
106 out.c[2] = (uint8)(buffer[i].c[0] << (8-shft)) |
107 (uint8)(buffer[i].c[3] >> shft);
108 out.c[3] = (uint8)(buffer[i].c[3] << (8-shft)) |
109 (uint8)(buffer[i].c[2] >> shft);
110 } else { /* sign=1 -> infinity or NaN */
111 out.c[0] = 0xff; /* set exp to 255 */
112 /* copy mantissa */
113 out.c[1] = buffer[i].c[0] | (uint8)0x80; /* LSB of exp = 1 */
114 out.c[2] = buffer[i].c[3];
115 out.c[3] = buffer[i].c[2];
116 }
117 buffer[i] = out; /* copy back result */
118 }
119 }
120
121 /**
122 * ieeeF2vaxF:
123 * @param buffer (float_uint_uchar *) big endian order float array
124 * @param size (unsigned int) number of items
125 *
126 * Translation from ieee floating point format to vax.
127 *
128 */
ieeeF2vaxF(union float_uint_uchar * buffer,const unsigned int size)129 static void ieeeF2vaxF(union float_uint_uchar *buffer, const unsigned int size)
130 {
131 union float_uint_uchar out;
132 unsigned char exp;
133 unsigned int i;
134
135 if ( buffer == NULL || size == 0) return;
136
137 for (i=0; i<size; i++) {
138 exp = (buffer[i].c[0]<<1) | (buffer[i].c[1]>>7); /* extract exponent */
139 if (exp) { /* non-zero exponent */
140 /* copy mantissa, last bit of exponent */
141 out.c[0] = buffer[i].c[1];
142 out.c[2] = buffer[i].c[3];
143 out.c[3] = buffer[i].c[2];
144 if (exp < 254) /* normal value */
145 out.c[1] = buffer[i].c[0] + (uint8)1; /* actually adds two to exp */
146 else { /* infinity or NaN */
147 if (exp == 254) /* unrepresentable - OFL */
148 /* set mant=0 for overflow */
149 out.c[0] = out.c[1] = out.c[2] = out.c[3] = 0;
150 out.c[0] &= 0x7f; /* set last bit of exp to 0 */
151 out.c[1] = 0x80; /* sign=1 exp=0 -> OFL or NaN. this will raise
152 a reserved operand exception if used. */
153 }
154 } else if (buffer[i].c[1] & 0x60) { /* denormalized value */
155 int shft;
156
157 shft = (buffer[i].c[1] & 0x40) ? 1 : 2; /* shift needed to normalize */
158 /* shift mantissa */
159 /* note last bit of exp set to 1 implicitly */
160 out.c[0] = (uint8)(buffer[i].c[1] << shft) |
161 (uint8)(buffer[i].c[2] >> (8-shft));
162 out.c[3] = (uint8)(buffer[i].c[2] << shft) |
163 (uint8)(buffer[i].c[3] >> (8-shft));
164 out.c[2] = (uint8)(buffer[i].c[3] << shft);
165 out.c[1] = (uint8)(buffer[i].c[0] & 0x80); /* sign */
166 if (shft==1) { /* set exp to 2 */
167 out.c[1] |= 0x01;
168 out.c[0] &= 0x7f; /* set LSB of exp to 0 */
169 }
170 } else /* zero */
171 out.c[0] = out.c[1] = out.c[2] = out.c[3] = 0;
172 buffer[i] = out; /* copy back the result */
173 }
174 }
175
176 /**
177 * convexF2ieeeF:
178 * @param buffer (float_uint_uchar *) float array with convex byte ordering
179 * @param size (unsigned int) number of items
180 *
181 * Translation from convex floating point format to ieee.
182 *
183 */
convexF2ieeeF(union float_uint_uchar * buffer,const unsigned int size)184 static void convexF2ieeeF(union float_uint_uchar *buffer, const unsigned int size)
185 {
186 union float_uint_uchar out;
187 unsigned char exp;
188 unsigned int i;
189
190 if ( buffer == NULL || size == 0) return;
191
192 for (i = 0; i < size; i++) {
193 exp = (buffer[i].c[0]<<1) | (buffer[i].c[1]>>7); /* extract exponent */
194 if (!exp && !buffer[i].c[0]) /* zero value */
195 out.c[0] = out.c[1] = out.c[2] = out.c[3] = 0;
196 else if (exp > 2) { /* normal value */
197 out.c[0] = buffer[i].c[0] - (uint8)1; /* subtracts 2 from exponent */
198 /* copy mantissa, LSB of exponent */
199 out.c[1] = buffer[i].c[1];
200 out.c[2] = buffer[i].c[2];
201 out.c[3] = buffer[i].c[3];
202 } else if (exp) { /* denormalized number */
203 int shft;
204
205 out.c[0] = buffer[i].c[0] & 0x80; /* keep sign, zero exponent */
206 shft = 3 - exp;
207 /* shift original mant by 1 or 2 to get denormalized mant */
208 /* prefix mantissa with '1'b or '01'b as appropriate */
209 out.c[1] = (uint8)((buffer[i].c[1] & 0x7f) >> shft) |
210 (uint8)(0x10 << exp);
211 out.c[2] = (uint8)(buffer[i].c[1] << (8-shft)) |
212 (uint8)(buffer[i].c[2] >> shft);
213 out.c[3] = (uint8)(buffer[i].c[2] << (8-shft)) |
214 (uint8)(buffer[i].c[3] >> shft);
215 } else { /* sign=1 -> infinity or NaN */
216 out.c[0] = 0xff; /* set exp to 255 */
217 /* copy mantissa */
218 out.c[1] = buffer[i].c[1] | (uint8)0x80; /* LSB of exp = 1 */
219 out.c[2] = buffer[i].c[2];
220 out.c[3] = buffer[i].c[3];
221 }
222 buffer[i] = out; /* copy back result */
223 }
224 }
225
226 /**
227 * ieeeF2convexF:
228 * @param buffer (float_uint_uchar *) float array with big endian byte ordering
229 * @param size (const unsigned int) numnber of items
230 *
231 * Translation from ieee floating point format to convex.
232 *
233 */
ieeeF2convexF(union float_uint_uchar * buffer,const unsigned int size)234 static void ieeeF2convexF(union float_uint_uchar *buffer, const unsigned int size)
235 {
236 union float_uint_uchar out;
237 unsigned char exp;
238 unsigned int i;
239
240 if ( buffer == NULL || size == 0) return;
241
242 for (i=0; i < size; i++) {
243 exp = (uint8)(buffer[i].c[0] << 1) |
244 (uint8)(buffer[i].c[1] >> 7); /* extract exponent */
245 if (exp) { /* non-zero exponent */
246 /* copy mantissa, last bit of exponent */
247 out.c[1] = buffer[i].c[1];
248 out.c[3] = buffer[i].c[3];
249 out.c[2] = buffer[i].c[2];
250 if (exp < 254) /* normal value */
251 out.c[0] = buffer[i].c[0] + (uint8)1; /* actually adds two to exp */
252 else { /* infinity or NaN */
253 if (exp == 254) /* unrepresentable - OFL */
254 /* set mant=0 for overflow */
255 out.c[0] = out.c[1] = out.c[2] = out.c[3] = 0;
256 out.c[1] &= 0x7f; /* set last bit of exp to 0 */
257 out.c[0] = 0x80; /* sign=1 exp=0 -> OFL or NaN. this will raise
258 a reserved operand exception if used. */
259 }
260 } else if (buffer[i].c[1] & 0x60) { /* denormalized value */
261 int shft;
262
263 shft = (buffer[i].c[1] & 0x40) ? 1 : 2; /* shift needed to normalize */
264 /* shift mantissa */
265 /* note last bit of exp set to 1 implicitly */
266 out.c[1] = (uint8)(buffer[i].c[1] << shft) |
267 (uint8)(buffer[i].c[2] >> (8-shft));
268 out.c[2] = (uint8)(buffer[i].c[2] << shft) |
269 (uint8)(buffer[i].c[3] >> (8-shft));
270 out.c[3] = (uint8)(buffer[i].c[3] << shft);
271 out.c[0] = (uint8)(buffer[i].c[0] & 0x80); /* sign */
272 if (shft==1) { /* set exp to 2 */
273 out.c[0] |= 0x01;
274 out.c[1] &= 0x7f; /* set LSB of exp to 0 */
275 }
276 } else /* zero */
277 out.c[0] = out.c[1] = out.c[2] = out.c[3] = 0;
278 buffer[i] = out; /* copy back the result */
279 }
280 }
281
282 /**
283 * ccp4_file_raw_read:
284 * @param cfile * (CCP4File *)
285 * @param buffer * (char *) input array
286 * @param n_items (size_t) number of items
287 *
288 * reads block of n_items bytes from cfile to buffer via
289 * FILE struct cfile->stream(fread) or file desc cfile->fd
290 * read/_read). Increments location value cfile->loc. The
291 * cfile->iostat flag is set on failure.
292 * @return number of bytes read.
293 */
ccp4_file_raw_read(CCP4File * cfile,char * buffer,size_t n_items)294 int ccp4_file_raw_read(CCP4File *cfile, char *buffer, size_t n_items)
295 {
296 int result;
297
298 if (cfile->buffered && cfile->stream) {
299 result = fread (buffer, (size_t) sizeof(char), n_items,
300 cfile->stream);
301 if (result != n_items && feof(cfile->stream)) {
302 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_EOF),
303 "ccp4_file_raw_read", NULL);
304 cfile->iostat = CIO_EOF;
305 result = EOF;
306 } else if (result != n_items && ferror(cfile->stream)) {
307 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_raw_read", NULL);
308 cfile->iostat = CIO_ReadFail;
309 result = 0; }
310 } else {
311 #if defined _MSC_VER
312 result = _read (cfile->fd, buffer, n_items);
313 #else
314 result = read (cfile->fd, buffer, n_items);
315 #endif
316 if (n_items && result <= 0) {
317 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_ReadFail),
318 "ccp4_file_raw_read", NULL);
319 cfile->iostat = CIO_ReadFail;
320 result = 0; }
321 }
322 cfile->last_op = READ_OP;
323
324 cfile->loc += result;
325 cfile->getbuff = 0;
326
327 return result;
328 }
329
330 /**
331 * ccp4_file_raw_write:
332 * @param cfile (CCP4File *)
333 * @param buffer (char *) output array
334 * @param n_items (size_t) number of items
335 *
336 * writes block of @n_items bytes from @buffer to @cfile via FILE struct
337 * @cfile->stream(fwrite) or file desc @cfile->fd(write/_write). Increments
338 * @cfile->loc on success, or resets on failure, which is then used to
339 * determine the file length. On failure @cfile->iostat is set.
340 * @return number of bytes written.
341 */
ccp4_file_raw_write(CCP4File * cfile,const char * buffer,size_t n_items)342 int ccp4_file_raw_write(CCP4File *cfile, const char *buffer, size_t n_items)
343 {
344 int result;
345
346 if (cfile->buffered && cfile->stream)
347 result = fwrite (buffer, (size_t) sizeof(char), n_items,
348 cfile->stream);
349 else
350 #if defined _MSC_VER
351 result = _write (cfile->fd, buffer, n_items);
352 #else
353 result = write (cfile->fd, buffer, n_items);
354 #endif
355
356 cfile->last_op = WRITE_OP;
357
358 if (result == n_items)
359 cfile->loc += n_items;
360 else {
361 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_WriteFail),
362 "ccp4_file_raw_write", NULL);
363 cfile->iostat = CIO_WriteFail;
364 ccp4_file_tell(cfile); }
365 cfile->length = MAX(cfile->loc,cfile->length);
366 cfile->getbuff = 0;
367
368 return result;
369 }
370
371 /**
372 * ccp4_file_raw_seek:
373 * @param cfile (CCP4File *)
374 * @param offset (long) offset in bytes
375 * @param whence (int) SEEK_SET, SEEK_CUR, or SEEK_END
376 *
377 * if the file is "seekable" (not stdin) the function
378 * seeks on @cfile by offset bytes using fseek/ftell (@cfile->stream)
379 * or lseek (@cfile->fd). %SEEK_SET is relative
380 * to start of file, %SEEK_CUR to current, %SEEK_END to
381 * end.
382 * @return offset in bytes on success, -1 on failure.
383 */
ccp4_file_raw_seek(CCP4File * cfile,long offset,int whence)384 int ccp4_file_raw_seek(CCP4File *cfile, long offset, int whence)
385 {
386 int result = -1;
387
388 if (!cfile->direct) {
389 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
390 "ccp4_file_raw_seek", NULL);
391 return result; }
392
393 if (cfile->buffered) {
394 #if defined (__alpha) && defined (vms)
395 (void) fflush (cfile->stream);
396 #endif
397 if (!(result = (fseek (cfile->stream,offset,whence))))
398 result = ftell(cfile->stream);
399 } else {
400 #if defined _MSC_VER
401 result = _lseek(cfile->fd,offset,whence);
402 #else
403 result = lseek(cfile->fd, offset, whence);
404 #endif
405 }
406
407 cfile->last_op = IRRELEVANT_OP;
408
409 if (result == -1) {
410 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_SeekFail),
411 "ccp4_file_raw_seek", NULL);
412 cfile->iostat = CIO_SeekFail;
413 } else
414 cfile->loc = result;
415 cfile->getbuff = 0;
416
417 return (result);
418 }
419
420 /**
421 * _file_free:
422 * @param cfile (CCP4File *)
423 *
424 * free up @cfile
425 */
_file_free(CCP4File * cfile)426 static void _file_free(CCP4File *cfile)
427 {
428 if(cfile->name) free(cfile->name);
429 cfile->name = NULL;
430 free(cfile);
431 }
432
433 /**
434 * _file_init:
435 * @param cfile ()
436 *
437 * initialise cfile struct
438 * @return cfile struct
439 */
_file_init()440 static CCP4File *_file_init()
441 {
442 CCP4File *cfile = (CCP4File *) malloc(sizeof(CCP4File));
443 char *foreign = getenv ("CONVERT_FROM");
444 char *native = getenv ("NATIVEMTZ");
445
446 memset(cfile,'\0',sizeof(CCP4File));
447 cfile->fd = -1;
448 cfile->buffered = 1;
449 cfile->binary = 1;
450 cfile->last_op = IRRELEVANT_OP;
451 cfile->mode = DEFMODE;
452 cfile->itemsize = _item_sizes[DEFMODE];
453 if (native == NULL && foreign != NULL) {
454 if (strcmp (foreign, "BEIEEE") == 0) {
455 cfile->fconvert = DFNTF_BEIEEE ;
456 cfile->iconvert = DFNTI_MBO ; }
457 else if (strcmp (foreign, "LEIEEE") == 0) {
458 cfile->fconvert = DFNTF_LEIEEE;
459 cfile->iconvert = DFNTI_IBO ; }
460 else if (strcmp (foreign, "VAX") == 0) {
461 cfile->fconvert = DFNTF_VAX ;
462 cfile->iconvert = DFNTI_IBO ; }
463 else if (strcmp (foreign, "CONVEXNATIVE") == 0) {
464 cfile->fconvert = DFNTF_CONVEXNATIVE ;
465 cfile->iconvert = DFNTI_MBO ; }
466 } else {
467 cfile->fconvert = nativeFT;
468 cfile->iconvert = nativeIT;
469 }
470 cfile->_read=_read_mode[DEFMODE];
471 cfile->_write=_write_mode[DEFMODE];
472 return (cfile);
473 }
474
475 /**
476 * _file_open_mode:
477 * @param cfile (CCP4File *)
478 * @param flag (const int) mode flag
479 *
480 * set file open mode elements of @cfile (see ccp4_sysdep.h)
481 * O_TMP = 0x0010
482 * O_RDONLY = 0x0000
483 * O_WRONLY = 0x0001
484 * O_RDWR = 0x0002
485 * O_APPEND = 0x0008
486 */
_file_open_mode(CCP4File * cfile,const int flag)487 static void _file_open_mode(CCP4File * cfile, const int flag)
488 {
489 if (flag & O_TMP)
490 cfile->scratch = 1;
491 if (flag & (O_WRONLY | O_RDWR | O_APPEND) ) {
492 cfile->write = 1;
493 if (flag & O_RDWR)
494 cfile->read = 1;
495 if (flag & O_APPEND)
496 cfile->append = 1;
497 } else
498 cfile->read = 1;
499 }
500
501 /**
502 * _file_close:
503 * @param cfile (CCP4File *)
504 *
505 * close @cfile if it is "owned" (@cfile->own) using fclose or close.
506 * Reset @cfile to some safe value. Note: flush anyway.
507 * @return 0 on success, -1 on failure.
508 */
_file_close(CCP4File * cfile)509 static int _file_close (CCP4File *cfile)
510 {
511 int result = 0;
512
513 if(cfile->buffered && cfile->stream) {
514 if (cfile->own)
515 result = fclose (cfile->stream);
516 else
517 result = fflush(cfile->stream);
518 } else {
519 if (cfile->own)
520 #if defined _MSC_VER
521 result = _close(cfile->fd);
522 #else
523 result = close (cfile->fd);
524 #endif
525 }
526
527 if (result == EOF)
528 cfile->iostat = CIO_CloseFail;
529 else
530 cfile->stream = NULL;
531
532 return (result);
533 }
534
535 /**
536 * ccp4_file_is_write:
537 * @param cfile (CCP4File *)
538 *
539 * is the @cfile writeable
540 * @return 1 if true
541 */
ccp4_file_is_write(const CCP4File * cfile)542 int ccp4_file_is_write(const CCP4File *cfile)
543 {
544 return (cfile->write);
545 }
546
547 /**
548 * ccp4_file_is_read:
549 * @param cfile (CCP4File *)
550 *
551 * is the @cfile readable
552 * @return 1 if true.
553 */
ccp4_file_is_read(const CCP4File * cfile)554 int ccp4_file_is_read(const CCP4File *cfile)
555 {
556 return (cfile->read);
557 }
558
559 /**
560 * ccp4_file_is_append:
561 * @param cfile (CCP4File *)
562 *
563 * is the @cfile in append mode
564 * @return 1 if true.
565 */
ccp4_file_is_append(const CCP4File * cfile)566 int ccp4_file_is_append(const CCP4File *cfile)
567 {
568 return (cfile->append);
569 }
570
571 /**
572 * ccp4_file_is_scratch:
573 * @param cfile (CCP4File *)
574 *
575 * is scratch file
576 * @return 1 if true.
577 */
ccp4_file_is_scratch(const CCP4File * cfile)578 int ccp4_file_is_scratch(const CCP4File *cfile)
579 {
580 return (cfile->scratch);
581 }
582
583 /**
584 * ccp4_file_is_buffered:
585 * @param cfile (CCP4File *)
586 *
587 * is the file buffered
588 * @return 1 if true
589 */
ccp4_file_is_buffered(const CCP4File * cfile)590 int ccp4_file_is_buffered(const CCP4File *cfile)
591 {
592 return (cfile->buffered);
593 }
594
595 /**
596 * ccp4_file_status:
597 * @param cfile (CCP4File *)
598 *
599 * @return @cfile error status
600 */
ccp4_file_status(const CCP4File * cfile)601 int ccp4_file_status(const CCP4File *cfile)
602 {
603 return (cfile->iostat);
604 }
605
ccp4_file_raw_setstamp(CCP4File * cfile,const size_t offset)606 int ccp4_file_raw_setstamp(CCP4File *cfile, const size_t offset)
607 {
608 cfile->stamp_loc = offset;
609 return 0;
610 }
611
612 /**
613 * ccp4_file_setstamp:
614 * @param cfile (CCP4File *)
615 * @param stamp_loc (size_t) offset in items
616 *
617 * set the machine stamp offset in CCP4 items determined
618 * by the mode of @cfile. See ccp4_file_setmode().
619 * @return 0 on success, %EOF on failure
620 */
ccp4_file_setstamp(CCP4File * cfile,const size_t offset)621 int ccp4_file_setstamp(CCP4File *cfile, const size_t offset)
622 {
623 if (!cfile) {
624 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_NullPtr),
625 "ccp4_file_setstamp", NULL);
626 return EOF; }
627
628 return ccp4_file_raw_setstamp(cfile, offset*cfile->itemsize);
629 }
630
631 /**
632 * ccp4_file_setmode:
633 * @param cfile (CCP4File *)
634 * @param mode (int) io_mode
635 *
636 * set the data mode of cfile to mode
637 * (CCP4_BYTE (8 bit) = 0,
638 * CCP4_INT16 (16 bit) = 1,
639 * CCP4_INT32 (32 bit) = 6,
640 * FLOAT32 (32 bit) = 2,
641 * COMP32 (2*16 bit) = 3,
642 * COMP64 (2*32 bit) = 4).
643 * @return 0 on success, EOF on failure.
644 */
ccp4_file_setmode(CCP4File * cfile,const int mode)645 int ccp4_file_setmode (CCP4File *cfile, const int mode)
646 {
647 if (!cfile) {
648 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_NullPtr),
649 "ccp4_file_mode", NULL);
650 return EOF; }
651
652 if (mode >= 0 && mode <= 6 && mode != 5) {
653 cfile->mode = mode;
654 cfile->itemsize = _item_sizes[mode];
655 cfile->_read=_read_mode[mode];
656 cfile->_write=_write_mode[mode];
657 } else {
658 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_BadMode),
659 "ccp4_file_mode", NULL);
660 return EOF; }
661
662 return 0;
663 }
664
665 /**
666 * ccp4_file_mode:
667 * @param cfile (CCP4File *)
668 *
669 * get data mode of @cfile (CCP4_BYTE =0, CCP4_INT16 =1, CCP4_INT32=6,
670 * FLOAT32 =2, COMP32 =3, COMP64 =4)
671 * @return %mode
672 */
ccp4_file_mode(const CCP4File * cfile)673 int ccp4_file_mode (const CCP4File *cfile)
674 {
675 if (!cfile) {
676 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_NullPtr),
677 "ccp4_file_mode", NULL);
678 return EOF; }
679
680 return (cfile->mode);
681 }
682
683 /**
684 * ccp4_file_itemsize:
685 * @param cfile (CCP4File *)
686 *
687 * @return %itemsize of @cfile.
688 */
ccp4_file_itemsize(const CCP4File * cfile)689 int ccp4_file_itemsize(const CCP4File *cfile)
690 {
691 if (!cfile) {
692 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_BadMode),
693 "ccp4_file_itemsize", NULL);
694 return EOF; }
695
696 return (cfile->itemsize);
697 }
698
699 /**
700 * ccp4_file_name:
701 * @param cfile (CCP4File *)
702 *
703 * strdup @cfile->name
704 * @return name of file as char *
705 */
ccp4_file_name(CCP4File * cfile)706 char *ccp4_file_name( CCP4File *cfile)
707 {
708 #if defined _MSC_VER
709 return ( cfile == NULL ? NULL : _strdup(cfile->name));
710 #else
711 return ( cfile == NULL ? NULL : strdup(cfile->name));
712 #endif
713 }
714
715 /**
716 * ccp4_file_setbyte:
717 * @param cfile (CCP4File *)
718 * @param byte_order (int)
719 *
720 * set byte ordering for file
721 * Return:
722 */
ccp4_file_setbyte(CCP4File * cfile,const int byte_order)723 int ccp4_file_setbyte(CCP4File *cfile, const int byte_order)
724 {
725 int result = (cfile->fconvert | (cfile->iconvert<<8));
726
727 switch (byte_order) {
728 case DFNTF_BEIEEE:
729 cfile->fconvert = DFNTF_BEIEEE;
730 cfile->iconvert = DFNTI_MBO;
731 break;
732 case DFNTF_LEIEEE:
733 cfile->fconvert = DFNTF_LEIEEE;
734 cfile->iconvert = DFNTI_IBO ;
735 break;
736 case DFNTF_VAX:
737 cfile->fconvert = DFNTF_VAX ;
738 cfile->iconvert = DFNTI_IBO ;
739 break;
740 case DFNTF_CONVEXNATIVE:
741 cfile->fconvert = DFNTF_CONVEXNATIVE ;
742 cfile->iconvert = DFNTI_MBO ;
743 break;
744 default:
745 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_BadMode),
746 "ccp4_file_setbyte", NULL);
747 result = 0;
748 }
749 return result;
750 }
751
752 /**
753 * ccp4_file_byte:
754 * @param cfile (CCP4File *)
755 *
756 * get byte ordering for file
757 * @return byte ordering information
758 */
ccp4_file_byte(CCP4File * cfile)759 int ccp4_file_byte(CCP4File *cfile)
760 {
761 return (cfile->fconvert | (cfile->iconvert<<8));
762 }
763
764 /**
765 * ccp4_file_open_file:
766 * @param file (const FILE *) FILE struct
767 * @param flag (const int) io mode (O_RDONLY =0, O_WRONLY =1, O_RDWR =2,
768 * O_TMP =, O_APPEND =)
769 *
770 * open @cfile with existing handle FILE struct file and mode @flag.
771 * The struct stat is check to determine if file is a regular file,
772 * if it is, and is not stdin, it is assumed to be direct access.
773 * @return (CCP4File *) on success, NULL on failure
774 */
ccp4_file_open_file(const FILE * file,const int flag)775 CCP4File *ccp4_file_open_file (const FILE *file, const int flag)
776 {
777 CCP4File *cfile;
778 #if defined _MSC_VER
779 struct _stat st;
780 #else
781 struct stat st;
782 #endif
783
784 if (!file) {
785 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
786 "ccp4_file_open_file", NULL);
787 return NULL; }
788
789 if (!(cfile = _file_init() ) ) {
790 ccp4_signal(CCP4_ERRLEVEL(3),
791 "ccp4_file_open_file", NULL);
792 return NULL; }
793
794 /* set values in structure */
795 _file_open_mode(cfile,flag);
796 cfile->stream = (FILE *) file;
797 cfile->buffered = 1;
798 cfile->open = 1;
799
800 #if defined _MSC_VER
801 _fstat(_fileno(cfile->stream), &st);
802 if ( !(st.st_mode & S_IFREG) || file == stdin) {
803 #else
804 fstat(fileno(cfile->stream), &st);
805 if ( !S_ISREG(st.st_mode) || file == stdin ) {
806 #endif
807 cfile->length = INT_MAX;
808 cfile->direct = 0;
809 } else {
810 cfile->length = st.st_size;
811 cfile->direct = 1;
812 }
813 cfile->loc = ftell( (FILE *)file);
814
815 return cfile;
816 }
817
818 /**
819 * ccp4_file_open_fd:
820 * @param fd (const int) file descriptor
821 * @param flag (const int) io mode (O_RDONLY =0, O_WRONLY =1, O_RDWR =2,
822 * O_TMP =, O_APPEND =)
823 *
824 * initialise CCP4File struct with file descriptor @fd and mode @flag
825 * The struct stat is check to determine if file is a regular file,
826 * if it is, and is not stdin, it is assumed to be direct access.
827 * @return (CCP4File *) on success, NULL on failure
828 */
829 CCP4File *ccp4_file_open_fd (const int fd, const int flag)
830 {
831 CCP4File * cfile;
832 #if defined _MSC_VER
833 struct _stat st;
834 #else
835 struct stat st;
836 #endif
837
838 if (!(cfile = _file_init() ) ) {
839 ccp4_signal(CCP4_ERRLEVEL(3),
840 "ccp4_file_open_fd", NULL);
841 return NULL; }
842
843 _file_open_mode(cfile, flag);
844 cfile->fd = fd;
845 cfile->open = 1;
846 cfile->buffered = 0;
847
848 #if defined _MSC_VER
849 _fstat(fd, &st);
850 if ( !(st.st_mode & S_IFREG) || fd == 0) {
851 #else
852 fstat(fd, &st);
853 if ( !S_ISREG(st.st_mode) || fd == 0 ) {
854 #endif
855 cfile->length = INT_MAX;
856 cfile->direct = 0;
857 cfile->loc = 0;
858 } else {
859 cfile->length = st.st_size;
860 cfile->direct = 1;
861 #if defined _MSC_VER
862 cfile->loc = _lseek(fd, 0L, SEEK_CUR);
863 #else
864 cfile->loc = lseek(fd, 0L, SEEK_CUR);
865 #endif
866 }
867
868 return cfile;
869 }
870
871 /**
872 * ccp4_file_open:
873 * @param filename (const char *) filename
874 * @param flag (const int) i/o mode, possible values are O_RDONLY, O_WRONLY,
875 * O_RDWR, O_APPEND, O_TMP, O_CREAT, O_TRUNC - see ccp4_sysdep.h
876 *
877 * initialise CCP4File struct for file filename with mode @flag.
878 * If !buffered use open(), otherwise fopen()
879 * The struct stat is check to determine if file is a regular file,
880 * if it is, and is not stdin, it is assumed to be direct access.
881 *
882 * @return (CCP4File *) on success, NULL on failure
883 */
884 CCP4File *ccp4_file_open (const char *filename, const int flag)
885 {
886 CCP4File *cfile;
887 int openflags = O_RDONLY;
888 char fmode[5];
889 #if defined _MSC_VER
890 struct _stat st;
891 #else
892 struct stat st;
893 #endif
894
895 if (!(cfile = _file_init())) {
896 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_open", NULL);
897 return NULL; }
898 _file_open_mode(cfile, flag);
899
900 if (!cfile->buffered) {
901 if (cfile->read && cfile->write) openflags = (O_RDWR | O_CREAT);
902 else if (cfile->write) openflags = (O_WRONLY | O_CREAT);
903 if (cfile->append) openflags |= O_APPEND;
904 if (flag & O_TRUNC) openflags |= O_TRUNC;
905 #if defined _MSC_VER
906 if (cfile->scratch) openflags |= O_TEMPORARY;
907 #endif
908 #if defined(__DECC) && defined(VMS) || defined (_MSC_VER)
909 openflags |= O_BINARY;
910 #endif
911 #if defined _MSC_VER
912 cfile->fd = _open(filename, openflags);
913 #else
914 cfile->fd = open(filename, openflags);
915 #endif
916 if (cfile->fd == -1) {
917 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_CantOpenFile),
918 "ccp4_file_open1", NULL);
919 return NULL;
920 } else {
921 #if defined _MSC_VER
922 _fstat(cfile->fd, &st); }
923 #else
924 fstat(cfile->fd, &st); }
925 #endif
926 } else {
927 char *mptr = fmode;
928 if (cfile->append) {
929 *mptr++ = 'a';
930 if (cfile->read) *mptr++ = '+';
931 } else {
932 if (cfile->read && cfile->write) {
933 if (flag & O_TRUNC) {*mptr++ = 'w'; }
934 else *mptr++ = 'r';
935 *mptr++ = '+';
936 } else if (cfile->write)
937 *mptr++ = 'w';
938 else
939 *mptr++ = 'r';
940 }
941 #if defined(__DECC) && defined(VMS) || defined (_WIN32)
942 *mptr++ = 'b';
943 #endif
944 *mptr++ = '\0';
945
946 #ifdef VMS
947 if (cfile->scratch)
948 cfile->stream = fopen (filename, fmode,
949 "mbc=16", /* bigger blocksize */
950 "fop=tmd"); /* temporary, delete on close */
951 else
952 cfile->stream = fopen (filename, fmode,
953 "mbc=16", /* bigger blocksize */
954 "ctx=stm", "mrs=0", "rat=cr", "rfm=stmlf");
955 #elif defined(_WIN32)
956 if (cfile->scratch) {
957 cfile->stream = tmpfile();
958 if (!cfile->stream) {
959 ccp4_signal(CCP4_ERRLEVEL(2) | CCP4_ERRNO(CIO_CantOpenFile),
960 "tmpfile() failed, opening normal file instead.", NULL);
961 cfile->stream = fopen (filename, fmode);
962 }
963 }
964 else
965 cfile->stream = fopen (filename, fmode);
966 #else
967 cfile->stream = fopen (filename, fmode);
968 if (cfile->stream)
969 if (cfile->scratch && unlink (filename)!=0) {
970 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_UnlinkFail),
971 "ccp4_file_open(unlink)", NULL);
972 cfile->iostat = CIO_UnlinkFail; return NULL; }
973 #endif
974 if (!cfile->stream) {
975 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_CantOpenFile),
976 "ccp4_file_open2", NULL);
977 cfile->iostat = CIO_CantOpenFile;
978 free(cfile);
979 return NULL; }
980 #if defined (__alpha) && defined (vms)
981 (void) fflush (cfile->stream);
982 #endif
983 #if defined _MSC_VER
984 _fstat(_fileno(cfile->stream), &st);
985 #else
986 fstat(fileno(cfile->stream), &st);
987 #endif
988 }
989 #if defined _MSC_VER
990 cfile->name = _strdup(filename);
991 #else
992 cfile->name = strdup(filename);
993 #endif
994 cfile->open = 1;
995 cfile->own = 1;
996 #if defined _MSC_VER
997 if ( !(st.st_mode & S_IFREG) ) {
998 #else
999 if ( !S_ISREG(st.st_mode) ) {
1000 #endif
1001 cfile->length = INT_MAX;
1002 cfile->direct = 0;
1003 } else {
1004 cfile->length = st.st_size;
1005 cfile->direct = 1;
1006 }
1007 cfile->loc = cfile->append ? cfile->length : 0;
1008
1009 return cfile;
1010 }
1011
1012 /**
1013 * ccp4_file_close:
1014 * @param cfile (CCP4File *)
1015 *
1016 * close @cfile if owned, close (non-buffered) or
1017 * fclose (buffered), or fflush if stream not owned.
1018 * Free resources.
1019 * @return 0 on success, EOF on failure
1020 */
1021 int ccp4_file_close (CCP4File *cfile)
1022 {
1023
1024 if (!cfile) {
1025 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_NullPtr),
1026 "ccp4_file_close", NULL);
1027 return EOF; }
1028
1029 if (_file_close (cfile) == EOF) {
1030 ccp4_signal(CCP4_ERRLEVEL(3),"ccp4_file_close", NULL);
1031 return EOF; }
1032
1033 _file_free(cfile);
1034
1035 return (0);
1036 }
1037
1038 /**
1039 * ccp4_file_rarch:
1040 * @param cfile (CCP4File *)
1041 *
1042 * read machine stamp from file @cfile->stream.
1043 * The machine stamp is at @cfile->stamp_loc items, set
1044 * by ccp4_file_setstamp() (default 0).
1045 * NB. these values may be overrriden with the environmental
1046 * variable CONVERT_FROM.
1047 * @return fileFT | (fileIT<<8)
1048 */
1049 int ccp4_file_rarch (CCP4File *cfile)
1050 {
1051 unsigned char mtstring[4]; /* machine stamp */
1052 char *native = getenv ("NATIVEMTZ");
1053 char *foreign = getenv ("CONVERT_FROM");
1054
1055 if (!cfile) {
1056 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_NullPtr),
1057 "ccp4_file_rarch", NULL);
1058 return EOF; }
1059
1060 if (native != NULL) return (nativeFT | (nativeIT<<8));
1061 if (foreign == NULL) {
1062 if (ccp4_file_raw_seek(cfile, cfile->stamp_loc, SEEK_SET) == -1) {
1063 ccp4_signal(CCP4_ERRLEVEL(3),"ccp4_file_rarch", NULL);
1064 return EOF; }
1065
1066 if (ccp4_file_raw_read(cfile, (char *) mtstring, 4UL) != 4) {
1067 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_rarch", NULL);
1068 return EOF; }
1069
1070 cfile->iconvert = (mtstring[1]>>4) & 0x0f;
1071 cfile->fconvert = (mtstring[0]>>4) & 0x0f;
1072
1073 /* iconvert and fconvert should be one of the DFNTI/DFNTF values listed
1074 in ccp4_sysdep.h and hence non-zero. Some machine stamps can be corrupted
1075 (e.g. mrc files from chimera). We try to trap for this, and revert to
1076 native. */
1077 if (cfile->iconvert == 0 || cfile->fconvert == 0) {
1078 if (ccp4_liberr_verbosity(-1))
1079 printf("Warning: Machine stamp corrupted? Assuming native format. \n");
1080 cfile->iconvert = nativeIT;
1081 cfile->fconvert = nativeFT;
1082 }
1083 }
1084
1085 return (cfile->fconvert | (cfile->iconvert<<8));
1086 }
1087
1088 /**
1089 * ccp4_file_warch:
1090 * @param cfile (CCP4File *)
1091 *
1092 * write machine stamp to file @cfile->stream.
1093 * The machine stamp is placed at @cfile->stamp_loc items,
1094 * set by ccp4_file_setstamp() (defaults to 0).
1095 *
1096 * @return 0 on success, EOF on failure
1097 */
1098 int ccp4_file_warch (CCP4File *cfile)
1099 {
1100 unsigned char mtstring[4]; /* machine stamp */
1101
1102 if (!cfile) {
1103 ccp4_signal(CCP4_ERRLEVEL(3)| CCP4_ERRNO(CIO_NullPtr),
1104 "ccp4_file_warch", NULL);
1105 return EOF; }
1106
1107 if (ccp4_file_raw_seek(cfile, cfile->stamp_loc, SEEK_SET) == -1) {
1108 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_warch", NULL);
1109 return EOF; }
1110
1111 mtstring[0] = cfile->fconvert | (cfile->fconvert << 4);
1112 mtstring[1] = 1 | (cfile->iconvert << 4);
1113 mtstring[2] = mtstring[3] = 0;
1114
1115 if (ccp4_file_raw_write(cfile, (const char *) mtstring, 4) != 4) {
1116 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_warch", NULL);
1117 return EOF; }
1118
1119 return 0;
1120 }
1121
1122 /**
1123 * ccp4_file_read:
1124 * @param cfile (CCP4File *)
1125 * @param buffer (uint8 *) buffer
1126 * @param nitems (size_t) number of items
1127 *
1128 * mode dependent read function. Reads @nitems items from stream
1129 * @cfile->stream to @buffer as determined by cfile->mode.
1130 *
1131 * @return number of items read on success, EOF on failure
1132 */
1133 int ccp4_file_read (CCP4File *cfile, uint8 *buffer, size_t nitems)
1134 {
1135 int result;
1136
1137 result = cfile->_read(cfile,(uint8 *) buffer,nitems);
1138
1139 if (result != nitems)
1140 ccp4_signal(CCP4_ERRLEVEL(3),
1141 "ccp4_file_read", NULL);
1142 return (result);
1143 }
1144
1145 /**
1146 * ccp4_file_readcomp:
1147 * @param cfile (CCP4File *)
1148 * @param buffer (uint8 *) buffer
1149 * @param nitems (size_t) number of items
1150 *
1151 * float complex {float,float} read function. Reads @nitems complex from stream
1152 * @cfile->stream to @buffer. Allows short count when eof is detected (
1153 * buffered input only).
1154 *
1155 * @return number of complex read on success, EOF on failure
1156 */
1157 int ccp4_file_readcomp (CCP4File *cfile, uint8 *buffer, size_t nitems)
1158 {
1159 int i, n, result;
1160
1161 if (!cfile) {
1162 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1163 "ccp4_file_readcomp", NULL);
1164 return EOF; }
1165
1166 if ( !cfile->read || cfile->iostat) {
1167 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1168 "ccp4_file_readcomp", NULL);
1169 return EOF; }
1170
1171 if (cfile->last_op == WRITE_OP)
1172 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1173 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readcomp", NULL);
1174 return EOF; }
1175
1176 n = _item_sizes[COMP64] * nitems;
1177 if ( (result = ccp4_file_raw_read (cfile, (char *) buffer, n)) != n) {
1178 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readcomp", NULL);
1179 if (cfile->stream && !feof(cfile->stream))
1180 return EOF; } /* short count on stream is OK if EOF */
1181
1182 result /= _item_sizes[COMP64];
1183 n = result;
1184 if (cfile->fconvert != nativeFT) {
1185 n *= 2; /* pairs of reals */
1186 switch (cfile->fconvert) { /* get to BE IEEE */
1187 case DFNTF_VAX :
1188 vaxF2ieeeF((union float_uint_uchar *) buffer, n);
1189 break;
1190 case DFNTF_CONVEXNATIVE :
1191 convexF2ieeeF((union float_uint_uchar *) buffer, n);
1192 break;
1193 case DFNTF_BEIEEE :
1194 break;
1195 case DFNTF_LEIEEE :
1196 {
1197 char j;
1198 for (i=0; i < n*4; i+=4) {
1199 j = buffer[i];
1200 buffer[i] = buffer[i+3];
1201 buffer[i+3] = j;
1202 j = buffer[i+1];
1203 buffer[i+1] = buffer[i+2];
1204 buffer[i+2] =j; }
1205 }
1206 break;
1207 default :
1208 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1209 "ccp4_file_readcomp", NULL);
1210 return EOF;
1211 }
1212 switch (nativeFT) { /* get to Native if not BE IEEE */
1213 case DFNTF_BEIEEE :
1214 break;
1215 case DFNTF_LEIEEE :
1216 {
1217 char j;
1218 for (i=0; i < n*4; i+=4) {
1219 j = buffer[i];
1220 buffer[i] = buffer[i+3];
1221 buffer[i+3] = j;
1222 j = buffer[i+1];
1223 buffer[i+1] = buffer[i+2];
1224 buffer[i+2] =j; }
1225 }
1226 break;
1227 case DFNTF_CONVEXNATIVE :
1228 ieeeF2convexF((union float_uint_uchar *) buffer, n);
1229 break;
1230 case DFNTF_VAX :
1231 ieeeF2vaxF((union float_uint_uchar *) buffer, n);
1232 break;
1233 default :
1234 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1235 "ccp4_file_readcomp", NULL);
1236 return EOF;
1237 }
1238 }
1239 return (result);
1240 }
1241
1242 /**
1243 * ccp4_file_readshortcomp:
1244 * @param cfile (CCP4File *)
1245 * @param buffer (uint8 *) buffer
1246 * @param nitems (size_t) number of items
1247 *
1248 * short complex {short,short} read function. Reads @nitems complex from stream
1249 * @cfile->stream to @buffer. Allows short count when eof is detected (
1250 * buffered input only).
1251 *
1252 * @return number of complex read on success, EOF on failure
1253 */
1254 int ccp4_file_readshortcomp (CCP4File *cfile, uint8 *buffer, size_t nitems)
1255 {
1256 int i, n, result;
1257
1258 if (!cfile) {
1259 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1260 "ccp4_file_readshortcomp", NULL);
1261 return EOF; }
1262
1263 if ( !cfile->read || cfile->iostat) {
1264 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1265 "ccp4_file_readshortcomp", NULL);
1266 return EOF; }
1267
1268 if (cfile->last_op == WRITE_OP)
1269 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1270 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readshortcomp", NULL);
1271 return EOF; }
1272
1273 n = _item_sizes[COMP32] * nitems;
1274 if ( (result = ccp4_file_raw_read (cfile, (char *) buffer, n)) != n) {
1275 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readshortcomp", NULL);
1276 if (cfile->stream && !feof(cfile->stream))
1277 return EOF; }
1278
1279 result /= _item_sizes[COMP32];
1280
1281 n = result;
1282 if (cfile->iconvert != nativeIT) {
1283 n *= 2; /* pairs of ints */
1284 {
1285 if ((cfile->iconvert==DFNTI_MBO && nativeIT==DFNTI_IBO) ||
1286 (cfile->iconvert==DFNTI_IBO && nativeIT==DFNTI_MBO)) {
1287 char j;
1288 for (i=0; i < n*2; i+=2) {
1289 j = buffer[i];
1290 buffer[i] = buffer[i+1];
1291 buffer[i+1] = j; } }
1292 else {
1293 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1294 "ccp4_file_readshortcomp", NULL);
1295 return EOF; }
1296 }
1297 }
1298 return (result);
1299 }
1300
1301 /**
1302 * ccp4_file_readfloat:
1303 * @param cfile (CCP4File *)
1304 * @param buffer (uint8 *) buffer
1305 * @param nitems (size_t) number of items
1306 *
1307 * float read function. Reads @nitems floats from stream
1308 * @cfile->stream to @buffer.
1309 *
1310 * @return number of floats read on success, EOF on failure
1311 */
1312 int ccp4_file_readfloat (CCP4File *cfile, uint8 *buffer, size_t nitems)
1313 {
1314 int i, n, result;
1315
1316 if (!cfile) {
1317 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1318 "ccp4_file_readfloat", NULL);
1319 return EOF; }
1320
1321 if (!cfile->read || cfile->iostat) {
1322 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1323 "ccp4_file_readfloat", NULL);
1324 return EOF; }
1325
1326 if (cfile->last_op == WRITE_OP)
1327 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1328 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readfloat", NULL);
1329 return EOF; }
1330
1331 n = _item_sizes[FLOAT32] * nitems;
1332 if ( (result = ccp4_file_raw_read (cfile, (char *) buffer, n)) != n) {
1333 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readfloat", NULL);
1334 if (cfile->stream && !feof(cfile->stream))
1335 return EOF; }
1336
1337 result /= _item_sizes[FLOAT32];
1338
1339 n = result;
1340 if (cfile->fconvert != nativeFT) {
1341 switch (cfile->fconvert) { /* get to BE IEEE */
1342 case DFNTF_VAX :
1343 vaxF2ieeeF((union float_uint_uchar *) buffer, n);
1344 break;
1345 case DFNTF_CONVEXNATIVE :
1346 convexF2ieeeF((union float_uint_uchar *) buffer, n);
1347 break;
1348 case DFNTF_BEIEEE :
1349 break;
1350 case DFNTF_LEIEEE :
1351 {
1352 char j;
1353 for (i=0; i < n*4; i+=4) {
1354 j = buffer[i];
1355 buffer[i] = buffer[i+3];
1356 buffer[i+3] = j;
1357 j = buffer[i+1];
1358 buffer[i+1] = buffer[i+2];
1359 buffer[i+2] =j; }
1360 }
1361 break;
1362 default :
1363 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1364 "ccp4_file_readfloat", NULL);
1365 return EOF;
1366 }
1367 switch (nativeFT) {
1368 case DFNTF_BEIEEE :
1369 break; /* done enough */
1370 case DFNTF_LEIEEE :
1371 {
1372 char j;
1373 for (i=0; i < n*4; i+=4) {
1374 j = buffer[i];
1375 buffer[i] = buffer[i+3];
1376 buffer[i+3] = j;
1377 j = buffer[i+1];
1378 buffer[i+1] = buffer[i+2];
1379 buffer[i+2] =j; }
1380 }
1381 break;
1382 case DFNTF_CONVEXNATIVE :
1383 ieeeF2convexF((union float_uint_uchar *) buffer, n);
1384 break;
1385 case DFNTF_VAX :
1386 ieeeF2vaxF((union float_uint_uchar *) buffer, n);
1387 break;
1388 default :
1389 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1390 "ccp4_file_readfloat", NULL);
1391 return EOF;
1392 }
1393 }
1394 return (result);
1395 }
1396
1397 /**
1398 * ccp4_file_readint:
1399 * @param cfile (CCP4File *)
1400 * @param buffer (uint8 *) buffer
1401 * @param nitems (size_t) number of items
1402 *
1403 * integer read function. Reads @nitems int from stream
1404 * @cfile->stream to @buffer.
1405 *
1406 * @return number of int read on success, EOF on failure
1407 */
1408 int ccp4_file_readint (CCP4File *cfile, uint8 *buffer, size_t nitems)
1409 {
1410 int n, result;
1411
1412 if (!cfile) {
1413 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1414 "ccp4_file_readint", NULL);
1415 return EOF; }
1416
1417 if ( !cfile->read || cfile->iostat) {
1418 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1419 "ccp4_file_readint", NULL);
1420 return EOF; }
1421
1422 if (cfile->last_op == WRITE_OP)
1423 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1424 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readint", NULL);
1425 return EOF; }
1426
1427 n = _item_sizes[CCP4_INT32] * nitems;
1428 if ( (result = ccp4_file_raw_read (cfile, (char *) buffer, n)) != n) {
1429 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readint", NULL);
1430 if (cfile->stream && !feof(cfile->stream))
1431 return EOF; }
1432
1433 result /= _item_sizes[CCP4_INT32];
1434
1435 n = result;
1436
1437 if (cfile->iconvert != nativeIT) {
1438 if ((cfile->iconvert==DFNTI_MBO && nativeIT==DFNTI_IBO) ||
1439 (cfile->iconvert==DFNTI_IBO && nativeIT==DFNTI_MBO)) {
1440 char j;
1441 int i;
1442 for (i=0; i < n*4; i+=4) {
1443 j = buffer[i];
1444 buffer[i] = buffer[i+3];
1445 buffer[i+3] = j;
1446 j = buffer[i+1];
1447 buffer[i+1] = buffer[i+2];
1448 buffer[i+2] =j; }
1449 } else {
1450 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1451 "ccp4_file_readint", NULL);
1452 return EOF; }
1453 }
1454 return (result);
1455 }
1456
1457 /**
1458 * ccp4_file_readshort:
1459 * @param cfile (CCP4File *)
1460 * @param buffer (uint8 *) buffer
1461 * @param nitems (size_t) number of items
1462 *
1463 * short read function. Reads @nitems shorts from stream
1464 * @cfile->stream to @buffer.
1465 *
1466 * @return number of shorts read on success, EOF on failure
1467 */
1468 int ccp4_file_readshort (CCP4File *cfile, uint8 *buffer, size_t nitems)
1469 {
1470 int n, result;
1471
1472 if (!cfile) {
1473 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1474 "ccp4_file_readshort", NULL);
1475 return EOF; }
1476
1477 if (!cfile->read || cfile->iostat) {
1478 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1479 "ccp4_file_readshort", NULL);
1480 return EOF; }
1481
1482 if (cfile->last_op == WRITE_OP)
1483 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1484 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readshort", NULL);
1485 return EOF; }
1486
1487 n = _item_sizes[CCP4_INT16] * nitems;
1488 if ( (result = ccp4_file_raw_read (cfile, (char *) buffer, n)) != n) {
1489 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readshort", NULL);
1490 if (cfile->stream && !feof(cfile->stream))
1491 return EOF; }
1492
1493 result /= _item_sizes[CCP4_INT16];
1494
1495 n = result;
1496 if (cfile->iconvert != nativeIT) {
1497 if ((cfile->iconvert==DFNTI_MBO && nativeIT==DFNTI_IBO) ||
1498 (cfile->iconvert==DFNTI_IBO && nativeIT==DFNTI_MBO)) {
1499 char j;
1500 int i;
1501 for (i=0; i < n*2; i+=2) {
1502 j = buffer[i];
1503 buffer[i] = buffer[i+1];
1504 buffer[i+1] = j; }
1505 } else {
1506 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1507 "ccp4_file_readshort", NULL);
1508 return EOF; }
1509 }
1510 return (result);
1511 }
1512
1513 /**
1514 * ccp4_file_readchar:
1515 * @param cfile (CCP4File *)
1516 * @param buffer (uint8 *) buffer
1517 * @param nitems (size_t) number of items
1518 *
1519 * character read function. Reads @nitems characters from stream
1520 * @cfile->stream to @buffer.
1521 *
1522 * @return number of characters read on success, EOF on failure
1523 */
1524 int ccp4_file_readchar (CCP4File *cfile, uint8 *buffer, size_t nitems)
1525 {
1526 size_t result;
1527
1528 if (! cfile) {
1529 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1530 "ccp4_file_readchar", NULL);
1531 return EOF; }
1532
1533 if (!cfile->read || cfile->iostat) {
1534 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1535 "ccp4_file_readchar", NULL);
1536 return EOF; }
1537
1538 if (cfile->last_op == WRITE_OP)
1539 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1540 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readchar", NULL);
1541 return EOF; }
1542
1543 if ( (result = ccp4_file_raw_read (cfile, (char *) buffer, nitems)) != nitems) {
1544 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_readchar", NULL);
1545 if (cfile->stream && !feof(cfile->stream))
1546 return EOF; }
1547
1548 return (result);
1549 }
1550
1551 /**
1552 * ccp4_file_write:
1553 * @param cfile (CCP4File *)
1554 * @param buffer (uint8 *) buffer
1555 * @param nitems (size_t) number of items
1556 *
1557 * mode dependent write function. Write @nitems items from @buffer
1558 * to @cfile->stream as determined by cfile->mode.
1559 *
1560 * @return number of items written on success, EOF on failure
1561 */
1562 int ccp4_file_write (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1563 {
1564 size_t result;
1565
1566 result = cfile->_write(cfile, buffer, nitems);
1567
1568 if ( result != nitems)
1569 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_write", NULL);
1570
1571 return (result);
1572 }
1573
1574 /**
1575 * ccp4_file_writecomp:
1576 * @param cfile (CCP4File *)
1577 * @param buffer (uint8 *) buffer
1578 * @param nitems (size_t) number of items
1579 *
1580 * complex {float,float} write function. Write @nitems items from @buffer
1581 * to @cfile->stream.
1582 *
1583 * @return number of complex items written on success, EOF on failure
1584 */
1585 int ccp4_file_writecomp (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1586 {
1587 size_t result = 0, n;
1588
1589 if (!cfile) {
1590 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1591 "ccp4_file_writecomp", NULL);
1592 return EOF; }
1593
1594 if (!cfile->write ||cfile->iostat) {
1595 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1596 "ccp4_file_writecomp", NULL);
1597 return EOF;}
1598
1599 if (cfile->last_op == READ_OP)
1600 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1601 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writecomp", NULL);
1602 return EOF; }
1603
1604 n = nitems * _item_sizes[COMP64];
1605
1606 if (cfile->fconvert != nativeFT) {
1607 char out_buffer[8];
1608 const char *out_ptr = (char *) buffer;
1609 size_t i;
1610 for (i = 0; i != nitems; i++) {
1611 switch (nativeFT) {
1612 case DFNTF_BEIEEE :
1613 memcpy(out_buffer, out_ptr, _item_sizes[COMP64]);
1614 out_ptr += _item_sizes[COMP64];
1615 break;
1616 case DFNTF_LEIEEE :
1617 out_buffer[3] = *out_ptr++;
1618 out_buffer[2] = *out_ptr++;
1619 out_buffer[1] = *out_ptr++;
1620 out_buffer[0] = *out_ptr++;
1621 out_buffer[7] = *out_ptr++;
1622 out_buffer[6] = *out_ptr++;
1623 out_buffer[5] = *out_ptr++;
1624 out_buffer[4] = *out_ptr++;
1625 break;
1626 case DFNTF_CONVEXNATIVE :
1627 memcpy(out_buffer, out_ptr, _item_sizes[COMP64]);
1628 out_ptr += _item_sizes[COMP64];
1629 ieeeF2convexF((union float_uint_uchar *) out_buffer, 2);
1630 break;
1631 case DFNTF_VAX :
1632 memcpy(out_buffer, out_ptr, _item_sizes[COMP64]);
1633 out_ptr += _item_sizes[COMP64];
1634 ieeeF2vaxF((union float_uint_uchar *) out_buffer, 2);
1635 break;
1636 default :
1637 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1638 "CCP4_File::writecomp", NULL);
1639 }
1640 switch (cfile->fconvert) {
1641 case DFNTF_VAX :
1642 vaxF2ieeeF((union float_uint_uchar *) out_buffer, 2);
1643 break;
1644 case DFNTF_CONVEXNATIVE :
1645 convexF2ieeeF((union float_uint_uchar *) out_buffer, 2);
1646 break;
1647 case DFNTF_BEIEEE :
1648 break;
1649 case DFNTF_LEIEEE :
1650 {
1651 char j;
1652 j = out_buffer[0];
1653 out_buffer[0] = out_buffer[3];
1654 out_buffer[3] = j;
1655 j = out_buffer[1];
1656 out_buffer[1] = out_buffer[2];
1657 out_buffer[2] =j;
1658 j = out_buffer[4];
1659 out_buffer[4] = out_buffer[7];
1660 out_buffer[7] = j;
1661 j = out_buffer[5];
1662 out_buffer[5] = out_buffer[6];
1663 out_buffer[6] =j;
1664 }
1665 break;
1666 default :
1667 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1668 "ccp4_file_writecomp", NULL);
1669 return EOF;
1670 }
1671 result += ccp4_file_raw_write (cfile, out_buffer, _item_sizes[COMP64]);
1672 }
1673 } else {
1674 result = ccp4_file_raw_write (cfile, (char *) buffer, n);
1675 }
1676
1677 if (result != n)
1678 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writecomp", NULL);
1679
1680 return (result / _item_sizes[COMP64]);
1681 }
1682
1683 /**
1684 * ccp4_file_writeshortcomp:
1685 * @param cfile (CCP4File *)
1686 * @param buffer (uint8 *) buffer
1687 * @param nitems (size_t) number of items
1688 *
1689 * short complex {short,short} write function. Write @nitems items from @buffer
1690 * to @cfile->stream.
1691 *
1692 * @return number of complex items written on success, EOF on failure
1693 */
1694 int ccp4_file_writeshortcomp (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1695 {
1696 size_t result = 0, n;
1697
1698 if (!cfile) {
1699 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1700 "ccp4_file_writeshortcomp", NULL);
1701 return EOF; }
1702
1703 if (!cfile->write ||cfile->iostat) {
1704 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1705 "ccp4_file_writeshortcomp", NULL);
1706 return EOF;}
1707
1708 if (cfile->last_op == READ_OP)
1709 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1710 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writeshortcomp", NULL);
1711 return EOF; }
1712
1713 n = nitems * _item_sizes[COMP32];
1714
1715 if (cfile->iconvert != nativeIT) {
1716 char out_buffer[4];
1717 const char *out_ptr = (char *) buffer;
1718 size_t i;
1719 for (i = 0; i != nitems; i++) {
1720 if ((cfile->iconvert==DFNTI_MBO && nativeIT==DFNTI_IBO) ||
1721 (cfile->iconvert==DFNTI_IBO && nativeIT==DFNTI_MBO)) {
1722 out_buffer[1] = *out_ptr++;
1723 out_buffer[0] = *out_ptr++;
1724 out_buffer[3] = *out_ptr++;
1725 out_buffer[2] = *out_ptr++;
1726 } else {
1727 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1728 "ccp4_file_writeshortcomp", NULL);
1729 return EOF; }
1730 result += ccp4_file_raw_write (cfile, out_buffer, _item_sizes[COMP32]);
1731 }
1732 } else {
1733 result = ccp4_file_raw_write (cfile, (char *) buffer, n);
1734 }
1735
1736 if ( result != n)
1737 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writeshortcomp", NULL);
1738
1739 return (result / _item_sizes[COMP32]);
1740 }
1741
1742 /**
1743 * ccp4_file_writefloat:
1744 * @param cfile (CCP4File *)
1745 * @param buffer (uint8 *) buffer
1746 * @param nitems (size_t) number of items
1747 *
1748 * float write function. Write @nitems items from @buffer
1749 * to @cfile->stream.
1750 *
1751 * Returns number of floats written on success, EOF on failure
1752 */
1753 int ccp4_file_writefloat (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1754 {
1755 size_t result = 0, n;
1756
1757 if (!cfile) {
1758 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1759 "ccp4_file_writefloat", NULL);
1760 return EOF; }
1761
1762 if (!cfile->write ||cfile->iostat) {
1763 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1764 "ccp4_file_writefloat", NULL);
1765 return EOF;}
1766
1767 if (cfile->last_op == READ_OP)
1768 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1769 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writefloat", NULL);
1770 return EOF; }
1771
1772 n = nitems * _item_sizes[FLOAT32];
1773
1774 if (cfile->fconvert != nativeFT) {
1775 char out_buffer[4];
1776 const char *out_ptr = (char *) buffer;
1777 size_t i;
1778 for (i = 0; i != nitems; i++) {
1779 switch (nativeFT) {
1780 case DFNTF_BEIEEE :
1781 memcpy(out_buffer, out_ptr, _item_sizes[FLOAT32]);
1782 out_ptr += _item_sizes[FLOAT32];
1783 break;
1784 case DFNTF_LEIEEE :
1785 out_buffer[3] = *out_ptr++;
1786 out_buffer[2] = *out_ptr++;
1787 out_buffer[1] = *out_ptr++;
1788 out_buffer[0] = *out_ptr++;
1789 break;
1790 case DFNTF_CONVEXNATIVE :
1791 memcpy(out_buffer, out_ptr, _item_sizes[FLOAT32]);
1792 out_ptr += _item_sizes[FLOAT32];
1793 ieeeF2convexF((union float_uint_uchar *) out_buffer, 1);
1794 break;
1795 case DFNTF_VAX :
1796 memcpy(out_buffer, out_ptr, _item_sizes[FLOAT32]);
1797 out_ptr += _item_sizes[FLOAT32];
1798 ieeeF2vaxF((union float_uint_uchar *) out_buffer, 1);
1799 break;
1800 default :
1801 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1802 "CCP4_File::writefloat", NULL);
1803 }
1804 switch (cfile->fconvert) {
1805 case DFNTF_VAX :
1806 vaxF2ieeeF((union float_uint_uchar *) out_buffer, 1);
1807 break;
1808 case DFNTF_CONVEXNATIVE :
1809 convexF2ieeeF((union float_uint_uchar *) out_buffer, 1);
1810 break;
1811 case DFNTF_BEIEEE :
1812 break;
1813 case DFNTF_LEIEEE :
1814 {
1815 char j;
1816 j = out_buffer[0];
1817 out_buffer[0] = out_buffer[3];
1818 out_buffer[3] = j;
1819 j = out_buffer[1];
1820 out_buffer[1] = out_buffer[2];
1821 out_buffer[2] =j;
1822 }
1823 break;
1824 default :
1825 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1826 "ccp4_file_writefloat", NULL);
1827 return EOF;
1828 }
1829 result += ccp4_file_raw_write (cfile, out_buffer, _item_sizes[FLOAT32]);
1830 }
1831 } else {
1832 result = ccp4_file_raw_write (cfile, (char *) buffer, n);
1833 }
1834
1835 if (result != n)
1836 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writefloat", NULL);
1837
1838 return (result / _item_sizes[FLOAT32]);
1839 }
1840
1841 /**
1842 * ccp4_file_writeint:
1843 * @param cfile (CCP4File *)
1844 * @param buffer (uint8 *) buffer
1845 * @param nitems (size_t) number of items
1846 *
1847 * int write function. Write @nitems items from @buffer
1848 * to @cfile->stream.
1849 *
1850 * @return number of int written on success, EOF on failure
1851 */
1852 int ccp4_file_writeint (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1853 {
1854 size_t result = 0, n;
1855
1856 if (!cfile) {
1857 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1858 "ccp4_file_writeint", NULL);
1859 return EOF; }
1860
1861 if (!cfile->write ||cfile->iostat) {
1862 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1863 "ccp4_file_writeint", NULL);
1864 return EOF;}
1865
1866 if (cfile->last_op == READ_OP)
1867 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1868 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writeint", NULL);
1869 return EOF; }
1870
1871 n = nitems * _item_sizes[CCP4_INT32];
1872
1873 if (cfile->iconvert != nativeIT) {
1874 char out_buffer[4];
1875 const char *out_ptr = (char *) buffer;
1876 size_t i;
1877 for (i = 0; i != nitems; i++) {
1878 if ((cfile->iconvert==DFNTI_MBO && nativeIT==DFNTI_IBO) ||
1879 (cfile->iconvert==DFNTI_IBO && nativeIT==DFNTI_MBO)) {
1880 out_buffer[3] = *out_ptr++;
1881 out_buffer[2] = *out_ptr++;
1882 out_buffer[1] = *out_ptr++;
1883 out_buffer[0] = *out_ptr++;
1884 } else {
1885 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1886 "ccp4_file_writeint", NULL);
1887 return EOF; }
1888 result += ccp4_file_raw_write (cfile, out_buffer, _item_sizes[CCP4_INT32]);
1889 }
1890 } else {
1891 result = ccp4_file_raw_write (cfile, (char *) buffer, n);
1892 }
1893
1894 if ( result != n)
1895 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writeint", NULL);
1896
1897 return (result / _item_sizes[CCP4_INT32]);
1898 }
1899
1900 /**
1901 * ccp4_file_writeshort:
1902 * @param cfile (CCP4File *)
1903 * @param buffer (uint8 *) buffer
1904 * @param nitems (size_t) number of items
1905 *
1906 * short write function. Write @nitems items from @buffer
1907 * to @cfile->stream.
1908 *
1909 * @return number of short written on success, EOF on failure
1910 */
1911 int ccp4_file_writeshort (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1912 {
1913 size_t result = 0, n;
1914
1915 if (!cfile) {
1916 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1917 "ccp4_file_writeshort", NULL);
1918 return EOF; }
1919
1920 if (!cfile->write ||cfile->iostat) {
1921 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1922 "ccp4_file_writeshort", NULL);
1923 return EOF;}
1924
1925 if (cfile->last_op == READ_OP)
1926 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1927 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writeshort", NULL);
1928 return EOF; }
1929
1930 n = nitems * _item_sizes[CCP4_INT16];
1931
1932 if (cfile->iconvert != nativeIT) {
1933 char out_buffer[2];
1934 const char *out_ptr = (char *) buffer;
1935 size_t i;
1936 for (i = 0; i != nitems; i++) {
1937 if ((cfile->iconvert==DFNTI_MBO && nativeIT==DFNTI_IBO) ||
1938 (cfile->iconvert==DFNTI_IBO && nativeIT==DFNTI_MBO)) {
1939 out_buffer[1] = *out_ptr++;
1940 out_buffer[0] = *out_ptr++;
1941 } else {
1942 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1943 "ccp4_file_readint", NULL);
1944 return EOF; }
1945 result += ccp4_file_raw_write (cfile, out_buffer, _item_sizes[CCP4_INT16]);
1946 }
1947 } else {
1948 result = ccp4_file_raw_write (cfile, (char *) buffer, n);
1949 }
1950
1951 if ( result != n)
1952 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writeshort", NULL);
1953
1954 return (result / _item_sizes[CCP4_INT16]);
1955 }
1956
1957 /**
1958 * ccp4_file_writechar:
1959 * @param cfile (CCP4File *)
1960 * @param buffer (uint8 *) buffer
1961 * @param nitems (size_t) number of items
1962 *
1963 * char write function. Write @nitems items from @buffer
1964 * to @cfile->stream.
1965 *
1966 * @return number of bytes written on success, EOF on failure
1967 */
1968 int ccp4_file_writechar (CCP4File *cfile, const uint8 *buffer, size_t nitems)
1969 {
1970 size_t result;
1971
1972 if (!cfile) {
1973 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
1974 "ccp4_file_writechar", NULL);
1975 return EOF; }
1976
1977 if (!cfile->write ||cfile->iostat) {
1978 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_BadMode),
1979 "ccp4_file_writechar", NULL);
1980 return EOF;}
1981
1982 if (cfile->last_op == READ_OP)
1983 if (ccp4_file_raw_seek(cfile,0L,SEEK_CUR) == -1) {
1984 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writechar", NULL);
1985 return EOF; }
1986
1987 if ( (result = ccp4_file_raw_write (cfile, (char *) buffer, nitems)) != nitems)
1988 ccp4_signal(CCP4_ERRLEVEL(3), "ccp4_file_writechar", NULL);
1989
1990 return (result);
1991 }
1992
1993 /**
1994 * ccp4_file_seek:
1995 * @param cfile (CCP4File *)
1996 * @param offset (long) offset in items
1997 * @param whence (int) SEEK_SET, SEEK_CUR, or SEEK_END
1998 *
1999 * seeks on file by offset items. SEEK_SET is relative
2000 * to start of file, SEEK_CUR to current, SEEK_END to
2001 * end.
2002 *
2003 * @return 0 on success, -1 on failure
2004 */
2005 int ccp4_file_seek (CCP4File *cfile, long offset, int whence)
2006 {
2007 int result;
2008
2009 if (!cfile) {
2010 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
2011 "ccp4_file_seek", NULL);
2012 return -1; }
2013
2014 result = ccp4_file_raw_seek(cfile, offset*cfile->itemsize, whence);
2015
2016 if (result != -1) ccp4_file_clearerr(cfile);
2017
2018 return ((result == -1) ? -1 : 0);
2019 }
2020
2021 /**
2022 * ccp4_file_rewind:
2023 * @param cfile (CCP4File *)
2024 *
2025 * Seek to start of file. Clear error status.
2026 *
2027 * @return 0 on success, EOF on failure
2028 */
2029 void ccp4_file_rewind (CCP4File *cfile)
2030 {
2031 if (!cfile) {
2032 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
2033 "ccp4_file_rewind", NULL);
2034 return ; }
2035
2036 if (ccp4_file_raw_seek(cfile, 0, SEEK_SET)) {
2037 ccp4_signal(CCP4_ERRLEVEL(3),
2038 "ccp4_file_rewind", NULL);
2039 } else {
2040 ccp4_file_clearerr(cfile);
2041 }
2042 }
2043
2044 /**
2045 * ccp4_file_length:
2046 * @param cfile (CCP4File *)
2047 *
2048 * Length of file on disk.
2049 * @return length of @cfile on success, EOF on failure
2050 */
2051 long ccp4_file_length (CCP4File *cfile)
2052 {
2053 #if defined _MSC_VER
2054 struct _stat st;
2055 #else
2056 struct stat st;
2057 #endif
2058
2059 if (!cfile) {
2060 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
2061 "ccp4_file_length", NULL);
2062 return EOF; }
2063
2064 cfile->last_op = IRRELEVANT_OP;
2065
2066 if (cfile->buffered && cfile->stream)
2067 fflush (cfile->stream);
2068 #if defined _MSC_VER
2069 _fstat(cfile->stream ? _fileno(cfile->stream) : cfile->fd, &st);
2070 #else
2071 fstat(cfile->stream ? fileno(cfile->stream) : cfile->fd, &st);
2072 #endif
2073 cfile->length = st.st_size;
2074
2075 return (st.st_size);
2076 }
2077
2078 /**
2079 * ccp4_file_tell:
2080 * @param cfile (CCP4File *)
2081 *
2082 * Current location in file, uses either ftell or lseek.
2083 * @return current offset of @cfile in bytes.
2084 */
2085 long ccp4_file_tell (CCP4File *cfile)
2086 {
2087 long result;
2088
2089 if (! cfile) {
2090 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
2091 "ccp4_file_tell", NULL);
2092 return EOF; }
2093
2094 cfile->last_op = IRRELEVANT_OP;
2095
2096 if (cfile->buffered && cfile->stream) {
2097 #if !defined (_MSC_VER)
2098 if ( cfile->last_op == WRITE_OP ) fflush (cfile->stream);
2099 #endif
2100 result = (long) ftell(cfile->stream);
2101 } else
2102 #if defined _MSC_VER
2103 result = _lseek(cfile->fd, 0L, SEEK_CUR);
2104 #else
2105 result = lseek(cfile->fd, 0L, SEEK_CUR);
2106 #endif
2107
2108 cfile->loc = result;
2109
2110 return (result);
2111 }
2112
2113 /**
2114 * ccp4_file_feof:
2115 * @param cfile (CCP4File *)
2116 *
2117 * @return true if @cfile is at EoF.
2118 *
2119 */
2120 int ccp4_file_feof(CCP4File *cfile)
2121 {
2122 if (!cfile) {
2123 ccp4_signal(CCP4_ERRLEVEL(3) | CCP4_ERRNO(CIO_NullPtr),
2124 "ccp4_file_feof", NULL);
2125 return EOF; }
2126
2127 return (cfile->stream) ? feof(cfile->stream) : cfile->loc >= cfile->length;
2128 }
2129
2130 /**
2131 * ccp4_file_clearerr:
2132 * @param cfile (CCP4File *)
2133 *
2134 * Clears error status of @cfile.
2135 *
2136 */
2137 void ccp4_file_clearerr(CCP4File *cfile)
2138 {
2139 if (!cfile || !cfile->stream)
2140 return;
2141 cfile->iostat = CIO_Ok;
2142 clearerr(cfile->stream);
2143 }
2144
2145 /**
2146 * ccp4_file_fatal:
2147 * @param cfile (CCP4File *)
2148 *
2149 * Die with error message based on @cfile error status.
2150 */
2151 void ccp4_file_fatal (CCP4File *cfile, char *message)
2152 {
2153 char *buff;
2154 size_t l;
2155
2156 if (!cfile)
2157 ccp4_signal(CCP4_ERRLEVEL(4) | CCP4_ERRNO(CIO_NullPtr), "ccp4_file_fatal",
2158 NULL);
2159
2160 l = strlen (message) + strlen (cfile->name) + 1;
2161 if ( !(buff = malloc(l)))
2162 ccp4_signal(CCP4_ERRLEVEL(4), "ccp4_file_fatal", NULL);
2163 buff[0] = '\0';
2164 strcat (buff, message);
2165 strcat (buff, cfile->name);
2166 ccp4_fatal(buff);
2167 }
2168
2169 /**
2170 * ccp4_file_error:
2171 * @param cfile (CCP4File *)
2172 *
2173 * print error mesage.
2174 * @return associated error code
2175 */
2176 int ccp4_file_error(CCP4File *cfile)
2177 {
2178 if (!cfile->iostat)
2179 return 0;
2180 fprintf(stderr,"%s %s \n",
2181 cfile->name,ccp4_strerror(cfile->iostat));
2182 return CCP4_ERRGETCODE(cfile->iostat);
2183 }
2184
2185 /**
2186 * ccp4_file_flush:
2187 * @param cfile (CCP4File *)
2188 *
2189 * flush buffer contents of @cfile
2190 */
2191 void ccp4_file_flush(CCP4File *cfile)
2192 {
2193 if (cfile && cfile->stream && cfile->buffered)
2194 fflush(cfile->stream);
2195 }
2196
2197 /**
2198 * ccp4_file_print:
2199 * @param cfile (CCP4File *)
2200 *
2201 * @return @cfile information in char array for printing.
2202 */
2203 char *ccp4_file_print(CCP4File *cfile, char *msg_start, char *msg_end)
2204 {
2205 char *msg_curr = msg_start;
2206
2207 if (!cfile)
2208 return msg_start;
2209
2210 if (cfile->name)
2211 if ((msg_end - msg_curr) > strlen(cfile->name)) {
2212 strcpy(msg_curr,cfile->name);
2213 msg_curr = strrchr(msg_curr,'\0'); }
2214
2215 if (cfile->open) {
2216 if ((msg_end - msg_curr) > 6 ) {
2217 strcat(msg_start, " opened");
2218 msg_curr = strrchr(msg_curr,'\0'); }
2219 } else {
2220 if ((msg_end - msg_curr) > 7 ) {
2221 strcat(msg_start, " closed");
2222 msg_curr = strrchr(msg_curr,'\0'); }
2223 }
2224
2225 if (cfile->append) {
2226 if ((msg_end - msg_curr) > 13 ) {
2227 strcat(msg_start, ", append mode");
2228 msg_curr = strrchr(msg_curr,'\0'); }
2229 } else if (cfile->read && cfile->write) {
2230 if ((msg_end - msg_curr) > 17 ) {
2231 strcat(msg_start, ", read-write mode");
2232 msg_curr = strrchr(msg_curr,'\0'); }
2233 } else if (cfile->write) {
2234 if ((msg_end - msg_curr) > 12 ) {
2235 strcat(msg_start, ", write mode");
2236 msg_curr = strrchr(msg_curr,'\0'); }
2237 } else {
2238 if ((msg_end - msg_curr) > 11 ) {
2239 strcat(msg_start, ", read mode");
2240 msg_curr = strrchr(msg_curr,'\0'); }
2241 }
2242
2243 return msg_curr;
2244 }
2245
2246