void MakeFile( TSTRING& strNameMakeMe )
{
    try
    {
        iFSServices* pFSServices = iFSServices::GetInstance(); ASSERT( pFSServices );
        pFSServices->MakeTempFilename( strNameMakeMe );

        std::string strA;
        for( TSTRING::iterator i = strNameMakeMe.begin(); i != strNameMakeMe.end(); i++ )
        {
            char ach[6];
            ASSERT( MB_CUR_MAX <= 6 );

            int n = wctomb( ach, *i );
            ASSERT( n != -1 );
            
            for( int j = 0; j < n; j++ )
                strA += ach[j];
        }

        TOFSTREAM file( strA.c_str() );
        ASSERT( file );
        file.close();
    }
    catch( eFSServices e )
    {
        ASSERT( false );
    }
    catch( ... )
    {
        ASSERT( false );
    }
}
bool cEncoder::AllTestsRunOnEncodedString( const TSTRING& s ) const
{
    TSTRING::const_iterator         cur = s.begin();  // pointer to working position in s
    const TSTRING::const_iterator   end = s.end();    // end of s
    TSTRING::const_iterator         first = end;          // identifies beginning of current character
    TSTRING::const_iterator         last  = end;          // identifies end of current character
    

    // while get next char (updates cur)
    while( cCharUtil::PopNextChar( cur, end, first, last ) )
    {
        sack_type::const_iterator atE;
        for( atE = m_encodings.begin(); 
             atE != m_encodings.end(); 
             atE++ )
        {
            if( (*atE)->NeedsEncoding( first, last ) )
            {
                return false;
            }
        }
    }

    return true;
}
////////////////////////////////////////////////////////////////////////////////
// Function name    : util_RemoveDuplicateSeps
// Description      :
// takes all adjacent slashes and replaces them with a single slash
//      ///root//foo -> /root/foo
//      rel//foo///  -> rel/foo/
//
// Return type      : void
// Argument         : TSTRING& strPath
///////////////////////////////////////////////////////////////////////////////
void util_RemoveDuplicateSeps(TSTRING& strPath)
{
    bool              fLastCharWasSep = false;
    TSTRING::iterator iter            = strPath.begin();
    while (iter != strPath.end())
    {
        bool fErasedChar = false;
        // if we've found a char that's not '/', then it's not the root
        if (*iter == TW_SLASH)
        {
            // if this char is a duplicate sep, erase it
            if (fLastCharWasSep)
            {
                iter        = strPath.erase(iter);
                fErasedChar = true;
            }

            fLastCharWasSep = true;
        }
        else
        {
            fLastCharWasSep = false;
        }

        // don't go past end of string (could happen with erase)
        if (!fErasedChar)
            iter++;
    }
}
TSTRING cCharEncoderUtil::HexValueToCharString( const TSTRING& str )
{
    TSTRING strOut;    
    TSTRING::const_iterator     at;

    for( at = str.begin(); at < str.end(); at += TCHAR_AS_HEX__IN_TCHARS )
    {
        strOut += hex_to_char( at, at + TCHAR_AS_HEX__IN_TCHARS );
    }

    return strOut;
}
TSTRING cCharEncoderUtil::CharStringToHexValue( const TSTRING& str )
{
    TSTRING strOut;
    TSTRING::const_iterator at;

    for( at = str.begin(); at < str.end(); at++ )
    {
        strOut += char_to_hex( *at );
    }

    return strOut;
}
void cParseNamedAttr::Validate() const
{
    if( NamesMatch( twparser::STR_PARSER_RULENAME, mstrName ) )
    {
        // no checking needed
    }
    else if( NamesMatch( twparser::STR_PARSER_EMAILTO, mstrName ) )
    {
        // no checking needed
    }
    else if( NamesMatch( twparser::STR_PARSER_SEVERITY, mstrName ) )
    {
        int iIgnore;
        cSeverityLimits sl;
        if( ! sl.InterpretInt( mstrValue, &iIgnore ) )
            throw eParserBadSevVal( mstrValue, mLineNum );
    }
    else if( NamesMatch( twparser::STR_PARSER_RECURSE, mstrName ) )
    {
        TSTRING str = mstrValue;
        std::transform( str.begin(), str.end(), str.begin(), _totlower );
    
        if( !NamesMatch( twparser::STR_PARSER_FALSE, str ) && !NamesMatch( twparser::STR_PARSER_TRUE, str ) )
        {
            // must be number
            int iIgnore;
            cRecurseDepthLimits rdl;
            if( ! rdl.InterpretInt( str, &iIgnore ) )
                throw eParserUnrecognizedAttrVal( mstrValue, mLineNum );                
        }
    }
    else
    {
        throw eParserUnrecognizedAttr( mstrName, mLineNum );
    }
}
////////////////////////////////////////////////////////////////////////////////
// Function name    : IsRoot
// Description      : A root path is all '/'s
//
// Return type      : bool
// Argument         : const TSTRING& strPath
///////////////////////////////////////////////////////////////////////////////
bool cUnixFSServices::IsRoot(const TSTRING& strPath) const
{
    // and empty path is NOT the root path
    if (strPath.empty())
        return false;

    // check to see if all characters are a slash
    for (TSTRING::const_iterator iter = strPath.begin(); iter != strPath.end(); iter++)
    {
        // if we've found a char that's not '/', then it's not the root path
        if (*iter != TW_SLASH)
            return false;
    }

    return true;
}
static void SplitString( const TSTRING& str, TCHAR c, std::vector<TSTRING>& vStrings )
{
    vStrings.clear();

    TSTRING::const_iterator i, prev;
    for( prev = i = str.begin(); i != str.end(); i++ )
    {
        if( *i == c )
        {
            vStrings.push_back(TSTRING());
            vStrings.back().assign( prev, i );
            prev = i+1;
        }
    }
    if( prev != i )
    {
        vStrings.push_back(TSTRING());
        vStrings.back().assign( prev, i );
    }
}
void cEncoder::Encode( TSTRING& strIn ) const
{
    // TODO:BAM -- reserve space for strOut as an optimization?
    TSTRING strOut;         // encoded string we will build up

    TSTRING::const_iterator         cur = strIn.begin();  // pointer to working position in strIn
    const TSTRING::const_iterator   end = strIn.end();    // end of strIn
    TSTRING::const_iterator         first = end;          // identifies beginning of current character
    TSTRING::const_iterator         last  = end;          // identifies end of current character

    // while get next char (updates cur)
    while( cCharUtil::PopNextChar( cur, end, first, last ) )
    {
        bool fCharEncoded = false; // answers: did char need encoding?
        sack_type::const_iterator atE;

        // for all encoders
        for( atE = m_encodings.begin(); 
             atE != m_encodings.end();
             atE++ )
        {
            // does char need encoding?
            if( (*atE)->NeedsEncoding( first, last ) )
            {
                strOut += Encode( first, last, atE );
                fCharEncoded = true;
                break;  // each char should only fail at most one 
                        // encoding test, so it should be cool to quit
            }
        }

        if( ! fCharEncoded )
        {
            strOut.append( first, last ); // simply add current char to output since it needed no encoding
        }
    }

    // pass back encoded string
    strIn = strOut;
}
void cEncoder::Decode( TSTRING& strIn ) const
{
    // TODO:BAM -- reserve space for strOut as an optimization?
    TSTRING strOut;         // decoded string we will build up

    TSTRING::const_iterator         cur = strIn.begin();  // pointer to working position in strIn
    const TSTRING::const_iterator   end = strIn.end();    // end of strIn
    TSTRING::const_iterator         first = end;          // identifies beginning of current character
    TSTRING::const_iterator         last  = end;          // identifies end of current character
    

    // while get next char (updates cur)
    while( cCharUtil::PopNextChar( cur, end, first, last ) )
    {
        // is this char the escape character?
        if( IsSingleTCHAR( first, last ) && 
            *first == iCharEncoder::EscapeChar() )
        {
            // get to identifier
            if( ! cCharUtil::PopNextChar( cur, end, first, last ) )
                ThrowAndAssert( eBadDecoderInput() );
            
            // this algorithm assumes that all identifiers are single char
            // so anything following the escape char should be a 
            // single-char identifier
            if( ! IsSingleTCHAR( first, last ) ) 
                THROW_INTERNAL( "displayencoder.cpp" );

            // determine to which encoding the identifier belongs
            bool fFoundEncoding = false;
            sack_type::const_iterator atE;
            for( atE = m_encodings.begin(); 
                 atE != m_encodings.end(); 
                 atE++ )
            {
                // is this the right encoding?
                if( *first == (*atE)->Identifier() )
                {
                    // this is the correct encoding....
                    fFoundEncoding = true;

                    // ...so decode char
                    strOut += (*atE)->Decode( &first, end ); // should modify cur
                    
                    cur = first; // advance current char pointer

                    break;  // no need to run other tests after 
                            // this because all identifiers should be unique
                }
            }

            if( ! fFoundEncoding )
                ThrowAndAssert( eUnknownEscapeEncoding( TSTRING( 1, *first ) ) );
        }
        else
        {        
            strOut.append( first, last );
        }
    }

    strIn = strOut;
}