void cGenreSwitcher::RegisterGenre(const cGenreInfo* pGI, RegisterFlags flags /* = REGISTER_FLAGS_NONE */)
{
    cDebug d("cGenreSwitcher::RegisterGenre");

    ASSERT(NULL != pGI);
    ASSERT(pGI->IsValid());

    d.TraceDebug(
        _T("ID: %x, long name: %s, short name: %s\n"), pGI->m_ID, pGI->m_sLongName.c_str(), pGI->m_sShortName.c_str());

    //
    // can only be one of each genre ID
    //
    if (m_vGenres.find(pGI) != m_vGenres.end())
    {
        // TODO: correct behavior?  Should this be allowable/ignored?
        THROW_INTERNAL("genreswitcher.cpp"); // Attempt to register duplicate genre ID.
    }

    //
    // save genre info
    //
    m_vGenres.push_back(pGI);

    //
    // set default genre if appropriate
    //
    if (flags & REGISTER_FLAGS_DEFAULT)
    {
        // can only be one default genre
        // TODO: should we allow more than one lib to vie for default genre on a platform?
        if (NULL != m_pDefaultGenre)
            THROW_INTERNAL("genreswitcher.cpp"); // "Two genres claim default genre status." );

        // save as default genre
        m_pDefaultGenre = pGI;
    }
}
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;
}