/**
 *
 * \file string5_kesz.cpp
 *
 * Itt kell megvalĂłsĂ­tania a hiĂĄnyzĂł tagfĂźggvĂŠnyeket.
 * SegĂ­tsĂŠgĂźl megadtuk a C-ben megĂ­rt vĂĄltozatban (string1.c) hasznĂĄlt fĂźggvĂŠnyneveket.
 *
 * Ha valamit INLINE-kĂŠnt valĂłsĂ­t meg, akkor annak a .h-ba kell kerĂźlnie,
 * akĂĄr kĂ­vĂźl akĂĄr osztĂĄlyon belĂźl definiĂĄlja. (Az inline fĂźggvĂŠnyeknek minden
 * fordítási egységben elérhetőknek kell lenniük)
 * *
 * A tesztelĂŠskor ne felejtse el beĂĄllĂ­tani a header ĂĄllomĂĄnyban az ELKESZULT makrĂłt.
 * A VC saját memóriafogyás ellenőrzője csak debug módban (Debug->Start) működik!
 *
 */

#ifdef _MSC_VER
// MSC ne adjon figyelmeztető üzenetet a stringkezelő függvényekre.
  #define _CRT_SECURE_NO_WARNINGS
#endif

#include <iostream>             // KiĂ­ratĂĄshoz
#include <cstring>              // StringmĹąveletekhez
      // a standard headerek utĂĄn kell lennie
#ifndef MEMTRACE
#include "memtrace.h"
#endif
#include "string5.h"

using std::cin;
using std::ios_base;

/// Konstruktor: egy char karakterből (createStrFromChar)
String::String(char ch) {
   // MeghatĂĄrozzuk a hosszĂĄt
    len = 1;
    // Lefoglalunk a helyet a hossznak + a lezarĂł nullĂĄnak
    pData = new char[len+1];
    // BetesszĂźk a karaktert
    pData[0] = ch;
    pData[1] = '\0';
}


// Konstruktor: egy nullĂĄval lezĂĄrt char sorozatbĂłl (createStringFromCharStr)
String::String(const char *p) {
    // MeghatĂĄrozzuk a hosszĂĄt
    len = strlen(p);
    // Helyet foglalunk
    pData = new char[len+1];
    // BemĂĄsoljuk a stringet, ami le van zĂĄrva 0-val Ă­gy hasznĂĄlhatĂł az strcpy is
    strcpy(pData, p);
}

// MĂĄsolĂł konstruktor
String::String(const String& s1) {
    // MeghatĂĄrozzuk a hosszĂĄt
    len = s1.len;
    // Helyet foglalunk
    pData = new char[len+1];
    // BemĂĄsoljuk a stringet, ami le van zĂĄrva 0-val Ă­gy hasznĂĄlhatĂł az strcpy is
    strcpy(pData, s1.pData);
}

//Egyenlőséget vizsgáló operátor
bool String::operator==(const String& tbc){
    //Ha nem egyezik meg a stringek hossza hamissal tér vissza
    if (len != tbc.len){
        return false;
    }
    //Egyébként pedig végigmegy a karaktereken,
    //és igazzal tér vissz ha egyeznek, amúgy pedig hamissal
    else {
        for (size_t i = 0; i < len; i++){
            if (this[i] == tbc[i]){
            }
            else{
                return false;
            }
        }
        return true;
    }
}

//Nem egyenlőséget vizsgáló operátor
bool String::operator!=(const String& tbc){
    if (len == tbc.len){
        return false;
    }
    else{
        for (size_t i = 0; i < len; i++){
            if (this[i] != tbc[i]){
                return true;
            }
        }
        return false;
    }
    return true;
}

// operator=
String& String::operator=(const String& rhs_s) {
    if (this != &rhs_s) {
        delete[] pData;
        len = rhs_s.len;
        // Helyet foglalunk
        pData = new char[len+1];
        // BemĂĄsoljuk a stringet, ami le van zĂĄrva 0-val Ă­gy hasznĂĄlhatĂł az strcpy is
        strcpy(pData, rhs_s.pData);
    }
    return *this;
}

// [] operåtorok: egy megadott indexŹ elem REFERENCIÁJÁVAL tÊrnek vissza.
// indexhiba esetĂŠn dobjon egy const char * tĂ­pusĂş hibĂĄt!
char& String::operator[](unsigned int idx) {
    if (idx >= len) throw "String: indexelesi hiba";
    return pData[idx];
}

const char& String::operator[](unsigned int idx) const {
    if (idx >= len) throw "String: indexelesi hiba";
    return pData[idx];
}

// + operĂĄtor, ami kĂŠt stringet ad Ăśssze (concatString)
String String::operator+(const String& rhs_s) const {
    String temp;		// ide kerĂźl az eredmĂŠny
                        // MeghatĂĄrozza az Ăşj string hosszĂĄt
    temp.len = len + rhs_s.len;
                        // FelszabadĂ­tja a temp adattaerĂźletĂŠt
    delete []temp.pData;
                        // lefoglalja a memĂłriĂĄt az Ăşj stringnek.
    temp.pData = new char[temp.len+1];
    // Az elejére bemásolja az első stringet
    strcpy(temp.pData, pData);
    // BemĂĄsolja a mĂĄsodik stringet.
    strcat(temp.pData, rhs_s.pData);

    return temp;		// visszatĂŠr az eredmĂŠnnyel
}

String& String::operator+=(char c){
    char temp[] = {c, '\0'};
    return (*this = *this + String(temp));
}

// << operator, ami kiĂ­r az ostream-re
std::ostream& operator<<(std::ostream& os, const String& s0) {
    os << s0.c_str();
    return os;
}

// << operátor, ami beolvas az istreamről egy szót
std::istream& operator>>(std::istream& is, String& s0) {
    unsigned char ch;
    s0 = String("");            // Ăźres string, ehhez fĹązĂźnk hozzĂĄ
	std::ios_base::fmtflags fl = is.flags(); // eltesszĂźk a rĂŠgi flag-eket
	is.setf(ios_base::skipws);			// az elejĂŠn eldobjuk a ws-t
    while (is >> ch) {
	    is.unsetf(ios_base::skipws);	// utĂĄna pedig mĂĄr nem
        if (isspace(ch)) {
            is.putback(ch);             // na ezt nem kĂŠrjĂźk
            break;
        } else {
            s0 = s0 + ch;               // vĂŠgĂŠre fĹązzĂźk a karaktert
        }
    }
	is.setf(fl);						// visszaĂĄllĂ­tjuk a flag-eket
    return is;
}