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

Last change on this file since 129 was 129, checked in by Sam Hocevar, 15 years ago
  • Get rid of jmalloc and replace it with standard malloc. Modern operating systems certainly perform a lot better than this custom implementation, and we have superior tools (eg. valgrind) to debug and profile memory usage without interfering with the code itself.
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.hpp"
24#include "palette.hpp"
25#include "specs.hpp"
26#include "system.h"
27#include "dprint.hpp"
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      if (access)
436        access=O_RDWR;
437      else access=O_WRONLY;
438
439  for (s=access_string;*s;s++)
440    if (toupper(*s)=='A')
441      access|=O_APPEND|O_WRONLY;
442
443  file_length=start_offset=-1;
444  current_offset = 0;
445
446  fd=-1;
447  if (search_order==SPEC_SEARCH_OUTSIDE_INSIDE)
448    open_external(filename,access_string,access);
449
450  if (fd<0)
451    open_internal(filename,access_string,access);
452
453  if (fd<0 && search_order==SPEC_SEARCH_INSIDE_OUTSIDE)
454    open_external(filename,access_string,access);
455
456  total_files_open++;
457}
458
459jFILE::~jFILE()
460{
461  flush_writes();
462  if (fd>=0 && !(flags&JFILE_CLONED))
463  {
464    total_files_open--;
465    if (fd != spec_main_fd)
466        close(fd);
467  }
468}
469
470int jFILE::unbuffered_tell()
471{
472//    int ret = ::lseek(fd,0,SEEK_CUR) - start_offset;
473//    if (ret != current_offset)
474//        fprintf(stderr,"Bad tell %d\n",current_offset);
475    return current_offset;
476}
477
478int jFILE::unbuffered_read(void *buf, size_t count)
479{
480    unsigned long len;
481
482    if (fd == spec_main_fd)
483    {
484        switch (fast_load_mode)
485        {
486        case 0:
487            if (current_offset+start_offset != spec_main_offset)
488                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
489           
490            len = ::read(fd,(char*)buf,count);
491            break;
492        case 1:
493            if (current_offset+start_offset != spec_main_offset)
494                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
495           
496            len = ::read(fd,(char*)buf,count);
497            ::write(fast_load_fd,(char*)&len,sizeof(len));
498            ::write(fast_load_fd,(char*)buf,len);
499            break;
500        case 2:
501            ::read(fast_load_fd,(char*)&len,sizeof(len));
502            len = ::read(fast_load_fd,(char*)buf,len);
503            break;
504        }
505       
506        spec_main_offset += len;
507    }
508    else
509    {
510        switch (fast_load_mode)
511        {
512        case 0:
513          len = ::read(fd,(char*)buf,count);
514          break;
515        case 1:
516          len = ::read(fd,(char*)buf,count);
517            ::write(fast_load_fd,(char*)&len,sizeof(len));
518            ::write(fast_load_fd,(char*)buf,len);
519          break;
520        case 2:
521            ::read(fast_load_fd,(char*)&len,sizeof(len));
522            len = ::read(fast_load_fd,(char*)buf,len);
523            if (count != len)
524                printf("short read! %ld:%ld\n",current_offset,len);
525          break;
526      }
527    }
528    current_offset += len;
529    return len;
530}
531
532int jFILE::unbuffered_write(void const *buf, size_t count)
533{
534  long ret = ::write(fd,(char*)buf,count);
535    current_offset += ret;
536    return ret;
537}
538
539int jFILE::unbuffered_seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
540{
541  long ret;
542
543  if (fast_load_mode == 2)
544  {
545    switch (whence)
546    {
547    case SEEK_SET :
548      current_offset = start_offset+offset;
549      break;
550    case SEEK_END :
551      current_offset = start_offset+file_length-offset;
552      break;
553    case SEEK_CUR :
554      current_offset += offset;
555      break;
556    default:
557      ret = -1;
558      break;
559    }
560    return current_offset;
561  }
562
563  switch (whence)
564  {
565    case SEEK_SET :
566    { ret = lseek(fd,start_offset+offset,SEEK_SET); } break;
567    case SEEK_END :
568    { ret = lseek(fd,start_offset+file_length-offset,SEEK_SET); } break;
569    case SEEK_CUR :
570    { ret = lseek(fd,offset,SEEK_CUR); } break;
571    default:
572        ret = -1;
573        break;
574  }
575  if (ret>=0)
576  {
577    current_offset = ret - start_offset;
578    if (spec_main_fd == fd)
579      spec_main_offset = ret;
580    return ret;
581  }
582  else
583    return -1;  // if a bad whence, then failure
584}
585
586
587uint8_t bFILE::read_uint8()
588{ uint8_t x;
589  read(&x,1);
590  return x;
591}
592
593uint16_t bFILE::read_uint16()
594{
595  uint16_t x;
596  read(&x,2);
597  return uint16_to_local(x);
598}
599
600
601uint32_t bFILE::read_uint32()
602{
603  uint32_t x;
604  read(&x,4);
605  return uint32_to_local(x);
606}
607
608void bFILE::write_uint8(uint8_t x)
609{
610  write(&x,1);
611}
612
613void bFILE::write_uint16(uint16_t x)
614{
615  x=uint16_to_local(x);
616  write(&x,2);
617}
618
619
620void bFILE::write_uint32(uint32_t x)
621{
622  x=uint32_to_local(x);
623  write(&x,4);
624}
625
626void bFILE::write_double(double x)
627{
628  double a;
629  write_uint32((long)(modf(x,&a)*(double)(1<<32-1)));
630  write_uint32((long)a);
631}
632
633double bFILE::read_double()
634{
635  long a,b;
636  a=read_uint32();
637  b=read_uint32();
638  return (double)b+a/(double)(1<<32-1);
639}
640
641spec_directory::~spec_directory()
642{
643
644  if (total)
645  {
646    free(data);
647    free(entries);
648  }
649}
650
651void spec_entry::print()
652{
653  printf("%15s%25s%8ld%8ld\n",spec_types[type],name,size,offset);
654}
655
656void spec_directory::calc_offsets()
657{
658  spec_entry **e;
659  int i;
660  long o=SPEC_SIG_SIZE+2;
661  if (total)
662  {
663    for (i=0,e=entries;i<total;i++,e++)          // calculate the size of directory info
664    {
665      o+=1+1+strlen((*e)->name)+1 +1 +8;
666    }
667
668    for (i=0,e=entries;i<total;i++,e++)          // calculate offset for each entry
669    {
670      (*e)->offset=o;
671      o+=(*e)->size;
672    }
673  }
674}
675
676spec_entry *spec_directory::find(char const *name, int type)
677{
678  int i;
679  spec_entry **e;
680  for (i=0,e=entries;i<total;i++,e++)
681    if (!strcmp((*e)->name,name) && (*e)->type==type)
682      return (*e);
683  return NULL;
684}
685
686spec_entry *spec_directory::find(char const *name)
687{
688  int i;
689  spec_entry **e;
690  for (i=0,e=entries;i<total;i++,e++)
691    if (!strcmp((*e)->name,name))
692      return (*e);
693  return NULL;
694}
695
696long spec_directory::find_number(char const *name)
697{
698  int i;
699  spec_entry **e;
700  for (i=0,e=entries;i<total;i++,e++)
701    if (!strcmp((*e)->name,name))
702      return i;
703  return -1;
704}
705
706spec_entry *spec_directory::find(int type)
707{
708  int i;
709  spec_entry **e;
710  for (i=0,e=entries;i<total;i++,e++)
711    if ((*e)->type==type)
712      return (*e);
713  return NULL;
714}
715
716long spec_directory::type_total(int type)
717{
718  int i,x=0;
719  spec_entry **e;
720  for (i=0,e=entries;i<total;i++,e++)
721    if ((*e)->type==type) x++;
722  return x;
723}
724
725long spec_directory::find_number(int type)
726{
727  int i;
728  spec_entry **e;
729  for (i=0,e=entries;i<total;i++,e++)
730    if ((*e)->type==type)
731      return i;
732  return -1;
733}
734
735void spec_directory::print()
736{
737  spec_entry **se;
738  int i;
739  printf("[   Entry type   ][   Entry name   ][  Size  ][ Offset ]\n");
740  for (i=0,se=entries;i<total;i++,se++)
741    (*se)->print();
742}
743
744
745void spec_directory::startup(bFILE *fp)
746{
747  char buf[256];
748  memset(buf,0,256);
749  fp->read(buf,8);
750  buf[9]=0;
751  size=0;
752  if (!strcmp(buf,SPEC_SIGNATURE))
753  {
754    total=fp->read_uint16();
755    entries=(spec_entry **)malloc(sizeof(spec_entry *)*total);
756    long start=fp->tell();
757
758    int i;
759    for (i=0;i<total;i++)
760    {
761      fp->read(buf,2);
762      long entry_size=sizeof(spec_entry)+(unsigned char)buf[1];
763      entry_size=(entry_size+3)&(~3);
764      fp->read(buf,(unsigned char)buf[1]);
765      fp->read(buf,9);
766
767      size+=entry_size;
768    }
769    data=malloc(size);
770    char *dp=(char *)data;
771    fp->seek(start,SEEK_SET);
772    for (i=0;i<total;i++)
773    {
774      spec_entry *se=(spec_entry *)dp;
775      entries[i]=se;
776
777      unsigned char len,flags,type;
778      fp->read(&type,1);
779      fp->read(&len,1);
780      se->type=type;
781      se->name=dp+sizeof(spec_entry);
782      fp->read(se->name,len);
783      fp->read(&flags,1);
784
785      se->size=fp->read_uint32();
786      se->offset=fp->read_uint32();
787      dp+=((sizeof(spec_entry)+len)+3)&(~3);
788    }
789  }
790  else
791  {
792    total=0;
793    data=NULL;
794    entries=NULL;
795  }
796}
797
798
799spec_directory::spec_directory(bFILE *fp)
800{ startup(fp); }
801
802spec_directory::spec_directory(FILE *fp)
803{
804  jFILE jfp(fp);
805  startup(&jfp);
806}
807
808spec_directory::spec_directory()
809{
810  size=0;
811  total=0;
812  data=NULL;
813  entries=NULL;
814}
815
816/*
817spec_directory::spec_directory(char *filename)
818{
819  jFILE *fp;
820  if (filename)
821  {
822    fp=new jFILE(filename,"rb");
823    if (!fp->open_failure())
824      startup(fp);
825    else
826    {
827      total=0;
828      entries=NULL;
829    }
830    delete fp;
831  } else printf("NULL filename to spec_directory::spec_directory\n");
832}*/
833
834int write_string(bFILE *fp, char const *st)
835{
836  unsigned char length=strlen(st)+1;
837  if (fp->write(&length,1)!=1) return 0;
838  if (fp->write(st,length)!=length) return 0;
839  return 1;
840}
841
842long spec_directory::data_start_offset()
843{
844    /* FIXME: no need for a for loop here! */
845    long i;
846    for(i = 0; i < total; i++)
847        return entries[i]->offset;
848
849    // If no entries, then no data, but return where it would start anyway
850    return SPEC_SIG_SIZE + 2;
851}
852
853long spec_directory::data_end_offset()
854{
855    /* FIXME: no need for a for loop here! */
856  spec_entry **e;
857  long i;
858  for (i=total-1,e=entries;i>=0;i--,e++)
859    return (*e)->offset+(*e)->size;
860
861  return SPEC_SIG_SIZE+2;
862}
863
864int spec_directory::write(bFILE *fp)
865{
866
867  char sig[SPEC_SIG_SIZE];
868  unsigned char flags=0;
869  unsigned long offset,data_size;
870  spec_entry **e;
871  strcpy(sig,SPEC_SIGNATURE);
872
873  if (fp->write(sig,sizeof(sig))!=sizeof(sig))    return 0;
874  fp->write_uint16(total);
875
876
877  int i;
878  for (i=0,e=entries;i<total;i++,e++)
879  {
880    if (fp->write(&(*e)->type,1)!=1)                 return 0;
881    if (!write_string(fp,(*e)->name))                return 0;
882    flags=0;
883    if (fp->write(&flags,1)!=1)                     return 0;
884
885    data_size=uint32_to_intel((*e)->size);
886    if (fp->write((char *)&data_size,4)!=4)              return 0;
887    offset=uint32_to_intel((*e)->offset);
888    if (fp->write((char *)&offset,4)!=4)                  return 0;
889
890  }
891  return 1;
892}
893
894jFILE *spec_directory::write(char const *filename)
895{
896  jFILE *fp;
897  fp=new jFILE(filename,"wb");
898  if (fp->open_failure()) { delete fp; return NULL; }
899  if (!write(fp))
900  {
901    delete fp;
902    return NULL;
903  } else return fp;
904
905}
906
907uint16_t read_uint16(FILE *fp)
908{
909  uint16_t x;
910  fread(&x,1,2,fp);
911  return uint16_to_local(x);
912}
913
914uint32_t read_uint32(FILE *fp)
915{
916  uint32_t x;
917  fread(&x,1,4,fp);
918  return uint32_to_local(x);
919}
920void write_uint16(FILE *fp, uint16_t x)
921{
922  x=uint16_to_local(x);
923  fwrite(&x,1,2,fp);
924}
925
926void write_uint32(FILE *fp, uint32_t x)
927{
928  x=uint32_to_local(x);
929  fwrite(&x,1,4,fp);
930}
931
932uint8_t read_uint8(FILE *fp) { return fgetc(fp)&0xff; }
933void write_uint8(FILE *fp, uint8_t x) { fputc((unsigned char)x,fp); }
934
935uint32_t read_other_uint32(FILE *fp)
936{
937  uint32_t x;
938  fread(&x,1,4,fp);
939  return big_uint32_to_local(x);
940}
941
942uint16_t read_other_uint16(FILE *fp)
943{
944  uint16_t x;
945  fread(&x,1,2,fp);
946  return big_uint16_to_local(x);
947}
948
949
950void write_other_uint16(FILE *fp, uint16_t x)
951{
952  x=big_uint16_to_local(x);
953  fwrite(&x,1,2,fp);
954}
955
956void write_other_int32(FILE *fp, uint32_t x)
957{
958  x=big_uint32_to_local(x);
959  fwrite(&x,1,4,fp);
960}
961
962void spec_directory::remove(spec_entry *e)
963{
964  int i;
965  for (i=0;i<total && entries[i]!=e;i++);            // find the entry in the array first
966
967  if (entries[i]==e)                                 // make sre it was found
968  {
969    delete e;
970    total--;
971    for (;i<total;i++)                               // compact the pointer array
972      entries[i]=entries[i+1];
973    entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
974  }
975  else
976    printf("Spec_directory::remove bad entry pointer\n");
977}
978
979
980
981void spec_directory::add_by_hand(spec_entry *e)
982{
983  total++;
984  entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
985  entries[total-1]=e;
986}
987
988void spec_directory::delete_entries()   // if the directory was created by hand instead of by file
989{
990  int i;
991  for (i=0;i<total;i++)
992    delete entries[i];
993
994  if (total)
995    free(entries);
996}
997
998void note_open_fd(int fd, char const *str)
999{
1000    total_files_open++;
1001}
1002
1003void note_close_fd(int fd)
1004{
1005    total_files_open--;
1006}
1007
1008void list_open_fds()
1009{
1010    printf("Total open file descriptors: %d\n", total_files_open);
1011}
1012
Note: See TracBrowser for help on using the repository browser.