diff --git a/src/actions.cpp b/src/actions.cpp index 04670b0..5dd063b 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -593,15 +593,15 @@ namespace quickbook mapped.start(actions.current_file); mapped.unindent_and_add(first.base(), last.base()); - file const* file_ptr = mapped.release(); + file_ptr f = mapped.release(); - if (file_ptr->source.empty()) + if (f->source.empty()) return; // Nothing left to do here. The program is empty. - parse_iterator first_(file_ptr->source.begin()); - parse_iterator last_(file_ptr->source.end()); + parse_iterator first_(f->source.begin()); + parse_iterator last_(f->source.end()); - file const* saved_file = file_ptr; + file_ptr saved_file = f; boost::swap(actions.current_file, saved_file); // print the code with syntax coloring @@ -1063,7 +1063,7 @@ namespace quickbook , quickbook::actions& actions ) { - file const* saved_current_file = actions.current_file; + file_ptr saved_current_file = actions.current_file; actions.current_file = content.get_file(); string_ref source = content.get_quickbook(); @@ -1792,8 +1792,7 @@ namespace quickbook qbk_version_n >= 106u ? file_state::scope_callables : file_state::scope_macros); - actions.current_file_tmp = load(paths.filename); // Throws load_error - actions.current_file = actions.current_file_tmp; + actions.current_file = load(paths.filename); // Throws load_error actions.filename_relative = paths.filename_relative; actions.imported = (load_type == block_tags::import); diff --git a/src/actions_class.hpp b/src/actions_class.hpp index 7de80b4..a9ebc74 100644 --- a/src/actions_class.hpp +++ b/src/actions_class.hpp @@ -46,15 +46,12 @@ namespace quickbook bool warned_about_breaks; bool conditional; id_manager& ids; - file* current_file_tmp; // Temporary non-const pointer to new - // current_file so that the - // version can be written to. // state saved for files and templates. bool imported; string_symbols macro; std::string source_mode; - file const* current_file; + file_ptr current_file; fs::path filename_relative; // for the __FILENAME__ macro. // (relative to the original file // or include path). diff --git a/src/actions_state.hpp b/src/actions_state.hpp index 3c1db1a..aefa7f9 100644 --- a/src/actions_state.hpp +++ b/src/actions_state.hpp @@ -37,7 +37,7 @@ namespace quickbook unsigned qbk_version; bool imported; std::string doc_type; - file const* current_file; + file_ptr current_file; fs::path filename_relative; fs::path xinclude_base; std::string source_mode; diff --git a/src/code_snippet.cpp b/src/code_snippet.cpp index 1662522..7b726ad 100644 --- a/src/code_snippet.cpp +++ b/src/code_snippet.cpp @@ -26,7 +26,7 @@ namespace quickbook struct code_snippet_actions { code_snippet_actions(std::vector& storage, - file* source_file, + file_ptr source_file, char const* source_type) : last_code_pos(source_file->source.begin()) , in_code(false) @@ -93,7 +93,7 @@ namespace quickbook int callout_id; boost::shared_ptr snippet_stack; std::vector& storage; - file* source_file; + file_ptr source_file; char const* const source_type; }; @@ -521,7 +521,7 @@ namespace quickbook ++i; } - file* body = f.release(); + file_ptr body = f.release(); value_builder builder; builder.set_tag(template_tags::snippet); diff --git a/src/doc_info_actions.cpp b/src/doc_info_actions.cpp index fa8f1c8..6301ddc 100644 --- a/src/doc_info_actions.cpp +++ b/src/doc_info_actions.cpp @@ -228,7 +228,7 @@ namespace quickbook "Version 1.1 is assumed" << std::endl; } - actions.current_file_tmp->version(qbk_version_n); + actions.current_file->version(qbk_version_n); // Compatibility Version diff --git a/src/files.cpp b/src/files.cpp index a2752c4..474cc0a 100644 --- a/src/files.cpp +++ b/src/files.cpp @@ -13,14 +13,13 @@ #include #include #include -#include #include namespace quickbook { namespace { - boost::unordered_map files; + boost::unordered_map files; } // Read the first few bytes in a file to see it starts with a byte order @@ -100,9 +99,9 @@ namespace quickbook } } - file* load(fs::path const& filename, unsigned qbk_version) + file_ptr load(fs::path const& filename, unsigned qbk_version) { - boost::unordered_map::iterator pos + boost::unordered_map::iterator pos = files.find(filename); if (pos == files.end()) @@ -124,15 +123,12 @@ namespace quickbook bool inserted; boost::tie(pos, inserted) = files.emplace( - boost::unordered::piecewise_construct, - boost::make_tuple(filename), - boost::make_tuple(filename, source, qbk_version) - ); + filename, new file(filename, source, qbk_version)); assert(inserted); } - return &pos->second; + return pos->second; } file_position relative_position( @@ -285,11 +281,11 @@ namespace quickbook struct mapped_file : file { - mapped_file(file const* original) : + mapped_file(file_ptr original) : file(original->path, std::string(), original->version()), original(original), mapped_sections() {} - file const* original; + file_ptr original; std::vector mapped_sections; void add_empty_mapped_file_section(std::string::const_iterator pos) { @@ -328,36 +324,33 @@ namespace quickbook struct mapped_file_builder_data { mapped_file_builder_data() { reset(); } - void reset() { new_file = mapped_files.end(); } + void reset() { new_file.reset(); } - std::list::iterator new_file; + boost::intrusive_ptr new_file; }; mapped_file_builder::mapped_file_builder() : data(0) {} mapped_file_builder::~mapped_file_builder() { delete data; } - void mapped_file_builder::start(file const* f) + void mapped_file_builder::start(file_ptr f) { if (!data) { data = new mapped_file_builder_data; } - assert(data->new_file == mapped_files.end()); - mapped_files.push_back(mapped_file(f)); - data->new_file = mapped_files.end(); - --data->new_file; + assert(!data->new_file); + data->new_file = new mapped_file(f); } - file* mapped_file_builder::release() + file_ptr mapped_file_builder::release() { - file* r = &*data->new_file; + file_ptr r = data->new_file; data->reset(); return r; } void mapped_file_builder::clear() { - mapped_files.erase(data->new_file); data->reset(); } diff --git a/src/files.hpp b/src/files.hpp index 220b435..1b0ef28 100644 --- a/src/files.hpp +++ b/src/files.hpp @@ -13,18 +13,17 @@ #include #include +#include #include #include +#include "intrusive_base.hpp" namespace quickbook { namespace fs = boost::filesystem; - struct load_error : std::runtime_error - { - explicit load_error(std::string const& arg) - : std::runtime_error(arg) {} - }; + struct file; + typedef boost::intrusive_ptr file_ptr; struct file_position { @@ -35,7 +34,7 @@ namespace quickbook { int column; }; - struct file + struct file : intrusive_base { fs::path const path; std::string source; @@ -48,7 +47,7 @@ namespace quickbook { path(path), source(source), qbk_version(qbk_version) {} - ~file() {} + virtual ~file() {} unsigned version() const { assert(qbk_version); @@ -67,9 +66,15 @@ namespace quickbook { }; // If version isn't supplied then it must be set later. - file* load(fs::path const& filename, + file_ptr load(fs::path const& filename, unsigned qbk_version = 0); + struct load_error : std::runtime_error + { + explicit load_error(std::string const& arg) + : std::runtime_error(arg) {} + }; + // Interface for creating fake files which are mapped to // real files, so that the position can be found later. @@ -83,8 +88,8 @@ namespace quickbook { mapped_file_builder(); ~mapped_file_builder(); - void start(file const*); - file* release(); + void start(file_ptr); + file_ptr release(); void clear(); bool empty() const; diff --git a/src/fwd.hpp b/src/fwd.hpp index 5e8a0e1..7995c14 100644 --- a/src/fwd.hpp +++ b/src/fwd.hpp @@ -12,6 +12,7 @@ #define BOOST_SPIRIT_FWD_HPP #include "iterator.hpp" +#include namespace quickbook { @@ -21,6 +22,7 @@ namespace quickbook struct id_manager; struct section_info; struct file; + typedef boost::intrusive_ptr file_ptr; typedef std::string::const_iterator string_iterator; typedef lookback_iterator parse_iterator; diff --git a/src/id_manager.cpp b/src/id_manager.cpp index 28350bc..e1c44c5 100644 --- a/src/id_manager.cpp +++ b/src/id_manager.cpp @@ -9,6 +9,7 @@ #include "id_manager.hpp" #include "utils.hpp" #include "string_ref.hpp" +#include "intrusive_base.hpp" #include #include #include @@ -30,32 +31,6 @@ namespace quickbook static const std::size_t max_size = 32; - // - // instructive_base - // - // I should probably make this a recursive template, or use SFINAE to check - // the release is correct, or maybe use a virtual destructor. But I'm - // feeling reckless. - // - - struct intrusive_base - { - intrusive_base() : ref_count_(0) {} - intrusive_base(intrusive_base const&) : ref_count_(0) {} - intrusive_base& operator=(intrusive_base const&) { return *this; } - ~intrusive_base() { assert(!ref_count_); } - - unsigned ref_count_; - - friend void intrusive_ptr_add_ref(intrusive_base* ptr) - { ++ptr->ref_count_; } - - template - friend void intrusive_ptr_release(T* ptr) - { if(--ptr->ref_count_ == 0) delete ptr; } - private: - }; - // // id_placeholder // @@ -176,7 +151,7 @@ private: void restore_section(); }; - struct file_info : intrusive_base + struct file_info : intrusive_base { boost::intrusive_ptr parent; boost::intrusive_ptr document; @@ -207,7 +182,7 @@ private: {} }; - struct doc_info : intrusive_base + struct doc_info : intrusive_base { boost::intrusive_ptr current_section; std::string last_title_1_1; @@ -218,7 +193,7 @@ private: {} }; - struct section_info : intrusive_base + struct section_info : intrusive_base { boost::intrusive_ptr parent; unsigned compatibility_version; @@ -820,7 +795,7 @@ private: // Data used for generating placeholders that have duplicates. // - struct id_generation_data : intrusive_base + struct id_generation_data : intrusive_base { id_generation_data(std::string const& src_id) : child_start(src_id.rfind('.') + 1), diff --git a/src/input_path.cpp b/src/input_path.cpp index b0f8185..7e98ffb 100644 --- a/src/input_path.cpp +++ b/src/input_path.cpp @@ -230,7 +230,7 @@ namespace detail { } } - ostream& outerr(file const* f, string_iterator pos) + ostream& outerr(file_ptr const& f, string_iterator pos) { return outerr(f->path, f->position_of(pos).line); } @@ -250,7 +250,7 @@ namespace detail { } } - ostream& outwarn(file const* f, string_iterator pos) + ostream& outwarn(file_ptr const& f, string_iterator pos) { return outwarn(f->path, f->position_of(pos).line); } diff --git a/src/input_path.hpp b/src/input_path.hpp index 2f59eeb..a23474d 100644 --- a/src/input_path.hpp +++ b/src/input_path.hpp @@ -92,8 +92,8 @@ namespace quickbook ostream& outerr(); ostream& outerr(fs::path const& file, int line = -1); ostream& outwarn(fs::path const& file, int line = -1); - ostream& outerr(file const*, string_iterator); - ostream& outwarn(file const*, string_iterator); + ostream& outerr(file_ptr const&, string_iterator); + ostream& outwarn(file_ptr const&, string_iterator); struct utf8_proxy { diff --git a/src/intrusive_base.hpp b/src/intrusive_base.hpp new file mode 100644 index 0000000..702c13d --- /dev/null +++ b/src/intrusive_base.hpp @@ -0,0 +1,36 @@ +/*============================================================================= + Copyright (c) 2011 Daniel James + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +#if !defined(BOOST_QUICKBOOK_INTRUSIVE_BASE_HPP) +#define BOOST_QUICKBOOK_INTRUSIVE_BASE_HPP + +namespace quickbook +{ + // + // instructive_base + // + + template + struct intrusive_base + { + intrusive_base() : ref_count_(0) {} + intrusive_base(intrusive_base const&) : ref_count_(0) {} + intrusive_base& operator=(intrusive_base const&) { return *this; } + ~intrusive_base() { assert(!ref_count_); } + + friend void intrusive_ptr_add_ref(T* ptr) + { ++ptr->ref_count_; } + + friend void intrusive_ptr_release(T* ptr) + { if(--ptr->ref_count_ == 0) delete ptr; } + private: + unsigned ref_count_; + }; +} + +#endif diff --git a/src/quickbook.cpp b/src/quickbook.cpp index c5f6bb0..7635e96 100644 --- a/src/quickbook.cpp +++ b/src/quickbook.cpp @@ -118,8 +118,7 @@ namespace quickbook actions actor(filein_, xinclude_base_, buffer, ids); set_macros(actor); - actor.current_file_tmp = load(filein_); // Throws load_error - actor.current_file = actor.current_file_tmp; + actor.current_file = load(filein_); // Throws load_error parse_file(actor); diff --git a/src/values.cpp b/src/values.cpp index 52aa9c2..e448073 100644 --- a/src/values.cpp +++ b/src/values.cpp @@ -47,7 +47,7 @@ namespace quickbook value_node::~value_node() { } - file const* value_node::get_file() const { UNDEFINED_ERROR(); } + file_ptr value_node::get_file() const { UNDEFINED_ERROR(); } string_iterator value_node::get_position() const { UNDEFINED_ERROR(); } int value_node::get_int() const { UNDEFINED_ERROR(); } string_ref value_node::get_quickbook() const { UNDEFINED_ERROR(); } @@ -321,7 +321,7 @@ namespace quickbook { public: explicit value_qbk_ref_impl( - file const*, + file_ptr const&, string_iterator begin, string_iterator end, value::tag_type); @@ -330,13 +330,13 @@ namespace quickbook virtual ~value_qbk_ref_impl(); virtual value_node* clone() const; - virtual file const* get_file() const; + virtual file_ptr get_file() const; virtual string_iterator get_position() const; virtual string_ref get_quickbook() const; virtual bool empty() const; virtual bool equals(value_node*) const; - file const* file_; + file_ptr file_; string_iterator begin_; string_iterator end_; }; @@ -346,13 +346,13 @@ namespace quickbook private: char const* type_name() const { return "quickbook/boostbook"; } - value_qbk_bbk_impl(file const*, + value_qbk_bbk_impl(file_ptr const&, string_iterator, string_iterator, std::string const&, value::tag_type); virtual ~value_qbk_bbk_impl(); virtual value_node* clone() const; - virtual file const* get_file() const; + virtual file_ptr get_file() const; virtual string_iterator get_position() const; virtual string_ref get_quickbook() const; virtual std::string get_boostbook() const; @@ -360,13 +360,13 @@ namespace quickbook virtual bool is_encoded() const; virtual bool equals(value_node*) const; - file const* file_; + file_ptr file_; string_iterator begin_; string_iterator end_; std::string bbk_value_; friend quickbook::value quickbook::qbk_bbk_value( - file const*, string_iterator, string_iterator, + file_ptr const&, string_iterator, string_iterator, std::string const&, quickbook::value::tag_type); }; @@ -410,7 +410,7 @@ namespace quickbook // value_qbk_ref_impl value_qbk_ref_impl::value_qbk_ref_impl( - file const* f, + file_ptr const& f, string_iterator begin, string_iterator end, value::tag_type tag @@ -427,7 +427,7 @@ namespace quickbook return new value_qbk_ref_impl(file_, begin_, end_, tag_); } - file const* value_qbk_ref_impl::get_file() const + file_ptr value_qbk_ref_impl::get_file() const { return file_; } string_iterator value_qbk_ref_impl::get_position() const @@ -451,7 +451,7 @@ namespace quickbook // value_qbk_bbk_impl value_qbk_bbk_impl::value_qbk_bbk_impl( - file const* f, + file_ptr const& f, string_iterator begin, string_iterator end, std::string const& bbk, @@ -475,7 +475,7 @@ namespace quickbook file_, begin_, end_, bbk_value_, tag_); } - file const* value_qbk_bbk_impl::get_file() const + file_ptr value_qbk_bbk_impl::get_file() const { return file_; } string_iterator value_qbk_bbk_impl::get_position() const @@ -509,7 +509,7 @@ namespace quickbook } } - value qbk_value_ref(file const* f, string_iterator x, string_iterator y, value::tag_type t) + value qbk_value_ref(file_ptr const& f, string_iterator x, string_iterator y, value::tag_type t) { return value(new detail::value_qbk_ref_impl(f, x, y, t)); } @@ -520,7 +520,7 @@ namespace quickbook } value qbk_bbk_value( - file const* f, string_iterator x, string_iterator y, + file_ptr const& f, string_iterator x, string_iterator y, std::string const& z, value::tag_type t) { return value(new detail::value_qbk_bbk_impl(f,x,y,z,t)); diff --git a/src/values.hpp b/src/values.hpp index ca3a407..4776bea 100644 --- a/src/values.hpp +++ b/src/values.hpp @@ -19,6 +19,7 @@ #include #include "fwd.hpp" #include "string_ref.hpp" +#include "files.hpp" namespace quickbook { @@ -48,7 +49,7 @@ namespace quickbook virtual char const* type_name() const = 0; virtual value_node* clone() const = 0; - virtual file const* get_file() const; + virtual file_ptr get_file() const; virtual string_iterator get_position() const; virtual string_ref get_quickbook() const; virtual std::string get_boostbook() const; @@ -108,7 +109,7 @@ namespace quickbook // Item accessors int get_tag() const { return value_->tag_; } - file const* get_file() const + file_ptr get_file() const { return value_->get_file(); } string_iterator get_position() const { return value_->get_position(); } @@ -239,9 +240,9 @@ namespace quickbook value int_value(int, value::tag_type = value::default_tag); // Boostbook and quickbook strings - value qbk_value_ref(file const*, string_iterator, string_iterator, value::tag_type = value::default_tag); + value qbk_value_ref(file_ptr const&, string_iterator, string_iterator, value::tag_type = value::default_tag); value bbk_value(std::string const&, value::tag_type = value::default_tag); - value qbk_bbk_value(file const*, string_iterator, string_iterator, std::string const&, + value qbk_bbk_value(file_ptr const&, string_iterator, string_iterator, std::string const&, value::tag_type = value::default_tag); //////////////////////////////////////////////////////////////////////////// diff --git a/src/values_parse.hpp b/src/values_parse.hpp index c37d0e7..db175a1 100644 --- a/src/values_parse.hpp +++ b/src/values_parse.hpp @@ -57,7 +57,7 @@ namespace quickbook { typedef void type; }; - value_entry(value_builder& b, file const** current_file) + value_entry(value_builder& b, file_ptr* current_file) : b(b), current_file(current_file) {} void operator()(parse_iterator begin, parse_iterator end, @@ -73,7 +73,7 @@ namespace quickbook { } value_builder& b; - file const** current_file; + file_ptr* current_file; }; struct value_sort @@ -92,7 +92,7 @@ namespace quickbook { struct value_parser { - value_parser(file const** current_file) + value_parser(file_ptr* current_file) : builder() , save(builder) , list(builder) diff --git a/test/unit/values_test.cpp b/test/unit/values_test.cpp index 8070a73..dbc3c7e 100644 --- a/test/unit/values_test.cpp +++ b/test/unit/values_test.cpp @@ -25,13 +25,17 @@ void empty_tests() void qbk_tests() { - quickbook::file fake_file( - "(fake file)", "Source", 105u); - quickbook::value q = quickbook::qbk_value_ref( - &fake_file, - fake_file.source.begin(), - fake_file.source.end()); - BOOST_TEST_EQ(q.get_quickbook(), fake_file.source); + std::string source = "Source"; + quickbook::value q; + { + quickbook::file_ptr fake_file = new quickbook::file( + "(fake file)", source, 105u); + q = quickbook::qbk_value_ref( + fake_file, + fake_file->source.begin(), + fake_file->source.end()); + } + BOOST_TEST_EQ(q.get_quickbook(), source); } void sort_test()