blob: fcc85e4a2264b8a1872650c02e8a3381f9a817ad [file] [log] [blame]
/***************************************************************************
*
* _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 ?
&_V3_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;
if (__bits & 1UL << __k) {
// `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 &= ~(1UL << __k);
--__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 &= ~(1UL << __k);
--__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