/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#include "TestUtility.h"


//
// Test application
//
int main()
{
    // It has to be a static/global and simple symbol for PROGMEM
    static const char PROGMEM pmABC_[3] = { 'A', 'b', 'c' };

    eCxx::PGMCharPointer    pmAbc    = eCxx::PGM_PTR(pmABC_);
    eCxx::PGMCharPointer    pmXyz    = PGM_STR    ("Xyz");
    eCxx::PGMCharPointerFar pmXyzfar = PGM_STR_FAR("Xyz");



    _____________USERSTR_NL2("String : initialization with PROGMEM");

    eCxx::String<5> str5a(pmAbc, 3); // Specify the length here because 'pmABC' is not null terminated
    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());

    eCxx::String<5> str5b(pmXyz);
    _CODESTR_NL1_CODERES_NL2("%s", str5b.cStr());

    eCxx::String<5> str5bf(pmXyzfar);
    _CODESTR_NL1_CODERES_NL2("%s", str5bf.cStr());

    _DIVIDERLINE_DASHSTR_NL2();



    _____________USERSTR_NL2("String : copy and move assignment operators with a string of different capacity");

    eCxx::String<2> str2;

    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());
    _EXECUTECODE_CODESTR_NL1( str2 = str5a; );
    _CODESTR_NL1_CODERES_NL1("%s", str2.cStr());
    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());

    _CODESTR_NL1_CODERES_NL2("%s", str5b.cStr());
    _EXECUTECODE_CODESTR_NL1( str2 = eCxx::move(str5b); );
    _CODESTR_NL1_CODERES_NL1("%s", str2.cStr());
    _CODESTR_NL1_CODERES_NL2("%s", str5b.cStr());

    _DIVIDERLINE_DASHSTR_NL2();



    _____________USERSTR_NL2("String : resize and character addition assignment operator");

    eCxx::String<10> str10;

    _EXECUTECODE_CODESTR_NL1( str10.resize(3, '*'); );
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _EXECUTECODE_CODESTR_NL1( --str10; );
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _EXECUTECODE_CODESTR_NL1( str10 += '#'; );
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _EXECUTECODE_CODESTR_NL1( str10 += '$'; );
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _EXECUTECODE_CODESTR_NL1( --str10; );
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _DIVIDERLINE_DASHSTR_NL2();



    _____________USERSTR_NL2("String : copy and move addition assignment operators with a string of different capacity");

    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());
    _EXECUTECODE_CODESTR_NL1( str10 += str5a; );
    _CODESTR_NL1_CODERES_NL1("%s", str10.cStr());
    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());

    _DIVIDERLINE_DASHSTR_NL2();

    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());
    _EXECUTECODE_CODESTR_NL1( str10 += eCxx::move(str5a); );
    _CODESTR_NL1_CODERES_NL1("%s", str10.cStr());
    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());

    _DIVIDERLINE_DASHSTR_NL2();



    _____________USERSTR_NL2("String : concatenation with PROGMEM");

    str10.clear();
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _EXECUTECODE_CODESTR_NL1( str10.concatWith(pmAbc, 3); ); // Specify the length here because 'pmABC' is not null terminated
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _DIVIDERLINE_DASHSTR_NL2();



    _____________USERSTR_NL2("String : comparison with PROGMEM and other string");

    str5a.clear(); str5a.concatWith(pmAbc, 3); // Specify the length here because 'pmABC' is not null terminated
    str5b.clear(); str5b.concatWith(pmXyz);

    _CODESTR_NL1_CODERES_NL2("%s", str5a.cStr());
    _CODESTR_NL1_CODERES_NL2("%s", str5b.cStr());
    _CODESTR_NL1_CODERES_NL2("%s", str10.cStr());

    _CODESTR_NL1_CODERES_NL2("%d", (int) str5a.equalsTo(pmAbc, 3)); // Specify the length here because 'pmABC' is not null terminated
    _CODESTR_NL1_CODERES_NL2("%d", (int) str5b.equalsTo(pmAbc, 3)); // Specify the length here because 'pmABC' is not null terminated
    _CODESTR_NL1_CODERES_NL2("%d", (int) str10.equalsTo(pmAbc, 3)); // Specify the length here because 'pmABC' is not null terminated

    _CODESTR_NL1_CODERES_NL2("%d", (int) (str5a == str10) );
    _CODESTR_NL1_CODERES_NL2("%d", (int) (str5b == str10) );



    return 0;
}
