summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-reader/ppm_expander.cpp
blob: 61ef90e2469ddbed27f338361a89345a0d0c68ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/*
 * Interface pour le programme de compression
 * (c) 1995 Fabrice Bellard
 */

#include <stdlib.h>
//#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

/***************************************************************************
 * Interface avec les routines de compression
 */

#define METHOD_NB      2   /* nombre total de méthodes de compression */

#define METHOD_STORE   0
#define METHOD_PPM     1


#define DEFAULT_SUFFIX  ".st"    /* extension par défault */
/* signature en début de fichier */
#define STAT_MAGIC_SIZE 4
char stat_magic[STAT_MAGIC_SIZE]={'P','P','M','S'};

#include "ppm_expander.h"

ppm_expander::~ppm_expander() {
  if (needppmend) ppm.PPM_End();
  ppm.arith.Arith_DecodeEnd();
  if (buf_in!=NULL) delete [] buf_in;
  if (buf_out!=NULL) delete [] buf_out;
  if (my_read_buf != NULL) delete my_read_buf;
  if (my_file_in != NULL) fclose(my_file_in);
}

int ppm_expander::OpenFile(const char* infile)
{
  my_file_in=fopen(infile,"rb");
  my_read_buf = new PPM_ReadBuf(my_file_in, this);
  return home();
}

void ppm_expander::sizes(unsigned long& file, unsigned long& text)
{
  struct stat _stat;
  fstat(fileno(my_file_in),&_stat);
  file = _stat.st_size;
  text = numblocks*blocksize;
}

int ppm_expander::home()
{
  fseek(my_file_in,0, SEEK_SET);
  unsigned char header[STAT_MAGIC_SIZE];
  size_t len=fread(header,1,STAT_MAGIC_SIZE,my_file_in);
  if (strncmp((char*)header,stat_magic,STAT_MAGIC_SIZE)!=0)  {
    return 1;
  }
  if (len!=(STAT_MAGIC_SIZE))  {
    return 1;
  }
  if (fread(&maxnode,sizeof(maxnode),1,my_file_in) != 1) return 1;
  if (fread(&blocksize,sizeof(blocksize),1,my_file_in) != 1) return 1;
  if (fread(&numblocks,sizeof(numblocks),1,my_file_in) != 1) return 1;
  //fprintf(stderr,"<%u,%u,%u>\n",maxnode,blocksize,numblocks);
  locate(0,0);
  outbytes = 0;
  return 0;
}

void ppm_expander::locate(unsigned int n) {
  locate(n/blocksize, n%blocksize);
  outbytes = n;
}

void ppm_expander::locate(unsigned short block, unsigned int n)
{
  if (needppmend)
    {
      ppm.PPM_End();
      needppmend = false;
    }
  size_t fpos;
  fseek(my_file_in,STAT_MAGIC_SIZE+sizeof(maxnode)+sizeof(blocksize)+sizeof(numblocks)+block*sizeof(fpos),SEEK_SET);
  fread(&fpos,sizeof(fpos),1,my_file_in);
  fseek(my_file_in,fpos,SEEK_SET);

  ppm.arith.Arith_DecodeInit(my_read_buf,buf_in,bufsize);
  int err=ppm.PPM_Init(maxnode);
  needppmend = true;
  curblock = block;
  for (int i = 0; i < n; i++) getch();
}

int ppm_expander::getch() {
  if (curblock >= numblocks) return EOF;
  int c=ppm.PPM_Decode();
  if (c == SYM_EOF)
    {
      if (++curblock >= numblocks) return EOF;
      locate(curblock,0);
      c = ppm.PPM_Decode();
    }
  outbytes++;
  return (c==SYM_EOF) ? EOF : c;
}

UINT PPM_ReadBuf::readbuf(UCHAR *buf,UINT len)
  {
    UINT len1;
    parent->unsuspend();
    len1=fread(buf,1,len,my_file_in);
    return len1;
  }


#ifndef __STATIC
extern "C"
{
  CExpander* newcodec() { return new ppm_expander; }
}
#endif