File: gzip.cc

package info (click to toggle)
yosys 0.52-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 69,796 kB
  • sloc: ansic: 696,955; cpp: 239,736; python: 14,617; yacc: 3,529; sh: 2,175; makefile: 1,945; lex: 697; perl: 445; javascript: 323; tcl: 162; vhdl: 115
file content (139 lines) | stat: -rw-r--r-- 3,307 bytes parent folder | download
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
#include "kernel/yosys_common.h"
#include "kernel/log.h"
#include "kernel/gzip.h"
#include <iostream>
#include <string>
#include <cstdarg>
#include <cstdio>

#if !defined(WIN32)
#include <dirent.h>
#include <unistd.h>
#else
#include <io.h>
#endif

YOSYS_NAMESPACE_BEGIN

#ifdef YOSYS_ENABLE_ZLIB

gzip_ostream::obuf::obuf() {
    setp(buffer, buffer + buffer_size - 1);
}

bool gzip_ostream::obuf::open(const std::string &filename) {
    gzf = Zlib::gzopen(filename.c_str(), "wb");
    return gzf != nullptr;
}

int gzip_ostream::obuf::sync() {
    int num = pptr() - pbase();
    if (num > 0) {
        if (Zlib::gzwrite(gzf, reinterpret_cast<const void*>(pbase()), num) != num) {
            return -1;
        }
        pbump(-num);
    }
    return 0;
}

gzip_ostream::obuf::~obuf() {
    if (gzf) {
        sync();
        Zlib::gzclose(gzf);
    }
}

bool gzip_istream::ibuf::open(const std::string& filename) {
	if (gzf) {
		Zlib::gzclose(gzf);
	}
	gzf = Zlib::gzopen(filename.c_str(), "rb");
	if (!gzf) {
		return false;
	}
	// Empty and point to start
	setg(buffer, buffer, buffer);
	return true;
}

// Called when the buffer is empty and more input is needed
std::istream::int_type gzip_istream::ibuf::underflow() {
	log_assert(gzf && "No gzfile opened\n");
	int bytes_read = Zlib::gzread(gzf, buffer, buffer_size);
	if (bytes_read <= 0) {
		if (Zlib::gzeof(gzf)) {
			// "On failure, the function ensures that either
			// gptr() == nullptr or gptr() == egptr."
			// Let's set gptr to egptr
			setg(eback(), egptr(), egptr());
			return traits_type::eof();
		}

		int err;
		const char* error_msg = Zlib::gzerror(gzf, &err);
		if (err != Z_OK)
			log_error("%s", error_msg);
		else
			log_error("Decompression logic failure: "\
					"read <=0 bytes but neither EOF nor error\n");
	}

	// Keep size and point to start
	setg(buffer, buffer, buffer + bytes_read);
	return traits_type::to_int_type(buffer[0]);
}

gzip_istream::ibuf::~ibuf() {
	if (gzf) {
		int err = Zlib::gzclose(gzf);
		if (err != Z_OK) {
			// OK to overwrite rr it, it doesn't change
			const char* error_msg = Zlib::gzerror(gzf, &err);
			log_error("%s", error_msg);
		}
	}
}

#endif // YOSYS_ENABLE_ZLIB


// Takes a successfully opened ifstream. If it's gzipped, returns an istream. Otherwise,
// returns the original ifstream, rewound to the start.
std::istream* uncompressed(const std::string filename, std::ios_base::openmode mode) {
	std::ifstream* f = new std::ifstream();
	f->open(filename, mode);
	if (f->fail())
		return f;
	// Check for gzip magic
	unsigned char magic[3];
	int n = 0;
	while (n < 3)
	{
		int c = f->get();
		if (c != EOF) {
			magic[n] = (unsigned char) c;
		}
		n++;
	}
	if (n == 3 && magic[0] == 0x1f && magic[1] == 0x8b) {
#ifdef YOSYS_ENABLE_ZLIB
		log("Found gzip magic in file `%s', decompressing using zlib.\n", filename.c_str());
		if (magic[2] != 8)
			log_cmd_error("gzip file `%s' uses unsupported compression type %02x\n",
				filename.c_str(), unsigned(magic[2]));
		gzip_istream* s = new gzip_istream();
		delete f;
		s->open(filename.c_str());
		return s;
#else
		log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str());
#endif // YOSYS_ENABLE_ZLIB
	} else {
		f->clear();
		f->seekg(0, std::ios::beg);
		return f;
	}
}

YOSYS_NAMESPACE_END