source: abuse/trunk/src/imlib/specs.cpp @ 481

Last change on this file since 481 was 481, checked in by Sam Hocevar, 12 years ago

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

File size: 20.8 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *
5 *  This software was released into the Public Domain. As with most public
6 *  domain software, no warranty is made or implied by Crack dot Com or
7 *  Jonathan Clark.
8 */
9
10#include "config.h"
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdint.h>
15#include <ctype.h>
16#include <fcntl.h>
17#include <math.h>
18#if (defined(__MACH__) || !defined(__APPLE__))
19#   include <sys/types.h>
20#   include <sys/stat.h>
21#endif
22
23#include "image.h"
24#include "palette.h"
25#include "specs.h"
26#include "system.h"
27#include "dprint.h"
28
29char const *spec_types[] =
30{
31    "Invalid type", // 0
32    "Color table",  // 1
33    "Palette",      // 2
34    "Invalid Type", // 3
35    "Image",        // 4
36    "Fore Tile",
37    "Back Tile",
38    "Character",
39    "8 Morph",
40    "16 Morph",
41    "Grue objs",
42    "Extern WAV",
43    "DMX MUS",
44    "Patched morph",
45    "Normal file",
46    "Compress1 file",
47    "Vector Image",
48    "Light list",
49    "Grue fgmap",
50    "Grue bgmap",
51    "Data array",
52    "Character2",
53    "Particle",
54    "Extern lcache"
55};
56
57
58int total_files_open=0;
59char spec_main_file[100];
60
61static char *spec_prefix=NULL;
62static char *save_spec_prefix=NULL;
63
64static jFILE spec_main_jfile((FILE*)0);
65static int spec_main_fd = -1;
66static long spec_main_offset = -1;
67static spec_directory spec_main_sd;
68
69static int fast_load_fd = -1;
70static int fast_load_mode = 0;
71
72void set_filename_prefix(char const *prefix)
73{
74    if( spec_prefix )
75    {
76        free( spec_prefix );
77    }
78   
79    if( prefix )
80    {
81        spec_prefix = strcpy( (char *)malloc( strlen( prefix ) + 2 ), prefix );
82        int len = strlen( prefix );
83        if( prefix[len - 1] != '\\' && prefix[len - 1] != '/')
84        {
85            spec_prefix[len] = '/';
86            spec_prefix[len + 1] = 0;
87        }
88    }
89    else
90    {
91        spec_prefix = NULL;
92    }
93}
94
95char *get_filename_prefix()
96{
97    return spec_prefix;
98}
99
100
101void set_save_filename_prefix(char const *save_prefix)
102{
103    if( save_spec_prefix )
104    {
105        free( save_spec_prefix );
106    }
107
108    if( save_prefix )
109    {
110        int len = strlen( save_prefix );
111        save_spec_prefix = (char *)malloc( len + 1 );
112        strcpy( save_spec_prefix, save_prefix );
113/* AK - Commented this out as it may cause problems
114        if( save_prefix[len - 1] != '\\' && save_prefix[len - 1] != '/' )
115        {
116            save_spec_prefix[len] = '/';
117            save_spec_prefix[len + 1] = '\0';
118        } */
119    }
120    else
121    {
122        save_spec_prefix = NULL;
123    }
124}
125
126char *get_save_filename_prefix()
127{
128  return save_spec_prefix;
129}
130
131int search_order=SPEC_SEARCH_OUTSIDE_INSIDE;
132
133static void (*no_space_handle_fun)()=NULL;
134
135void set_no_space_handler(void (*handle_fun)())
136{
137  no_space_handle_fun=handle_fun;
138}
139
140
141bFILE::bFILE()
142{
143  rbuf_size=8192;
144  rbuf=(unsigned char *)malloc(rbuf_size);
145  rbuf_start=rbuf_end=0;
146
147  wbuf_size=8192;
148  wbuf=(unsigned char *)malloc(wbuf_size);
149  wbuf_end=0;
150}
151
152bFILE::~bFILE()
153{
154  if (rbuf) free(rbuf);
155  flush_writes();
156  if (wbuf) free(wbuf);
157}
158
159int bFILE::flush_writes()
160{
161  if (wbuf_end!=0)
162  {
163    unsigned long ret=unbuffered_write(wbuf,wbuf_end);
164    if (ret!=wbuf_end && no_space_handle_fun)
165      no_space_handle_fun();
166
167    wbuf_end=0;
168    return ret;
169  }
170  return 0;
171}
172
173int bFILE::read(void *buf, size_t count)       // returns number of bytes read, calls unbuffer_read
174{
175  if (!allow_read_buffering())
176    return unbuffered_read(buf,count);
177
178  int total_read=0,error=0;
179  if (!count) return 0;
180  while (count && !error)
181  {
182    if (rbuf_start<rbuf_end)
183    {
184      unsigned int avail_size=rbuf_end-rbuf_start;
185      int copy_size=avail_size>count ? count : avail_size;
186      memcpy(buf,rbuf+rbuf_start,copy_size);
187      buf=(void *)(((unsigned char *)buf)+copy_size);
188      rbuf_start+=copy_size;
189      if (rbuf_start>=rbuf_end)
190      {
191                if (rbuf_end!=rbuf_size)  // buffer wasn't full before so there is no way we can complete read
192                  error=1;
193                rbuf_start=rbuf_end=0;
194      }
195      total_read+=copy_size;
196      count-=copy_size;
197    } else
198    {
199      rbuf_end=unbuffered_read(rbuf,rbuf_size);
200      if (rbuf_end==0) error=1;
201      rbuf_start=0;
202    }
203  }
204  return total_read;
205}
206
207
208int bFILE::write(void const *buf, size_t count)      // returns number of bytes written
209{
210  if (allow_write_buffering())
211  {
212    int total_written=0;
213    while (count)
214    {
215      int copy_size=wbuf_end+count<=wbuf_size ? count :  wbuf_size-wbuf_end;
216      memcpy(wbuf+wbuf_end,buf,copy_size);
217      wbuf_end+=copy_size;
218      count-=copy_size;
219      buf=(void *)(((char *)buf)+copy_size);
220      if (wbuf_end==wbuf_size)
221        if ((unsigned int)flush_writes()!=wbuf_size)
222      return total_written;
223
224      total_written+=copy_size;
225    }
226    return total_written;
227  } else
228  {
229    unsigned long ret=unbuffered_write(buf,count);
230    if (ret!=count && no_space_handle_fun)
231      no_space_handle_fun();
232  }
233  return 0;
234}
235
236int bFILE::seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
237{
238//    rbuf_start=rbuf_end=0;
239//    unbuffered_seek(offset,SEEK_SET);
240
241  long realpos=unbuffered_tell();
242  long curpos=realpos-rbuf_end+rbuf_start;
243  if (whence==SEEK_CUR) offset+=curpos;
244  else if (whence==SEEK_END) offset=file_size()-offset;
245
246  if (offset<realpos-(long)rbuf_end || offset>=realpos)
247  {
248    rbuf_start=rbuf_end=0;
249    unbuffered_seek(offset,SEEK_SET);
250  } else
251    rbuf_start=rbuf_end-(realpos-offset);
252  return 1;
253}
254
255int bFILE::tell()
256{
257  return unbuffered_tell()-rbuf_end+rbuf_start+
258         wbuf_end;    // if this a write file, add on how much we've written
259}
260
261int bFILE::allow_read_buffering() { return 1; }
262int bFILE::allow_write_buffering() { return 1; }
263
264void bFILE::set_read_buffer_size(long size)
265{
266  unbuffered_seek(tell(),SEEK_SET);
267  rbuf_start=rbuf_end=0;
268  if (rbuf)
269    free(rbuf);
270  rbuf_size=size;
271  rbuf=(unsigned char *)malloc(rbuf_size);
272}
273
274void set_spec_main_file(char const *filename, int Search_order)
275{
276  dprintf("Specs : main file set to %s\n",filename);
277  strcpy(spec_main_file,filename);
278  search_order=Search_order;
279
280#if (defined(__APPLE__) && !defined(__MACH__))
281  spec_main_jfile.open_external(filename,"rb",O_BINARY|O_RDONLY);
282#else
283  spec_main_jfile.open_external(filename,"rb",O_RDONLY);
284#endif
285  spec_main_fd = spec_main_jfile.get_fd();
286  if (spec_main_fd==-1)
287    return;
288  spec_main_sd.startup(&spec_main_jfile);
289}
290
291void fast_load_start_recording(char *filename)
292{
293    fast_load_fd = ::open(filename,O_CREAT|O_RDWR,S_IRWXU | S_IRWXG | S_IRWXO);
294    fast_load_mode = 1;
295}
296
297void fast_load_stop_recording()
298{
299    fast_load_mode = 0;
300}
301
302void fast_load_start_reloading(char *filename)
303{
304    fast_load_fd = ::open(filename,O_RDONLY);
305    fast_load_mode = 2;
306}
307
308void fast_load_stop_reloading()
309{
310    fast_load_mode = 0;
311}
312
313jFILE::jFILE(FILE *file_pointer)                       // assumes fp is at begining of file
314{
315  access=0;
316  fd=-1;
317  file_length=0;
318  start_offset=0;
319  flags=JFILE_CLONED;
320}
321
322void jFILE::open_external(char const *filename, char const *mode, int flags)
323{
324  int skip_size=0;
325  char tmp_name[200];
326  if (spec_prefix && filename[0] != '/')
327    sprintf(tmp_name,"%s%s",spec_prefix,filename);
328  else strcpy(tmp_name,filename);
329
330//  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
331  if (flags&O_WRONLY)
332  {
333    if ((flags&O_APPEND)==0)
334    {
335      skip_size=1;
336      //int errval = unlink(tmp_name);
337    }
338
339    flags-=O_WRONLY;
340    flags|=O_CREAT|O_RDWR;
341
342    fd=open(tmp_name,flags,S_IRWXU | S_IRWXG | S_IRWXO);
343  } else
344    fd=open(tmp_name,flags);
345
346//  umask(old_mask);
347  if (fd>=0 && !skip_size)
348  {
349    file_length=lseek(fd,0,SEEK_END);
350    if ((flags&O_APPEND)==0)
351      lseek(fd,0,SEEK_SET);
352    else
353        current_offset = file_length;
354    start_offset=0;
355  } else
356  {
357    file_length=0;
358    start_offset=0;
359  }
360}
361
362
363class null_file : public bFILE     // this file type will use virtual opens inside of a spe
364{
365  public :
366  virtual int open_failure() { return 1; }
367  virtual int unbuffered_read(void *buf, size_t count)   { return 0; }
368  virtual int unbuffered_write(void const *buf, size_t count)  { return 0; }
369  virtual int unbuffered_seek(long offset, int whence)   { return 0; }
370
371  virtual int unbuffered_tell() { return 0; }
372  virtual int file_size() { return 0; }
373  virtual ~null_file() { ; }
374} ;
375
376
377static bFILE *(*open_file_fun)(char const *,char const *)=NULL;
378int (*verify_file_fun)(char const *,char const *)=NULL;
379
380void set_file_opener(bFILE *(*open_fun)(char const *, char const *))
381{
382  open_file_fun=open_fun;
383}
384
385bFILE *open_file(char const *filename, char const *mode)
386{
387  if (!verify_file_fun || verify_file_fun(filename,mode))
388  {
389    if (open_file_fun)
390      return open_file_fun(filename,mode);
391    else return new jFILE(filename,mode);
392  } else return new null_file;
393}
394
395void jFILE::open_internal(char const *filename, char const *mode, int flags)
396{
397  int wr=0;
398  for (char const *s=mode;*s;s++)
399    if (toupper(*s)=='A' || toupper(*s)=='W')
400      wr=1;
401
402  if (wr)
403    fd=-1;                 // only allow extern file openings for writing
404  else
405  {
406       fd = spec_main_fd;
407    if (fd>=0)                    // if we were able to open the main file, see if it's in there
408    {
409      start_offset=0;
410      spec_entry *se=spec_main_sd.find(filename);
411      if (se)
412      {
413    start_offset=se->offset;
414    current_offset = 0;
415    file_length=se->size;
416    rbuf_start=rbuf_end=0;
417      } else
418      {
419    close(fd);
420    fd=-1;
421      }
422    }
423  }
424}
425
426jFILE::jFILE(char const *filename, char const *access_string)      // same as fopen parameters
427{
428 flags=access=0;
429 char const *s=access_string;
430  for (;*s;s++)
431    if (toupper(*s)=='R') access=O_RDONLY;
432
433  for (s=access_string;*s;s++)
434    if (toupper(*s)=='W')
435    {
436      if (access)
437        access=O_RDWR;
438      else access=O_WRONLY;
439    }
440
441  for (s=access_string;*s;s++)
442    if (toupper(*s)=='A')
443      access|=O_APPEND|O_WRONLY;
444
445  file_length=start_offset=-1;
446  current_offset = 0;
447
448  fd=-1;
449  if (search_order==SPEC_SEARCH_OUTSIDE_INSIDE)
450    open_external(filename,access_string,access);
451
452  if (fd<0)
453    open_internal(filename,access_string,access);
454
455  if (fd<0 && search_order==SPEC_SEARCH_INSIDE_OUTSIDE)
456    open_external(filename,access_string,access);
457
458  total_files_open++;
459}
460
461jFILE::~jFILE()
462{
463  flush_writes();
464  if (fd>=0 && !(flags&JFILE_CLONED))
465  {
466    total_files_open--;
467    if (fd != spec_main_fd)
468        close(fd);
469  }
470}
471
472int jFILE::unbuffered_tell()
473{
474//    int ret = ::lseek(fd,0,SEEK_CUR) - start_offset;
475//    if (ret != current_offset)
476//        fprintf(stderr,"Bad tell %d\n",current_offset);
477    return current_offset;
478}
479
480int jFILE::unbuffered_read(void *buf, size_t count)
481{
482    unsigned long len;
483
484    if (fd == spec_main_fd)
485    {
486        switch (fast_load_mode)
487        {
488        case 0:
489            if (current_offset+start_offset != spec_main_offset)
490                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
491           
492            len = ::read(fd,(char*)buf,count);
493            break;
494        case 1:
495            if (current_offset+start_offset != spec_main_offset)
496                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
497           
498            len = ::read(fd,(char*)buf,count);
499            ::write(fast_load_fd,(char*)&len,sizeof(len));
500            ::write(fast_load_fd,(char*)buf,len);
501            break;
502        case 2:
503            ::read(fast_load_fd,(char*)&len,sizeof(len));
504            len = ::read(fast_load_fd,(char*)buf,len);
505            break;
506        }
507       
508        spec_main_offset += len;
509    }
510    else
511    {
512        switch (fast_load_mode)
513        {
514        case 0:
515          len = ::read(fd,(char*)buf,count);
516          break;
517        case 1:
518          len = ::read(fd,(char*)buf,count);
519            ::write(fast_load_fd,(char*)&len,sizeof(len));
520            ::write(fast_load_fd,(char*)buf,len);
521          break;
522        case 2:
523            ::read(fast_load_fd,(char*)&len,sizeof(len));
524            len = ::read(fast_load_fd,(char*)buf,len);
525            if (count != len)
526                printf("short read! %ld:%ld\n",current_offset,len);
527          break;
528      }
529    }
530    current_offset += len;
531    return len;
532}
533
534int jFILE::unbuffered_write(void const *buf, size_t count)
535{
536  long ret = ::write(fd,(char*)buf,count);
537    current_offset += ret;
538    return ret;
539}
540
541int jFILE::unbuffered_seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
542{
543  long ret;
544
545  if (fast_load_mode == 2)
546  {
547    switch (whence)
548    {
549    case SEEK_SET :
550      current_offset = start_offset+offset;
551      break;
552    case SEEK_END :
553      current_offset = start_offset+file_length-offset;
554      break;
555    case SEEK_CUR :
556      current_offset += offset;
557      break;
558    default:
559      ret = -1;
560      break;
561    }
562    return current_offset;
563  }
564
565  switch (whence)
566  {
567    case SEEK_SET :
568    { ret = lseek(fd,start_offset+offset,SEEK_SET); } break;
569    case SEEK_END :
570    { ret = lseek(fd,start_offset+file_length-offset,SEEK_SET); } break;
571    case SEEK_CUR :
572    { ret = lseek(fd,offset,SEEK_CUR); } break;
573    default:
574        ret = -1;
575        break;
576  }
577  if (ret>=0)
578  {
579    current_offset = ret - start_offset;
580    if (spec_main_fd == fd)
581      spec_main_offset = ret;
582    return ret;
583  }
584  else
585    return -1;  // if a bad whence, then failure
586}
587
588
589uint8_t bFILE::read_uint8()
590{ uint8_t x;
591  read(&x,1);
592  return x;
593}
594
595uint16_t bFILE::read_uint16()
596{
597  uint16_t x;
598  read(&x,2);
599  return uint16_to_local(x);
600}
601
602
603uint32_t bFILE::read_uint32()
604{
605  uint32_t x;
606  read(&x,4);
607  return uint32_to_local(x);
608}
609
610void bFILE::write_uint8(uint8_t x)
611{
612  write(&x,1);
613}
614
615void bFILE::write_uint16(uint16_t x)
616{
617  x=uint16_to_local(x);
618  write(&x,2);
619}
620
621
622void bFILE::write_uint32(uint32_t x)
623{
624  x=uint32_to_local(x);
625  write(&x,4);
626}
627
628void bFILE::write_double(double x)
629{
630  double a;
631  write_uint32((long)(modf(x,&a)*(double)(1<<31)));
632  write_uint32((long)a);
633}
634
635double bFILE::read_double()
636{
637  long a,b;
638  a=read_uint32();
639  b=read_uint32();
640  return (double)b+a/(double)(1<<31);
641}
642
643spec_directory::~spec_directory()
644{
645
646  if (total)
647  {
648    free(data);
649    free(entries);
650  }
651}
652
653void spec_entry::print()
654{
655  printf("%15s%25s%8ld%8ld\n",spec_types[type],name,size,offset);
656}
657
658void spec_directory::calc_offsets()
659{
660  spec_entry **e;
661  int i;
662  long o=SPEC_SIG_SIZE+2;
663  if (total)
664  {
665    for (i=0,e=entries;i<total;i++,e++)          // calculate the size of directory info
666    {
667      o+=1+1+strlen((*e)->name)+1 +1 +8;
668    }
669
670    for (i=0,e=entries;i<total;i++,e++)          // calculate offset for each entry
671    {
672      (*e)->offset=o;
673      o+=(*e)->size;
674    }
675  }
676}
677
678spec_entry *spec_directory::find(char const *name, int type)
679{
680  int i;
681  spec_entry **e;
682  for (i=0,e=entries;i<total;i++,e++)
683    if (!strcmp((*e)->name,name) && (*e)->type==type)
684      return (*e);
685  return NULL;
686}
687
688spec_entry *spec_directory::find(char const *name)
689{
690  int i;
691  spec_entry **e;
692  for (i=0,e=entries;i<total;i++,e++)
693    if (!strcmp((*e)->name,name))
694      return (*e);
695  return NULL;
696}
697
698long spec_directory::find_number(char const *name)
699{
700  int i;
701  spec_entry **e;
702  for (i=0,e=entries;i<total;i++,e++)
703    if (!strcmp((*e)->name,name))
704      return i;
705  return -1;
706}
707
708spec_entry *spec_directory::find(int type)
709{
710  int i;
711  spec_entry **e;
712  for (i=0,e=entries;i<total;i++,e++)
713    if ((*e)->type==type)
714      return (*e);
715  return NULL;
716}
717
718long spec_directory::type_total(int type)
719{
720  int i,x=0;
721  spec_entry **e;
722  for (i=0,e=entries;i<total;i++,e++)
723    if ((*e)->type==type) x++;
724  return x;
725}
726
727long spec_directory::find_number(int type)
728{
729  int i;
730  spec_entry **e;
731  for (i=0,e=entries;i<total;i++,e++)
732    if ((*e)->type==type)
733      return i;
734  return -1;
735}
736
737void spec_directory::print()
738{
739  spec_entry **se;
740  int i;
741  printf("[   Entry type   ][   Entry name   ][  Size  ][ Offset ]\n");
742  for (i=0,se=entries;i<total;i++,se++)
743    (*se)->print();
744}
745
746
747void spec_directory::startup(bFILE *fp)
748{
749  char buf[256];
750  memset(buf,0,256);
751  fp->read(buf,8);
752  buf[9]=0;
753  size=0;
754  if (!strcmp(buf,SPEC_SIGNATURE))
755  {
756    total=fp->read_uint16();
757    entries=(spec_entry **)malloc(sizeof(spec_entry *)*total);
758    long start=fp->tell();
759
760    int i;
761    for (i=0;i<total;i++)
762    {
763      fp->read(buf,2);
764      long entry_size=sizeof(spec_entry)+(unsigned char)buf[1];
765      entry_size=(entry_size+3)&(~3);
766      fp->read(buf,(unsigned char)buf[1]);
767      fp->read(buf,9);
768
769      size+=entry_size;
770    }
771    data=malloc(size);
772    char *dp=(char *)data;
773    fp->seek(start,SEEK_SET);
774    for (i=0;i<total;i++)
775    {
776      spec_entry *se=(spec_entry *)dp;
777      entries[i]=se;
778
779      unsigned char len,flags,type;
780      fp->read(&type,1);
781      fp->read(&len,1);
782      se->type=type;
783      se->name=dp+sizeof(spec_entry);
784      fp->read(se->name,len);
785      fp->read(&flags,1);
786
787      se->size=fp->read_uint32();
788      se->offset=fp->read_uint32();
789      dp+=((sizeof(spec_entry)+len)+3)&(~3);
790    }
791  }
792  else
793  {
794    total=0;
795    data=NULL;
796    entries=NULL;
797  }
798}
799
800
801spec_directory::spec_directory(bFILE *fp)
802{ startup(fp); }
803
804spec_directory::spec_directory(FILE *fp)
805{
806  jFILE jfp(fp);
807  startup(&jfp);
808}
809
810spec_directory::spec_directory()
811{
812  size=0;
813  total=0;
814  data=NULL;
815  entries=NULL;
816}
817
818/*
819spec_directory::spec_directory(char *filename)
820{
821  jFILE *fp;
822  if (filename)
823  {
824    fp=new jFILE(filename,"rb");
825    if (!fp->open_failure())
826      startup(fp);
827    else
828    {
829      total=0;
830      entries=NULL;
831    }
832    delete fp;
833  } else printf("NULL filename to spec_directory::spec_directory\n");
834}*/
835
836int write_string(bFILE *fp, char const *st)
837{
838  unsigned char length=strlen(st)+1;
839  if (fp->write(&length,1)!=1) return 0;
840  if (fp->write(st,length)!=length) return 0;
841  return 1;
842}
843
844long spec_directory::data_start_offset()
845{
846    /* FIXME: no need for a for loop here! */
847    long i;
848    for(i = 0; i < total; i++)
849        return entries[i]->offset;
850
851    // If no entries, then no data, but return where it would start anyway
852    return SPEC_SIG_SIZE + 2;
853}
854
855long spec_directory::data_end_offset()
856{
857    /* FIXME: no need for a for loop here! */
858  spec_entry **e;
859  long i;
860  for (i=total-1,e=entries;i>=0;i--,e++)
861    return (*e)->offset+(*e)->size;
862
863  return SPEC_SIG_SIZE+2;
864}
865
866int spec_directory::write(bFILE *fp)
867{
868
869  char sig[SPEC_SIG_SIZE];
870  unsigned char flags=0;
871  unsigned long offset,data_size;
872  spec_entry **e;
873  strcpy(sig,SPEC_SIGNATURE);
874
875  if (fp->write(sig,sizeof(sig))!=sizeof(sig))    return 0;
876  fp->write_uint16(total);
877
878
879  int i;
880  for (i=0,e=entries;i<total;i++,e++)
881  {
882    if (fp->write(&(*e)->type,1)!=1)                 return 0;
883    if (!write_string(fp,(*e)->name))                return 0;
884    flags=0;
885    if (fp->write(&flags,1)!=1)                     return 0;
886
887    data_size=uint32_to_intel((*e)->size);
888    if (fp->write((char *)&data_size,4)!=4)              return 0;
889    offset=uint32_to_intel((*e)->offset);
890    if (fp->write((char *)&offset,4)!=4)                  return 0;
891
892  }
893  return 1;
894}
895
896jFILE *spec_directory::write(char const *filename)
897{
898  jFILE *fp;
899  fp=new jFILE(filename,"wb");
900  if (fp->open_failure()) { delete fp; return NULL; }
901  if (!write(fp))
902  {
903    delete fp;
904    return NULL;
905  } else return fp;
906
907}
908
909uint16_t read_uint16(FILE *fp)
910{
911  uint16_t x;
912  fread(&x,1,2,fp);
913  return uint16_to_local(x);
914}
915
916uint32_t read_uint32(FILE *fp)
917{
918  uint32_t x;
919  fread(&x,1,4,fp);
920  return uint32_to_local(x);
921}
922void write_uint16(FILE *fp, uint16_t x)
923{
924  x=uint16_to_local(x);
925  fwrite(&x,1,2,fp);
926}
927
928void write_uint32(FILE *fp, uint32_t x)
929{
930  x=uint32_to_local(x);
931  fwrite(&x,1,4,fp);
932}
933
934uint8_t read_uint8(FILE *fp) { return fgetc(fp)&0xff; }
935void write_uint8(FILE *fp, uint8_t x) { fputc((unsigned char)x,fp); }
936
937uint32_t read_other_uint32(FILE *fp)
938{
939  uint32_t x;
940  fread(&x,1,4,fp);
941  return big_uint32_to_local(x);
942}
943
944uint16_t read_other_uint16(FILE *fp)
945{
946  uint16_t x;
947  fread(&x,1,2,fp);
948  return big_uint16_to_local(x);
949}
950
951
952void write_other_uint16(FILE *fp, uint16_t x)
953{
954  x=big_uint16_to_local(x);
955  fwrite(&x,1,2,fp);
956}
957
958void write_other_int32(FILE *fp, uint32_t x)
959{
960  x=big_uint32_to_local(x);
961  fwrite(&x,1,4,fp);
962}
963
964void spec_directory::remove(spec_entry *e)
965{
966  int i;
967  for (i=0;i<total && entries[i]!=e;i++);            // find the entry in the array first
968
969  if (entries[i]==e)                                 // make sre it was found
970  {
971    delete e;
972    total--;
973    for (;i<total;i++)                               // compact the pointer array
974      entries[i]=entries[i+1];
975    entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
976  }
977  else
978    printf("Spec_directory::remove bad entry pointer\n");
979}
980
981
982
983void spec_directory::add_by_hand(spec_entry *e)
984{
985  total++;
986  entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
987  entries[total-1]=e;
988}
989
990void spec_directory::delete_entries()   // if the directory was created by hand instead of by file
991{
992  int i;
993  for (i=0;i<total;i++)
994    delete entries[i];
995
996  if (total)
997    free(entries);
998}
999
1000void note_open_fd(int fd, char const *str)
1001{
1002    total_files_open++;
1003}
1004
1005void note_close_fd(int fd)
1006{
1007    total_files_open--;
1008}
1009
1010void list_open_fds()
1011{
1012    printf("Total open file descriptors: %d\n", total_files_open);
1013}
1014
Note: See TracBrowser for help on using the repository browser.