annotate DEPENDENCIES/generic/include/boost/chrono/detail/scan_keyword.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // scan_keyword.hpp --------------------------------------------------------------//
Chris@16 2 //===----------------------------------------------------------------------===//
Chris@16 3 //
Chris@16 4 // The LLVM Compiler Infrastructure
Chris@16 5 //
Chris@16 6 // This file is dual licensed under the MIT and the University of Illinois Open
Chris@16 7 // Source Licenses. See LICENSE.TXT for details.
Chris@16 8 //
Chris@16 9 //===----------------------------------------------------------------------===//
Chris@16 10 // Adaptation to Boost of the libcxx
Chris@16 11
Chris@16 12 // Copyright 2010 Vicente J. Botet Escriba
Chris@16 13
Chris@16 14 // Distributed under the Boost Software License, Version 1.0.
Chris@16 15 // See http://www.boost.org/LICENSE_1_0.txt
Chris@16 16
Chris@16 17 #ifndef BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP
Chris@16 18 #define BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP
Chris@16 19
Chris@16 20 #include <boost/chrono/config.hpp>
Chris@16 21
Chris@101 22 #include <boost/move/unique_ptr.hpp>
Chris@16 23 #include <ios>
Chris@16 24 #include <exception>
Chris@16 25 #include <stdlib.h>
Chris@16 26 #include <boost/throw_exception.hpp>
Chris@16 27
Chris@16 28 namespace boost {
Chris@101 29 using movelib::unique_ptr;
Chris@16 30
Chris@16 31 namespace chrono {
Chris@16 32 namespace chrono_detail {
Chris@16 33
Chris@16 34 inline void free_aux(void* ptr) { free(ptr); }
Chris@16 35
Chris@16 36 // scan_keyword
Chris@16 37 // Scans [b, e) until a match is found in the basic_strings range
Chris@16 38 // [kb, ke) or until it can be shown that there is no match in [kb, ke).
Chris@16 39 // b will be incremented (visibly), consuming CharT until a match is found
Chris@16 40 // or proved to not exist. A keyword may be "", in which will match anything.
Chris@16 41 // If one keyword is a prefix of another, and the next CharT in the input
Chris@16 42 // might match another keyword, the algorithm will attempt to find the longest
Chris@16 43 // matching keyword. If the longer matching keyword ends up not matching, then
Chris@16 44 // no keyword match is found. If no keyword match is found, ke is returned
Chris@16 45 // and failbit is set in err.
Chris@16 46 // Else an iterator pointing to the matching keyword is found. If more than
Chris@16 47 // one keyword matches, an iterator to the first matching keyword is returned.
Chris@16 48 // If on exit b == e, eofbit is set in err.
Chris@16 49 // Examples:
Chris@16 50 // Keywords: "a", "abb"
Chris@16 51 // If the input is "a", the first keyword matches and eofbit is set.
Chris@16 52 // If the input is "abc", no match is found and "ab" are consumed.
Chris@16 53
Chris@16 54 template <class InputIterator, class ForwardIterator>
Chris@16 55 ForwardIterator
Chris@16 56 scan_keyword(InputIterator& b, InputIterator e,
Chris@16 57 ForwardIterator kb, ForwardIterator ke,
Chris@16 58 std::ios_base::iostate& err
Chris@16 59 )
Chris@16 60 {
Chris@16 61 typedef typename std::iterator_traits<InputIterator>::value_type CharT;
Chris@16 62 size_t nkw = std::distance(kb, ke);
Chris@16 63 const unsigned char doesnt_match = '\0';
Chris@16 64 const unsigned char might_match = '\1';
Chris@16 65 const unsigned char does_match = '\2';
Chris@16 66 unsigned char statbuf[100];
Chris@16 67 unsigned char* status = statbuf;
Chris@16 68 // Change free by free_aux to avoid
Chris@16 69 // Error: Could not find a match for boost::interprocess::unique_ptr<unsigned char, void(*)(void*)>::unique_ptr(int, extern "C" void(void*))
Chris@16 70 unique_ptr<unsigned char, void(*)(void*)> stat_hold(0, free_aux);
Chris@16 71 if (nkw > sizeof(statbuf))
Chris@16 72 {
Chris@16 73 status = (unsigned char*)malloc(nkw);
Chris@16 74 if (status == 0)
Chris@16 75 throw_exception(std::bad_alloc());
Chris@16 76 stat_hold.reset(status);
Chris@16 77 }
Chris@16 78 size_t n_might_match = nkw; // At this point, any keyword might match
Chris@16 79 size_t n_does_match = 0; // but none of them definitely do
Chris@16 80 // Initialize all statuses to might_match, except for "" keywords are does_match
Chris@16 81 unsigned char* st = status;
Chris@16 82 for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
Chris@16 83 {
Chris@16 84 if (!ky->empty())
Chris@16 85 *st = might_match;
Chris@16 86 else
Chris@16 87 {
Chris@16 88 *st = does_match;
Chris@16 89 --n_might_match;
Chris@16 90 ++n_does_match;
Chris@16 91 }
Chris@16 92 }
Chris@16 93 // While there might be a match, test keywords against the next CharT
Chris@16 94 for (size_t indx = 0; b != e && n_might_match > 0; ++indx)
Chris@16 95 {
Chris@16 96 // Peek at the next CharT but don't consume it
Chris@16 97 CharT c = *b;
Chris@16 98 bool consume = false;
Chris@16 99 // For each keyword which might match, see if the indx character is c
Chris@16 100 // If a match if found, consume c
Chris@16 101 // If a match is found, and that is the last character in the keyword,
Chris@16 102 // then that keyword matches.
Chris@16 103 // If the keyword doesn't match this character, then change the keyword
Chris@16 104 // to doesn't match
Chris@16 105 st = status;
Chris@16 106 for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
Chris@16 107 {
Chris@16 108 if (*st == might_match)
Chris@16 109 {
Chris@16 110 CharT kc = (*ky)[indx];
Chris@16 111 if (c == kc)
Chris@16 112 {
Chris@16 113 consume = true;
Chris@16 114 if (ky->size() == indx+1)
Chris@16 115 {
Chris@16 116 *st = does_match;
Chris@16 117 --n_might_match;
Chris@16 118 ++n_does_match;
Chris@16 119 }
Chris@16 120 }
Chris@16 121 else
Chris@16 122 {
Chris@16 123 *st = doesnt_match;
Chris@16 124 --n_might_match;
Chris@16 125 }
Chris@16 126 }
Chris@16 127 }
Chris@16 128 // consume if we matched a character
Chris@16 129 if (consume)
Chris@16 130 {
Chris@16 131 ++b;
Chris@16 132 // If we consumed a character and there might be a matched keyword that
Chris@16 133 // was marked matched on a previous iteration, then such keywords
Chris@16 134 // which are now marked as not matching.
Chris@16 135 if (n_might_match + n_does_match > 1)
Chris@16 136 {
Chris@16 137 st = status;
Chris@16 138 for (ForwardIterator ky = kb; ky != ke; ++ky, ++st)
Chris@16 139 {
Chris@16 140 if (*st == does_match && ky->size() != indx+1)
Chris@16 141 {
Chris@16 142 *st = doesnt_match;
Chris@16 143 --n_does_match;
Chris@16 144 }
Chris@16 145 }
Chris@16 146 }
Chris@16 147 }
Chris@16 148 }
Chris@16 149 // We've exited the loop because we hit eof and/or we have no more "might matches".
Chris@16 150 if (b == e)
Chris@16 151 err |= std::ios_base::eofbit;
Chris@16 152 // Return the first matching result
Chris@16 153 for (st = status; kb != ke; ++kb, ++st)
Chris@16 154 if (*st == does_match)
Chris@16 155 break;
Chris@16 156 if (kb == ke)
Chris@16 157 err |= std::ios_base::failbit;
Chris@16 158 return kb;
Chris@16 159 }
Chris@16 160 }
Chris@16 161 }
Chris@16 162 }
Chris@16 163 #endif // BOOST_CHRONO_DETAIL_SCAN_KEYWORD_HPP