Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 09:44:57

0001 //  scan_keyword.hpp  --------------------------------------------------------------//
0002 //===----------------------------------------------------------------------===//
0003 //
0004 //                     The LLVM Compiler Infrastructure
0005 //
0006 // This file is dual licensed under the MIT and the University of Illinois Open
0007 // Source Licenses. See LICENSE.TXT for details.
0008 //
0009 //===----------------------------------------------------------------------===//
0010 //  Adaptation to Boost of the libcxx
0011 
0012 //  Copyright 2010 Vicente J. Botet Escriba
0013 
0014 //  Distributed under the Boost Software License, Version 1.0.
0015 //  See http://www.boost.org/LICENSE_1_0.txt
0016 
0017 #ifndef BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP
0018 #define BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP
0019 
0020 #include <boost/chrono/config.hpp>
0021 
0022 #include <boost/move/unique_ptr.hpp>
0023 #include <ios>
0024 #include <exception>
0025 #include <stdlib.h>
0026 #include <boost/throw_exception.hpp>
0027 
0028 namespace boost {
0029     using movelib::unique_ptr;
0030 
0031 namespace chrono {
0032 namespace chrono_detail {
0033 
0034 inline void free_aux(void* ptr) { free(ptr); }
0035 
0036 // scan_keyword
0037 // Scans [b, e) until a match is found in the basic_strings range
0038 //  [kb, ke) or until it can be shown that there is no match in [kb, ke).
0039 //  b will be incremented (visibly), consuming CharT until a match is found
0040 //  or proved to not exist.  A keyword may be "", in which will match anything.
0041 //  If one keyword is a prefix of another, and the next CharT in the input
0042 //  might match another keyword, the algorithm will attempt to find the longest
0043 //  matching keyword.  If the longer matching keyword ends up not matching, then
0044 //  no keyword match is found.  If no keyword match is found, ke is returned
0045 //  and failbit is set in err.
0046 //  Else an iterator pointing to the matching keyword is found.  If more than
0047 //  one keyword matches, an iterator to the first matching keyword is returned.
0048 //  If on exit b == e, eofbit is set in err.
0049 //  Examples:
0050 //  Keywords:  "a", "abb"
0051 //  If the input is "a", the first keyword matches and eofbit is set.
0052 //  If the input is "abc", no match is found and "ab" are consumed.
0053 
0054 template <class InputIterator, class ForwardIterator>
0055 ForwardIterator
0056 scan_keyword(InputIterator& b, InputIterator e,
0057                ForwardIterator kb, ForwardIterator ke,
0058                std::ios_base::iostate& err
0059                )
0060 {
0061     typedef typename std::iterator_traits<InputIterator>::value_type CharT;
0062     size_t nkw = std::distance(kb, ke);
0063     const unsigned char doesnt_match = '\0';
0064     const unsigned char might_match = '\1';
0065     const unsigned char does_match = '\2';
0066     unsigned char statbuf[100];
0067     unsigned char* status = statbuf;
0068     //  Change free by free_aux to avoid
0069     // Error: Could not find a match for boost::interprocess::unique_ptr<unsigned char, void(*)(void*)>::unique_ptr(int, extern "C" void(void*))
0070     unique_ptr<unsigned char, void(*)(void*)> stat_hold(BOOST_NULLPTR, free_aux);
0071     if (nkw > sizeof(statbuf))
0072     {
0073         status = (unsigned char*)malloc(nkw);
0074         if (status == BOOST_NULLPTR)
0075         {
0076           throw_exception(std::bad_alloc());
0077         }
0078         stat_hold.reset(status);
0079     }
0080     size_t n_might_match = nkw;  // At this point, any keyword might match
0081     size_t n_does_match = 0;       // but none of them definitely do
0082     // Initialize all statuses to might_match, except for "" keywords are does_match
0083     unsigned char* st = status;
0084     for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
0085     {
0086         if (!ky->empty())
0087             *st = might_match;
0088         else
0089         {
0090             *st = does_match;
0091             --n_might_match;
0092             ++n_does_match;
0093         }
0094     }
0095     // While there might be a match, test keywords against the next CharT
0096     for (size_t indx = 0; b != e && n_might_match > 0; ++indx)
0097     {
0098         // Peek at the next CharT but don't consume it
0099         CharT c = *b;
0100         bool consume = false;
0101         // For each keyword which might match, see if the indx character is c
0102         // If a match if found, consume c
0103         // If a match is found, and that is the last character in the keyword,
0104         //    then that keyword matches.
0105         // If the keyword doesn't match this character, then change the keyword
0106         //    to doesn't match
0107         st = status;
0108         for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
0109         {
0110             if (*st == might_match)
0111             {
0112                 CharT kc = (*ky)[indx];
0113                 if (c == kc)
0114                 {
0115                     consume = true;
0116                     if (ky->size() == indx+1)
0117                     {
0118                         *st = does_match;
0119                         --n_might_match;
0120                         ++n_does_match;
0121                     }
0122                 }
0123                 else
0124                 {
0125                     *st = doesnt_match;
0126                     --n_might_match;
0127                 }
0128             }
0129         }
0130         // consume if we matched a character
0131         if (consume)
0132         {
0133             ++b;
0134             // If we consumed a character and there might be a matched keyword that
0135             //   was marked matched on a previous iteration, then such keywords
0136             //   which are now marked as not matching.
0137             if (n_might_match + n_does_match > 1)
0138             {
0139                 st = status;
0140                 for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
0141                 {
0142                     if (*st == does_match && ky->size() != indx+1)
0143                     {
0144                         *st = doesnt_match;
0145                         --n_does_match;
0146                     }
0147                 }
0148             }
0149         }
0150     }
0151     // We've exited the loop because we hit eof and/or we have no more "might matches".
0152     if (b == e)
0153         err |= std::ios_base::eofbit;
0154     // Return the first matching result
0155     for (st = status; kb != ke; ++kb, ++st)
0156         if (*st == does_match)
0157             break;
0158     if (kb == ke)
0159         err |= std::ios_base::failbit;
0160     return kb;
0161 }
0162 }
0163 }
0164 }
0165 #endif // BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP