| /*************************************************************************** |
| * |
| * _punct.cc |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| * |
| * Copyright 1994-2006 Rogue Wave Software. |
| * |
| **************************************************************************/ |
| |
| |
| #include <streambuf> |
| #include <loc/_ctype.h> |
| |
| |
| _RWSTD_NAMESPACE (__rw) { |
| |
| |
| _EXPORT |
| template <class _CharT, class _InputIter> |
| _InputIter __rw_match_name (_InputIter __it, _InputIter __end, |
| const _CharT* const *__names, |
| const _RWSTD_SIZE_T *__sizes, |
| _RWSTD_SIZE_T __count, |
| _RWSTD_SIZE_T &__inx, |
| int &__err, |
| _STD::ios_base *__flags) |
| { |
| const _RWSTD_SIZE_T __badval = _RWSTD_SIZE_MAX; |
| |
| // make sure there are enough bits for all `count' `names' |
| _RWSTD_ASSERT (__count <= sizeof (_RWSTD_SIZE_T) * _RWSTD_CHAR_BIT); |
| |
| // on input, `err' contains the maximum allowed number of matches |
| const _RWSTD_SIZE_T __matchmax = (_RWSTD_SIZE_T)__err; |
| |
| __err = 0; |
| |
| _RWSTD_SIZE_T __bits = ~0UL; // a bit for each `name' |
| _RWSTD_SIZE_T __nmatch = __count; // total number of positive matches |
| _RWSTD_SIZE_T __pos = 0; // position within input |
| _RWSTD_SIZE_T __num = __inx; // input as a number |
| |
| __inx = __badval; // invalidate |
| |
| const _STD::ctype<_CharT> *__ctp = __flags ? |
| &_RWSTD_USE_FACET (_STD::ctype<_CharT>, __flags->getloc ()) : 0; |
| |
| _CharT __ch; |
| |
| for (; (__bits || __num != __badval) && !__err; ++__it, ++__pos) { |
| |
| if (__it == __end) { |
| __err |= _RWSTD_IOS_EOFBIT; |
| __ch = _CharT (); |
| } |
| else |
| __ch = *__it; |
| |
| if (__ctp && __num != __badval) { |
| if (__ctp->is (_STD::ctype_base::digit, __ch)) |
| __num = __num * 10 + __ctp->narrow (__ch, '0') - '0'; |
| else |
| __num = __badval; |
| } |
| |
| // iterate over all names, clear bits of those that do not match |
| for (_RWSTD_SIZE_T __k = 0; __k != __count; ++__k) { |
| |
| typedef _STD::char_traits<_CharT> _Traits; |
| |
| const _RWSTD_SIZE_T __mask = |
| _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, 1UL) << __k; |
| |
| if (__bits & __mask) { |
| // `name' is still in the set, see if the next char matches |
| // (case insensitive comparison done if `ctp' is nonzero) |
| if ( __pos < __sizes [__k] |
| && !__err |
| && (__ctp ? |
| _Traits::eq ((__ctp->toupper)(__names [__k][__pos]), |
| (__ctp->toupper)(__ch)) |
| : _Traits::eq (__names [__k][__pos], __ch))) { |
| |
| // next character on `name' mactches input |
| if (__badval == __inx) { |
| // no prior match, remember this one |
| __inx = __k; |
| } |
| else if ( __k != __inx |
| && __sizes [__k] == __sizes [__inx] |
| && __pos + 1 == __sizes [__inx]) { |
| |
| // this match is a duplicate of the last best one |
| // remove this match from the set |
| __bits &= ~__mask; |
| --__nmatch; |
| } |
| else if ( __sizes [__k] < __sizes [__inx] |
| || __pos >= __sizes [__inx]) { |
| // this match is either shorter than the last one |
| // or the last one will be eliminated |
| __inx = __k; |
| } |
| } |
| else { |
| if (1 == __nmatch) { |
| if (__badval == __inx && __badval == __num) |
| return __it; |
| goto __endloop; |
| } |
| |
| if (__inx == __k) { |
| // if this `name' is the current shortest match... |
| if (__err && __pos == __sizes [__k]) { |
| // ...and we're at eof, return successfully |
| return __it; |
| } |
| // otherwise forget the match |
| __inx = __badval; |
| } |
| |
| // clear the bit for the `name' that failed to match |
| // and decrement the numeber of matches |
| __bits &= ~__mask; |
| --__nmatch; |
| } |
| } |
| } |
| |
| if (1 == __nmatch && __pos + 1 == __sizes [__inx]) |
| return ++__it; |
| } |
| |
| __endloop: |
| |
| if (__matchmax < __nmatch || __pos < __sizes [__inx]) |
| __inx = __badval; |
| |
| if (__ctp && __badval == __inx && !__err && __num != __badval) { |
| |
| // if symbolic matching fails, fall back on numeric parsing |
| for ( ; ; ) { |
| if (++__it == __end) { |
| __err |= _RWSTD_IOS_EOFBIT; |
| break; |
| } |
| |
| __ch = *__it; |
| |
| if (__ctp->is (_STD::ctype_base::digit, __ch)) |
| __num = __num * 10 + __ctp->narrow (__ch, '0') - '0'; |
| else |
| break; |
| } |
| |
| __inx = __count + __num; |
| } |
| |
| return __it; |
| } |
| |
| |
| } // namespace __rw |