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
|
/* -*- c++ -*- */
/*
* Copyright 2004 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef _XYZZY_H_
#define _XYZZY_H_ 1
#include <cstdio>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <fstream>
#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <libguile.h>
using namespace std;
// - Special case filenames that start with /-xyzzy-/... and search for
// and load them using the single file. We'd stick "/-zyzzy-" first
// in the default load-path.
// - Create a C read-only "port" that "reads" from the string in the file.
// (See guile docs on creating new kinds of ports)
// - Override the default implementation of "primitive-load" and "%search-load-path"
// to make that happen. See load.c in the guile source code. Figure
// out how to get the override done before guile is fully
// initialized. (Guile loads ice-9/boot9.scm to start itself up. We'd
// need to redirect before then.)
struct header {
char magic[8];
boost::uint32_t offset_to_directory; // byte offset from start of file
boost::uint32_t size_of_directory; // bytes
boost::uint32_t number_of_dir_entries;
boost::uint32_t offset_to_strings; // byte offset from start of file
boost::uint32_t size_of_strings; // bytes
};
struct directory_entry {
boost::uint32_t offset_to_name; // from start of strings
boost::uint32_t offset_to_contents; // from start of strings
};
// Each string starts with a uint32_t length, followed by length bytes.
// There is no trailing \0 in the string.
struct string_entry {
boost::uint32_t length;
boost::uint8_t *base;
};
class XYZZY {
public:
XYZZY();
~XYZZY();
// Initialize with the data file produced by gen-xyzzy.
bool init();
bool init(const std::string &filespec);
// Does a file with name 'filename' exist in magic filesystem?
bool file_exists(const std::string &filespec);
// Return a C port that will read the file contents
SCM make_read_only_port(const std::string &filespec);
/// Parse a string data structure
static std::string read_string(boost::uint8_t *entry, size_t length);
static std::string read_string(struct string_entry &entry);
static std::string read_string(std::ifstream &stream);
// Read the header of the datafile
boost::shared_ptr<struct header> read_header(boost::uint8_t *header);
boost::shared_ptr<struct directory_entry> read_dir_entry(boost::uint8_t *header);
std::string &get_contents(const std::string &filespec) { return _contents[filespec]; };
private:
std::string _filespec;
std::map<std::string, std::string> _contents;
};
// C linkage bindings for Guile
extern "C" {
// These are the callbacks for thw guile ports
int xyzzy_fill_input (SCM port);
void xyzzy_write (SCM port, const void *data, size_t size);
void xyzzy_flush (SCM port);
int xyzzy_close (SCM port);
// Initialize with the data file produced by gen-xyzzy.
bool xyzzy_init(const std::string &filespec);
// Does a file with name 'filename' exist in magic filesystem?
bool xyzzy_file_exists(const std::string &filespec);
// Return a C port that will read the file contents
SCM xyzzy_make_read_only_port(const std::string &filespec);
} // end of extern C
#endif // _XYZZY_H_ 1
|