我想要做的是,在 boost::wave 中的 c 类文件的预处理期间(我实际上正在处理 glsl 文件),而不是从磁盘加载包含的文件,我想从地图中“加载”它们,其中map.first 是文件名,map.second 是内容。
我需要为输入策略的内部类提供这些文件名/文件内容的映射。但是,我不确定如何才能真正将地图放入内部类......
上下文是这样创建的:
typedef boost::wave::context<
std::string::iterator,
lex_iterator_type,
custom_directives_hooks::load_file_or_string_to_string,
custom_directives_hooks
> context_type;
自定义指令是这样的(在底部附近定义了自定义输入策略):
#if !defined(BOOST_WAVE_CUSTOM_DIRECTIVES_HOOKS_INCLUDED)
#define BOOST_WAVE_CUSTOM_DIRECTIVES_HOOKS_INCLUDED
#include <cstdio>
#include <iostream>
#include <ostream>
#include <string>
#include <algorithm>
#include <map>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/util/macro_helpers.hpp>
#include <boost/wave/preprocessing_hooks.hpp>
#include <boost/wave/cpp_iteration_context.hpp>
#include <iterator>
#include <fstream>
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
#include <sstream>
#endif
#include <boost/wave/wave_config.hpp>
#include <boost/wave/cpp_exceptions.hpp>
#include <boost/wave/language_support.hpp>
#include <boost/wave/util/file_position.hpp>
namespace wave = boost::wave;
class custom_directives_hooks
: public wave::context_policies::default_preprocessing_hooks
{
public:
custom_directives_hooks(std::map<std::string, std::string> files) : files_(files) {
}
//custom_directives_hooks(std::set<std::string> &files_) : files(files_), include_depth(0) {
//}
template <typename ContextT, typename ContainerT>
bool
found_unknown_directive(ContextT const& ctx, ContainerT const& line,
ContainerT& pending)
{
typedef typename ContainerT::const_iterator iterator_type;
iterator_type it = line.begin();
wave::token_id id = wave::util::impl::skip_whitespace(it, line.end());
if (id != wave::T_IDENTIFIER)
return false; // nothing we could do
if ((*it).get_value() == "version" || (*it).get_value() == "extension") {
// Handle #version and #extension directives
std::copy(line.begin(), line.end(), std::back_inserter(pending));
return true;
}
if ( (*it).get_value() == "type") {
// Handle type directive
return true;
}
// Unknown directive
return false;
}
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
void opened_include_file(std::string const &relname, std::string const &filename,
std::size_t /*include_depth*/, bool is_system_include)
#else
template <typename ContextT>
void opened_include_file(ContextT const& ctx, std::string const& relname,
std::string const& filename, bool is_system_include)
#endif
{
std::cout << "opened_include_file: " << "relname: " << relname << " filename: " << filename << " is_system_include: " << is_system_include << std::endl;
/*
std::set<std::string>::iterator it = files.find(filename);
if (it == files.end()) {
// print indented filename
for (std::size_t i = 0; i < include_depth; ++i)
std::cout << " ";
std::cout << filename << std::endl;
files.insert(filename);
}
++include_depth;
*/
}
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
void returning_from_include_file()
#else
template <typename ContextT>
void returning_from_include_file(ContextT const& ctx)
#endif
{
//--include_depth;
}
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
// old signature
void
found_include_directive(std::string const& filename, bool include_next)
{}
#else
// new signature
template <typename ContextT>
bool
found_include_directive(ContextT const& ctx, std::string const& filename, bool include_next) {
std::cout << "found_include_directive:" << filename << std::endl;
return false; // ok to include this file
}
#endif
template <typename ContextT>
bool
locate_include_file(ContextT& ctx, std::string &file_path,
bool is_system, char const *current_name, std::string &dir_path,
std::string &native_name)
{
// Check if file is in the files map
if (files_.find(file_path) != files_.end()) {
std::cout << "locate_include_file: file_path:" << file_path << " dir_path:" << dir_path << " native_name:" << native_name << std::endl;
native_name = file_path;
} else {
if (!ctx.find_include_file (file_path, dir_path, is_system, current_name))
return false; // could not locate file
namespace fs = boost::filesystem;
fs::path native_path(wave::util::create_path(file_path));
if (!fs::exists(native_path)) {
//BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_include_file,
// file_path.c_str(), ctx.get_main_pos());
std::cout << "error: doesn't exist" << std::endl;
return false;
}
// return the unique full file system path of the located file
native_name = wave::util::native_file_string(native_path);
}
typedef typename ContextT::iterator_type iterator_type;
std::streambuf* buffer = nullptr;
wave::language_support language();
ctx.instring.assign(
std::istreambuf_iterator<char>(buffer),
std::istreambuf_iterator<char>());
ctx.first = iterator_type(
ctx.instring.begin(), ctx.instring.end(),
PositionT(ctx.filename), language);
ctx.last = iterator_type();
return true; // include file has been located successfully
}
struct load_file_or_string_to_string
{
template <typename IterContextT>
class inner
{
public:
template <typename PositionT>
static void init_iterators(IterContextT &iter_ctx,
PositionT const &act_pos, wave::language_support language)
{
static std::map<std::string, std::string> theFiles;
typedef typename IterContextT::iterator_type iterator_type;
std::cout << "init_iterators: " << iter_ctx.filename << std::endl;
std::streambuf* buffer = nullptr;
const char* cString = iter_ctx.filename.c_str();
if (theFiles.find(std::string(cString)) != theFiles.end()) {
std::stringstream ss( theFiles[std::string(cString)] );
buffer = ss.rdbuf();
} else {
// read in the file
std::ifstream instream(iter_ctx.filename.c_str());
if (!instream.is_open()) {
//BOOST_WAVE_THROW_CTX(iter_ctx.ctx, wave::preprocess_exception,
// wave::bad_include_file, iter_ctx.filename.c_str(), act_pos);
std::cout << "error: not open" << std::endl;
return;
}
instream.unsetf(std::ios::skipws);
buffer = instream.rdbuf();
}
iter_ctx.instring.assign(
std::istreambuf_iterator<char>(buffer),
std::istreambuf_iterator<char>());
iter_ctx.first = iterator_type(
iter_ctx.instring.begin(), iter_ctx.instring.end(),
PositionT(iter_ctx.filename), language);
iter_ctx.last = iterator_type();
}
private:
std::string instring;
};
};
std::map<std::string, std::string> files_;
};
#endif // !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
有没有人有什么建议??