<commit_before>/*************************************************************************
 *
 *  $RCSfile: export2.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: nf $ $Date: 2000-11-27 07:10:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include "export.hxx"

//
// class ResData();
//

/*****************************************************************************/
ResData::~ResData()
/*****************************************************************************/
{
    if ( pStringList ) {
        // delete existing res. of type StringList
        for ( ULONG i = 0; i < pStringList->Count(); i++ ) {
            delete [] pStringList->GetObject( i );
        }
        delete pStringList;
    }
    if ( pFilterList ) {
        // delete existing res. of type FilterList
        for ( ULONG i = 0; i < pFilterList->Count(); i++ ) {
            delete [] pFilterList->GetObject( i );
        }
        delete pFilterList;
    }
    if ( pItemList ) {
        // delete existing res. of type ItemList
        for ( ULONG i = 0; i < pItemList->Count(); i++ ) {
            delete [] pItemList->GetObject( i );
        }
        delete pItemList;
    }
    if ( pUIEntries ) {
        // delete existing res. of type UIEntries
        for ( ULONG i = 0; i < pUIEntries->Count(); i++ ) {
            delete [] pUIEntries->GetObject( i );
        }
        delete pUIEntries;
    }
}

//
// class Export
//

/*****************************************************************************/
USHORT Export::LangId[ LANGUAGES ] =
/*****************************************************************************/
{
    // translation table: Index <=> LangId
    COMMENT,
    ENGLISH_US,
    PORTUGUESE,
    GERMAN_DE,
    RUSSIAN,
    GREEK,
    DUTCH,
    FRENCH,
    SPANISH,
    FINNISH,
    HUNGARIAN,
    ITALIAN,
    CZECH,
    SLOVAK,
    ENGLISH,
    DANISH,
    SWEDISH,
    NORWEGIAN,
    POLISH,
    GERMAN,
    PORTUGUESE_BRAZILIAN,
    JAPANESE,
    KOREAN,
    CHINESE_SIMPLIFIED,
    CHINESE_TRADITIONAL,
    TURKISH,
    ARABIC,
    HEBREW
};

/*****************************************************************************/
USHORT Export::GetLangIndex( USHORT nLangId )
/*****************************************************************************/
{
    for ( USHORT i = 0; i < LANGUAGES; i++ )
        if ( nLangId == LangId[ i ] )
            return i;
    return 0xFFFF;
}

/*****************************************************************************/
CharSet Export::GetCharSet( USHORT nLangId )
/*****************************************************************************/
{
    switch ( nLangId ) {
        case COMMENT: return RTL_TEXTENCODING_MS_1252;
        case ENGLISH_US: return RTL_TEXTENCODING_MS_1252;
        case PORTUGUESE: return RTL_TEXTENCODING_MS_1252;
        case RUSSIAN: return RTL_TEXTENCODING_MS_1251;
        case GREEK: return RTL_TEXTENCODING_MS_1253;
        case DUTCH: return RTL_TEXTENCODING_MS_1252;
        case FRENCH: return RTL_TEXTENCODING_MS_1252;
        case SPANISH: return RTL_TEXTENCODING_MS_1252;
        case FINNISH: return RTL_TEXTENCODING_MS_1252;
        case HUNGARIAN: return RTL_TEXTENCODING_MS_1250;
        case ITALIAN: return RTL_TEXTENCODING_MS_1252;
        case CZECH: return RTL_TEXTENCODING_MS_1250;
        case SLOVAK: return RTL_TEXTENCODING_MS_1250;
        case ENGLISH: return RTL_TEXTENCODING_MS_1252;
        case DANISH: return RTL_TEXTENCODING_MS_1252;
        case SWEDISH: return RTL_TEXTENCODING_MS_1252;
        case NORWEGIAN: return RTL_TEXTENCODING_MS_1252;
        case POLISH: return RTL_TEXTENCODING_MS_1250;
        case GERMAN: return RTL_TEXTENCODING_MS_1252;
        case PORTUGUESE_BRAZILIAN: return RTL_TEXTENCODING_MS_1252;
        case JAPANESE: return RTL_TEXTENCODING_MS_932;
        case KOREAN: return RTL_TEXTENCODING_MS_949;
        case CHINESE_SIMPLIFIED: return RTL_TEXTENCODING_MS_936;
        case CHINESE_TRADITIONAL: return RTL_TEXTENCODING_MS_950;
        case TURKISH: return RTL_TEXTENCODING_MS_1254;
        case ARABIC: return RTL_TEXTENCODING_MS_1256;
        case HEBREW: return RTL_TEXTENCODING_MS_1255;
    }
    return 0xFFFF;
}

/*****************************************************************************/
USHORT Export::GetLangByIsoLang( const ByteString &rIsoLang )
/*****************************************************************************/
{
    ByteString sLang( rIsoLang );

    sLang.ToUpperAscii();

    if ( sLang == ByteString( COMMENT_ISO ).ToUpperAscii())
        return COMMENT;
    else if ( sLang == ByteString( ENGLISH_US_ISO ).ToUpperAscii())
        return ENGLISH_US;
    else if ( sLang == ByteString( PORTUGUESE_ISO ).ToUpperAscii())
        return PORTUGUESE;
    else if ( sLang == ByteString( RUSSIAN_ISO ).ToUpperAscii())
        return RUSSIAN;
    else if ( sLang == ByteString( GREEK_ISO ).ToUpperAscii())
        return GREEK;
    else if ( sLang == ByteString( DUTCH_ISO ).ToUpperAscii())
        return DUTCH;
    else if ( sLang == ByteString( FRENCH_ISO ).ToUpperAscii())
        return FRENCH;
    else if ( sLang == ByteString( SPANISH_ISO ).ToUpperAscii())
        return SPANISH;
    else if ( sLang == ByteString( FINNISH_ISO ).ToUpperAscii())
        return FINNISH;
    else if ( sLang == ByteString( HUNGARIAN_ISO ).ToUpperAscii())
        return HUNGARIAN;
    else if ( sLang == ByteString( ITALIAN_ISO ).ToUpperAscii())
        return ITALIAN;
    else if ( sLang == ByteString( CZECH_ISO ).ToUpperAscii())
        return CZECH;
    else if ( sLang == ByteString( SLOVAK_ISO ).ToUpperAscii())
        return SLOVAK;
    else if ( sLang == ByteString( ENGLISH_ISO ).ToUpperAscii())
        return ENGLISH;
    else if ( sLang == ByteString( DANISH_ISO ).ToUpperAscii())
        return DANISH;
    else if ( sLang == ByteString( SWEDISH_ISO ).ToUpperAscii())
        return SWEDISH;
    else if ( sLang == ByteString( NORWEGIAN_ISO ).ToUpperAscii())
        return NORWEGIAN;
    else if ( sLang == ByteString( POLISH_ISO ).ToUpperAscii())
        return POLISH;
    else if ( sLang == ByteString( GERMAN_ISO ).ToUpperAscii())
        return GERMAN;
    else if ( sLang == ByteString( PORTUGUESE_BRAZILIAN_ISO ).ToUpperAscii())
        return PORTUGUESE_BRAZILIAN;
    else if ( sLang == ByteString( JAPANESE_ISO ).ToUpperAscii())
        return JAPANESE;
    else if ( sLang == ByteString( KOREAN_ISO ).ToUpperAscii())
        return KOREAN;
    else if ( sLang == ByteString( CHINESE_SIMPLIFIED_ISO ).ToUpperAscii())
        return CHINESE_SIMPLIFIED;
    else if ( sLang == ByteString( CHINESE_TRADITIONAL_ISO ).ToUpperAscii())
        return CHINESE_TRADITIONAL;
    else if ( sLang == ByteString( TURKISH_ISO ).ToUpperAscii())
        return TURKISH;
    else if ( sLang == ByteString( ARABIC_ISO ).ToUpperAscii())
        return ARABIC;
    else if ( sLang == ByteString( HEBREW_ISO ).ToUpperAscii())
        return HEBREW;

    return 0xFFFF;
}

/*****************************************************************************/
ByteString Export::GetIsoLangByIndex( USHORT nIndex )
/*****************************************************************************/
{
    switch ( nIndex ) {
        case COMMENT_INDEX: return COMMENT_ISO;
        case ENGLISH_US_INDEX: return ENGLISH_US_ISO;
        case PORTUGUESE_INDEX: return PORTUGUESE_ISO;
        case RUSSIAN_INDEX: return RUSSIAN_ISO;
        case GREEK_INDEX: return GREEK_ISO;
        case DUTCH_INDEX: return DUTCH_ISO;
        case FRENCH_INDEX: return FRENCH_ISO;
        case SPANISH_INDEX: return SPANISH_ISO;
        case FINNISH_INDEX: return FINNISH_ISO;
        case HUNGARIAN_INDEX: return HUNGARIAN_ISO;
        case ITALIAN_INDEX: return ITALIAN_ISO;
        case CZECH_INDEX: return CZECH_ISO;
        case SLOVAK_INDEX: return SLOVAK_ISO;
        case ENGLISH_INDEX: return ENGLISH_ISO;
        case DANISH_INDEX: return DANISH_ISO;
        case SWEDISH_INDEX: return SWEDISH_ISO;
        case NORWEGIAN_INDEX: return NORWEGIAN_ISO;
        case POLISH_INDEX: return POLISH_ISO;
        case GERMAN_INDEX: return GERMAN_ISO;
        case PORTUGUESE_BRAZILIAN_INDEX: return PORTUGUESE_BRAZILIAN_ISO;
        case JAPANESE_INDEX: return JAPANESE_ISO;
        case KOREAN_INDEX: return KOREAN_ISO;
        case CHINESE_SIMPLIFIED_INDEX: return CHINESE_SIMPLIFIED_ISO;
        case CHINESE_TRADITIONAL_INDEX: return CHINESE_TRADITIONAL_ISO;
        case TURKISH_INDEX: return TURKISH_ISO;
        case ARABIC_INDEX: return ARABIC_ISO;
        case HEBREW_INDEX: return HEBREW_ISO;
    }
    return "";
}

/*****************************************************************************/
void Export::QuotHTML( ByteString &rString )
/*****************************************************************************/
{
    ByteString sReturn;
    for ( ULONG i = 0; i < rString.Len(); i++ ) {
        switch ( rString.GetChar( i )) {
            case '<':
                sReturn += "<";
            break;

            case '>':
                sReturn += ">";
            break;

            case '\"':
                sReturn += """;
            break;

            case '\'':
                sReturn += "'";
            break;

            case '&':
                if ((( i + 4 ) < rString.Len()) &&
                    ( rString.Copy( i, 5 ) == "&" ))
                        sReturn += rString.GetChar( i );
                else
                    sReturn += "&";
            break;

            default:
                sReturn += rString.GetChar( i );
            break;
        }
    }
    rString = sReturn;
}

/*****************************************************************************/
void Export::UnquotHTML( ByteString &rString )
/*****************************************************************************/
{
    ByteString sReturn;
    while ( rString.Len()) {
        if ( rString.Copy( 0, 5 ) == "&" ) {
            sReturn += "&";
            rString.Erase( 0, 5 );
        }
        else if ( rString.Copy( 0, 4 ) == "<" ) {
            sReturn += "<";
            rString.Erase( 0, 4 );
        }
        else if ( rString.Copy( 0, 4 ) == ">" ) {
            sReturn += ">";
            rString.Erase( 0, 4 );
        }
        else if ( rString.Copy( 0, 6 ) == """ ) {
            sReturn += "\"";
            rString.Erase( 0, 6 );
        }
        else if ( rString.Copy( 0, 6 ) == "'" ) {
            sReturn += "\'";
            rString.Erase( 0, 6 );
        }
        else {
            sReturn += rString.GetChar( 0 );
            rString.Erase( 0, 1 );
        }
    }
    rString = sReturn;
}

/*****************************************************************************/
const ByteString Export::LangName[ LANGUAGES ] =
/*****************************************************************************/
{
    "language_user1",
    "english_us",
    "portuguese",
    "german_de",
    "russian",
    "greek",
    "dutch",
    "french",
    "spanish",
    "finnish",
    "hungarian",
    "italian",
    "czech",
    "slovak",
    "english",
    "danish",
    "swedish",
    "norwegian",
    "polish",
    "german",
    "portuguese_brazilian",
    "japanese",
    "korean",
    "chinese_simplified",
    "chinese_traditional",
    "turkish",
    "arabic",
    "hebrew"
};
<commit_msg>Fix #81620#<commit_after>/*************************************************************************
 *
 *  $RCSfile: export2.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: nf $ $Date: 2000-12-08 12:49:25 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include "export.hxx"

//
// class ResData();
//

/*****************************************************************************/
ResData::~ResData()
/*****************************************************************************/
{
    if ( pStringList ) {
        // delete existing res. of type StringList
        for ( ULONG i = 0; i < pStringList->Count(); i++ ) {
            delete [] pStringList->GetObject( i );
        }
        delete pStringList;
    }
    if ( pFilterList ) {
        // delete existing res. of type FilterList
        for ( ULONG i = 0; i < pFilterList->Count(); i++ ) {
            delete [] pFilterList->GetObject( i );
        }
        delete pFilterList;
    }
    if ( pItemList ) {
        // delete existing res. of type ItemList
        for ( ULONG i = 0; i < pItemList->Count(); i++ ) {
            delete [] pItemList->GetObject( i );
        }
        delete pItemList;
    }
    if ( pUIEntries ) {
        // delete existing res. of type UIEntries
        for ( ULONG i = 0; i < pUIEntries->Count(); i++ ) {
            delete [] pUIEntries->GetObject( i );
        }
        delete pUIEntries;
    }
}

//
// class Export
//

/*****************************************************************************/
USHORT Export::LangId[ LANGUAGES ] =
/*****************************************************************************/
{
    // translation table: Index <=> LangId
    COMMENT,
    ENGLISH_US,
    PORTUGUESE,
    GERMAN_DE,
    RUSSIAN,
    GREEK,
    DUTCH,
    FRENCH,
    SPANISH,
    FINNISH,
    HUNGARIAN,
    ITALIAN,
    CZECH,
    SLOVAK,
    ENGLISH,
    DANISH,
    SWEDISH,
    NORWEGIAN,
    POLISH,
    GERMAN,
    PORTUGUESE_BRAZILIAN,
    JAPANESE,
    KOREAN,
    CHINESE_SIMPLIFIED,
    CHINESE_TRADITIONAL,
    TURKISH,
    ARABIC,
    HEBREW
};

/*****************************************************************************/
USHORT Export::GetLangIndex( USHORT nLangId )
/*****************************************************************************/
{
    for ( USHORT i = 0; i < LANGUAGES; i++ )
        if ( nLangId == LangId[ i ] )
            return i;
    return 0xFFFF;
}

/*****************************************************************************/
CharSet Export::GetCharSet( USHORT nLangId )
/*****************************************************************************/
{
    switch ( nLangId ) {
        case COMMENT: return RTL_TEXTENCODING_MS_1252;
        case ENGLISH_US: return RTL_TEXTENCODING_MS_1252;
        case PORTUGUESE: return RTL_TEXTENCODING_MS_1252;
        case RUSSIAN: return RTL_TEXTENCODING_MS_1251;
        case GREEK: return RTL_TEXTENCODING_MS_1253;
        case DUTCH: return RTL_TEXTENCODING_MS_1252;
        case FRENCH: return RTL_TEXTENCODING_MS_1252;
        case SPANISH: return RTL_TEXTENCODING_MS_1252;
        case FINNISH: return RTL_TEXTENCODING_MS_1252;
        case HUNGARIAN: return RTL_TEXTENCODING_MS_1250;
        case ITALIAN: return RTL_TEXTENCODING_MS_1252;
        case CZECH: return RTL_TEXTENCODING_MS_1250;
        case SLOVAK: return RTL_TEXTENCODING_MS_1250;
        case ENGLISH: return RTL_TEXTENCODING_MS_1252;
        case DANISH: return RTL_TEXTENCODING_MS_1252;
        case SWEDISH: return RTL_TEXTENCODING_MS_1252;
        case NORWEGIAN: return RTL_TEXTENCODING_MS_1252;
        case POLISH: return RTL_TEXTENCODING_MS_1250;
        case GERMAN: return RTL_TEXTENCODING_MS_1252;
        case PORTUGUESE_BRAZILIAN: return RTL_TEXTENCODING_MS_1252;
        case JAPANESE: return RTL_TEXTENCODING_MS_932;
        case KOREAN: return RTL_TEXTENCODING_MS_949;
        case CHINESE_SIMPLIFIED: return RTL_TEXTENCODING_MS_936;
        case CHINESE_TRADITIONAL: return RTL_TEXTENCODING_MS_950;
        case TURKISH: return RTL_TEXTENCODING_MS_1254;
        case ARABIC: return RTL_TEXTENCODING_MS_1256;
        case HEBREW: return RTL_TEXTENCODING_MS_1255;
    }
    return 0xFFFF;
}

/*****************************************************************************/
USHORT Export::GetLangByIsoLang( const ByteString &rIsoLang )
/*****************************************************************************/
{
    ByteString sLang( rIsoLang );

    sLang.ToUpperAscii();

    if ( sLang == ByteString( COMMENT_ISO ).ToUpperAscii())
        return COMMENT;
    else if ( sLang == ByteString( ENGLISH_US_ISO ).ToUpperAscii())
        return ENGLISH_US;
    else if ( sLang == ByteString( PORTUGUESE_ISO ).ToUpperAscii())
        return PORTUGUESE;
    else if ( sLang == ByteString( RUSSIAN_ISO ).ToUpperAscii())
        return RUSSIAN;
    else if ( sLang == ByteString( GREEK_ISO ).ToUpperAscii())
        return GREEK;
    else if ( sLang == ByteString( DUTCH_ISO ).ToUpperAscii())
        return DUTCH;
    else if ( sLang == ByteString( FRENCH_ISO ).ToUpperAscii())
        return FRENCH;
    else if ( sLang == ByteString( SPANISH_ISO ).ToUpperAscii())
        return SPANISH;
    else if ( sLang == ByteString( FINNISH_ISO ).ToUpperAscii())
        return FINNISH;
    else if ( sLang == ByteString( HUNGARIAN_ISO ).ToUpperAscii())
        return HUNGARIAN;
    else if ( sLang == ByteString( ITALIAN_ISO ).ToUpperAscii())
        return ITALIAN;
    else if ( sLang == ByteString( CZECH_ISO ).ToUpperAscii())
        return CZECH;
    else if ( sLang == ByteString( SLOVAK_ISO ).ToUpperAscii())
        return SLOVAK;
    else if ( sLang == ByteString( ENGLISH_ISO ).ToUpperAscii())
        return ENGLISH;
    else if ( sLang == ByteString( DANISH_ISO ).ToUpperAscii())
        return DANISH;
    else if ( sLang == ByteString( SWEDISH_ISO ).ToUpperAscii())
        return SWEDISH;
    else if ( sLang == ByteString( NORWEGIAN_ISO ).ToUpperAscii())
        return NORWEGIAN;
    else if ( sLang == ByteString( POLISH_ISO ).ToUpperAscii())
        return POLISH;
    else if ( sLang == ByteString( GERMAN_ISO ).ToUpperAscii())
        return GERMAN;
    else if ( sLang == ByteString( PORTUGUESE_BRAZILIAN_ISO ).ToUpperAscii())
        return PORTUGUESE_BRAZILIAN;
    else if ( sLang == ByteString( JAPANESE_ISO ).ToUpperAscii())
        return JAPANESE;
    else if ( sLang == ByteString( KOREAN_ISO ).ToUpperAscii())
        return KOREAN;
    else if ( sLang == ByteString( CHINESE_SIMPLIFIED_ISO ).ToUpperAscii())
        return CHINESE_SIMPLIFIED;
    else if ( sLang == ByteString( CHINESE_TRADITIONAL_ISO ).ToUpperAscii())
        return CHINESE_TRADITIONAL;
    else if ( sLang == ByteString( TURKISH_ISO ).ToUpperAscii())
        return TURKISH;
    else if ( sLang == ByteString( ARABIC_ISO ).ToUpperAscii())
        return ARABIC;
    else if ( sLang == ByteString( HEBREW_ISO ).ToUpperAscii())
        return HEBREW;

    return 0xFFFF;
}

/*****************************************************************************/
ByteString Export::GetIsoLangByIndex( USHORT nIndex )
/*****************************************************************************/
{
    switch ( nIndex ) {
        case COMMENT_INDEX: return COMMENT_ISO;
        case ENGLISH_US_INDEX: return ENGLISH_US_ISO;
        case PORTUGUESE_INDEX: return PORTUGUESE_ISO;
        case RUSSIAN_INDEX: return RUSSIAN_ISO;
        case GREEK_INDEX: return GREEK_ISO;
        case DUTCH_INDEX: return DUTCH_ISO;
        case FRENCH_INDEX: return FRENCH_ISO;
        case SPANISH_INDEX: return SPANISH_ISO;
        case FINNISH_INDEX: return FINNISH_ISO;
        case HUNGARIAN_INDEX: return HUNGARIAN_ISO;
        case ITALIAN_INDEX: return ITALIAN_ISO;
        case CZECH_INDEX: return CZECH_ISO;
        case SLOVAK_INDEX: return SLOVAK_ISO;
        case ENGLISH_INDEX: return ENGLISH_ISO;
        case DANISH_INDEX: return DANISH_ISO;
        case SWEDISH_INDEX: return SWEDISH_ISO;
        case NORWEGIAN_INDEX: return NORWEGIAN_ISO;
        case POLISH_INDEX: return POLISH_ISO;
        case GERMAN_INDEX: return GERMAN_ISO;
        case PORTUGUESE_BRAZILIAN_INDEX: return PORTUGUESE_BRAZILIAN_ISO;
        case JAPANESE_INDEX: return JAPANESE_ISO;
        case KOREAN_INDEX: return KOREAN_ISO;
        case CHINESE_SIMPLIFIED_INDEX: return CHINESE_SIMPLIFIED_ISO;
        case CHINESE_TRADITIONAL_INDEX: return CHINESE_TRADITIONAL_ISO;
        case TURKISH_INDEX: return TURKISH_ISO;
        case ARABIC_INDEX: return ARABIC_ISO;
        case HEBREW_INDEX: return HEBREW_ISO;
    }
    return "";
}

/*****************************************************************************/
void Export::QuotHTML( ByteString &rString )
/*****************************************************************************/
{
    ByteString sReturn;
    BOOL bBreak = FALSE;
    for ( ULONG i = 0; i < rString.Len(); i++ ) {
        ByteString sTemp = rString.Copy( i );
        if ( sTemp.Search( "<Arg n=" ) == 0 ) {
            while ( i == rString.Len() || rString.GetChar( i ) == '>' ) {
                 sReturn += rString.GetChar( i );
                i++;
            }
        }
        if ( i < rString.Len()) {
            switch ( rString.GetChar( i )) {
                case '<':
                    sReturn += "<";
                break;

                case '>':
                    sReturn += ">";
                break;

                case '\"':
                    sReturn += """;
                break;

                case '\'':
                    sReturn += "'";
                break;

                case '&':
                    if ((( i + 4 ) < rString.Len()) &&
                        ( rString.Copy( i, 5 ) == "&" ))
                            sReturn += rString.GetChar( i );
                    else
                        sReturn += "&";
                break;

                default:
                    sReturn += rString.GetChar( i );
                break;
            }
        }
    }
    rString = sReturn;
}

/*****************************************************************************/
void Export::UnquotHTML( ByteString &rString )
/*****************************************************************************/
{
    ByteString sReturn;
    while ( rString.Len()) {
        if ( rString.Copy( 0, 5 ) == "&" ) {
            sReturn += "&";
            rString.Erase( 0, 5 );
        }
        else if ( rString.Copy( 0, 4 ) == "<" ) {
            sReturn += "<";
            rString.Erase( 0, 4 );
        }
        else if ( rString.Copy( 0, 4 ) == ">" ) {
            sReturn += ">";
            rString.Erase( 0, 4 );
        }
        else if ( rString.Copy( 0, 6 ) == """ ) {
            sReturn += "\"";
            rString.Erase( 0, 6 );
        }
        else if ( rString.Copy( 0, 6 ) == "'" ) {
            sReturn += "\'";
            rString.Erase( 0, 6 );
        }
        else {
            sReturn += rString.GetChar( 0 );
            rString.Erase( 0, 1 );
        }
    }
    rString = sReturn;
}

/*****************************************************************************/
const ByteString Export::LangName[ LANGUAGES ] =
/*****************************************************************************/
{
    "language_user1",
    "english_us",
    "portuguese",
    "german_de",
    "russian",
    "greek",
    "dutch",
    "french",
    "spanish",
    "finnish",
    "hungarian",
    "italian",
    "czech",
    "slovak",
    "english",
    "danish",
    "swedish",
    "norwegian",
    "polish",
    "german",
    "portuguese_brazilian",
    "japanese",
    "korean",
    "chinese_simplified",
    "chinese_traditional",
    "turkish",
    "arabic",
    "hebrew"
};
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Jose Fonseca
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/*
 * Simple addr2line like utility.
 */

#define __STDC_FORMAT_MACROS 1

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

#include <windows.h>
#include <dbghelp.h>

#include <getopt.h>

#include "symbols.h"
#include "wine.h"

static void
usage(const char *argv0)
{
    fprintf(stderr,
            "usage: %s -e EXECUTABLE ADDRESS ...\n"
            "\n"
            "options:\n"
            "  -C             demangle C++ function names\n"
            "  -D             enables debugging output (for debugging addr2line itself)\n"
            "  -e EXECUTABLE  specify the EXE/DLL\n"
            "  -f             show functions\n"
            "  -H             displays command line help text\n"
            "  -p             pretty print\n",
            argv0);
}

static BOOL CALLBACK
callback(HANDLE hProcess, ULONG ActionCode, ULONG64 CallbackData, ULONG64 UserContext)
{
    if (ActionCode == CBA_DEBUG_INFO) {
        fputs((LPCSTR)(UINT_PTR)CallbackData, stderr);
        return TRUE;
    }

    return FALSE;
}

int
main(int argc, char **argv)
{
    BOOL bRet;
    DWORD dwRet;
    bool debug = false;
    char *szModule = nullptr;
    bool functions = false;
    bool demangle = false;
    bool pretty = false;

    while (1) {
        int opt = getopt(argc, argv, "?CDe:fHp");

        switch (opt) {
        case 'C':
            demangle = true;
            break;
        case 'D':
            debug = true;
            break;
        case 'e':
            szModule = optarg;
            break;
        case 'f':
            functions = true;
            break;
        case 'H':
            usage(argv[0]);
            return EXIT_SUCCESS;
        case 'p':
            pretty = true;
            break;
        case '?':
            fprintf(stderr, "error: invalid option `%c`\n", optopt);
            /* pass-through */
        default:
            usage(argv[0]);
            return EXIT_FAILURE;
        case -1:
            break;
        }
        if (opt == -1) {
            break;
        }
    }

    if (szModule == nullptr) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    // Load the module
    HMODULE hModule = nullptr;
#ifdef _WIN64
    // XXX: The GetModuleFileName function does not retrieve the path for
    // modules that were loaded using the LOAD_LIBRARY_AS_DATAFILE flag
    hModule = LoadLibraryExA(szModule, NULL, LOAD_LIBRARY_AS_DATAFILE);
#endif
    if (!hModule) {
        hModule = LoadLibraryExA(szModule, NULL, DONT_RESOLVE_DLL_REFERENCES);
    }
    if (!hModule) {
        fprintf(stderr, "error: failed to load %s\n", szModule);
        return EXIT_FAILURE;
    }

    // Handles for modules loaded with DATAFILE/IMAGE_RESOURCE flags have lower
    // bits set
    DWORD64 BaseOfDll = (DWORD64)(UINT_PTR)hModule;
    BaseOfDll &= ~DWORD64(3);

    DWORD dwSymOptions = SymGetOptions();

    dwSymOptions |= SYMOPT_LOAD_LINES;

#ifndef NDEBUG
    dwSymOptions |= SYMOPT_DEBUG;
#endif

    // We can get more information by calling UnDecorateSymbolName() ourselves.
    dwSymOptions &= ~SYMOPT_UNDNAME;

    SymSetOptions(dwSymOptions);

    HANDLE hProcess = GetCurrentProcess();
    bRet = InitializeSym(hProcess, FALSE);
    assert(bRet);

    if (debug) {
        SymRegisterCallback64(hProcess, &callback, 0);
    }

    dwRet = SymLoadModuleEx(hProcess, NULL, szModule, NULL, BaseOfDll, 0, NULL, 0);
    if (!dwRet) {
        fprintf(stderr, "warning: failed to load module symbols\n");
    }

    if (!GetModuleHandleA("symsrv.dll")) {
        fprintf(stderr, "warning: symbol server not loaded\n");
    }

    while (optind < argc) {
        const char *arg = argv[optind++];

        DWORD64 dwRelAddr;
        if (arg[0] == '0' && arg[1] == 'x') {
            sscanf(&arg[2], "%08" PRIX64, &dwRelAddr);
        } else {
            dwRelAddr = atol(arg);
        }

        UINT_PTR dwAddr = BaseOfDll + dwRelAddr;

        if (functions) {
            struct {
                SYMBOL_INFO Symbol;
                CHAR Name[512];
            } sym;
            char UnDecoratedName[512];
            const char *function = "??";
            ZeroMemory(&sym, sizeof sym);
            sym.Symbol.SizeOfStruct = sizeof sym.Symbol;
            sym.Symbol.MaxNameLen = sizeof sym.Symbol.Name + sizeof sym.Name;
            DWORD64 dwSymDisplacement = 0;
            bRet = SymFromAddr(hProcess, dwAddr, &dwSymDisplacement, &sym.Symbol);
            if (bRet) {
                function = sym.Symbol.Name;
                if (demangle) {
                    if (UnDecorateSymbolName(sym.Symbol.Name, UnDecoratedName,
                                             sizeof UnDecoratedName, UNDNAME_COMPLETE)) {
                        function = UnDecoratedName;
                    }
                }
            }
            fputs(function, stdout);
            fputs(pretty ? " at " : "\n", stdout);
        }

        IMAGEHLP_LINE64 line;
        ZeroMemory(&line, sizeof line);
        line.SizeOfStruct = sizeof line;
        DWORD dwLineDisplacement = 0;
        bRet = SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &line);
        if (bRet) {
            fprintf(stdout, "%s:%lu\n", line.FileName, line.LineNumber);
        } else {
            fputs("??:?\n", stdout);
        }
        fflush(stdout);
    }

    SymCleanup(hProcess);

    FreeLibrary(hModule);

    return 0;
}
<commit_msg>addr2line: Check InitializeSym result.<commit_after>/*
 * Copyright 2014 Jose Fonseca
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/*
 * Simple addr2line like utility.
 */

#define __STDC_FORMAT_MACROS 1

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

#include <windows.h>
#include <dbghelp.h>

#include <getopt.h>

#include "symbols.h"
#include "wine.h"

static void
usage(const char *argv0)
{
    fprintf(stderr,
            "usage: %s -e EXECUTABLE ADDRESS ...\n"
            "\n"
            "options:\n"
            "  -C             demangle C++ function names\n"
            "  -D             enables debugging output (for debugging addr2line itself)\n"
            "  -e EXECUTABLE  specify the EXE/DLL\n"
            "  -f             show functions\n"
            "  -H             displays command line help text\n"
            "  -p             pretty print\n",
            argv0);
}

static BOOL CALLBACK
callback(HANDLE hProcess, ULONG ActionCode, ULONG64 CallbackData, ULONG64 UserContext)
{
    if (ActionCode == CBA_DEBUG_INFO) {
        fputs((LPCSTR)(UINT_PTR)CallbackData, stderr);
        return TRUE;
    }

    return FALSE;
}

int
main(int argc, char **argv)
{
    BOOL bRet;
    DWORD dwRet;
    bool debug = false;
    char *szModule = nullptr;
    bool functions = false;
    bool demangle = false;
    bool pretty = false;

    while (1) {
        int opt = getopt(argc, argv, "?CDe:fHp");

        switch (opt) {
        case 'C':
            demangle = true;
            break;
        case 'D':
            debug = true;
            break;
        case 'e':
            szModule = optarg;
            break;
        case 'f':
            functions = true;
            break;
        case 'H':
            usage(argv[0]);
            return EXIT_SUCCESS;
        case 'p':
            pretty = true;
            break;
        case '?':
            fprintf(stderr, "error: invalid option `%c`\n", optopt);
            /* pass-through */
        default:
            usage(argv[0]);
            return EXIT_FAILURE;
        case -1:
            break;
        }
        if (opt == -1) {
            break;
        }
    }

    if (szModule == nullptr) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }

    // Load the module
    HMODULE hModule = nullptr;
#ifdef _WIN64
    // XXX: The GetModuleFileName function does not retrieve the path for
    // modules that were loaded using the LOAD_LIBRARY_AS_DATAFILE flag
    hModule = LoadLibraryExA(szModule, NULL, LOAD_LIBRARY_AS_DATAFILE);
#endif
    if (!hModule) {
        hModule = LoadLibraryExA(szModule, NULL, DONT_RESOLVE_DLL_REFERENCES);
    }
    if (!hModule) {
        fprintf(stderr, "error: failed to load %s\n", szModule);
        return EXIT_FAILURE;
    }

    // Handles for modules loaded with DATAFILE/IMAGE_RESOURCE flags have lower
    // bits set
    DWORD64 BaseOfDll = (DWORD64)(UINT_PTR)hModule;
    BaseOfDll &= ~DWORD64(3);

    DWORD dwSymOptions = SymGetOptions();

    dwSymOptions |= SYMOPT_LOAD_LINES;

#ifndef NDEBUG
    dwSymOptions |= SYMOPT_DEBUG;
#endif

    // We can get more information by calling UnDecorateSymbolName() ourselves.
    dwSymOptions &= ~SYMOPT_UNDNAME;

    SymSetOptions(dwSymOptions);

    HANDLE hProcess = GetCurrentProcess();
    bRet = InitializeSym(hProcess, FALSE);
    if (!bRet) {
        fprintf(stderr, "warning: failed to initialize DbgHelp\n");
        return EXIT_FAILURE;
    }

    if (debug) {
        SymRegisterCallback64(hProcess, &callback, 0);
    }

    dwRet = SymLoadModuleEx(hProcess, NULL, szModule, NULL, BaseOfDll, 0, NULL, 0);
    if (!dwRet) {
        fprintf(stderr, "warning: failed to load module symbols\n");
    }

    if (!GetModuleHandleA("symsrv.dll")) {
        fprintf(stderr, "warning: symbol server not loaded\n");
    }

    while (optind < argc) {
        const char *arg = argv[optind++];

        DWORD64 dwRelAddr;
        if (arg[0] == '0' && arg[1] == 'x') {
            sscanf(&arg[2], "%08" PRIX64, &dwRelAddr);
        } else {
            dwRelAddr = atol(arg);
        }

        UINT_PTR dwAddr = BaseOfDll + dwRelAddr;

        if (functions) {
            struct {
                SYMBOL_INFO Symbol;
                CHAR Name[512];
            } sym;
            char UnDecoratedName[512];
            const char *function = "??";
            ZeroMemory(&sym, sizeof sym);
            sym.Symbol.SizeOfStruct = sizeof sym.Symbol;
            sym.Symbol.MaxNameLen = sizeof sym.Symbol.Name + sizeof sym.Name;
            DWORD64 dwSymDisplacement = 0;
            bRet = SymFromAddr(hProcess, dwAddr, &dwSymDisplacement, &sym.Symbol);
            if (bRet) {
                function = sym.Symbol.Name;
                if (demangle) {
                    if (UnDecorateSymbolName(sym.Symbol.Name, UnDecoratedName,
                                             sizeof UnDecoratedName, UNDNAME_COMPLETE)) {
                        function = UnDecoratedName;
                    }
                }
            }
            fputs(function, stdout);
            fputs(pretty ? " at " : "\n", stdout);
        }

        IMAGEHLP_LINE64 line;
        ZeroMemory(&line, sizeof line);
        line.SizeOfStruct = sizeof line;
        DWORD dwLineDisplacement = 0;
        bRet = SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &line);
        if (bRet) {
            fprintf(stdout, "%s:%lu\n", line.FileName, line.LineNumber);
        } else {
            fputs("??:?\n", stdout);
        }
        fflush(stdout);
    }

    SymCleanup(hProcess);

    FreeLibrary(hModule);

    return 0;
}
<|endoftext|>


<commit_before>//=============================================================================
// File: px4muorb_KraitRpcWrapper.hpp
//
//  @@-COPYRIGHT-START-@@
//
// Copyright 2015 Qualcomm Technologies, Inc. All rights reserved.
// Confidential & Proprietary - Qualcomm Technologies, Inc. ("QTI")
//
// The party receiving this software directly from QTI (the "Recipient")
// may use this software as reasonably necessary solely for the purposes
// set forth in the agreement between the Recipient and QTI (the
// "Agreement"). The software may be used in source code form solely by
// the Recipient's employees (if any) authorized by the Agreement. Unless
// expressly authorized in the Agreement, the Recipient may not sublicense,
// assign, transfer or otherwise provide the source code to any third
// party. Qualcomm Technologies, Inc. retains all ownership rights in and
// to the software
//
// This notice supersedes any other QTI notices contained within the software
// except copyright notices indicating different years of publication for
// different portions of the software. This notice does not supersede the
// application of any third party copyright notice to that third party's
// code.
//
//  @@-COPYRIGHT-END-@@
//
//=============================================================================
#ifndef _px4muorb_KraitRpcWrapper_hpp_
#define _px4muorb_KraitRpcWrapper_hpp_
#include <stdint.h>

namespace px4muorb
{
class KraitRpcWrapper;
}

class px4muorb::KraitRpcWrapper
{
public:
	/**
	 * Constructor
	 */
	KraitRpcWrapper();

	/**
	 * destructor
	 */
	~KraitRpcWrapper();

	/**
	 * Initiatizes the rpc channel px4 muorb
	 */
	bool Initialize();

	/**
	 * Terminate to clean up the resources.  This should be called at program exit
	 */
	bool Terminate();

	/**
	 * Muorb related functions to pub/sub of orb topic from krait to adsp
	 */
	int32_t AddSubscriber(const char *topic);
	int32_t RemoveSubscriber(const char *topic);
	int32_t SendData(const char *topic, int32_t length_in_bytes, const uint8_t *data);
	int32_t ReceiveData(int32_t *msg_type, char **topic, int32_t *length_in_bytes, uint8_t **data);
	int32_t IsSubscriberPresent(const char *topic, int32_t *status);
	int32_t ReceiveBulkData(uint8_t **bulk_data, int32_t *length_in_bytes, int32_t *topic_count);
	int32_t UnblockReceiveData();
};
#endif // _px4muorb_KraitWrapper_hpp_
<commit_msg>Fixed copyright header<commit_after>/****************************************************************************
 *
 * Copyright (c) 2016 Ramakrishna Kintada. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/
#ifndef _px4muorb_KraitRpcWrapper_hpp_
#define _px4muorb_KraitRpcWrapper_hpp_
#include <stdint.h>

namespace px4muorb
{
class KraitRpcWrapper;
}

class px4muorb::KraitRpcWrapper
{
public:
	/**
	 * Constructor
	 */
	KraitRpcWrapper();

	/**
	 * destructor
	 */
	~KraitRpcWrapper();

	/**
	 * Initiatizes the rpc channel px4 muorb
	 */
	bool Initialize();

	/**
	 * Terminate to clean up the resources.  This should be called at program exit
	 */
	bool Terminate();

	/**
	 * Muorb related functions to pub/sub of orb topic from krait to adsp
	 */
	int32_t AddSubscriber(const char *topic);
	int32_t RemoveSubscriber(const char *topic);
	int32_t SendData(const char *topic, int32_t length_in_bytes, const uint8_t *data);
	int32_t ReceiveData(int32_t *msg_type, char **topic, int32_t *length_in_bytes, uint8_t **data);
	int32_t IsSubscriberPresent(const char *topic, int32_t *status);
	int32_t ReceiveBulkData(uint8_t **bulk_data, int32_t *length_in_bytes, int32_t *topic_count);
	int32_t UnblockReceiveData();
};
#endif // _px4muorb_KraitWrapper_hpp_
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\uti.hpp"
#include <fstream>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

template __declspec( dllexport ) class uti::UTF8String< >;

typedef uti::UTF8String< > String;

//template<> std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString( String* str )
//{
//	RETURN_WIDE_STRING( str->c_str() );
//}
template<> std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString( const String& str )
{
	RETURN_WIDE_STRING( str.c_str() );
}
//template<> std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString(const String* str )
//{
//	RETURN_WIDE_STRING( str->c_str() );
//}

namespace utiTest
{
	TEST_CLASS( UTF8Test )
	{
	public:

		TEST_METHOD( CTorTest )
		{

			try
			{
				String::ReplacementChar = "|";
				const char blah [] = { 0xFFu, 0xC0u, 0x00 };
				String string( blah );

				Assert::AreEqual( '|', string.c_str()[ 0 ] );

				const char excpected [] = "||";

				String test( excpected );

				Assert::AreEqual( test, string );
			}
			catch( ... )
			{
				Assert::Fail();
			}

			try
			{
				const char blah [] = "Some Test";

				String string( blah );

				Assert::AreEqual( 9U, string.CharCount() );
				Assert::AreEqual( 9U, string.Size() );

			}
			catch( ... )
			{
				Assert::Fail();
			}

			try
			{
				const char test [] = "Some Test";

				String string1 = test;
				String string2 = string1;

				String string3;
				string3 = string2;

				Assert::IsTrue( string1 == string2 );
				Assert::IsTrue( string2 == string3 );
				unsigned int iterations = 0;
				for( auto it = string3.Begin(); it != string3.End(); ++it, ++iterations )
				{
					Assert::AreEqual( *it, test[ iterations ] );

				}

				Assert::AreEqual( 9U, iterations );
			}
			catch( ... )
			{
				Assert::Fail();
			}

		}

		TEST_METHOD( CTorFailTest )
		{
			try
			{
				String string( ( const char* )nullptr );

				String string2 = string;

				String string3 = string + string2;

				Assert::IsTrue( string.Size() == 0 );
				Assert::IsTrue( string.CharCount() == 0 );
				Assert::IsTrue( string2.Size() == 0 );
				Assert::IsTrue( string2.CharCount() == 0 );
				Assert::IsTrue( string3.Size() == 0 );
				Assert::IsTrue( string3.CharCount() == 0 );
			}
			catch( ... )
			{
				Assert::Fail( L"Nullptr crashed the string constructor" );
			}
		}

		TEST_METHOD( IteratorTest )
		{
			String bla( "Test" );
			const char test [] = "Test";
			unsigned int iterations = 0;
			auto it = bla.Begin();

#ifdef DEBUG

			try
			{
				it--;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

			for( ; it != bla.End(); ++it, ++iterations )
			{
				Assert::AreEqual( *it, test[ iterations ] );

			}

			Assert::AreEqual( 4U, iterations );

#ifdef DEBUG
			try
			{
				it++;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

		}

		TEST_METHOD( ReverseIterator )
		{
			String bla( "Test" );
			const char* test = "Test";
			unsigned int iterations = 0;
			auto it = bla.rBegin();

#ifdef DEBUG
			try
			{
				it--;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

			for( ; it != bla.rEnd(); ++it, ++iterations )
			{
				Assert::AreEqual( test[ 3U - iterations ], *it );
			}

			Assert::AreEqual( 4U, iterations );

#ifdef DEBUG
			try
			{
				it++;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

		}

		TEST_METHOD( ConcatTest )
		{
			String first( "Some" );
			String second( "Test" );
			String expected( "SomeTest" );
			Assert::IsTrue( ( first + second ) == expected,
				( ToString( first + second ) + ToString( " does not match " ) + ToString( expected ) ).c_str() );
		}

		TEST_METHOD( ValidityTest )
		{
			char surrogate [] = { 0xd8U, 0x00U };

			Assert::AreEqual( String::ValidChar( surrogate ), 0U );
		}

		TEST_METHOD( WCharTest )
		{
			String myString = String::FromUTF16LE( L"" );
			Assert::AreEqual( 0U, myString.CharCount(), L"Converting empty widechar didn't create an empty UTf string!" );
			Assert::AreEqual( '\0', myString.Data()[ 0 ], L"Converting empty widechar didn't has an null terminated character!" );

			myString = String::FromUTF16LE( L"WideChar" );
			String myNotWideString( "WideChar" );

			Assert::AreEqual( myNotWideString.Size(), myString.Size(), L"Converting empty widechar didn't produces correct size" );
			Assert::AreEqual( myNotWideString.CharCount(), myString.CharCount(), L"Converting empty widechar didn't produces correct charCount" );

			Assert::AreEqual( myNotWideString, myString, L"Creating the same ascii text in ascii and unicode did not match" );

		}

		TEST_METHOD( CompleteCodePointTest )
		{
			std::ifstream file;
			file.open( "../test.txt", std::ios::binary );

			if( !file.is_open() )
			{
				Assert::Fail( L"Could not open File 'test.txt'" );
			}
			else
			{
				file.seekg( 0, std::ios::end );

				size_t fileSize = (size_t)file.tellg().seekpos();

				file.seekg( 0, std::ios::beg );

				char* content = new char[ fileSize + 1 ];
				content[ fileSize ] = '\0';

				size_t pos = 0;

				do
				{
					file.read( content + pos, 1000 );
					pos += (size_t)file.gcount();
				 }while( !file.eof() && file.gcount() != 0 );

				if( pos < 4416047U ) //Exact Byte size of test.txt
				{
					Assert::Fail( (
						std::wstring( L"Failed to read " ) +
						std::to_wstring( fileSize ) +
						std::wstring( L" Bytes of data, could only read " ) +
						std::to_wstring( pos ) + std::wstring( L" Bytes!" )
						).c_str() );
					return;
				}

				file.close();

				size_t charCount = 0;

				for( size_t i = 0; i < fileSize; )
				{
					size_t length = String::ValidChar( content + i );
					if( length == 0 )
					{
						Assert::Fail( (std::wstring( L"Invalid Char at position " ) + std::to_wstring( i )).c_str() );
						break;
					}
					else
					{
						i += length;
						charCount++;
					}

				}

				String completeUTF8( content );
				Assert::AreEqual( fileSize, completeUTF8.Size() );

				//TODO check CharCount as soon as its available;

				delete content;
			}
		}

		TEST_METHOD( SubstrTestOneParam )
		{
			String string( "Hello World" );
			String expected( "Hello" );

			auto it = string.CharBegin();

			for( size_t i = 0; i < 5; i++ )
			{
				++it;
			}

			String sub = string.Substr( it );

			Assert::AreNotEqual( string, sub, L"Substring does match original string!" );
			Assert::AreEqual( 5U, sub.CharCount(), L"Char Size of substring does not match!" );
			Assert::AreEqual( 5U, sub.Size(), L"Byte Size of substring does not match!" );
			Assert::AreEqual( expected, sub, L"Substring does not match expected string." );
		}

		TEST_METHOD( SubstrTestTwoParam )
		{
			String string( "Hello World" );
			String expected( "Wo" );

			auto beginIterator = string.CharBegin();

			for( size_t i = 0; i < 6; i++ )
			{
				++beginIterator;
			}

			auto endIterator = beginIterator;
			for( size_t i = 0; i < 2; i++ )
			{
				++endIterator;
			}

			String sub = string.Substr( beginIterator, endIterator );

			Assert::AreNotEqual( string, sub, L"Substring does match original string!" );
			Assert::AreEqual( 2U, sub.CharCount(), L"Char Size of substring does not match!" );
			Assert::AreEqual( 2U, sub.Size(), L"Byte Size of substring does not match!" );
			Assert::IsTrue( sub.Data()[ 0 ] == 'W' );
			Assert::IsTrue( sub.Data()[ 1 ] == 'o' );
			Assert::AreEqual( expected, sub, L"Substring does not match expected string." );
		}

	};
}
<commit_msg>Added negative test for Substr.<commit_after>#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\uti.hpp"
#include <fstream>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

template __declspec( dllexport ) class uti::UTF8String< >;

typedef uti::UTF8String< > String;

//template<> std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString( String* str )
//{
//	RETURN_WIDE_STRING( str->c_str() );
//}
template<> std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString( const String& str )
{
	RETURN_WIDE_STRING( str.c_str() );
}
//template<> std::wstring Microsoft::VisualStudio::CppUnitTestFramework::ToString(const String* str )
//{
//	RETURN_WIDE_STRING( str->c_str() );
//}

namespace utiTest
{
	TEST_CLASS( UTF8Test )
	{
	public:

		TEST_METHOD( CTorTest )
		{

			try
			{
				String::ReplacementChar = "|";
				const char blah [] = { 0xFFu, 0xC0u, 0x00 };
				String string( blah );

				Assert::AreEqual( '|', string.c_str()[ 0 ] );

				const char excpected [] = "||";

				String test( excpected );

				Assert::AreEqual( test, string );
			}
			catch( ... )
			{
				Assert::Fail();
			}

			try
			{
				const char blah [] = "Some Test";

				String string( blah );

				Assert::AreEqual( 9U, string.CharCount() );
				Assert::AreEqual( 9U, string.Size() );

			}
			catch( ... )
			{
				Assert::Fail();
			}

			try
			{
				const char test [] = "Some Test";

				String string1 = test;
				String string2 = string1;

				String string3;
				string3 = string2;

				Assert::IsTrue( string1 == string2 );
				Assert::IsTrue( string2 == string3 );
				unsigned int iterations = 0;
				for( auto it = string3.Begin(); it != string3.End(); ++it, ++iterations )
				{
					Assert::AreEqual( *it, test[ iterations ] );

				}

				Assert::AreEqual( 9U, iterations );
			}
			catch( ... )
			{
				Assert::Fail();
			}

		}

		TEST_METHOD( CTorFailTest )
		{
			try
			{
				String string( ( const char* )nullptr );

				String string2 = string;

				String string3 = string + string2;

				Assert::IsTrue( string.Size() == 0 );
				Assert::IsTrue( string.CharCount() == 0 );
				Assert::IsTrue( string2.Size() == 0 );
				Assert::IsTrue( string2.CharCount() == 0 );
				Assert::IsTrue( string3.Size() == 0 );
				Assert::IsTrue( string3.CharCount() == 0 );
			}
			catch( ... )
			{
				Assert::Fail( L"Nullptr crashed the string constructor" );
			}
		}

		TEST_METHOD( IteratorTest )
		{
			String bla( "Test" );
			const char test [] = "Test";
			unsigned int iterations = 0;
			auto it = bla.Begin();

#ifdef DEBUG

			try
			{
				it--;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

			for( ; it != bla.End(); ++it, ++iterations )
			{
				Assert::AreEqual( *it, test[ iterations ] );

			}

			Assert::AreEqual( 4U, iterations );

#ifdef DEBUG
			try
			{
				it++;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

		}

		TEST_METHOD( ReverseIterator )
		{
			String bla( "Test" );
			const char* test = "Test";
			unsigned int iterations = 0;
			auto it = bla.rBegin();

#ifdef DEBUG
			try
			{
				it--;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

			for( ; it != bla.rEnd(); ++it, ++iterations )
			{
				Assert::AreEqual( test[ 3U - iterations ], *it );
			}

			Assert::AreEqual( 4U, iterations );

#ifdef DEBUG
			try
			{
				it++;

				Assert::Fail();
			}
			catch( uti::UTFException& )
			{

			}
#endif // DEBUG

		}

		TEST_METHOD( ConcatTest )
		{
			String first( "Some" );
			String second( "Test" );
			String expected( "SomeTest" );
			Assert::IsTrue( ( first + second ) == expected,
				( ToString( first + second ) + ToString( " does not match " ) + ToString( expected ) ).c_str() );
		}

		TEST_METHOD( ValidityTest )
		{
			char surrogate [] = { 0xd8U, 0x00U };

			Assert::AreEqual( String::ValidChar( surrogate ), 0U );
		}

		TEST_METHOD( WCharTest )
		{
			String myString = String::FromUTF16LE( L"" );
			Assert::AreEqual( 0U, myString.CharCount(), L"Converting empty widechar didn't create an empty UTf string!" );
			Assert::AreEqual( '\0', myString.Data()[ 0 ], L"Converting empty widechar didn't has an null terminated character!" );

			myString = String::FromUTF16LE( L"WideChar" );
			String myNotWideString( "WideChar" );

			Assert::AreEqual( myNotWideString.Size(), myString.Size(), L"Converting empty widechar didn't produces correct size" );
			Assert::AreEqual( myNotWideString.CharCount(), myString.CharCount(), L"Converting empty widechar didn't produces correct charCount" );

			Assert::AreEqual( myNotWideString, myString, L"Creating the same ascii text in ascii and unicode did not match" );

		}

		TEST_METHOD( CompleteCodePointTest )
		{
			std::ifstream file;
			file.open( "../test.txt", std::ios::binary );

			if( !file.is_open() )
			{
				Assert::Fail( L"Could not open File 'test.txt'" );
			}
			else
			{
				file.seekg( 0, std::ios::end );

				size_t fileSize = (size_t)file.tellg().seekpos();

				file.seekg( 0, std::ios::beg );

				char* content = new char[ fileSize + 1 ];
				content[ fileSize ] = '\0';

				size_t pos = 0;

				do
				{
					file.read( content + pos, 1000 );
					pos += (size_t)file.gcount();
				 }while( !file.eof() && file.gcount() != 0 );

				if( pos < 4416047U ) //Exact Byte size of test.txt
				{
					Assert::Fail( (
						std::wstring( L"Failed to read " ) +
						std::to_wstring( fileSize ) +
						std::wstring( L" Bytes of data, could only read " ) +
						std::to_wstring( pos ) + std::wstring( L" Bytes!" )
						).c_str() );
					return;
				}

				file.close();

				size_t charCount = 0;

				for( size_t i = 0; i < fileSize; )
				{
					size_t length = String::ValidChar( content + i );
					if( length == 0 )
					{
						Assert::Fail( (std::wstring( L"Invalid Char at position " ) + std::to_wstring( i )).c_str() );
						break;
					}
					else
					{
						i += length;
						charCount++;
					}

				}

				String completeUTF8( content );
				Assert::AreEqual( fileSize, completeUTF8.Size() );

				//TODO check CharCount as soon as its available;

				delete content;
			}
		}

		TEST_METHOD( SubstrTestOneParam )
		{
			String string( "Hello World" );
			String expected( "Hello" );

			auto it = string.CharBegin();

			for( size_t i = 0; i < 5; i++ )
			{
				++it;
			}

			String sub = string.Substr( it );

			Assert::AreNotEqual( string, sub, L"Substring does match original string!" );
			Assert::AreEqual( 5U, sub.CharCount(), L"Char Size of substring does not match!" );
			Assert::AreEqual( 5U, sub.Size(), L"Byte Size of substring does not match!" );
			Assert::AreEqual( expected, sub, L"Substring does not match expected string." );
		}

		TEST_METHOD( SubstrTestTwoParam )
		{
			String string( "Hello World" );
			String expected( "Wo" );

			auto beginIterator = string.CharBegin();

			for( size_t i = 0; i < 6; i++ )
			{
				++beginIterator;
			}

			auto endIterator = beginIterator;
			for( size_t i = 0; i < 2; i++ )
			{
				++endIterator;
			}

			String sub = string.Substr( beginIterator, endIterator );

			Assert::AreNotEqual( string, sub, L"Substring does match original string!" );
			Assert::AreEqual( 2U, sub.CharCount(), L"Char Size of substring does not match!" );
			Assert::AreEqual( 2U, sub.Size(), L"Byte Size of substring does not match!" );
			Assert::IsTrue( sub.Data()[ 0 ] == 'W' );
			Assert::IsTrue( sub.Data()[ 1 ] == 'o' );
			Assert::AreEqual( expected, sub, L"Substring does not match expected string." );
		}

		TEST_METHOD( SubstrFailTest )
		{

			String str1( "FirstString" );
			String str2( "SecondString" );

			auto beginIterator = str2.CharBegin();
			auto endIterator = str2.CharEnd();

			// Using wrong iterator from other string should return empty string
			String sub = str1.Substr( beginIterator, endIterator );

			Assert::AreEqual( 0U, sub.Size(), L"String with wrong iterator does not return empty string" );
			Assert::AreNotEqual( str1, sub, L"Substring does match original string!" );
			Assert::AreNotEqual( str2, sub, L"Substring does match second string!" );

			// Using start Iterator which is greater than the end iterator should return empty string
			sub = str1.Substr( str1.CharEnd(), str1.CharBegin());

			Assert::AreEqual( 0U, sub.Size(), L"String with wrong iterator does not return empty string" );
			Assert::AreNotEqual( str1, sub, L"Substring does match original string!" );
			Assert::AreNotEqual( str2, sub, L"Substring does match second string!" );

		}

	};
}
<|endoftext|>


<commit_before>///
/// @file   S2_hard_mpi_LoadBalancer.cpp
/// @brief  The S2_hard_mpi_LoadBalancer evenly distributes the
///         computation of the hard special leaves onto cluster nodes.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2_hard_mpi_LoadBalancer.hpp>
#include <S2_hard_mpi_msg.hpp>
#include <primecount-internal.hpp>
#include <min_max.hpp>

#include <stdint.h>
#include <algorithm>

using namespace std;

namespace primecount {

S2_hard_mpi_LoadBalancer::S2_hard_mpi_LoadBalancer(int64_t low,
                                                   int64_t high,
                                                   int64_t y,
                                                   int64_t z,
                                                   int slave_procs)
  : low_(low),
    high_(high),
    y_(y),
    z_(z),
    slave_procs_(slave_procs),
    max_finished_(0),
    segment_size_(isqrt(z)),
    segments_per_thread_(1),
    proc_interval_(0),
    start_time_(get_wtime()),
    seconds_(0)
{ }

bool S2_hard_mpi_LoadBalancer::finished() const
{
  return low_ > z_;
}

bool S2_hard_mpi_LoadBalancer::is_increase(double seconds,
                                           double percent) const
{
  // calculate remaining time till finished
  double elapsed_time = get_wtime() - start_time_;
  double remaining_time = elapsed_time * (100 / max(1.0, percent)) - elapsed_time;

  // for performance reasons all processes should
  // finish nearly at the same time
  double near_finish_time = elapsed_time / 100;
  double divisor = 100 / pow(5.0, 100 / in_between(1, percent, 100));
  double max_time = remaining_time / max(1.0, divisor);
  double is_increase = max3(0.1, max_time, near_finish_time);

  return seconds < is_increase;
}

void S2_hard_mpi_LoadBalancer::update(S2_hard_mpi_msg* msg,
                                      double percent)
{
  if (msg->high() >= max_finished_)
  {
    max_finished_ = msg->high();
    proc_interval_ = msg->high() - msg->low();
    segment_size_ = msg->segment_size();
    segments_per_thread_ = max(segments_per_thread_, msg->segments_per_thread());
    seconds_ = msg->seconds();
  }

  int64_t next_interval = proc_interval_;

  // balance load by increasing or decreasing the
  // next interval based on previous run-time
  if (is_increase(seconds_, percent))
    next_interval *= 2;
  else
    next_interval = max(next_interval / 2, isqrt(z_));

  low_ = high_ + 1;
  high_ = min(low_ + next_interval, z_);

  // udpate existing message with new work todo
  msg->set(msg->proc_id(), low_, high_, segment_size_, segments_per_thread_);
}

} // namespace
<commit_msg>Refactoring<commit_after>///
/// @file   S2_hard_mpi_LoadBalancer.cpp
/// @brief  The S2_hard_mpi_LoadBalancer evenly distributes the
///         computation of the hard special leaves onto cluster nodes.
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2_hard_mpi_LoadBalancer.hpp>
#include <S2_hard_mpi_msg.hpp>
#include <primecount-internal.hpp>
#include <min_max.hpp>

#include <stdint.h>
#include <algorithm>

using namespace std;

namespace primecount {

S2_hard_mpi_LoadBalancer::S2_hard_mpi_LoadBalancer(int64_t low,
                                                   int64_t high,
                                                   int64_t y,
                                                   int64_t z,
                                                   int slave_procs)
  : low_(low),
    high_(high),
    y_(y),
    z_(z),
    slave_procs_(slave_procs),
    max_finished_(0),
    segment_size_(isqrt(z)),
    segments_per_thread_(1),
    proc_interval_(0),
    start_time_(get_wtime()),
    seconds_(0)
{ }

bool S2_hard_mpi_LoadBalancer::finished() const
{
  return low_ > z_;
}

bool S2_hard_mpi_LoadBalancer::is_increase(double seconds,
                                           double percent) const
{
  // avoid division by 0
  percent = in_between(1, percent, 100);

  // calculate remaining time till finished
  double elapsed_time = get_wtime() - start_time_;
  double remaining_time = elapsed_time * (100 / percent) - elapsed_time;

  // for performance reasons all processes should
  // finish nearly at the same time
  double near_finish_time = elapsed_time / 100;
  double divisor = max(1.0, 100 / pow(5.0, 100 / percent));
  double max_time = remaining_time / divisor;
  double is_increase = max3(0.1, max_time, near_finish_time);

  return seconds < is_increase;
}

void S2_hard_mpi_LoadBalancer::update(S2_hard_mpi_msg* msg,
                                      double percent)
{
  if (msg->high() >= max_finished_)
  {
    max_finished_ = msg->high();
    proc_interval_ = msg->high() - msg->low();
    segment_size_ = msg->segment_size();
    segments_per_thread_ = max(segments_per_thread_, msg->segments_per_thread());
    seconds_ = msg->seconds();
  }

  int64_t next_interval = proc_interval_;

  // balance load by increasing or decreasing the
  // next interval based on previous run-time
  if (is_increase(seconds_, percent))
    next_interval *= 2;
  else
    next_interval = max(next_interval / 2, isqrt(z_));

  low_ = high_ + 1;
  high_ = min(low_ + next_interval, z_);

  // udpate existing message with new work todo
  msg->set(msg->proc_id(), low_, high_, segment_size_, segments_per_thread_);
}

} // namespace
<|endoftext|>


<commit_before>#include "GlyphContainer.hpp"
#include <stdio.h>

GlyphContainer::GlyphContainer(int size, sf::Vector2i layout, const sf::Texture& bg_text) :
  _background(bg_text)
{
  _nglyphs = size;
  _glyphs = std::vector<Glyph>();
  _layout = layout;
}

GlyphContainer::~GlyphContainer() {}

void GlyphContainer::draw(sf::RenderTarget* target) {
  target->draw(_background);
  for (auto g : _glyphs) {
    g.draw(target);
  }
}

void GlyphContainer::update(float deltaTime) {
  // TODO OR NOT TODO
}

void GlyphContainer::setRenderTarget(sf::RenderTarget* t) {
  _window = t;
  for (auto g : _glyphs) {
    g.setRenderTarget(t);
  }
}

void GlyphContainer::setPosition(const sf::Vector2f& pos) {
  _background.setPosition(pos);
  _pos = pos;

  sf::Vector2f g_size;

  if(!empty())
    g_size = _glyphs[0].getSize();
  else
    return;

  for(unsigned int i = 0; i < _layout.x; i++) {
    for(unsigned int j = 0; j < _layout.y; j++) {
      if((i * _layout.y + j) > _glyphs.size())
        return;

      sf::Vector2f n_pos = _pos + sf::Vector2f(i * g_size.x,
                                               j * g_size.y);
      _glyphs[i * _layout.y + j].setPosition(n_pos);
    }
  }
}

void GlyphContainer::setSize(const sf::Vector2f& size) {
  setSize(size.x, size.y);
}

void GlyphContainer::setSize(float width, float height) {
  float x_ratio = width / _background.getTexture()->getSize().x;
  float y_ratio = height / _background.getTexture()->getSize().y;
  _background.setScale(sf::Vector2f(x_ratio, y_ratio));

  sf::Vector2f gsize = calculateGlyphSize();
  for(auto g : _glyphs) {
    g.setSize(gsize);
  }
  // Recalculate positions
  setPosition(_pos);
}

Glyph GlyphContainer::top() {
  return _glyphs[_glyphs.size()];
}

void GlyphContainer::pop() {
  _glyphs.erase(_glyphs.end()--);
}

void GlyphContainer::add(Glyph g) {
  printf("Lmao1\n");
  if(_glyphs.size() == 0) {
    printf("Lmao2\n");
    g.setSize(calculateGlyphSize());
    printf("Lmao3\n");
  } else {
    printf("Lmao4\n");
    g.setSize(_glyphs[0].getSize());
    printf("Lmao5\n");
  }
  printf("Lmao6\n");
  _glyphs.push_back(g);
  printf("Lmao\n");
  // Recalculate position
  setPosition(_pos);
}

void GlyphContainer::add(GlyphID gid) {
  Glyph g = Glyph(gid);
  add(g);
}

bool GlyphContainer::empty() {
  return _glyphs.size() == 0;
}

Glyph GlyphContainer::get(int index) {
  return _glyphs[index];
}

GlyphID GlyphContainer::getGlyphID() {
  if(!empty())
    return _glyphs[0].getID();
  else
    return glyph_none;
}

sf::Vector2f GlyphContainer::calculateGlyphSize() {
  //sheeeeet
  float width;
  float height;

  width = _background.getTexture()->getSize().x / _layout.x * _background.getScale().x;
  height = _background.getTexture()->getSize().y / _layout.y * _background.getScale().y;

  return sf::Vector2f(width, height);
}
<commit_msg>nomerges<commit_after>#include "GlyphContainer.hpp"
#include <stdio.h>

GlyphContainer::GlyphContainer(int size, sf::Vector2i layout, const sf::Texture& bg_text) :
  _background(bg_text)
{
  _nglyphs = size;
  _glyphs = std::vector<Glyph>();
  _layout = layout;
}

GlyphContainer::~GlyphContainer() {}

void GlyphContainer::draw(sf::RenderTarget* target) {
  target->draw(_background);
  for (auto g : _glyphs) {
    g.draw(target);
  }
}

void GlyphContainer::update(float deltaTime) {
  // TODO OR NOT TODO
}

void GlyphContainer::setRenderTarget(sf::RenderTarget* t) {
  _window = t;
  for (auto g : _glyphs) {
    g.setRenderTarget(t);
  }
}

void GlyphContainer::setPosition(const sf::Vector2f& pos) {
  _background.setPosition(pos);
  _pos = pos;

  sf::Vector2f g_size;

  if(!empty())
    g_size = _glyphs[0].getSize();
  else
    return;

  for(unsigned int i = 0; i < _layout.x; i++) {
    for(unsigned int j = 0; j < _layout.y; j++) {
      if((i * _layout.y + j) > _glyphs.size())
        return;

      sf::Vector2f n_pos = _pos + sf::Vector2f(i * g_size.x,
                                               j * g_size.y);
      _glyphs[i * _layout.y + j].setPosition(n_pos);
    }
  }
}

void GlyphContainer::setSize(const sf::Vector2f& size) {
  setSize(size.x, size.y);
}

void GlyphContainer::setSize(float width, float height) {
  float x_ratio = width / _background.getTexture()->getSize().x;
  float y_ratio = height / _background.getTexture()->getSize().y;
  _background.setScale(sf::Vector2f(x_ratio, y_ratio));

  sf::Vector2f gsize = calculateGlyphSize();
  for(auto g : _glyphs) {
    g.setSize(gsize);
  }
  // Recalculate positions
  setPosition(_pos);
}

Glyph GlyphContainer::top() {
  return _glyphs[_glyphs.size()];
}

void GlyphContainer::pop() {
  _glyphs.erase(_glyphs.end()--);
}

void GlyphContainer::add(Glyph g) {

  if(_glyphs.size() == 0) {

    g.setSize(calculateGlyphSize());

  } else {

    g.setSize(_glyphs[0].getSize());

  }

  _glyphs.push_back(g);

  // Recalculate position
  setPosition(_pos);
}

void GlyphContainer::add(GlyphID gid) {
  Glyph g = Glyph(gid);
  add(g);
}

bool GlyphContainer::empty() {
  return _glyphs.size() == 0;
}

Glyph GlyphContainer::get(int index) {
  return _glyphs[index];
}

GlyphID GlyphContainer::getGlyphID() {
  if(!empty())
    return _glyphs[0].getID();
  else
    return glyph_none;
}

sf::Vector2f GlyphContainer::calculateGlyphSize() {
  //sheeeeet
  float width;
  float height;

  width = _background.getTexture()->getSize().x / _layout.x * _background.getScale().x;
  height = _background.getTexture()->getSize().y / _layout.y * _background.getScale().y;

  return sf::Vector2f(width, height);
}
<|endoftext|>


<commit_before>#include "VCardParser.h"
#include <assert.h>
#include <QIODevice>
#include <QByteArray>
#include <QDebug>
#include "Exceptions.h"
#include "Contact.h"

/** Provides the actual parsing implementation. */
class VCardParserImpl
{
public:
	/** Creates a new parser instance and binds it to the specified data source and destination contact book. */
	VCardParserImpl(QIODevice & a_Source, ContactBookPtr a_Dest):
		m_State(psIdle),
		m_Source(a_Source),
		m_Dest(a_Dest),
		m_CurrentLineNum(0)
	{
	}

	/** Parses the source data from m_Source into the bound destination contact book m_Dest.
	Throws an EException descendant on error. Note that m_Dest may still be filled with some contacts
	that parsed successfully. */
	void parse()
	{
		// Parse line-by-line, unwrap the lines here:
		QByteArray acc;  // Accumulator for the current line
		while (!m_Source.atEnd())
		{
			QByteArray cur = m_Source.readLine();
			if (
				!cur.isEmpty() &&
				(
					(cur.at(0) == 0x20) ||  // Continuation by a SP
					(cur.at(0) == 0x09) ||  // Continuation by a HT
					!cur.contains(':')      // Some bad serializers don't fold the lines properly, continuations are made without the leading space (LG G4)
				)
			)
			{
				// This was a folded line, append it to the accumulator:
				cur.remove(0, 1);
				acc.append(cur);
			}
			else
			{
				// This is a (start of a) new line, process the accumulator and store the new line in it:
				if (!acc.isEmpty())
				{
					processLine(acc);
				}
				std::swap(acc, cur);
			}
		}
		// Process the last line:
		if (!acc.isEmpty())
		{
			processLine(acc);
		}
	}

protected:

	/** The state of the outer state-machine, checking the sentences' sequencing (begin, version, <data>, end). */
	enum State
	{
		psIdle,        //< The parser has no current contact, it expects a new "BEGIN:VCARD" sentence
		psBeginVCard,  //< The parser has just read the "BEGIN:VCARD" line, expects a "VERSION" sentence
		psContact,     //< The parser is reading individual contact property sentence
	} m_State;

	/** The source data provider. */
	QIODevice & m_Source;

	/** The contact book into which the data is to be written. */
	ContactBookPtr m_Dest;

	/** The current contact being parsed.
	Only valid in the psContact state. */
	ContactPtr m_CurrentContact;

	/** The number of the line currently being processed (for error reporting). */
	int m_CurrentLineNum;

	/** Parses the given single (unfolded) line. */
	void processLine(const QByteArray & a_Line)
	{
		m_CurrentLineNum += 1;
		if (a_Line.isEmpty() || (a_Line == "\n"))
		{
			return;
		}
		try
		{
			auto sentence = breakUpSentence(a_Line);
			switch (m_State)
			{
				case psIdle:       processSentenceIdle(sentence);       break;
				case psBeginVCard: processSentenceBeginVCard(sentence); break;
				case psContact:    processSentenceContact(sentence);    break;
			}
		}
		catch (const EParseError & exc)
		{
			qWarning() << QString::fromUtf8("Cannot parse VCARD, line %1: %2. The line contents: \"%3\"")
				.arg(m_CurrentLineNum)
				.arg(QString::fromStdString(exc.m_Message))
				.arg(QString::fromUtf8(a_Line));
			throw;
		}
	}

	/** Breaks the specified single (unfolded) line into the contact sentence representation. */
	Contact::Sentence breakUpSentence(const QByteArray & a_Line)
	{
		Contact::Sentence res;

		// The state of the inner state-machine, parsing a single sentence.
		// Each sentence has a basic structure of "[group.]key[;param1;param2]=value"
		enum
		{
			ssBegin,             //< The parser is reading the beginning of the sentence (group or key)
			ssKey,               //< The parser is reading the key (the group was present)
			ssParamName,         //< The parser is reading the param name
			ssParamValue,        //< The parser is reading the param value
			ssParamValueDQuote,  //< The parser is reading the param value and is inside a dquote
			ssParamValueEnd,     //< The parser has just finished the DQuote of a param value
		} sentenceState = ssBegin;

		auto len = a_Line.length();
		assert(len > 0);
		if (a_Line.at(len - 1) == '\n')
		{
			assert(len > 1);
			len -= 1;
		}
		int last = 0;
		QByteArray currentParamName, currentParamValue;
		for (auto i = 0; i < len; ++i)
		{
			auto ch = a_Line.at(i);
			switch (sentenceState)
			{
				case ssBegin:
				{
					if (ch == '.')
					{
						res.m_Group = a_Line.mid(0, i - 1);
						last = i + 1;
						sentenceState = ssKey;
						continue;
					}
					// fallthrough
				}  // case ssBegin

				case ssKey:
				{
					if (ch == ';')
					{
						if (last == i)
						{
							throw EParseError(__FILE__, __LINE__, "An empty key is not allowed");
						}
						res.m_Key = a_Line.mid(last, i - last).toLower();
						last = i + 1;
						sentenceState = ssParamName;
						continue;
					}
					if (ch == ':')
					{
						if (last == i)
						{
							throw EParseError(__FILE__, __LINE__, "An empty key is not allowed");
						}
						res.m_Key = a_Line.mid(last, i - last).toLower();
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					if (ch == '.')
					{
						throw EParseError(__FILE__, __LINE__, "A group has already been parsed, cannot add another one.");
					}
					break;
				}  // case ssKey

				case ssParamName:
				{
					if (ch == '=')
					{
						if (i == last)
						{
							throw EParseError(__FILE__, __LINE__, "A parameter with no name is not allowed");
						}
						currentParamName = a_Line.mid(last, i - last).toLower();
						last = i + 1;
						currentParamValue.clear();
						sentenceState = ssParamValue;
						continue;
					}
					if (ch == ';')
					{
						// Value-less parameter with another parameter following ("TEL;CELL;OTHER:...")
						res.m_Params.emplace_back(a_Line.mid(last, i - last), QByteArray());
						last = i + 1;
						currentParamValue.clear();
						currentParamName.clear();
						continue;
					}
					if (ch == ':')
					{
						// Value-less parameter ending the params ("TEL;CELL:...")
						res.m_Params.emplace_back(a_Line.mid(last, i - last), QByteArray());
						last = i + 1;
						last = i + 1;
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					break;
				}  // case ssParamName

				case ssParamValue:
				{
					if (ch == '"')
					{
						if (i > last)
						{
							throw EParseError(__FILE__, __LINE__, "Param value double-quoting is wrong");
						}
						last = i + 1;
					}
					if (ch == ',')
					{
						res.m_Params.emplace_back(currentParamName, a_Line.mid(last, i - last));
						last = i + 1;
						continue;
					}
					if (ch == ':')
					{
						res.m_Params.emplace_back(currentParamName, a_Line.mid(last, i - last));
						last = i + 1;
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					break;
				}  // case ssParamValue

				case ssParamValueDQuote:
				{
					if (ch == '"')
					{
						res.m_Params.emplace_back(currentParamName, std::move(currentParamValue));
						last = i + 1;
						sentenceState = ssParamValueEnd;
						continue;
					}
					if (ch == '\\')
					{
						// Skip the escape
						continue;
					}
					else
					{
						currentParamValue.append(ch);
					}
					break;
				}  // case ssParamValueDQuote

				case ssParamValueEnd:
				{
					if (ch == ',')
					{
						last = i + 1;
						currentParamValue.clear();
						sentenceState = ssParamValue;
					}
					if (ch == ':')
					{
						res.m_Params.emplace_back(currentParamName, a_Line.mid(last, i - last));
						last = i + 1;
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					throw EParseError(__FILE__, __LINE__, "An extra character following a param value double-quote");
				}  // case ssParamValueEnd
			}
		}  // for i - a_Line[]

		throw EParseError(__FILE__, __LINE__, "Incomplete sentence");
	}

	/** Processes the given sentence in the psIdle parser state. */
	void processSentenceIdle(const Contact::Sentence & a_Sentence)
	{
		// The only valid line in this context is the "BEGIN:VCARD" line.
		// Any other line will cause an error throw
		if (
			!a_Sentence.m_Group.isEmpty()
		)
		{
			throw EParseError(__FILE__, __LINE__, "Expected a BEGIN:VCARD sentence, got a different sentence");
		}
		m_State = psBeginVCard;
	}

	/** Parses the given single sentence in the psBeginVCard parser state. */
	void processSentenceBeginVCard(const Contact::Sentence & a_Sentence)
	{
		// The only valid sentence in this context is the "VERSION:X" line.
		if (
			!a_Sentence.m_Group.isEmpty() ||
			(a_Sentence.m_Key != "version") ||
			!a_Sentence.m_Params.empty()
		)
		{
			throw EParseError(__FILE__, __LINE__, "Expected a VERSION sentence, got a different sentence");
		}
		if (a_Sentence.m_Value.toFloat() == 0)
		{
			throw EParseError(__FILE__, __LINE__, "The VERSION sentence has an invalid value.");
		}

		m_CurrentContact.reset(new Contact);
		m_State = psContact;
	}

	/** Parses the given single (unfolded) line in the psContact parser state. */
	void processSentenceContact(const Contact::Sentence & a_Sentence)
	{
		// If the sentence is "END:VCARD", terminate the current contact:
		if (
			a_Sentence.m_Group.isEmpty() &&
			(a_Sentence.m_Key == "end") &&
			a_Sentence.m_Params.empty() &&
			(a_Sentence.m_Value.toLower() == "vcard")
		)
		{
			if (m_CurrentContact != nullptr)
			{
				m_Dest->addContact(m_CurrentContact);
			}
			m_CurrentContact.reset();
			m_State = psIdle;
			return;
		}

		// Add the sentence to the current contact:
		m_CurrentContact->addSentence(a_Sentence);
	}
};

void VCardParser::parse(QIODevice & a_Source, ContactBookPtr a_Dest)
{
	VCardParserImpl impl(a_Source, a_Dest);
	impl.parse();
}

std::vector<std::vector<QByteArray>> VCardParser::breakValueIntoComponents(const QByteArray & a_Value)
{
	std::vector<std::vector<QByteArray>> res;
	res.push_back({});
	auto * curComponent = &res.back();
	curComponent->push_back({});
	auto * curValue = &curComponent->back();
	auto len = a_Value.length();
	for (int i = 0; i < len; ++i)
	{
		auto ch = a_Value.at(i);
		switch (ch)
		{
			case ';':
			{
				// Start a new component:
				res.push_back({});
				curComponent = &res.back();
				curComponent->push_back({});
				curValue = &curComponent->back();
				break;
			}  // case ';'

			case ',':
			{
				// Start a new value:
				curComponent->push_back({});
				curValue = &curComponent->back();
				break;
			}

			case '\\':
			{
				// Skip the escape char and push the next char directly into the current value:
				i = 1 + 1;
				curValue->append(a_Value.at(i));
				break;
			}

			default:
			{
				curValue->append(ch);
				break;
			}
		}  // switch (ch)
	}  // for i - a_Value[]

	return res;
}

<commit_msg>VCardParser: Fixed param-value parsing, added encoding support.<commit_after>#include "VCardParser.h"
#include <assert.h>
#include <QIODevice>
#include <QByteArray>
#include <QDebug>
#include "Exceptions.h"
#include "Contact.h"

/** Provides the actual parsing implementation. */
class VCardParserImpl
{
public:
	/** Creates a new parser instance and binds it to the specified data source and destination contact book. */
	VCardParserImpl(QIODevice & a_Source, ContactBookPtr a_Dest):
		m_State(psIdle),
		m_Source(a_Source),
		m_Dest(a_Dest),
		m_CurrentLineNum(0)
	{
	}

	/** Parses the source data from m_Source into the bound destination contact book m_Dest.
	Throws an EException descendant on error. Note that m_Dest may still be filled with some contacts
	that parsed successfully. */
	void parse()
	{
		// Parse line-by-line, unwrap the lines here:
		QByteArray acc;  // Accumulator for the current line
		while (!m_Source.atEnd())
		{
			QByteArray cur = m_Source.readLine();
			if (
				!cur.isEmpty() &&
				(
					(cur.at(0) == 0x20) ||  // Continuation by a SP
					(cur.at(0) == 0x09) ||  // Continuation by a HT
					!cur.contains(':')      // Some bad serializers don't fold the lines properly, continuations are made without the leading space (LG G4)
				)
			)
			{
				// This was a folded line, append it to the accumulator:
				cur.remove(0, 1);
				acc.append(cur);
			}
			else
			{
				// This is a (start of a) new line, process the accumulator and store the new line in it:
				if (!acc.isEmpty())
				{
					processLine(acc);
				}
				std::swap(acc, cur);
			}
		}
		// Process the last line:
		if (!acc.isEmpty())
		{
			processLine(acc);
		}
	}

protected:

	/** The state of the outer state-machine, checking the sentences' sequencing (begin, version, <data>, end). */
	enum State
	{
		psIdle,        //< The parser has no current contact, it expects a new "BEGIN:VCARD" sentence
		psBeginVCard,  //< The parser has just read the "BEGIN:VCARD" line, expects a "VERSION" sentence
		psContact,     //< The parser is reading individual contact property sentence
	} m_State;

	/** The source data provider. */
	QIODevice & m_Source;

	/** The contact book into which the data is to be written. */
	ContactBookPtr m_Dest;

	/** The current contact being parsed.
	Only valid in the psContact state. */
	ContactPtr m_CurrentContact;

	/** The number of the line currently being processed (for error reporting). */
	int m_CurrentLineNum;

	/** Parses the given single (unfolded) line. */
	void processLine(const QByteArray & a_Line)
	{
		m_CurrentLineNum += 1;
		if (a_Line.isEmpty() || (a_Line == "\n"))
		{
			return;
		}
		try
		{
			auto sentence = breakUpSentence(a_Line);
			switch (m_State)
			{
				case psIdle:       processSentenceIdle(sentence);       break;
				case psBeginVCard: processSentenceBeginVCard(sentence); break;
				case psContact:    processSentenceContact(sentence);    break;
			}
		}
		catch (const EParseError & exc)
		{
			qWarning() << QString::fromUtf8("Cannot parse VCARD, line %1: %2. The line contents: \"%3\"")
				.arg(m_CurrentLineNum)
				.arg(QString::fromStdString(exc.m_Message))
				.arg(QString::fromUtf8(a_Line));
			throw;
		}
	}

	/** Breaks the specified single (unfolded) line into the contact sentence representation. */
	Contact::Sentence breakUpSentence(const QByteArray & a_Line)
	{
		Contact::Sentence res;

		// The state of the inner state-machine, parsing a single sentence.
		// Each sentence has a basic structure of "[group.]key[;param1;param2]=value"
		enum
		{
			ssBegin,             //< The parser is reading the beginning of the sentence (group or key)
			ssKey,               //< The parser is reading the key (the group was present)
			ssParamName,         //< The parser is reading the param name
			ssParamValue,        //< The parser is reading the param value
			ssParamValueDQuote,  //< The parser is reading the param value and is inside a dquote
			ssParamValueEnd,     //< The parser has just finished the DQuote of a param value
		} sentenceState = ssBegin;

		auto len = a_Line.length();
		assert(len > 0);
		if (a_Line.at(len - 1) == '\n')
		{
			assert(len > 1);
			len -= 1;
		}
		int last = 0;
		QByteArray currentParamName, currentParamValue;
		for (auto i = 0; i < len; ++i)
		{
			auto ch = a_Line.at(i);
			switch (sentenceState)
			{
				case ssBegin:
				{
					if (ch == '.')
					{
						res.m_Group = a_Line.mid(0, i - 1);
						last = i + 1;
						sentenceState = ssKey;
						continue;
					}
					// fallthrough
				}  // case ssBegin

				case ssKey:
				{
					if (ch == ';')
					{
						if (last == i)
						{
							throw EParseError(__FILE__, __LINE__, "An empty key is not allowed");
						}
						res.m_Key = a_Line.mid(last, i - last).toLower();
						last = i + 1;
						sentenceState = ssParamName;
						continue;
					}
					if (ch == ':')
					{
						if (last == i)
						{
							throw EParseError(__FILE__, __LINE__, "An empty key is not allowed");
						}
						res.m_Key = a_Line.mid(last, i - last).toLower();
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					if (ch == '.')
					{
						throw EParseError(__FILE__, __LINE__, "A group has already been parsed, cannot add another one.");
					}
					break;
				}  // case ssKey

				case ssParamName:
				{
					if (ch == '=')
					{
						if (i == last)
						{
							throw EParseError(__FILE__, __LINE__, "A parameter with no name is not allowed");
						}
						currentParamName = a_Line.mid(last, i - last).toLower();
						last = i + 1;
						currentParamValue.clear();
						sentenceState = ssParamValue;
						continue;
					}
					if (ch == ';')
					{
						// Value-less parameter with another parameter following ("TEL;CELL;OTHER:...")
						res.m_Params.emplace_back(a_Line.mid(last, i - last), QByteArray());
						last = i + 1;
						currentParamValue.clear();
						currentParamName.clear();
						continue;
					}
					if (ch == ':')
					{
						// Value-less parameter ending the params ("TEL;CELL:...")
						res.m_Params.emplace_back(a_Line.mid(last, i - last), QByteArray());
						last = i + 1;
						last = i + 1;
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					break;
				}  // case ssParamName

				case ssParamValue:
				{
					if (ch == '"')
					{
						if (i > last)
						{
							throw EParseError(__FILE__, __LINE__, "Param value double-quoting is wrong");
						}
						last = i + 1;
						sentenceState = ssParamValueDQuote;
						continue;
					}
					if (ch == ',')
					{
						res.m_Params.emplace_back(currentParamName, a_Line.mid(last, i - last));
						last = i + 1;
						continue;
					}
					if (ch == ':')
					{
						res.m_Params.emplace_back(currentParamName, a_Line.mid(last, i - last));
						last = i + 1;
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					if (ch == ';')
					{
						res.m_Params.emplace_back(currentParamName, a_Line.mid(last, i - last));
						last = i + 1;
						sentenceState = ssParamName;
						currentParamName.clear();
						continue;
					}
					break;
				}  // case ssParamValue

				case ssParamValueDQuote:
				{
					if (ch == '"')
					{
						res.m_Params.emplace_back(currentParamName, std::move(currentParamValue));
						last = i + 1;
						sentenceState = ssParamValueEnd;
						continue;
					}
					if (ch == '\\')
					{
						// Skip the escape
						continue;
					}
					else
					{
						currentParamValue.append(ch);
					}
					break;
				}  // case ssParamValueDQuote

				case ssParamValueEnd:
				{
					if (ch == ':')
					{
						last = i + 1;
						res.m_Value = a_Line.mid(i + 1, len - i - 1);
						return res;
					}
					if (ch == ';')
					{
						last = i + 1;
						sentenceState = ssParamName;
						continue;
					}
					throw EParseError(__FILE__, __LINE__, "An invalid character following a param value double-quote");
				}  // case ssParamValueEnd
			}
		}  // for i - a_Line[]

		throw EParseError(__FILE__, __LINE__, "Incomplete sentence");
	}

	/** Processes the given sentence in the psIdle parser state. */
	void processSentenceIdle(const Contact::Sentence & a_Sentence)
	{
		// The only valid line in this context is the "BEGIN:VCARD" line.
		// Any other line will cause an error throw
		if (
			!a_Sentence.m_Group.isEmpty()
		)
		{
			throw EParseError(__FILE__, __LINE__, "Expected a BEGIN:VCARD sentence, got a different sentence");
		}
		m_State = psBeginVCard;
	}

	/** Parses the given single sentence in the psBeginVCard parser state. */
	void processSentenceBeginVCard(const Contact::Sentence & a_Sentence)
	{
		// The only valid sentence in this context is the "VERSION:X" line.
		if (
			!a_Sentence.m_Group.isEmpty() ||
			(a_Sentence.m_Key != "version") ||
			!a_Sentence.m_Params.empty()
		)
		{
			throw EParseError(__FILE__, __LINE__, "Expected a VERSION sentence, got a different sentence");
		}
		if (a_Sentence.m_Value.toFloat() == 0)
		{
			throw EParseError(__FILE__, __LINE__, "The VERSION sentence has an invalid value.");
		}

		m_CurrentContact.reset(new Contact);
		m_State = psContact;
	}

	/** Parses the given single (unfolded) line in the psContact parser state.
	May modify the sentence / trash it. */
	void processSentenceContact(Contact::Sentence & a_Sentence)
	{
		// If the sentence is "END:VCARD", terminate the current contact:
		if (
			a_Sentence.m_Group.isEmpty() &&
			(a_Sentence.m_Key == "end") &&
			a_Sentence.m_Params.empty() &&
			(a_Sentence.m_Value.toLower() == "vcard")
		)
		{
			if (m_CurrentContact != nullptr)
			{
				m_Dest->addContact(m_CurrentContact);
			}
			m_CurrentContact.reset();
			m_State = psIdle;
			return;
		}

		// Decode any encoding on the sentence's value:
		std::vector<QByteArray> enc;
		for (const auto & p: a_Sentence.m_Params)
		{
			if (p.m_Name == "encoding")
			{
				enc = p.m_Values;
			}
		}
		decodeValueEncoding(a_Sentence, enc);

		// Add the sentence to the current contact:
		m_CurrentContact->addSentence(a_Sentence);
	}

	/** Decodes the sentence's value according to the specified encoding.
	a_EncodingSpec is the encoding to be decoded, represented as a VCard property values. */
	void decodeValueEncoding(Contact::Sentence & a_Sentence, const std::vector<QByteArray> & a_EncodingSpec)
	{
		for (const auto & enc: a_EncodingSpec)
		{
			auto lcEnc = enc.toLower();
			if ((lcEnc == "b") || (lcEnc == "base64"))
			{
				a_Sentence.m_Value = QByteArray::fromBase64(a_Sentence.m_Value);
				return;
			}
			if (lcEnc == "quoted-printable")
			{
				a_Sentence.m_Value = decodeQuotedPrintable(a_Sentence.m_Value);
				return;
			}
		}
	}

	/** Returns the data after performing a quoted-printable decoding on it. */
	static QByteArray decodeQuotedPrintable(const QByteArray & a_Src)
	{
		QByteArray res;
		auto len = a_Src.length();
		res.reserve(len / 3);
		for (int i = 0; i < len; ++i)
		{
			auto ch = a_Src.at(i);
			if (ch == '=')
			{
				if (i + 2 == len)
				{
					// There's only one char left in the input, cannot decode -> copy to output
					res.append(a_Src.mid(i));
					return res;
				}
				auto hex = a_Src.mid(i + 1, 2);
				bool isOK;
				auto decodedCh = hex.toInt(&isOK, 16);
				if (isOK)
				{
					res.append(decodedCh);
				}
				else
				{
					res.append(a_Src.mid(i, 3));
				}
				i += 2;
			}
			else
			{
				res.append(ch);
			}
		}
		return res;
	}
};

void VCardParser::parse(QIODevice & a_Source, ContactBookPtr a_Dest)
{
	VCardParserImpl impl(a_Source, a_Dest);
	impl.parse();
}

std::vector<std::vector<QByteArray>> VCardParser::breakValueIntoComponents(const QByteArray & a_Value)
{
	std::vector<std::vector<QByteArray>> res;
	res.push_back({});
	auto * curComponent = &res.back();
	curComponent->push_back({});
	auto * curValue = &curComponent->back();
	auto len = a_Value.length();
	for (int i = 0; i < len; ++i)
	{
		auto ch = a_Value.at(i);
		switch (ch)
		{
			case ';':
			{
				// Start a new component:
				res.push_back({});
				curComponent = &res.back();
				curComponent->push_back({});
				curValue = &curComponent->back();
				break;
			}  // case ';'

			case ',':
			{
				// Start a new value:
				curComponent->push_back({});
				curValue = &curComponent->back();
				break;
			}

			case '\\':
			{
				// Skip the escape char and push the next char directly into the current value:
				i = 1 + 1;
				curValue->append(a_Value.at(i));
				break;
			}

			default:
			{
				curValue->append(ch);
				break;
			}
		}  // switch (ch)
	}  // for i - a_Value[]

	return res;
}

<|endoftext|>


<commit_before>#ifndef CMDSTAN_WRITE_DATETIME_HPP
#define CMDSTAN_WRITE_DATETIME_HPP

#include <stan/callbacks/writer.hpp>
#include <stan/version.hpp>
#include <chrono>
#include <iomanip>
#include <string>

namespace cmdstan {

void write_datetime(stan::callbacks::writer &writer) {
  const std::time_t current_datetime
      = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
  std::tm* curr_tm = std::localtime(&current_datetime);
  std::stringstream current_datetime_msg;
  current_datetime_msg << "start_datetime = "
  << std::setfill('0') << (1900+curr_tm->tm_year) << "-"
  << std::setw(2) << (curr_tm->tm_mon+1) << "-"
  << std::setw(2) << curr_tm->tm_mday << " "
  << std::setw(2) << curr_tm->tm_hour << ":"
  << std::setw(2) << curr_tm->tm_min << ":"
  << std::setw(2) << curr_tm->tm_sec;
  writer(current_datetime_msg.str());
}

}  // namespace cmdstan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef CMDSTAN_WRITE_DATETIME_HPP
#define CMDSTAN_WRITE_DATETIME_HPP

#include <stan/callbacks/writer.hpp>
#include <stan/version.hpp>
#include <chrono>
#include <iomanip>
#include <string>

namespace cmdstan {

void write_datetime(stan::callbacks::writer& writer) {
  const std::time_t current_datetime
      = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
  std::tm* curr_tm = std::localtime(&current_datetime);
  std::stringstream current_datetime_msg;
  current_datetime_msg << "start_datetime = " << std::setfill('0')
                       << (1900 + curr_tm->tm_year) << "-" << std::setw(2)
                       << (curr_tm->tm_mon + 1) << "-" << std::setw(2)
                       << curr_tm->tm_mday << " " << std::setw(2)
                       << curr_tm->tm_hour << ":" << std::setw(2)
                       << curr_tm->tm_min << ":" << std::setw(2)
                       << curr_tm->tm_sec;
  writer(current_datetime_msg.str());
}

}  // namespace cmdstan
#endif
<|endoftext|>