LCOV - code coverage report
Current view: top level - usr/include/boost/algorithm/string/detail - finder.hpp (source / functions) Hit Total Coverage
Test: bitcoincash_test.info Lines: 10 10 100.0 %
Date: 2018-04-13 15:12:50 Functions: 2 2 100.0 %

          Line data    Source code
       1             : //  Boost string_algo library finder.hpp header file  ---------------------------//
       2             : 
       3             : //  Copyright Pavol Droba 2002-2006.
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : //    (See accompanying file LICENSE_1_0.txt or copy at
       7             : //          http://www.boost.org/LICENSE_1_0.txt)
       8             : 
       9             : //  See http://www.boost.org/ for updates, documentation, and revision history.
      10             : 
      11             : #ifndef BOOST_STRING_FINDER_DETAIL_HPP
      12             : #define BOOST_STRING_FINDER_DETAIL_HPP
      13             : 
      14             : #include <boost/algorithm/string/config.hpp>
      15             : #include <boost/algorithm/string/constants.hpp>
      16             : #include <boost/detail/iterator.hpp>
      17             : 
      18             : #include <boost/range/iterator_range_core.hpp>
      19             : #include <boost/range/begin.hpp>
      20             : #include <boost/range/end.hpp>
      21             : #include <boost/range/empty.hpp>
      22             : #include <boost/range/as_literal.hpp>
      23             : 
      24             : namespace boost {
      25             :     namespace algorithm {
      26             :         namespace detail {
      27             : 
      28             : 
      29             : //  find first functor -----------------------------------------------//
      30             : 
      31             :             // find a subsequence in the sequence ( functor )
      32             :             /*
      33             :                 Returns a pair <begin,end> marking the subsequence in the sequence.
      34             :                 If the find fails, functor returns <End,End>
      35             :             */
      36             :             template<typename SearchIteratorT,typename PredicateT>
      37             :             struct first_finderF
      38             :             {
      39             :                 typedef SearchIteratorT search_iterator_type;
      40             : 
      41             :                 // Construction
      42             :                 template< typename SearchT >
      43             :                 first_finderF( const SearchT& Search, PredicateT Comp ) :
      44             :                     m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
      45             :                 first_finderF(
      46             :                         search_iterator_type SearchBegin,
      47             :                         search_iterator_type SearchEnd,
      48             :                         PredicateT Comp ) :
      49             :                     m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
      50             : 
      51             :                 // Operation
      52             :                 template< typename ForwardIteratorT >
      53             :                 iterator_range<ForwardIteratorT>
      54             :                 operator()(
      55             :                     ForwardIteratorT Begin,
      56             :                     ForwardIteratorT End ) const
      57             :                 {
      58             :                     typedef iterator_range<ForwardIteratorT> result_type;
      59             :                     typedef ForwardIteratorT input_iterator_type;
      60             : 
      61             :                     // Outer loop
      62             :                     for(input_iterator_type OuterIt=Begin;
      63             :                         OuterIt!=End;
      64             :                         ++OuterIt)
      65             :                     {
      66             :                         // Sanity check
      67             :                         if( boost::empty(m_Search) )
      68             :                             return result_type( End, End );
      69             : 
      70             :                         input_iterator_type InnerIt=OuterIt;
      71             :                         search_iterator_type SubstrIt=m_Search.begin();
      72             :                         for(;
      73             :                             InnerIt!=End && SubstrIt!=m_Search.end();
      74             :                             ++InnerIt,++SubstrIt)
      75             :                         {
      76             :                             if( !( m_Comp(*InnerIt,*SubstrIt) ) )
      77             :                                 break;
      78             :                         }
      79             : 
      80             :                         // Substring matching succeeded
      81             :                         if ( SubstrIt==m_Search.end() )
      82             :                             return result_type( OuterIt, InnerIt );
      83             :                     }
      84             : 
      85             :                     return result_type( End, End );
      86             :                 }
      87             : 
      88             :             private:
      89             :                 iterator_range<search_iterator_type> m_Search;
      90             :                 PredicateT m_Comp;
      91             :             };
      92             : 
      93             : //  find last functor -----------------------------------------------//
      94             : 
      95             :             // find the last match a subsequence in the sequence ( functor )
      96             :             /*
      97             :                 Returns a pair <begin,end> marking the subsequence in the sequence.
      98             :                 If the find fails, returns <End,End>
      99             :             */
     100             :             template<typename SearchIteratorT, typename PredicateT>
     101             :             struct last_finderF
     102             :             {
     103             :                 typedef SearchIteratorT search_iterator_type;
     104             :                 typedef first_finderF<
     105             :                     search_iterator_type,
     106             :                     PredicateT> first_finder_type;
     107             : 
     108             :                 // Construction
     109             :                 template< typename SearchT >
     110             :                 last_finderF( const SearchT& Search, PredicateT Comp ) :
     111             :                     m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {}
     112             :                 last_finderF(
     113             :                         search_iterator_type SearchBegin,
     114             :                         search_iterator_type SearchEnd,
     115             :                         PredicateT Comp ) :
     116             :                     m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {}
     117             : 
     118             :                 // Operation
     119             :                 template< typename ForwardIteratorT >
     120             :                 iterator_range<ForwardIteratorT>
     121             :                 operator()(
     122             :                     ForwardIteratorT Begin,
     123             :                     ForwardIteratorT End ) const
     124             :                 {
     125             :                     typedef iterator_range<ForwardIteratorT> result_type;
     126             : 
     127             :                     if( boost::empty(m_Search) )
     128             :                         return result_type( End, End );
     129             : 
     130             :                     typedef BOOST_STRING_TYPENAME boost::detail::
     131             :                         iterator_traits<ForwardIteratorT>::iterator_category category;
     132             : 
     133             :                     return findit( Begin, End, category() );
     134             :                 }
     135             : 
     136             :             private:
     137             :                 // forward iterator
     138             :                 template< typename ForwardIteratorT >
     139             :                 iterator_range<ForwardIteratorT>
     140             :                 findit(
     141             :                     ForwardIteratorT Begin,
     142             :                     ForwardIteratorT End,
     143             :                     std::forward_iterator_tag ) const
     144             :                 {
     145             :                     typedef iterator_range<ForwardIteratorT> result_type;
     146             : 
     147             :                     first_finder_type first_finder(
     148             :                         m_Search.begin(), m_Search.end(), m_Comp );
     149             : 
     150             :                     result_type M=first_finder( Begin, End );
     151             :                     result_type Last=M;
     152             : 
     153             :                     while( M )
     154             :                     {
     155             :                         Last=M;
     156             :                         M=first_finder( ::boost::end(M), End );
     157             :                     }
     158             : 
     159             :                     return Last;
     160             :                 }
     161             : 
     162             :                 // bidirectional iterator
     163             :                 template< typename ForwardIteratorT >
     164             :                 iterator_range<ForwardIteratorT>
     165             :                 findit(
     166             :                     ForwardIteratorT Begin,
     167             :                     ForwardIteratorT End,
     168             :                     std::bidirectional_iterator_tag ) const
     169             :                 {
     170             :                     typedef iterator_range<ForwardIteratorT> result_type;
     171             :                     typedef ForwardIteratorT input_iterator_type;
     172             : 
     173             :                     // Outer loop
     174             :                     for(input_iterator_type OuterIt=End;
     175             :                         OuterIt!=Begin; )
     176             :                     {
     177             :                         input_iterator_type OuterIt2=--OuterIt;
     178             : 
     179             :                         input_iterator_type InnerIt=OuterIt2;
     180             :                         search_iterator_type SubstrIt=m_Search.begin();
     181             :                         for(;
     182             :                             InnerIt!=End && SubstrIt!=m_Search.end();
     183             :                             ++InnerIt,++SubstrIt)
     184             :                         {
     185             :                             if( !( m_Comp(*InnerIt,*SubstrIt) ) )
     186             :                                 break;
     187             :                         }
     188             : 
     189             :                         // Substring matching succeeded
     190             :                         if( SubstrIt==m_Search.end() )
     191             :                             return result_type( OuterIt2, InnerIt );
     192             :                     }
     193             : 
     194             :                     return result_type( End, End );
     195             :                 }
     196             : 
     197             :             private:
     198             :                 iterator_range<search_iterator_type> m_Search;
     199             :                 PredicateT m_Comp;
     200             :             };
     201             : 
     202             : //  find n-th functor -----------------------------------------------//
     203             : 
     204             :             // find the n-th match of a subsequence in the sequence ( functor )
     205             :             /*
     206             :                 Returns a pair <begin,end> marking the subsequence in the sequence.
     207             :                 If the find fails, returns <End,End>
     208             :             */
     209             :             template<typename SearchIteratorT, typename PredicateT>
     210             :             struct nth_finderF
     211             :             {
     212             :                 typedef SearchIteratorT search_iterator_type;
     213             :                 typedef first_finderF<
     214             :                     search_iterator_type,
     215             :                     PredicateT> first_finder_type;
     216             :                 typedef last_finderF<
     217             :                     search_iterator_type,
     218             :                     PredicateT> last_finder_type;
     219             : 
     220             :                 // Construction
     221             :                 template< typename SearchT >
     222             :                 nth_finderF(
     223             :                         const SearchT& Search,
     224             :                         int Nth,
     225             :                         PredicateT Comp) :
     226             :                     m_Search(::boost::begin(Search), ::boost::end(Search)),
     227             :                     m_Nth(Nth),
     228             :                     m_Comp(Comp) {}
     229             :                 nth_finderF(
     230             :                         search_iterator_type SearchBegin,
     231             :                         search_iterator_type SearchEnd,
     232             :                         int Nth,
     233             :                         PredicateT Comp) :
     234             :                     m_Search(SearchBegin, SearchEnd),
     235             :                     m_Nth(Nth),
     236             :                     m_Comp(Comp) {}
     237             : 
     238             :                 // Operation
     239             :                 template< typename ForwardIteratorT >
     240             :                 iterator_range<ForwardIteratorT>
     241             :                 operator()(
     242             :                     ForwardIteratorT Begin,
     243             :                     ForwardIteratorT End ) const
     244             :                 {
     245             :                     if(m_Nth>=0)
     246             :                     {
     247             :                         return find_forward(Begin, End, m_Nth);
     248             :                     }
     249             :                     else
     250             :                     {
     251             :                         return find_backward(Begin, End, -m_Nth);
     252             :                     }
     253             : 
     254             :                 }
     255             : 
     256             :             private:
     257             :                 // Implementation helpers
     258             :                 template< typename ForwardIteratorT >
     259             :                 iterator_range<ForwardIteratorT>
     260             :                 find_forward(
     261             :                     ForwardIteratorT Begin,
     262             :                     ForwardIteratorT End,
     263             :                     unsigned int N) const
     264             :                 {
     265             :                     typedef iterator_range<ForwardIteratorT> result_type;
     266             : 
     267             :                     // Sanity check
     268             :                     if( boost::empty(m_Search) )
     269             :                         return result_type( End, End );
     270             : 
     271             :                     // Instantiate find functor
     272             :                     first_finder_type first_finder(
     273             :                         m_Search.begin(), m_Search.end(), m_Comp );
     274             : 
     275             :                     result_type M( Begin, Begin );
     276             : 
     277             :                     for( unsigned int n=0; n<=N; ++n )
     278             :                     {
     279             :                         // find next match
     280             :                         M=first_finder( ::boost::end(M), End );
     281             : 
     282             :                         if ( !M )
     283             :                         {
     284             :                             // Subsequence not found, return
     285             :                             return M;
     286             :                         }
     287             :                     }
     288             : 
     289             :                     return M;
     290             :                 }
     291             : 
     292             :                 template< typename ForwardIteratorT >
     293             :                 iterator_range<ForwardIteratorT>
     294             :                 find_backward(
     295             :                     ForwardIteratorT Begin,
     296             :                     ForwardIteratorT End,
     297             :                     unsigned int N) const
     298             :                 {
     299             :                     typedef iterator_range<ForwardIteratorT> result_type;
     300             : 
     301             :                     // Sanity check
     302             :                     if( boost::empty(m_Search) )
     303             :                         return result_type( End, End );
     304             : 
     305             :                     // Instantiate find functor
     306             :                     last_finder_type last_finder(
     307             :                         m_Search.begin(), m_Search.end(), m_Comp );
     308             : 
     309             :                     result_type M( End, End );
     310             : 
     311             :                     for( unsigned int n=1; n<=N; ++n )
     312             :                     {
     313             :                         // find next match
     314             :                         M=last_finder( Begin, ::boost::begin(M) );
     315             : 
     316             :                         if ( !M )
     317             :                         {
     318             :                             // Subsequence not found, return
     319             :                             return M;
     320             :                         }
     321             :                     }
     322             : 
     323             :                     return M;
     324             :                 }
     325             : 
     326             : 
     327             :             private:
     328             :                 iterator_range<search_iterator_type> m_Search;
     329             :                 int m_Nth;
     330             :                 PredicateT m_Comp;
     331             :             };
     332             : 
     333             : //  find head/tail implementation helpers ---------------------------//
     334             : 
     335             :             template<typename ForwardIteratorT>
     336             :                 iterator_range<ForwardIteratorT>
     337             :             find_head_impl(
     338             :                 ForwardIteratorT Begin,
     339             :                 ForwardIteratorT End,
     340             :                 unsigned int N,
     341             :                 std::forward_iterator_tag )
     342             :             {
     343             :                 typedef ForwardIteratorT input_iterator_type;
     344             :                 typedef iterator_range<ForwardIteratorT> result_type;
     345             : 
     346             :                 input_iterator_type It=Begin;
     347             :                 for(
     348             :                     unsigned int Index=0;
     349             :                     Index<N && It!=End; ++Index,++It ) {};
     350             : 
     351             :                 return result_type( Begin, It );
     352             :             }
     353             : 
     354             :             template< typename ForwardIteratorT >
     355             :                 iterator_range<ForwardIteratorT>
     356             :             find_head_impl(
     357             :                 ForwardIteratorT Begin,
     358             :                 ForwardIteratorT End,
     359             :                 unsigned int N,
     360             :                 std::random_access_iterator_tag )
     361             :             {
     362             :                 typedef iterator_range<ForwardIteratorT> result_type;
     363             : 
     364             :                 if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
     365             :                     return result_type( Begin, End );
     366             : 
     367             :                 return result_type(Begin,Begin+N);
     368             :             }
     369             : 
     370             :             // Find head implementation
     371             :             template<typename ForwardIteratorT>
     372             :                 iterator_range<ForwardIteratorT>
     373             :             find_head_impl(
     374             :                 ForwardIteratorT Begin,
     375             :                 ForwardIteratorT End,
     376             :                 unsigned int N )
     377             :             {
     378             :                 typedef BOOST_STRING_TYPENAME boost::detail::
     379             :                     iterator_traits<ForwardIteratorT>::iterator_category category;
     380             : 
     381             :                 return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() );
     382             :             }
     383             : 
     384             :             template< typename ForwardIteratorT >
     385             :                 iterator_range<ForwardIteratorT>
     386             :             find_tail_impl(
     387             :                 ForwardIteratorT Begin,
     388             :                 ForwardIteratorT End,
     389             :                 unsigned int N,
     390             :                 std::forward_iterator_tag )
     391             :             {
     392             :                 typedef ForwardIteratorT input_iterator_type;
     393             :                 typedef iterator_range<ForwardIteratorT> result_type;
     394             : 
     395             :                 unsigned int Index=0;
     396             :                 input_iterator_type It=Begin;
     397             :                 input_iterator_type It2=Begin;
     398             : 
     399             :                 // Advance It2 by N increments
     400             :                 for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {};
     401             : 
     402             :                 // Advance It, It2 to the end
     403             :                 for(; It2!=End; ++It,++It2 ) {};
     404             : 
     405             :                 return result_type( It, It2 );
     406             :             }
     407             : 
     408             :             template< typename ForwardIteratorT >
     409             :                 iterator_range<ForwardIteratorT>
     410             :             find_tail_impl(
     411             :                 ForwardIteratorT Begin,
     412             :                 ForwardIteratorT End,
     413             :                 unsigned int N,
     414             :                 std::bidirectional_iterator_tag )
     415             :             {
     416             :                 typedef ForwardIteratorT input_iterator_type;
     417             :                 typedef iterator_range<ForwardIteratorT> result_type;
     418             : 
     419             :                 input_iterator_type It=End;
     420             :                 for(
     421             :                     unsigned int Index=0;
     422             :                     Index<N && It!=Begin; ++Index,--It ) {};
     423             : 
     424             :                 return result_type( It, End );
     425             :             }
     426             : 
     427             :             template< typename ForwardIteratorT >
     428             :                 iterator_range<ForwardIteratorT>
     429             :             find_tail_impl(
     430             :                 ForwardIteratorT Begin,
     431             :                 ForwardIteratorT End,
     432             :                 unsigned int N,
     433             :                 std::random_access_iterator_tag )
     434             :             {
     435             :                 typedef iterator_range<ForwardIteratorT> result_type;
     436             : 
     437             :                 if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) )
     438             :                     return result_type( Begin, End );
     439             : 
     440             :                 return result_type( End-N, End );
     441             :             }
     442             : 
     443             :                         // Operation
     444             :             template< typename ForwardIteratorT >
     445             :             iterator_range<ForwardIteratorT>
     446             :             find_tail_impl(
     447             :                 ForwardIteratorT Begin,
     448             :                 ForwardIteratorT End,
     449             :                 unsigned int N )
     450             :             {
     451             :                 typedef BOOST_STRING_TYPENAME boost::detail::
     452             :                     iterator_traits<ForwardIteratorT>::iterator_category category;
     453             : 
     454             :                 return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() );
     455             :             }
     456             : 
     457             : 
     458             : 
     459             : //  find head functor -----------------------------------------------//
     460             : 
     461             : 
     462             :             // find a head in the sequence ( functor )
     463             :             /*
     464             :                 This functor find a head of the specified range. For
     465             :                 a specified N, the head is a subsequence of N starting
     466             :                 elements of the range.
     467             :             */
     468             :             struct head_finderF
     469             :             {
     470             :                 // Construction
     471             :                 head_finderF( int N ) : m_N(N) {}
     472             : 
     473             :                 // Operation
     474             :                 template< typename ForwardIteratorT >
     475             :                 iterator_range<ForwardIteratorT>
     476             :                 operator()(
     477             :                     ForwardIteratorT Begin,
     478             :                     ForwardIteratorT End ) const
     479             :                 {
     480             :                     if(m_N>=0)
     481             :                     {
     482             :                         return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N );
     483             :                     }
     484             :                     else
     485             :                     {
     486             :                         iterator_range<ForwardIteratorT> Res=
     487             :                             ::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N );
     488             : 
     489             :                         return ::boost::make_iterator_range(Begin, Res.begin());
     490             :                     }
     491             :                 }
     492             : 
     493             :             private:
     494             :                 int m_N;
     495             :             };
     496             : 
     497             : //  find tail functor -----------------------------------------------//
     498             : 
     499             : 
     500             :             // find a tail in the sequence ( functor )
     501             :             /*
     502             :                 This functor find a tail of the specified range. For
     503             :                 a specified N, the head is a subsequence of N starting
     504             :                 elements of the range.
     505             :             */
     506             :             struct tail_finderF
     507             :             {
     508             :                 // Construction
     509             :                 tail_finderF( int N ) : m_N(N) {}
     510             : 
     511             :                 // Operation
     512             :                 template< typename ForwardIteratorT >
     513             :                 iterator_range<ForwardIteratorT>
     514             :                 operator()(
     515             :                     ForwardIteratorT Begin,
     516             :                     ForwardIteratorT End ) const
     517             :                 {
     518             :                     if(m_N>=0)
     519             :                     {
     520             :                         return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N );
     521             :                     }
     522             :                     else
     523             :                     {
     524             :                         iterator_range<ForwardIteratorT> Res=
     525             :                             ::boost::algorithm::detail::find_head_impl( Begin, End, -m_N );
     526             : 
     527             :                         return ::boost::make_iterator_range(Res.end(), End);
     528             :                     }
     529             :                 }
     530             : 
     531             :             private:
     532             :                 int m_N;
     533             :             };
     534             : 
     535             : //  find token functor -----------------------------------------------//
     536             : 
     537             :             // find a token in a sequence ( functor )
     538             :             /*
     539             :                 This find functor finds a token specified be a predicate
     540             :                 in a sequence. It is equivalent of std::find algorithm,
     541             :                 with an exception that it return range instead of a single
     542             :                 iterator.
     543             : 
     544             :                 If bCompress is set to true, adjacent matching tokens are
     545             :                 concatenated into one match.
     546             :             */
     547             :             template< typename PredicateT >
     548       59589 :             struct token_finderF
     549             :             {
     550             :                 // Construction
     551             :                 token_finderF(
     552             :                     PredicateT Pred,
     553             :                     token_compress_mode_type eCompress=token_compress_off ) :
     554        1422 :                         m_Pred(Pred), m_eCompress(eCompress) {}
     555             : 
     556             :                 // Operation
     557             :                 template< typename ForwardIteratorT >
     558             :                 iterator_range<ForwardIteratorT>
     559        4079 :                 operator()(
     560             :                     ForwardIteratorT Begin,
     561             :                     ForwardIteratorT End ) const
     562             :                 {
     563             :                     typedef iterator_range<ForwardIteratorT> result_type;
     564             : 
     565        4195 :                     ForwardIteratorT It=std::find_if( Begin, End, m_Pred );
     566             : 
     567        4079 :                     if( It==End )
     568             :                     {
     569        2796 :                         return result_type( End, End );
     570             :                     }
     571             :                     else
     572             :                     {
     573        1283 :                         ForwardIteratorT It2=It;
     574             : 
     575        1283 :                         if( m_eCompress==token_compress_on )
     576             :                         {
     577             :                             // Find first non-matching character
     578          40 :                             while( It2!=End && m_Pred(*It2) ) ++It2;
     579             :                         }
     580             :                         else
     581             :                         {
     582             :                             // Advance by one position
     583             :                             ++It2;
     584             :                         }
     585             : 
     586        1283 :                         return result_type( It, It2 );
     587             :                     }
     588             :                 }
     589             : 
     590             :             private:
     591             :                 PredicateT m_Pred;
     592             :                 token_compress_mode_type m_eCompress;
     593             :             };
     594             : 
     595             : //  find range functor -----------------------------------------------//
     596             : 
     597             :             // find a range in the sequence ( functor )
     598             :             /*
     599             :                 This functor actually does not perform any find operation.
     600             :                 It always returns given iterator range as a result.
     601             :             */
     602             :             template<typename ForwardIterator1T>
     603             :             struct range_finderF
     604             :             {
     605             :                 typedef ForwardIterator1T input_iterator_type;
     606             :                 typedef iterator_range<input_iterator_type> result_type;
     607             : 
     608             :                 // Construction
     609             :                 range_finderF(
     610             :                     input_iterator_type Begin,
     611             :                     input_iterator_type End ) : m_Range(Begin, End) {}
     612             : 
     613             :                 range_finderF(const iterator_range<input_iterator_type>& Range) :
     614             :                     m_Range(Range) {}
     615             : 
     616             :                 // Operation
     617             :                 template< typename ForwardIterator2T >
     618             :                 iterator_range<ForwardIterator2T>
     619             :                 operator()(
     620             :                     ForwardIterator2T,
     621             :                     ForwardIterator2T ) const
     622             :                 {
     623             : #if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) 
     624             :                     return iterator_range<const ForwardIterator2T>(this->m_Range);
     625             : #else
     626             :                     return m_Range;
     627             : #endif
     628             :                 }
     629             : 
     630             :             private:
     631             :                 iterator_range<input_iterator_type> m_Range;
     632             :             };
     633             : 
     634             : 
     635             :         } // namespace detail
     636             :     } // namespace algorithm
     637             : } // namespace boost
     638             : 
     639             : #endif  // BOOST_STRING_FINDER_DETAIL_HPP

Generated by: LCOV version 1.12