| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092 | ////  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)////  Distributed under 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)//#ifndef BOOST_LOCALE_BOUNDARY_INDEX_HPP_INCLUDED#define BOOST_LOCALE_BOUNDARY_INDEX_HPP_INCLUDED#include <boost/locale/config.hpp>#include <boost/locale/boundary/types.hpp>#include <boost/locale/boundary/facets.hpp>#include <boost/locale/boundary/segment.hpp>#include <boost/locale/boundary/boundary_point.hpp>#include <boost/iterator/iterator_facade.hpp>#include <boost/type_traits/is_same.hpp>#include <boost/shared_ptr.hpp>#include <boost/cstdint.hpp>#include <boost/assert.hpp>#ifdef BOOST_MSVC#  pragma warning(push)#  pragma warning(disable : 4275 4251 4231 4660)#endif#include <string>#include <locale>#include <vector>#include <iterator>#include <algorithm>#include <stdexcept>#include <iostream>namespace boost {    namespace locale {                namespace boundary {            ///            /// \defgroup boundary Boundary Analysis            ///            /// This module contains all operations required for %boundary analysis of text: character, word, like and sentence boundaries            ///            /// @{            ///            /// \cond INTERNAL            namespace details {                template<typename IteratorType,typename CategoryType = typename std::iterator_traits<IteratorType>::iterator_category>                struct mapping_traits {                    typedef typename std::iterator_traits<IteratorType>::value_type char_type;                    static index_type map(boundary_type t,IteratorType b,IteratorType e,std::locale const &l)                    {                        std::basic_string<char_type> str(b,e);                        return std::use_facet<boundary_indexing<char_type> >(l).map(t,str.c_str(),str.c_str()+str.size());                    }                };                template<typename CharType,typename SomeIteratorType>                struct linear_iterator_traits {                    static const bool is_linear =                        is_same<SomeIteratorType,CharType*>::value                        || is_same<SomeIteratorType,CharType const*>::value                        || is_same<SomeIteratorType,typename std::basic_string<CharType>::iterator>::value                        || is_same<SomeIteratorType,typename std::basic_string<CharType>::const_iterator>::value                        || is_same<SomeIteratorType,typename std::vector<CharType>::iterator>::value                        || is_same<SomeIteratorType,typename std::vector<CharType>::const_iterator>::value                        ;                };                template<typename IteratorType>                struct mapping_traits<IteratorType,std::random_access_iterator_tag> {                    typedef typename std::iterator_traits<IteratorType>::value_type char_type;                    static index_type map(boundary_type t,IteratorType b,IteratorType e,std::locale const &l)                    {                        index_type result;                        //                        // Optimize for most common cases                        //                        // C++0x requires that string is continious in memory and all known                        // string implementations                        // do this because of c_str() support.                         //                        if(linear_iterator_traits<char_type,IteratorType>::is_linear && b!=e)                        {                            char_type const *begin = &*b;                            char_type const *end = begin + (e-b);                            index_type tmp=std::use_facet<boundary_indexing<char_type> >(l).map(t,begin,end);                            result.swap(tmp);                        }                        else {                            std::basic_string<char_type> str(b,e);                            index_type tmp = std::use_facet<boundary_indexing<char_type> >(l).map(t,str.c_str(),str.c_str()+str.size());                            result.swap(tmp);                        }                        return result;                    }                };                template<typename BaseIterator>                class mapping {                public:                    typedef BaseIterator base_iterator;                    typedef typename std::iterator_traits<base_iterator>::value_type char_type;                    mapping(boundary_type type,                            base_iterator begin,                            base_iterator end,                            std::locale const &loc)                         :                               index_(new index_type()),                            begin_(begin),                            end_(end)                    {                        index_type idx=details::mapping_traits<base_iterator>::map(type,begin,end,loc);                        index_->swap(idx);                    }                    mapping()                    {                    }                    index_type const &index() const                    {                        return *index_;                    }                    base_iterator begin() const                    {                        return begin_;                    }                    base_iterator end() const                    {                        return end_;                    }                private:                    boost::shared_ptr<index_type> index_;                    base_iterator begin_,end_;                };                template<typename BaseIterator>                class segment_index_iterator :                     public boost::iterator_facade<                        segment_index_iterator<BaseIterator>,                        segment<BaseIterator>,                        boost::bidirectional_traversal_tag,                        segment<BaseIterator> const &                    >                {                public:                    typedef BaseIterator base_iterator;                    typedef mapping<base_iterator> mapping_type;                    typedef segment<base_iterator> segment_type;                                        segment_index_iterator() : current_(0,0),map_(0)                    {                    }                    segment_index_iterator(base_iterator p,mapping_type const *map,rule_type mask,bool full_select) :                        map_(map),                        mask_(mask),                        full_select_(full_select)                    {                        set(p);                    }                    segment_index_iterator(bool is_begin,mapping_type const *map,rule_type mask,bool full_select) :                        map_(map),                        mask_(mask),                        full_select_(full_select)                    {                        if(is_begin)                            set_begin();                        else                            set_end();                    }                    segment_type const &dereference() const                    {                        return value_;                    }                    bool equal(segment_index_iterator const &other) const                    {                        return map_ == other.map_ && current_.second == other.current_.second;                    }                    void increment()                    {                        std::pair<size_t,size_t> next = current_;                        if(full_select_) {                            next.first = next.second;                            while(next.second < size()) {                                next.second++;                                if(valid_offset(next.second))                                    break;                            }                            if(next.second == size())                                next.first = next.second - 1;                        }                        else {                            while(next.second < size()) {                                next.first = next.second;                                next.second++;                                if(valid_offset(next.second))                                    break;                            }                        }                        update_current(next);                    }                    void decrement()                    {                        std::pair<size_t,size_t> next = current_;                        if(full_select_) {                            while(next.second >1) {                                next.second--;                                if(valid_offset(next.second))                                    break;                            }                            next.first = next.second;                            while(next.first >0) {                                next.first--;                                if(valid_offset(next.first))                                    break;                            }                        }                        else {                            while(next.second >1) {                                next.second--;                                if(valid_offset(next.second))                                    break;                            }                            next.first = next.second - 1;                        }                        update_current(next);                    }                private:                    void set_end()                    {                        current_.first  = size() - 1;                        current_.second = size();                        value_ = segment_type(map_->end(),map_->end(),0);                    }                    void set_begin()                    {                        current_.first = current_.second = 0;                        value_ = segment_type(map_->begin(),map_->begin(),0);                        increment();                    }                    void set(base_iterator p)                    {                        size_t dist=std::distance(map_->begin(),p);                        index_type::const_iterator b=map_->index().begin(),e=map_->index().end();                        index_type::const_iterator                             boundary_point=std::upper_bound(b,e,break_info(dist));                        while(boundary_point != e && (boundary_point->rule & mask_)==0)                            boundary_point++;                        current_.first = current_.second = boundary_point - b;                                                if(full_select_) {                            while(current_.first > 0) {                                current_.first --;                                if(valid_offset(current_.first))                                    break;                            }                        }                        else {                            if(current_.first > 0)                                current_.first --;                        }                        value_.first = map_->begin();                        std::advance(value_.first,get_offset(current_.first));                        value_.second = value_.first;                        std::advance(value_.second,get_offset(current_.second) - get_offset(current_.first));                        update_rule();                    }                    void update_current(std::pair<size_t,size_t> pos)                    {                        std::ptrdiff_t first_diff = get_offset(pos.first) - get_offset(current_.first);                        std::ptrdiff_t second_diff = get_offset(pos.second) - get_offset(current_.second);                        std::advance(value_.first,first_diff);                        std::advance(value_.second,second_diff);                        current_ = pos;                        update_rule();                    }                    void update_rule()                    {                        if(current_.second != size()) {                            value_.rule(index()[current_.second].rule);                        }                    }                    size_t get_offset(size_t ind) const                    {                        if(ind == size())                            return index().back().offset;                        return index()[ind].offset;                    }                    bool valid_offset(size_t offset) const                    {                        return  offset == 0                                 || offset == size() // make sure we not acess index[size]                                || (index()[offset].rule & mask_)!=0;                    }                                        size_t size() const                    {                        return index().size();                    }                                        index_type const &index() const                    {                        return map_->index();                    }                                                        segment_type value_;                    std::pair<size_t,size_t> current_;                    mapping_type const *map_;                    rule_type mask_;                    bool full_select_;                };                                            template<typename BaseIterator>                class boundary_point_index_iterator :                     public boost::iterator_facade<                        boundary_point_index_iterator<BaseIterator>,                        boundary_point<BaseIterator>,                        boost::bidirectional_traversal_tag,                        boundary_point<BaseIterator> const &                    >                {                public:                    typedef BaseIterator base_iterator;                    typedef mapping<base_iterator> mapping_type;                    typedef boundary_point<base_iterator> boundary_point_type;                                        boundary_point_index_iterator() : current_(0),map_(0)                    {                    }                    boundary_point_index_iterator(bool is_begin,mapping_type const *map,rule_type mask) :                        map_(map),                        mask_(mask)                    {                        if(is_begin)                            set_begin();                        else                            set_end();                    }                    boundary_point_index_iterator(base_iterator p,mapping_type const *map,rule_type mask) :                        map_(map),                        mask_(mask)                    {                        set(p);                    }                    boundary_point_type const &dereference() const                    {                        return value_;                    }                    bool equal(boundary_point_index_iterator const &other) const                    {                        return map_ == other.map_ && current_ == other.current_;                    }                    void increment()                    {                        size_t next = current_;                        while(next < size()) {                            next++;                            if(valid_offset(next))                                break;                        }                        update_current(next);                    }                    void decrement()                    {                        size_t next = current_;                        while(next>0) {                            next--;                            if(valid_offset(next))                                break;                        }                        update_current(next);                    }                private:                    void set_end()                    {                        current_ = size();                        value_ = boundary_point_type(map_->end(),0);                    }                    void set_begin()                    {                        current_ = 0;                        value_ = boundary_point_type(map_->begin(),0);                    }                    void set(base_iterator p)                    {                        size_t dist =  std::distance(map_->begin(),p);                        index_type::const_iterator b=index().begin();                        index_type::const_iterator e=index().end();                        index_type::const_iterator ptr = std::lower_bound(b,e,break_info(dist));                        if(ptr==index().end())                            current_=size()-1;                        else                            current_=ptr - index().begin();                        while(!valid_offset(current_))                            current_ ++;                        std::ptrdiff_t diff = get_offset(current_) - dist;                        std::advance(p,diff);                        value_.iterator(p);                        update_rule();                    }                    void update_current(size_t pos)                    {                        std::ptrdiff_t diff = get_offset(pos) - get_offset(current_);                        base_iterator i=value_.iterator();                        std::advance(i,diff);                        current_ = pos;                        value_.iterator(i);                        update_rule();                    }                    void update_rule()                    {                        if(current_ != size()) {                            value_.rule(index()[current_].rule);                        }                    }                    size_t get_offset(size_t ind) const                    {                        if(ind == size())                            return index().back().offset;                        return index()[ind].offset;                    }                    bool valid_offset(size_t offset) const                    {                        return  offset == 0                                 || offset + 1 >= size() // last and first are always valid regardless of mark                                || (index()[offset].rule & mask_)!=0;                    }                                        size_t size() const                    {                        return index().size();                    }                                        index_type const &index() const                    {                        return map_->index();                    }                                                        boundary_point_type value_;                    size_t current_;                    mapping_type const *map_;                    rule_type mask_;                };            } // details            /// \endcond            template<typename BaseIterator>            class segment_index;            template<typename BaseIterator>            class boundary_point_index;                        ///            /// \brief This class holds an index of segments in the text range and allows to iterate over them             ///            /// This class is provides \ref begin() and \ref end() member functions that return bidirectional iterators            /// to the \ref segment objects.            ///            /// It provides two options on way of selecting segments:            ///            /// -   \ref rule(rule_type mask) - a mask that allows to select only specific types of segments according to            ///     various masks %as \ref word_any.            ///     \n            ///     The default is to select any types of boundaries.            ///     \n             ///     For example: using word %boundary analysis, when the provided mask is \ref word_kana then the iterators            ///     would iterate only over the words containing Kana letters and \ref word_any would select all types of            ///     words excluding ranges that consist of white space and punctuation marks. So iterating over the text            ///     "to be or not to be?" with \ref word_any rule would return segments "to", "be", "or", "not", "to", "be", instead            ///     of default "to", " ", "be", " ", "or", " ", "not", " ", "to", " ", "be", "?".            /// -   \ref full_select(bool how) - a flag that defines the way a range is selected if the rule of the previous            ///     %boundary point does not fit the selected rule.            ///     \n            ///     For example: We want to fetch all sentences from the following text: "Hello! How\nare you?".            ///     \n            ///     This text contains three %boundary points separating it to sentences by different rules:            ///     - The exclamation mark "!" ends the sentence "Hello!"            ///     - The line feed that splits the sentence "How\nare you?" into two parts.            ///     - The question mark that ends the second sentence.            ///     \n            ///     If you would only change the \ref rule() to \ref sentence_term then the segment_index would            ///     provide two sentences "Hello!" and "are you?" %as only them actually terminated with required            ///     terminator "!" or "?". But changing \ref full_select() to true, the selected segment would include            ///     all the text up to previous valid %boundary point and would return two expected sentences:            ///     "Hello!" and "How\nare you?".            ///                 /// This class allows to find a segment according to the given iterator in range using \ref find() member            /// function.            ///            /// \note            ///            /// -   Changing any of the options - \ref rule() or \ref full_select() and of course re-indexing the text            ///     invalidates existing iterators and they can't be used any more.            /// -   segment_index can be created from boundary_point_index or other segment_index that was created with            ///     same \ref boundary_type.  This is very fast operation %as they shared same index            ///     and it does not require its regeneration.            ///            /// \see            ///            /// - \ref boundary_point_index            /// - \ref segment            /// - \ref boundary_point            ///            template<typename BaseIterator>            class segment_index {            public:                                ///                /// The type of the iterator used to iterate over the original text                ///                typedef BaseIterator base_iterator;                #ifdef BOOST_LOCALE_DOXYGEN                ///                /// The bidirectional iterator that iterates over \ref value_type objects.                ///                /// -   The iterators may be invalidated by use of any non-const member function                ///     including but not limited to \ref rule(rule_type) and \ref full_select(bool).                /// -   The returned value_type object is valid %as long %as iterator points to it.                ///     So this following code is wrong %as t used after p was updated:                ///     \code                ///     segment_index<some_iterator>::iterator p=index.begin();                ///     segment<some_iterator> &t = *p;                ///     ++p;                ///     cout << t.str() << endl;                ///     \endcode                ///                typedef unspecified_iterator_type iterator;                ///                /// \copydoc iterator                ///                typedef unspecified_iterator_type const_iterator;                #else                typedef details::segment_index_iterator<base_iterator> iterator;                typedef details::segment_index_iterator<base_iterator> const_iterator;                #endif                ///                /// The type dereferenced by the \ref iterator and \ref const_iterator. It is                /// an object that represents selected segment.                ///                typedef segment<base_iterator> value_type;                ///                /// Default constructor.                 ///                /// \note                ///                /// When this object is constructed by default it does not include a valid index, thus                /// calling \ref begin(), \ref end() or \ref find() member functions would lead to undefined                /// behavior                ///                segment_index() : mask_(0xFFFFFFFFu),full_select_(false)                {                }                ///                /// Create a segment_index for %boundary analysis \ref boundary_type "type" of the text                /// in range [begin,end) using a rule \a mask for locale \a loc.                ///                segment_index(boundary_type type,                            base_iterator begin,                            base_iterator end,                            rule_type mask,                            std::locale const &loc=std::locale())                     :                        map_(type,begin,end,loc),                        mask_(mask),                        full_select_(false)                {                }                ///                /// Create a segment_index for %boundary analysis \ref boundary_type "type" of the text                /// in range [begin,end) selecting all possible segments (full mask) for locale \a loc.                ///                segment_index(boundary_type type,                            base_iterator begin,                            base_iterator end,                            std::locale const &loc=std::locale())                     :                        map_(type,begin,end,loc),                        mask_(0xFFFFFFFFu),                        full_select_(false)                {                }                ///                /// Create a segment_index from a \ref boundary_point_index. It copies all indexing information                /// and used default rule (all possible segments)                ///                /// This operation is very cheap, so if you use boundary_point_index and segment_index on same text                /// range it is much better to create one from another rather then indexing the same                /// range twice.                ///                /// \note \ref rule() flags are not copied                ///                segment_index(boundary_point_index<base_iterator> const &);                ///                /// Copy an index from a \ref boundary_point_index. It copies all indexing information                /// and uses the default rule (all possible segments)                ///                /// This operation is very cheap, so if you use boundary_point_index and segment_index on same text                /// range it is much better to create one from another rather then indexing the same                /// range twice.                ///                /// \note \ref rule() flags are not copied                ///                segment_index const &operator = (boundary_point_index<base_iterator> const &);                                ///                /// Create a new index for %boundary analysis \ref boundary_type "type" of the text                /// in range [begin,end) for locale \a loc.                ///                /// \note \ref rule() and \ref full_select() remain unchanged.                ///                void map(boundary_type type,base_iterator begin,base_iterator end,std::locale const &loc=std::locale())                {                    map_ = mapping_type(type,begin,end,loc);                }                ///                /// Get the \ref iterator on the beginning of the segments range.                ///                /// Preconditions: the segment_index should have a mapping                ///                /// \note                ///                /// The returned iterator is invalidated by access to any non-const member functions of this object                ///                iterator begin() const                {                    return iterator(true,&map_,mask_,full_select_);                }                ///                /// Get the \ref iterator on the ending of the segments range.                ///                /// Preconditions: the segment_index should have a mapping                ///                /// The returned iterator is invalidated by access to any non-const member functions of this object                ///                iterator end() const                {                    return iterator(false,&map_,mask_,full_select_);                }                ///                /// Find a first valid segment following a position \a p.                 ///                /// If \a p is inside a valid segment this segment is selected:                ///                /// For example: For \ref word %boundary analysis with \ref word_any rule():                ///                /// - "to| be or ", would point to "be",                /// - "t|o be or ", would point to "to",                /// - "to be or| ", would point to end.                ///                ///                                 /// Preconditions: the segment_index should have a mapping and \a p should be valid iterator                /// to the text in the mapped range.                ///                /// The returned iterator is invalidated by access to any non-const member functions of this object                ///                iterator find(base_iterator p) const                {                    return iterator(p,&map_,mask_,full_select_);                }                               ///                /// Get the mask of rules that are used                ///                 rule_type rule() const                {                    return mask_;                }                ///                /// Set the mask of rules that are used                ///                 void rule(rule_type v)                {                    mask_ = v;                }                ///                /// Get the full_select property value -  should segment include in the range                /// values that not belong to specific \ref rule() or not.                ///                /// The default value is false.                ///                /// For example for \ref sentence %boundary with rule \ref sentence_term the segments                /// of text "Hello! How\nare you?" are "Hello!\", "are you?" when full_select() is false                /// because "How\n" is selected %as sentence by a rule spits the text by line feed. If full_select()                /// is true the returned segments are "Hello! ", "How\nare you?" where "How\n" is joined with the                /// following part "are you?"                ///                bool full_select()  const                 {                    return full_select_;                }                ///                /// Set the full_select property value -  should segment include in the range                /// values that not belong to specific \ref rule() or not.                ///                /// The default value is false.                ///                /// For example for \ref sentence %boundary with rule \ref sentence_term the segments                /// of text "Hello! How\nare you?" are "Hello!\", "are you?" when full_select() is false                /// because "How\n" is selected %as sentence by a rule spits the text by line feed. If full_select()                /// is true the returned segments are "Hello! ", "How\nare you?" where "How\n" is joined with the                /// following part "are you?"                ///                void full_select(bool v)                 {                    full_select_ = v;                }                            private:                friend class boundary_point_index<base_iterator>;                typedef details::mapping<base_iterator> mapping_type;                mapping_type  map_;                rule_type mask_;                bool full_select_;            };            ///            /// \brief This class holds an index of \ref boundary_point "boundary points" and allows iterating            /// over them.            ///            /// This class is provides \ref begin() and \ref end() member functions that return bidirectional iterators            /// to the \ref boundary_point objects.            ///            /// It provides an option that affects selecting %boundary points according to different rules:            /// using \ref rule(rule_type mask) member function. It allows to set a mask that select only specific            /// types of %boundary points like \ref sentence_term.            ///            /// For example for a sentence %boundary analysis of a text "Hello! How\nare you?" when the default            /// rule is used the %boundary points would be:            ///            /// - "|Hello! How\nare you?"            /// - "Hello! |How\nare you?"            /// - "Hello! How\n|are you?"            /// - "Hello! How\nare you?|"            ///            /// However if \ref rule() is set to \ref sentence_term then the selected %boundary points would be:             ///            /// - "|Hello! How\nare you?"            /// - "Hello! |How\nare you?"            /// - "Hello! How\nare you?|"            ///             /// Such that a %boundary point defined by a line feed character would be ignored.            ///                 /// This class allows to find a boundary_point according to the given iterator in range using \ref find() member            /// function.            ///            /// \note            /// -   Even an empty text range [x,x) considered to have a one %boundary point x.            /// -   \a a and \a b points of the range [a,b) are always considered %boundary points            ///     regardless the rules used.            /// -   Changing any of the option \ref rule() or course re-indexing the text            ///     invalidates existing iterators and they can't be used any more.            /// -   boundary_point_index can be created from segment_index or other boundary_point_index that was created with            ///     same \ref boundary_type.  This is very fast operation %as they shared same index            ///     and it does not require its regeneration.            ///            /// \see            ///            /// - \ref segment_index            /// - \ref boundary_point            /// - \ref segment            ///            template<typename BaseIterator>            class boundary_point_index {            public:                ///                /// The type of the iterator used to iterate over the original text                ///                typedef BaseIterator base_iterator;                #ifdef BOOST_LOCALE_DOXYGEN                ///                /// The bidirectional iterator that iterates over \ref value_type objects.                ///                /// -   The iterators may be invalidated by use of any non-const member function                ///     including but not limited to \ref rule(rule_type) member function.                /// -   The returned value_type object is valid %as long %as iterator points to it.                ///     So this following code is wrong %as t used after p was updated:                ///     \code                ///     boundary_point_index<some_iterator>::iterator p=index.begin();                ///     boundary_point<some_iterator> &t = *p;                ///     ++p;                ///     rule_type r = t->rule();                ///     \endcode                ///                typedef unspecified_iterator_type iterator;                ///                /// \copydoc iterator                ///                typedef unspecified_iterator_type const_iterator;                #else                typedef details::boundary_point_index_iterator<base_iterator> iterator;                typedef details::boundary_point_index_iterator<base_iterator> const_iterator;                #endif                ///                /// The type dereferenced by the \ref iterator and \ref const_iterator. It is                /// an object that represents the selected \ref boundary_point "boundary point".                ///                typedef boundary_point<base_iterator> value_type;                                ///                /// Default constructor.                 ///                /// \note                ///                /// When this object is constructed by default it does not include a valid index, thus                /// calling \ref begin(), \ref end() or \ref find() member functions would lead to undefined                /// behavior                ///                boundary_point_index() : mask_(0xFFFFFFFFu)                {                }                                ///                /// Create a segment_index for %boundary analysis \ref boundary_type "type" of the text                /// in range [begin,end) using a rule \a mask for locale \a loc.                ///                boundary_point_index(boundary_type type,                            base_iterator begin,                            base_iterator end,                            rule_type mask,                            std::locale const &loc=std::locale())                     :                        map_(type,begin,end,loc),                        mask_(mask)                {                }                ///                /// Create a segment_index for %boundary analysis \ref boundary_type "type" of the text                /// in range [begin,end) selecting all possible %boundary points (full mask) for locale \a loc.                ///                boundary_point_index(boundary_type type,                            base_iterator begin,                            base_iterator end,                            std::locale const &loc=std::locale())                     :                        map_(type,begin,end,loc),                        mask_(0xFFFFFFFFu)                {                }                ///                /// Create a boundary_point_index from a \ref segment_index. It copies all indexing information                /// and uses the default rule (all possible %boundary points)                ///                /// This operation is very cheap, so if you use boundary_point_index and segment_index on same text                /// range it is much better to create one from another rather then indexing the same                /// range twice.                ///                /// \note \ref rule() flags are not copied                ///                boundary_point_index(segment_index<base_iterator> const &other);                ///                /// Copy a boundary_point_index from a \ref segment_index. It copies all indexing information                /// and keeps the current \ref rule() unchanged                ///                /// This operation is very cheap, so if you use boundary_point_index and segment_index on same text                /// range it is much better to create one from another rather then indexing the same                /// range twice.                ///                /// \note \ref rule() flags are not copied                ///                boundary_point_index const &operator=(segment_index<base_iterator> const &other);                ///                /// Create a new index for %boundary analysis \ref boundary_type "type" of the text                /// in range [begin,end) for locale \a loc.                ///                /// \note \ref rule() remains unchanged.                ///                void map(boundary_type type,base_iterator begin,base_iterator end,std::locale const &loc=std::locale())                {                    map_ = mapping_type(type,begin,end,loc);                }                ///                /// Get the \ref iterator on the beginning of the %boundary points range.                ///                /// Preconditions: this boundary_point_index should have a mapping                ///                /// \note                ///                /// The returned iterator is invalidated by access to any non-const member functions of this object                ///                iterator begin() const                {                    return iterator(true,&map_,mask_);                }                ///                /// Get the \ref iterator on the ending of the %boundary points range.                ///                /// Preconditions: this boundary_point_index should have a mapping                ///                /// \note                ///                /// The returned iterator is invalidated by access to any non-const member functions of this object                ///                iterator end() const                {                    return iterator(false,&map_,mask_);                }                ///                /// Find a first valid %boundary point on a position \a p or following it.                ///                /// For example: For \ref word %boundary analysis of the text "to be or"                ///                /// - "|to be", would return %boundary point at "|to be",                /// - "t|o be", would point to "to| be"                ///                                 /// Preconditions: the boundary_point_index should have a mapping and \a p should be valid iterator                /// to the text in the mapped range.                ///                /// The returned iterator is invalidated by access to any non-const member functions of this object                ///                iterator find(base_iterator p) const                {                    return iterator(p,&map_,mask_);                }                                ///                /// Get the mask of rules that are used                ///                 rule_type rule() const                {                    return mask_;                }                ///                /// Set the mask of rules that are used                ///                 void rule(rule_type v)                {                    mask_ = v;                }            private:                friend class segment_index<base_iterator>;                typedef details::mapping<base_iterator> mapping_type;                mapping_type  map_;                rule_type mask_;            };                       /// \cond INTERNAL              template<typename BaseIterator>            segment_index<BaseIterator>::segment_index(boundary_point_index<BaseIterator> const &other) :                map_(other.map_),                mask_(0xFFFFFFFFu),                full_select_(false)            {            }                        template<typename BaseIterator>            boundary_point_index<BaseIterator>::boundary_point_index(segment_index<BaseIterator> const &other) :                map_(other.map_),                mask_(0xFFFFFFFFu)            {            }            template<typename BaseIterator>            segment_index<BaseIterator> const &segment_index<BaseIterator>::operator=(boundary_point_index<BaseIterator> const &other)            {                map_ = other.map_;                return *this;            }                        template<typename BaseIterator>            boundary_point_index<BaseIterator> const &boundary_point_index<BaseIterator>::operator=(segment_index<BaseIterator> const &other)            {                map_ = other.map_;                return *this;            }            /// \endcond                      typedef segment_index<std::string::const_iterator> ssegment_index;      ///< convenience typedef            typedef segment_index<std::wstring::const_iterator> wssegment_index;    ///< convenience typedef            #ifdef BOOST_LOCALE_ENABLE_CHAR16_T            typedef segment_index<std::u16string::const_iterator> u16ssegment_index;///< convenience typedef            #endif            #ifdef BOOST_LOCALE_ENABLE_CHAR32_T            typedef segment_index<std::u32string::const_iterator> u32ssegment_index;///< convenience typedef            #endif                       typedef segment_index<char const *> csegment_index;                     ///< convenience typedef            typedef segment_index<wchar_t const *> wcsegment_index;                 ///< convenience typedef            #ifdef BOOST_LOCALE_ENABLE_CHAR16_T            typedef segment_index<char16_t const *> u16csegment_index;              ///< convenience typedef            #endif            #ifdef BOOST_LOCALE_ENABLE_CHAR32_T            typedef segment_index<char32_t const *> u32csegment_index;              ///< convenience typedef            #endif            typedef boundary_point_index<std::string::const_iterator> sboundary_point_index;///< convenience typedef            typedef boundary_point_index<std::wstring::const_iterator> wsboundary_point_index;///< convenience typedef            #ifdef BOOST_LOCALE_ENABLE_CHAR16_T            typedef boundary_point_index<std::u16string::const_iterator> u16sboundary_point_index;///< convenience typedef            #endif            #ifdef BOOST_LOCALE_ENABLE_CHAR32_T            typedef boundary_point_index<std::u32string::const_iterator> u32sboundary_point_index;///< convenience typedef            #endif                       typedef boundary_point_index<char const *> cboundary_point_index;       ///< convenience typedef            typedef boundary_point_index<wchar_t const *> wcboundary_point_index;   ///< convenience typedef            #ifdef BOOST_LOCALE_ENABLE_CHAR16_T            typedef boundary_point_index<char16_t const *> u16cboundary_point_index;///< convenience typedef            #endif            #ifdef BOOST_LOCALE_ENABLE_CHAR32_T            typedef boundary_point_index<char32_t const *> u32cboundary_point_index;///< convenience typedef            #endif        } // boundary    } // locale} // boost////// \example boundary.cpp/// Example of using segment_index/// \example wboundary.cpp/// Example of using segment_index over wide strings///#ifdef BOOST_MSVC#pragma warning(pop)#endif#endif// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
 |