summaryrefslogtreecommitdiff
path: root/gr-run-waveform/xyzzy.h
blob: d56e48763238d3ab8e0892b725ab7fcf0c66302c (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
/* -*- 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 <iostream>
#include <fstream>
#include <boost/cstdint.hpp>
#include <boost/shared_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);

    boost::shared_ptr<struct header> read_header(boost::uint8_t *header);
    
    boost::shared_ptr<struct directory_entry> read_dir_entry(boost::uint8_t *header);
    
private:
    std::string   _filespec;
    std::map<std::string, directory_entry> _directories;
};

// C linkage bindings for Guile
extern "C" {
    
// 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