/* -*- c++ -*- */ /* * Copyright 2010 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. */ #include #include #include #include #include #include #include #include #include #include #include // Include our definitions #include "xyzzy.h" using namespace std; typedef void* handle_t; XYZZY::XYZZY() { // nothing to initialize } XYZZY::~XYZZY() { _contents.clear(); } // Initialize with the data file produced by gen-xyzzy. bool XYZZY::init() { _filespec = DATAROOTDIR; _filespec += "/gnuradio/gr-run-waveform/"; _filespec += "filesystem.dat"; return init(_filespec); }; bool XYZZY::init(const std::string &file) { ifstream in(file.c_str(), ios_base::binary|ios_base::in); if (!in) { cerr << ("gr-run-waveform: couldn't open data file: ") << file << endl; return false; } size_t length = sizeof(struct header); char head[length]; in.read(head, length); boost::shared_ptr header = read_header(reinterpret_cast(&head)); // Check the magic number to make sure it's the right type of file. if (strncmp(header->magic, "-XyZzY-", 8) != 0) { cerr << "ERROR: bad magic number" << endl; return false; } // Read in the Directory table length = sizeof(struct directory_entry); char dir[length]; boost::uint32_t ssize; for (size_t i=0; inumber_of_dir_entries; ++i) { in.read(dir, length); int store = in.tellg(); boost::shared_ptr entry = read_dir_entry( reinterpret_cast(dir)); // Get the file name in.seekg(header->offset_to_strings + entry->offset_to_name); string name = XYZZY::read_string(in); // cout << name << endl; // Get the contents, which is one big string in.seekg(header->offset_to_strings + entry->offset_to_contents); string contents = XYZZY::read_string(in); // cout << contents << endl; in.seekg(store); _contents[name] = contents; } // cout << "Loaded " << _contents.size() << " Filesystem entries" << endl; in.close(); return true; }; // Does a file with name 'filename' exist in magic filesystem? // bool file_exists(handle, const std::string &filespec); bool XYZZY::file_exists(const std::string &filespec) { if (filespec.substr(0, 9) == "/-xyzzy-/") { // look for prefix std::map::iterator it; it = _contents.find(filespec.substr(9, filespec.size())); if (it != _contents.end()) { return true; } return false; } return false; } string XYZZY::read_string(boost::uint8_t *entry, size_t length) { string str(reinterpret_cast(entry), length); return str; } string XYZZY::read_string(struct string_entry & entry) { return read_string(entry.base, entry.length); } string XYZZY::read_string(std::ifstream &stream) { boost::uint32_t length; char num[sizeof(boost::uint32_t)]; stream.read(reinterpret_cast(&length), sizeof(boost::uint32_t)); boost::uint32_t len = __builtin_bswap32(length); // All the strings are 32 bit word aligned, so we have to adjust // how many bytes to read. size_t padding = sizeof(boost::uint32_t) - (len % sizeof(boost::uint32_t)); size_t newsize = (padding == 4) ? len : len + padding; char sstr[newsize]; // Read the string stream.read(sstr, newsize); string filespec(reinterpret_cast(sstr), len); return filespec; } boost::shared_ptr XYZZY::read_header(boost::uint8_t *header) { boost::shared_ptr newhead(new struct header); struct header *ptr = reinterpret_cast(header); std::copy(header, header + 8, newhead->magic); newhead->offset_to_directory = __builtin_bswap32(ptr->offset_to_directory); newhead->size_of_directory = __builtin_bswap32(ptr->size_of_directory); newhead->number_of_dir_entries = __builtin_bswap32(ptr->number_of_dir_entries); newhead->offset_to_strings = __builtin_bswap32(ptr->offset_to_strings); newhead->size_of_strings = __builtin_bswap32(ptr->size_of_strings); return newhead; } boost::shared_ptr XYZZY::read_dir_entry(boost::uint8_t *entry) { boost::shared_ptr newdir(new struct directory_entry); struct directory_entry *ptr = reinterpret_cast(entry); newdir->offset_to_name = __builtin_bswap32(ptr->offset_to_name); newdir->offset_to_contents = __builtin_bswap32(ptr->offset_to_contents); return newdir; } // C linkage for guile extern "C" { static XYZZY datafile; SCM xyzzy_open_file(SCM filename) #define FUNC_NAME "xyzzy-open-file" { const char *c_filename = scm_to_locale_string(filename); // fprintf(stderr, "TRACE %s: %d, %s\n", __FUNCTION__, __LINE__, c_filename); if (!xyzzy_file_exists(c_filename)){ SCM_MISC_ERROR("file does not exist: ~S", scm_list_1(filename)); } std::string filespec(c_filename); std::string &contents = datafile.get_contents(filespec.substr(9, filespec.size())); SCM port = scm_open_input_string (scm_from_locale_string (contents.c_str())); return port; } #undef FUNC_NAME // Initialize with the data file produced by gen-xyzzy. int xyzzy_init(const char *filespec) { if (filespec == 0 || *filespec == 0) return datafile.init(); else return datafile.init(filespec); } // Does a file with name 'filename' exist in magic filesystem? int xyzzy_file_exists(const char *filespec) { return datafile.file_exists(filespec); } } // end of extern C