#ifndef STRING_H
#define STRING_H

#include <cstddef>
#include <iostream>

const int null = 0;

#define implicit


/** @class String
	@brief Facilita el trabajo con cadenas de caracteres de C
*/
class String
{
  private:
	/// La cadena de C terminada en nulo. Siempre tiene memoria alojada en segmento de heap
	char* str;
	/// La longitud actual de la cadena apuntada por @a str
	size_t len;

  public:
	/// Constructor por defecto y de conversion
	/// ToDo: recibir un parametro 'size_t len = (size_t)-1' por si el llamador conoce el length
	implicit String(const char* str = "");
	/// Crea un buffer con la capacidad dada
	explicit String(size_t capacity);
	/// Constructor de copia. Se invoca cuando
	/// String str2 = str1;
	/// String str3 = String("algo");
	/// String str4 = "algo";
	/// void foo(String str5); foo("algo");
	String(const String& other);
	/// Operador de asignacion. Se invoca cuando
	/// String str1;
	/// str1 = str0;
	/// str1 = String("algo");
	/// str1 = "algo";
	const String& operator=(const String& other);
	/// Destructor
	~String();
	/// Retorna la cantidad de caracteres almacenados en el String
	inline size_t length() const { return len; }
	/// Permite acceder al string de C solo para lectura
	inline const char* c_str() const { return str; }
	/// Permite utilizar un objeto String en un contexto donde se requiere un const char*
	inline operator const char*() const { return str; }
	/// Permite acceder al i-esimo caracter almacenado en el String
	/// El caracter puede ser modificado por el llamador, lo cual afectara al objeto String
	/// @remarks No se verifica que @a i este fuera de rango
	inline char& operator[](size_t i) { return str[i]; }
	/// Permite acceder al caracter i-simo del String en modo solo lectura
	/// @remarks No se verifica que @a i este fuera de rango
	inline const char& operator[](size_t i) const { return str[i]; }
	/// Obtiene el sub-string de length caracteres a partir del caracter start
	String substr(size_t start, size_t length = (size_t)-1) const;
	/// Obtiene el sub-string de length caracteres a partir del caracter start
	String operator()(size_t start, size_t length = (size_t)-1) const;

	// Amistad con los operadores sobrecargados para que puedan acceder a los miembros de datos
	friend std::ostream& operator<<(std::ostream& output, const String& str);
	friend String operator+(const String& a, const String& b);
};

/// Permite cout << str1 << str2 << ...
std::ostream& operator<<(std::ostream& output, const String& str);

/// Permite str1 + str2
String operator+(const String& a, const String& b);

#endif // STRING_H
