File: SimpleDecompressor.c

package info (click to toggle)
unar 1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 6,664 kB
  • sloc: ansic: 52,939; objc: 39,563; cpp: 4,074; makefile: 99; perl: 10
file content (140 lines) | stat: -rw-r--r-- 3,232 bytes parent folder | download | duplicates (5)
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdio.h>
#include <stdint.h>

#include "VariantG.h"
#include "VariantH.h"
#include "VariantI.h"
#include "SubAllocatorVariantG.h"
#include "SubAllocatorVariantH.h"
#include "SubAllocatorVariantI.h"
#include "SubAllocatorBrimstone.h"

static inline uint16_t EndianSwap16(uint16_t val) { return (val>>8)|(val<<8); }
static inline uint32_t EndianSwap32(uint32_t val) { return (val>>24)|((val>>8)&0x0000ff00)|((val<<8)&0x00ff0000)|(val<<24); }

static int STDIORead(void *context);

int main(int argc,const char **argv)
{
	FILE *fh;

	if(argc>=2)
	{
		fh=fopen(argv[1],"rb");
		if(!fh)
		{
			fprintf(stderr,"Couldn't open file \"%s\".\n",argv[1]);
			return 1;
		}
	}
	else fh=stdin;

	struct
	{
		uint32_t magic;
		uint32_t attribs;
		uint16_t info;
		uint16_t namelen;
		uint16_t time,date;
	} header;

	fread(&header,sizeof(header),1,fh);

	if(header.magic!=0x84acaf8f&&header.magic!=0x8fafac84)
	{
		fprintf(stderr,"\"%s\" does not look like a PPMd file.\n",argv[1]);
		return 1;
	}

	if(header.magic==0x8fafac84)
	{
		header.attribs=EndianSwap32(header.attribs);
		header.info=EndianSwap16(header.info);
		header.namelen=EndianSwap16(header.namelen);
		header.time=EndianSwap16(header.time);
		header.date=EndianSwap16(header.date);
	}

	int maxorder=(header.info&0x0f)+1;
	int suballocsize=((header.info>>4)&0xff)+1;
	int variant=(header.info>>12)+'A';

	int modelrestoration=-1;
	if(variant>='I')
	{
		modelrestoration=header.namelen>>14;
		header.namelen&=0x3fff;
	}

	fprintf(stderr,"PPMd variant %c file.\n",variant);
	fprintf(stderr,"Max order = %d\n",maxorder);
	fprintf(stderr,"Suballocator size = %d\n",suballocsize);
	if(modelrestoration>=0) fprintf(stderr,"Model restoration = %d\n",modelrestoration);
	fprintf(stderr,"File attributes = %x\n",header.attribs);
	fprintf(stderr,"Time and date = %04x %04x\n",header.time,header.date);

	uint8_t namebuf[header.namelen];
	fread(namebuf,header.namelen,1,fh);

	fprintf(stderr,"Filename = ");
	fwrite(namebuf,header.namelen,1,stderr);
	fprintf(stderr,"\n");

	if(variant!='G'&&variant!='I'&&variant!='H')
	{
		fprintf(stderr,"Variant %c is not supported.\n",variant);
		return 1;
	}

	switch(variant)
	{
		case 'G':
		{
			PPMdSubAllocatorVariantG *alloc=CreateSubAllocatorVariantG(suballocsize<<20);
			PPMdModelVariantG model;
			StartPPMdModelVariantG(&model,STDIORead,fh,&alloc->core,maxorder,false);
			for(;;)
			{
				int byte=NextPPMdVariantGByte(&model);
				if(byte<0) break;
				fputc(byte,stdout);
			}
		}
		break;

		case 'H':
		{
			PPMdSubAllocatorVariantH *alloc=CreateSubAllocatorVariantH(suballocsize<<20);
			PPMdModelVariantH model;
			StartPPMdModelVariantH(&model,STDIORead,fh,alloc,maxorder,false);
			for(;;)
			{
				int byte=NextPPMdVariantHByte(&model);
				if(byte<0) break;
				fputc(byte,stdout);
			}
		}
		break;

		case 'I':
		{
			PPMdSubAllocatorVariantI *alloc=CreateSubAllocatorVariantI(suballocsize<<20);
			PPMdModelVariantI model;
			StartPPMdModelVariantI(&model,STDIORead,fh,alloc,maxorder,modelrestoration);
			for(;;)
			{
				int byte=NextPPMdVariantIByte(&model);
				if(byte<0) break;
				fputc(byte,stdout);
			}
		}
		break;
	}
}

static int STDIORead(void *context)
{
	FILE *fh=context;
	return fgetc(fh)&0xff;
}