#ifndef STRING_H
#define STRING_H
/**
 * \file string2_kesz.h
 *
 * Ez a fĂĄjl tartalmazza a
 *   - String osztĂĄly deklarĂĄciĂłjĂĄt
 *   - az inline fĂźggvĂŠnyeket. Ha valamit inline-kÁŠnt akar megvalĂłsĂ­tani,
 *     akkor azt ebbe a fĂĄjlba Ă­rja! Tipikusan a rĂśvid kĂłdokat szokĂĄs
 *     inline-kĂŠt megvalĂłsĂ­tani (pl: c_str).
 *     MĂĄs fĂźggvĂŠnyeket ill. definĂ­ciĂłkat ne Ă­rjon a .h fĂĄjlba!
 *
 * A C-ben megĂ­rt (string1.c) fĂźggvĂŠnyek most tagfĂźggvĂŠnyekkĂŠ vĂĄltak, ĂŠs
 *   eltűnt az első paraméterük (s0) (ebből lett a this).
 * A nevĂźk is megvĂĄltozott, mert most mĂĄr az ĂśsszetartozĂĄst, ĂŠs a
 *   paramĂŠterek tĂ­pusĂĄra valĂł utalĂĄst mĂĄr nem a nĂŠv hordozza, hanem az osztĂĄly.
 * A createString... alakú függvényekből konstruktorok keletkeztek.
 * A disposeString destruktorrĂĄ alakĂźlt ĂĄt.
 * Egyes műveletvégző függvényekből pedig operátor függvény lett.
 */

/**
 * Az Ön feladata a string2.cpp fájlban megvalósítani (definiálni) az egyes
 * fĂźggvĂŠnyeket.
 *
 * Ahogyan halad a megvalĂłsĂ­tĂĄssal egyre tĂśbb tesztesetet kell lefuttatni,
 * ezĂŠrt az ELKESZULT makrĂł ĂŠrtĂŠket folyamatosan nĂśvelje a feladatsorszĂĄmoknak
 * megfelelően!
 *
 * Tanulságos a megvalósítás előtt már a megnövelt értékkel is lefordítani
 * a programot, ĂŠs elemezni a kapott hibajelzĂŠst.
 *
 */

#define ELKESZULT 13

/**
 * \section fel Feladat:
 * A tantermi gyakorlatokon, valamint a 3. laborgyakorlaton is foglalkoztunk egy
 * olyan sztring (String) adatszerkezet és a rajta műveleteket végző függvények
 * megtervezĂŠsĂŠvel/impelmentĂĄlĂĄsĂĄval ami dinamikusan tĂĄrol ĂŠs annyi memĂłriĂĄt foglal
 * amennyi a tĂĄrolĂĄshoz szĂźksĂŠges.
 *
 * Ezeket ĂŠs a tanultakat felhasznĂĄlva a string2.h ĂŠs a string2.cpp ĂĄllomĂĄnyokban
 * definiĂĄljon ill. implementĂĄljon egy olyan sztring (String) osztĂĄlyt C++ nyelven, ami
 * dinamikusan tĂĄrol ĂŠs rendelkezik az alĂĄbbi tulajosnĂĄgokkal!
 *
 *  1  A paramĂŠter nĂŠlkĂźl hĂ­vhatĂł konstruktora Ăźres sztringet hozzon ĂŠtre!
 *  2. Van olyan tagfĂźggvĂŠnye ( c_str() ), ami C-sztringgel, azaz nullĂĄval lezĂĄrt
 *     karaktersorozatra mutatĂł pointerel (const char *) tĂŠr vissza.
 *  3. Van olyan konstruktora, ami karakterből hoz létre sztringet.
 *  4. Van olyan konstruktora, ami C-sztringből (const char*) hoz létre sztringet.
 *  5. Az osztĂĄlybĂłl lĂŠtrehozott objektum legyen ĂĄtadhatĂł ĂŠrtĂŠkkparamĂŠterkĂŠnt!
 *  6. TĂĄmogassa a tĂśbbszĂśrĂśs ĂŠrtĂŠkadĂĄst (b = a = a)!
 *  7  Legyenek olyan operĂĄrorai (operator+), amivel a sztring vĂŠgĂŠhez sztringet,
 *     ĂŠs karaktert lehet fĹązni!
 *  8. Lehessen karakterhez is sztringet fĹązni a + operĂĄtorral!
 *  9. A tárolt a karakterek legyenek elérhetőek a szokásos módon indexeléssel!
 *     Az indexelĂŠssel elĂŠr elem legyen hasznĂĄlhatĂł balĂŠrtĂŠkkĂŠnt is!
 *     A konstans objektumok is legyenek indexelhetők.
 *     Az indexelĂŠs operĂĄtor hiba esetĂŠn dobjon const char * kivĂŠtelt!
 * 10. KĂŠszĂ­tsen olyan << operĂĄtort, amivel egy sztring kiĂ­rhatĂł egy ostream tĂ­pusĂş
 *     objektumra!
 *
 * Szorgalmi feladatok:
 * 11. Készítsen olyan fűzhető >> operátort, amivel be tud olvasni egy szót egy sztring-be!
 *     A beolvasĂł mĹąkĂśdjĂśn Ăşgy, mint a scanf %s, azaz a szĂł vĂŠgĂŠt white space hatĂĄrolja!
 *     A szĂł eleji white space karaktereket pedig el kell dobni.
 *    *Megj: az istream wshite space kezelĂŠse a flags() tagfĂźggvĂŠnnyel szabĂĄlyozhatĂł
 * 12. PrĂłbĂĄlja ki az ĂŠkezetes karakterek rendezĂŠsĂŠt is! Ehhez elkĂŠszĂ­tettĂźnk egy
 *     egyszerĹą kĂłdrĂŠszletet ami qsort() fĂźggvĂŠnyt hasznĂĄl.
 *     Értse meg a rendez.cpp fájlban levő kód működését és futtassa a programot!
 * 13. A setlocale fĂźggvĂŠnyhĂ­vĂĄs beĂĄllĂ­tja a karakterek ĂŠs sztringek ĂśsszehasonlĂ­tĂĄsĂĄhoz
 *     szĂźksĂŠges nyelvi kĂśrnyezetet (LC_COLLATE) prĂłbĂĄlja ki! VĂĄltozott a rendezĂŠsi
 *     sorrend?
 */

#include <iostream>
/**
 * Header fĂĄjlokbĂłl megfontoltan kell include-ot hasznĂĄlni.
 * NĂŠvteret azonban nem cĂŠlszerĹą kinyitni, mert annak hatĂĄsa zavarĂł lehet
 * ott ahol ez a header include-olva lesz.
 */

#ifndef MEMTRACE
#include "memtrace.h"
#endif // MEMTRACE

/**
 * A String osztĂĄly.
 * A 'pData'-ban vannak a karakterek (a lezĂĄrĂł nullĂĄval egyĂźtt), 'len' a hossza.
 * A hosszba nem szĂĄmĂ­t bele a lezĂĄrĂł nulla.
 */
class String {
    char *pData;         /// pointer az adatra
    size_t len;    /// hossz lezĂĄrĂł nulla nĂŠlkĂźl
public:


	size_t size() const { return len; }

    size_t getlen(){
        return len;
    }

    /// Default konstruktor:
    String() :pData(0), len(0) {}

    /// C-stringet ad vissza
    const char* c_str() const { if (pData) return pData; else return "";}

    /// Konstruktor: egy char karakterből (createStrFromChar)
    String(char ch);

    /// Konstruktor: egy nullĂĄval lezĂĄrt char sorozatbĂłl (createStringFromCharStr)
    String(const char *p);

    /// MÁSOLÓ konstruktor, ami a createStringFromString-ből keletkezett
    /// @param s1 - String, amiből létrehozzuk az új String-et
    String(const String& s1);

    /// Destruktor (disposeString)
    ~String() { delete[] pData; }

  /// EgyĂŠb tagfĂźggvĂŠnyek:
    /// KiĂ­runk egy Stringet (debug cĂŠlokra) (ez kĂŠsz)
    /// Elötte kiírunk egy tetszőleges szöveget.
    /// @param txt - nullĂĄval lezĂĄrt szĂśvegre mutatĂł pointer
    void printDbg(const char *txt = "") const {
        std::cout << txt << "[" << len << "], "
                  << (pData ? pData : "(NULL)") << std::endl;
    }

  /// OperĂĄtorok:
    /// Értékadó operátor is kell !
    /// @param rhs_s - jobboldali String
    /// @return baoldali (mĂłdosĂ­tott) string (referenciĂĄja)
    String& operator=(const String& rhs_s);

    bool operator==(const String& tbc);

    bool operator!=(const String& tbc);

    String& operator+=(const String& rhs_s) {
        *this = *this + rhs_s;
        return *this;
    }

    String& operator+=(char c);

    /// KĂŠt Stringet ĂśsszefĹąz (concatString)
    /// @param rhs_s - jobboldali String
    /// @return Ăşj String, ami tartalmazza a kĂŠt stringet egmĂĄs utĂĄn
    String operator+(const String& rhs_s) const ;

    /// Sztrinhez karaktert ĂśsszefĹąz (concatString)
    /// @param rhs_c - jobboldali karakter
    /// @return Ăşj String, ami tartalmazza a kĂŠt sztringet egymĂĄs utĂĄn
    String operator+(char rhs_c) const { return *this + String(rhs_c);}

    /// A string egy megadott indexŹ elemÊnek REFERENCIÁJÁVAL tÊr vissza.
    /// charAtString-ből keletkezett, de ezt bal oldalon is lehet használni
    /// @param idx - charakter indexe
    /// @return karakter (referencia)
    ///         IndexelĂŠsi hiba esetĂŠn const char* kivĂŠtelt dob (assert helyett).
    char& operator[](unsigned int idx);

    /// A string egy megadott indexŹ elemÊnek REFERENCIÁJÁVAL tÊr vissza.
    /// charAtString-ből keletkezett. Konstans stringre alkalmazható.
    /// IndexelĂŠsi hiba esetĂŠn const char* kivĂŠtelt dob (assert helyett).
    /// @param idx - karakter indexe
    /// @return karakter (referencia)
    ///         IndexelĂŠsi hiba esetĂŠn const char* kivĂŠtelt dob (assert helyett).
    const char& operator[](unsigned int idx) const;

    void erase() { *this = ""; }
};

/// GlobĂĄlis fĂźggvĂŠnyek:
/// kiĂ­r az ostream-re (printString)
/// Nem célszerű using-ot használni, mert ez egy include file. Így ki kell írni az std::-t
/// @param os - ostream tĂ­pusĂş objektum
/// @param s0 - String, amit kiĂ­runk
/// @return os
/// VigyĂĄzat nem tagfĂźggvĂŠny! Nem is tĹąnik el az s0 !
/// Nem kell, hogy barĂĄt legyen, mert a c_str() segĂ­t
std::ostream& operator<<(std::ostream& os, const String& s0);

/// Beolvas az istream-ről egy szót egy string-be.
/// @param is - istream tĂ­pusĂş objektum
/// @param s0 - String, amibe beolvas
/// @return is
/// VigyĂĄzat nem tagfĂźggvĂŠny! Nem is tĹąnik el az s0 !
/// Nem kell, hogy barĂĄt legyen mert van Str + ch
std::istream& operator>>(std::istream& is, String& s0);

/// String operator+(char ch, const String& str);
/// Vagy inline, vagy nem itt a helye!
/// Nem kell, hogy barát legyen mert tudunk chr-ből str-be konvertálni
/// kĂŠt str pedig ĂśsszeadhatĂł
inline String operator+(char ch, const String& str) { return String(ch) + str; }

#endif