/*! \file pichar.h
 * \ingroup Text
 * \~\brief
 * \~english UTF-16 character type
 * \~russian Тип UTF-16 символа
 */
/*
    PIP - Platform Independent Primitives
    Unicode char
    Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef PICHAR_H
#define PICHAR_H

#include "piincludes.h"

extern PIP_EXPORT char * __syslocname__;
extern PIP_EXPORT char * __sysoemname__;
extern PIP_EXPORT char * __utf8name__;

//! \~\ingroup Text
//! \~\brief
//! \~english Single UTF-16 character.
//! \~russian Один UTF-16 символ.
class PIP_EXPORT PIChar {
	friend class PIString;
	friend PIP_EXPORT PICout operator<<(PICout s, const PIChar & v);

public:
	//! \~english Constructs a character from an ASCII byte.
	//! \~russian Создает символ из ASCII байта.
	PIChar(char c) { ch = c; }

	//! \~english Constructs a character from an ASCII byte.
	//! \~russian Создает символ из ASCII байта.
	PIChar(uchar c) { ch = c; }

	//! \~english Constructs a character from a UTF-16 code unit.
	//! \~russian Создает символ из UTF-16 кодовой единицы.
	PIChar(ushort c = 0) { ch = c; }

	//! \~english Constructs a character from `wchar_t`.
	//! \~russian Создает символ из `wchar_t`.
	PIChar(wchar_t c) { ch = c; }

	//! \~english Constructs a character from `char16_t`.
	//! \~russian Создает символ из `char16_t`.
	PIChar(char16_t c) { ch = c; }

	//! \~english Assigns an ASCII byte.
	//! \~russian Присваивает ASCII байт.
	PIChar & operator=(const char v) {
		ch = v;
		return *this;
	}

	//! \~english Assigns a `wchar_t` character.
	//! \~russian Присваивает символ `wchar_t`.
	PIChar & operator=(const wchar_t v) {
		ch = v;
		return *this;
	}

	//! \~english Returns `true` if characters are equal.
	//! \~russian Возвращает `true`, если символы равны.
	bool operator==(const PIChar & o) const;

	//! \~english Returns `true` if characters are not equal.
	//! \~russian Возвращает `true`, если символы не равны.
	bool operator!=(const PIChar & o) const { return !(*this == o); }

	//! \~english Returns `true` if this character is greater than `o`.
	//! \~russian Возвращает `true`, если этот символ больше `o`.
	bool operator>(const PIChar & o) const;

	//! \~english Returns `true` if this character is less than `o`.
	//! \~russian Возвращает `true`, если этот символ меньше `o`.
	bool operator<(const PIChar & o) const;

	//! \~english Returns `true` if this character is greater than or equal to `o`.
	//! \~russian Возвращает `true`, если этот символ больше либо равен `o`.
	bool operator>=(const PIChar & o) const;

	//! \~english Returns `true` if this character is less than or equal to `o`.
	//! \~russian Возвращает `true`, если этот символ меньше либо равен `o`.
	bool operator<=(const PIChar & o) const;

	//! \~english Returns `true` if the character is a digit.
	//! \~russian Возвращает `true`, если символ является цифрой.
	bool isDigit() const;

	//! \~english Returns `true` if the character is a hexadecimal digit.
	//! \~russian Возвращает `true`, если символ является шестнадцатеричной цифрой.
	bool isHex() const;

	//! \~english Returns `true` if the character is visible and not a space.
	//! \~russian Возвращает `true`, если символ является графическим и не является пробельным.
	bool isGraphical() const;

	//! \~english Returns `true` if the character is a control character.
	//! \~russian Возвращает `true`, если символ является управляющим.
	bool isControl() const;

	//! \~english Returns `true` if the character is lowercase.
	//! \~russian Возвращает `true`, если символ в нижнем регистре.
	bool isLower() const;

	//! \~english Returns `true` if the character is uppercase.
	//! \~russian Возвращает `true`, если символ в верхнем регистре.
	bool isUpper() const;

	//! \~english Returns `true` if the character is printable.
	//! \~russian Возвращает `true`, если символ является печатным.
	bool isPrint() const;

	//! \~english Returns `true` if the character is whitespace.
	//! \~russian Возвращает `true`, если символ является пробельным.
	bool isSpace() const;

	//! \~english Returns `true` if the character is alphabetic.
	//! \~russian Возвращает `true`, если символ является буквой.
	bool isAlpha() const;

	//! \~english Returns `true` if the character is ASCII.
	//! \~russian Возвращает `true`, если символ входит в ASCII.
	bool isAscii() const;

	//! \~english Returns a `wchar_t` view of the internal single-character storage.
	//! \~russian Возвращает представление внутреннего буфера одного символа как `wchar_t`.
	const wchar_t * toWCharPtr() const;

	//! \~english Returns a `char` view of the internal single-character storage.
	//! \~russian Возвращает представление внутреннего буфера одного символа как `char`.
	const char * toCharPtr() const;

	//! \~english Returns the character as `wchar_t`.
	//! \~russian Возвращает символ как `wchar_t`.
	wchar_t toWChar() const;

	//! \~english Returns the low ASCII byte of the character.
	//! \~russian Возвращает младший ASCII байт символа.
	char toAscii() const { return ch % 256; }

	//! \~english Returns the character as a single byte in console codepage.
	//! \~russian Возвращает символ как один байт в консольной кодировке.
	char toConsole1Byte() const;

	//! \~english Returns the character as a single byte in system codepage.
	//! \~russian Возвращает символ как один байт в системной кодировке.
	char toSystem() const;

	//! \~english Returns the UTF-16 code unit of the character.
	//! \~russian Возвращает UTF-16 кодовую единицу символа.
	ushort unicode16Code() const { return ch; }

	//! \~english Returns an uppercase copy of the character.
	//! \~russian Возвращает копию символа в верхнем регистре.
	PIChar toUpper() const;

	//! \~english Returns a lowercase copy of the character.
	//! \~russian Возвращает копию символа в нижнем регистре.
	PIChar toLower() const;

	//! \~english Creates a character from a single console-codepage byte.
	//! \~russian Создает символ из одного байта консольной кодировки.
	static PIChar fromConsole(char c);

	//! \~english Creates a character from a single system-codepage byte.
	//! \~russian Создает символ из одного байта системной кодировки.
	static PIChar fromSystem(char c);

	//! \~english Creates a character from the first system-codepage character in `c`.
	//! \~russian Создает символ из первого символа в `c` в системной кодировке.
	static PIChar fromSystem(const char * c);

	//! \~english Creates a character from the first UTF-8 character in `c`.
	//! \~russian Создает символ из первого UTF-8 символа в `c`.
	static PIChar fromUTF8(const char * c);

private:
	ushort ch;
};

//! \relatesalso PIChar
//! \~english Writes the character to \a PICout.
//! \~russian Записывает символ в \a PICout.
PIP_EXPORT PICout operator<<(PICout s, const PIChar & v);

//! \relatesalso PIChar
//! \~english Returns `true` if the ASCII byte `v` is equal to `c`.
//! \~russian Возвращает `true`, если ASCII байт `v` равен `c`.
inline bool operator==(const char v, const PIChar & c) {
	return (PIChar(v) == c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the ASCII byte `v` is greater than `c`.
//! \~russian Возвращает `true`, если ASCII байт `v` больше `c`.
inline bool operator>(const char v, const PIChar & c) {
	return (PIChar(v) > c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the ASCII byte `v` is less than `c`.
//! \~russian Возвращает `true`, если ASCII байт `v` меньше `c`.
inline bool operator<(const char v, const PIChar & c) {
	return (PIChar(v) < c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the ASCII byte `v` is greater than or equal to `c`.
//! \~russian Возвращает `true`, если ASCII байт `v` больше либо равен `c`.
inline bool operator>=(const char v, const PIChar & c) {
	return (PIChar(v) >= c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the ASCII byte `v` is less than or equal to `c`.
//! \~russian Возвращает `true`, если ASCII байт `v` меньше либо равен `c`.
inline bool operator<=(const char v, const PIChar & c) {
	return (PIChar(v) <= c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the UTF-16 code unit `v` is equal to `c`.
//! \~russian Возвращает `true`, если UTF-16 кодовая единица `v` равна `c`.
inline bool operator==(ushort v, const PIChar & c) {
	return (PIChar(v) == c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the UTF-16 code unit `v` is greater than `c`.
//! \~russian Возвращает `true`, если UTF-16 кодовая единица `v` больше `c`.
inline bool operator>(ushort v, const PIChar & c) {
	return (PIChar(v) > c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the UTF-16 code unit `v` is less than `c`.
//! \~russian Возвращает `true`, если UTF-16 кодовая единица `v` меньше `c`.
inline bool operator<(ushort v, const PIChar & c) {
	return (PIChar(v) < c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the UTF-16 code unit `v` is greater than or equal to `c`.
//! \~russian Возвращает `true`, если UTF-16 кодовая единица `v` больше либо равна `c`.
inline bool operator>=(ushort v, const PIChar & c) {
	return (PIChar(v) >= c);
}

//! \relatesalso PIChar
//! \~english Returns `true` if the UTF-16 code unit `v` is less than or equal to `c`.
//! \~russian Возвращает `true`, если UTF-16 кодовая единица `v` меньше либо равна `c`.
inline bool operator<=(ushort v, const PIChar & c) {
	return (PIChar(v) <= c);
}

#endif // PICHAR_H
