title: Boost Wave custom input policy
body: <p>What I'm trying to do is, during preprocessing of c like files in
  boost::wave (I'm actually processing glsl files), instead of loading
  included files from disk, I want to 'load' them from a map, where map.first is the filename and map.second is the contents.</p>
  
  <p>I need to give the inner class of the input policy a map of these
  filenames/file contents.  However, I'm not sure how I can actually get a
  map into the inner class...</p>
  
  <p>The context is created like so:</p>
  
  <pre><code>typedef boost::wave::context&lt;
                  std::string::iterator, 
                  lex_iterator_type,
                  custom_directives_hooks::load_file_or_string_to_string,
                  custom_directives_hooks
              &gt; context_type;
  </code></pre>
  
  <p>And custom directives is like so (with the custom input policy defined near the bottom):</p>
  
  <pre><code>#if !defined(BOOST_WAVE_CUSTOM_DIRECTIVES_HOOKS_INCLUDED)
  #define BOOST_WAVE_CUSTOM_DIRECTIVES_HOOKS_INCLUDED
  
  #include &lt;cstdio&gt;
  #include &lt;iostream&gt;
  #include &lt;ostream&gt;
  #include &lt;string&gt;
  #include &lt;algorithm&gt;
  #include &lt;map&gt;
  
  #include &lt;boost/assert.hpp&gt;
  #include &lt;boost/config.hpp&gt;
  
  #include &lt;boost/wave/token_ids.hpp&gt;
  #include &lt;boost/wave/util/macro_helpers.hpp&gt;
  #include &lt;boost/wave/preprocessing_hooks.hpp&gt;
  #include &lt;boost/wave/cpp_iteration_context.hpp&gt;
  
  #include &lt;iterator&gt;
  #include &lt;fstream&gt;
  #if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
  #include &lt;sstream&gt;
  #endif
  
  #include &lt;boost/wave/wave_config.hpp&gt;
  #include &lt;boost/wave/cpp_exceptions.hpp&gt;
  #include &lt;boost/wave/language_support.hpp&gt;
  #include &lt;boost/wave/util/file_position.hpp&gt;
  
  namespace wave = boost::wave;
  
  class custom_directives_hooks
  :   public wave::context_policies::default_preprocessing_hooks
  {
  public:
  
      custom_directives_hooks(std::map&lt;std::string, std::string&gt; files) : files_(files) {
      }
  
      //custom_directives_hooks(std::set&lt;std::string&gt; &amp;files_) : files(files_), include_depth(0) {
      //}
  
      template &lt;typename ContextT, typename ContainerT&gt;
      bool
      found_unknown_directive(ContextT const&amp; ctx, ContainerT const&amp; line, 
          ContainerT&amp; 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 &amp;relname, std::string const &amp;filename, 
          std::size_t /*include_depth*/, bool is_system_include) 
  #else
      template &lt;typename ContextT&gt;
      void opened_include_file(ContextT const&amp; ctx, std::string const&amp; relname, 
          std::string const&amp; filename, bool is_system_include) 
  #endif
      {
          std::cout &lt;&lt; "opened_include_file: " &lt;&lt; "relname: " &lt;&lt; relname &lt;&lt; " filename: " &lt;&lt; filename &lt;&lt; " is_system_include: " &lt;&lt; is_system_include &lt;&lt; std::endl;
          /*
          std::set&lt;std::string&gt;::iterator it = files.find(filename);
  
          if (it == files.end()) {
              // print indented filename
              for (std::size_t i = 0; i &lt; include_depth; ++i)
                  std::cout &lt;&lt; " ";
              std::cout &lt;&lt; filename &lt;&lt; std::endl;
  
              files.insert(filename);
          }
          ++include_depth;
          */
      }
  
  #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
      void returning_from_include_file() 
  #else
      template &lt;typename ContextT&gt;
      void returning_from_include_file(ContextT const&amp; ctx) 
  #endif
      {
          //--include_depth;
      }
  
  #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
      // old signature
      void 
      found_include_directive(std::string const&amp; filename, bool include_next) 
      {}
  #else
      // new signature
      template &lt;typename ContextT&gt;
      bool 
      found_include_directive(ContextT const&amp; ctx, std::string const&amp; filename, bool include_next) {
          std::cout &lt;&lt; "found_include_directive:" &lt;&lt; filename &lt;&lt; std::endl;
  
          return false;    // ok to include this file
      }
  #endif
  
  
      template &lt;typename ContextT&gt;
      bool 
      locate_include_file(ContextT&amp; ctx, std::string &amp;file_path, 
          bool is_system, char const *current_name, std::string &amp;dir_path, 
          std::string &amp;native_name) 
      {
          // Check if file is in the files map
          if (files_.find(file_path) != files_.end()) {
              std::cout &lt;&lt; "locate_include_file: file_path:" &lt;&lt; file_path &lt;&lt; " dir_path:" &lt;&lt; dir_path &lt;&lt; " native_name:" &lt;&lt; native_name &lt;&lt; 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 &lt;&lt; "error: doesn't exist" &lt;&lt; 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&lt;char&gt;(buffer),
              std::istreambuf_iterator&lt;char&gt;());
  
          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 &lt;typename IterContextT&gt;
          class inner
          {
          public:     
              template &lt;typename PositionT&gt;
              static void init_iterators(IterContextT &amp;iter_ctx,
                  PositionT const &amp;act_pos, wave::language_support language)
              {
                  static std::map&lt;std::string, std::string&gt; theFiles;
  
                  typedef typename IterContextT::iterator_type iterator_type;
  
                  std::cout &lt;&lt; "init_iterators: " &lt;&lt; iter_ctx.filename &lt;&lt; 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 &lt;&lt; "error: not open" &lt;&lt; std::endl;
                          return;
                      }
                      instream.unsetf(std::ios::skipws);
                      buffer = instream.rdbuf();
                  }
  
                  iter_ctx.instring.assign(
                      std::istreambuf_iterator&lt;char&gt;(buffer),
                      std::istreambuf_iterator&lt;char&gt;());
  
                  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&lt;std::string, std::string&gt; files_;
  };
  
  #endif // !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
  </code></pre>
  
  <p>Does anyone have any suggestions??</p>