################################################################################
  Kodowanie Windows-1250, koniec wiersza CR+LF, test: Za gl ja
  Base - Modu podstawowy
  Copyleft (C) 2007 Adam Sawicki
  Licencja: GNU LGPL
  Kontakt: mailto:sawickiap@poczta.onet.pl , http://regedit.gamedev.pl/
################################################################################


Wstp
================================================================================

Ten modu to modu bazowy. Plik Base.hpp wczaj wszystkie pozostae pliki
biblioteki i uytkownik rwnie jest spodziewany aby to robi przed wczaniem
wszelkich innych nagwkw biblioteki, poniewa korzystaj one ze zdefiniowanych
w Base.hpp typw i innych elementw, a same go nie wczaj.

Nie uywa Error ani adnego innego moduu. To inne jego uywaj. adne z jego
funkcji nie zgaszaj bdw przez wyjtki.


Skadniki
================================================================================

- Podstawy:
  - Wcza:
    <cassert>, <string>, <vector>
  - Definiuje:
    using std::string;
  - Typy cakowitoliczbowe:
    uint1, uint2, uint4, uint8
    int1, int2, int4, int8
- Rne drobne, uyteczne makra i funkcje
- Operator dosownej reinterpretacji bitowej absolute_cast
- Inteligentne wskanki i uchwyty
  > parametryzowane polityk zwalniania
  > Z wyczn wasnoci lub ze zliczaniem referencji
- Funkcje do operacji na znakach i acuchach, w tym oprcz prostych take:
  > Konwersja midzy stronami kodowymi:
    Windows-1250, ISO-8859-2, IBM CP852, UTF-8
  > Dopasowanie do maski ze znakami wieloznacznymi '*' i '?'
  > Odlego edycyjna acuchw - Levenshtein Distance
  > Porwnywanie acuchw w tzw. porzdku naturalnym
- Funkcje do operacji na ciekach do plikw
  > Dziaajce zarwno dla cieek Windows jak i Linux
- Konwersje rnych typw do i z acucha znakw, w tym:
  > Wasne IntToStr, StrToInt, UintToStr, StrToUint sprawdzajce bdy skadni i
    zakresu
  > Uoglniony, rozszerzony mechanizm konwersji zrealizowany za pomoc szablonw
    SthToStr i StrToSth
  > Wygodny mechanizm formuowania acuchw korzystajcy z powyszego, np.:
    string s = Format("x=#, y=#") % x % y;
- Dokadny pomiar czasu i czekanie okrelony czas
- Podstawowe typy, stae, makra i funkcje matematyczne, w tym oprcz prostych
  take:
  > Funkcja wygadzajca metod Critically Damped Smoothing
  > Funkcje okresowe - sinus, trjkta, prostoktna, pioksztatna, PWM
- Generator liczb pseudolosowych
  > Bardzo szybki, deterministyczny
  > Losowanie liczb rnych typw
  > Generowanie losowych danych binarnych
  > Losowanie liczb o rozkadzie normalnym (Gaussa)
- Generator unikatowych identyfikatorw
- Parser parametrw przekazanych z wiersza polece
  > Szybki i prosty w uyciu
  > Wsparcie zarwno dla main (int argc, char **argv), jak i WinMain (char
    *CmdLine)
  > Obsuguje opcje krtkie (jednoznakowe) i dugie (wieloznakowe), w formatach:
    ] Linuksa:  -a -b -c -abc --duga -lARG -l ARG -l=ARG
    ] Windowsa: /a /b /c      /duga  /lARG /l ARG /l=ARG
- Klasa bazowa dla wzorca projektowego Singleton


absolute_cast
================================================================================

To brakujcy w C++ operator dosownej reinterpretacji bitowej midzy wartociami
dowolnego typu. Ma sens tylko w przypadku typw o takim samym rozmiarze w sensie
liczby zajmowanych bajtw. Jest to sprytnie napisana funkcja szablonona, ktrej
mona uywa niczym wbudowanych operatorw rzutowania C++ takich jak static_cast
czy reinterpret_cast. Jej wynalazc jest Karol Kuczmarski "Xion". Przykad:

	float F = 10.5f;
	uint4 I1 = static_cast<uint4>(F);
	uint4 I2 = absolute_cast<uint4>(F);

I1 bdzie wynosio 10 - nastpia konwersja wartoci liczbowej.
I2 bdzie wynosio 1093140480 - nastpia dosowna reinterpretacja bitw.

Wicej informacji na temat problemu konwersji midzy typami w C++ znajdziesz w
moim artykule "Rzutowanie typw w C++", Adam Sawicki, Czerwiec 2006,
http://regedit.gamedev.pl/produkcje/artykuly/rzutowanie_typow_w_cpp.php5


Konwersje
================================================================================

Modu Base oferuje konwersje midzy rnymi typami a acuchami w obydwie
strony, take z dodatkowymi opcjami. Su do tego funkcje takie jak np.:
IntToStr, StrToInt, FloatToStr, StrToFloat, BoolToStr, StrToBool itd.

Uoglnion wersj tych konwersji s szablony funkcji SthToStr i StrToSth.
Obsuguj one nastpujce typy:

- SthToStr i StrToSth:
  bool, char, int2, int4, int8, uint1, uint2, uint4, uint8, float, double,
  string, std::vector<T>
- Tylko SthToStr:
  char*, const char*, void*, const void*

Prba uycia tych funkcji dla nieobsugiwanego typu zakoczy si Assertion
Failed. Mona sprawdzi, czy dany typ jest obsugiwany uywajc:

	bool B1 = StrToSth_obj<SOME_TYPE>::IsSupported();
	bool B2 = SthToStr_obj<SOME_TYPE>::IsSupported();

Mona pisa konwersje do i z wasnych typw. Szablon takiej konwersji jest
nastpujcy. Naley zamieni T na konkretny typ i wpisa konwersj w miejscu //.
Kod ten naley wpisa poza jakkolwiek przestrzeni nazw.

	template <>
	struct SthToStr_obj<T>
	{
		void operator () (string *Str, const T &Sth)
		{
			//
		}
		static inline bool IsSupported() { return true; }
	};

	template <>
	struct StrToSth_obj<T>
	{
		bool operator () (T *Sth, const string &Str)
		{
			//
		}
		static inline bool IsSupported() { return true; }
	};

Jeli StrToSth si nie uda, warto parametru wyjciowego jest niezdefiniowana.

Modu Error rozszerza ten mechanizm o szablon funkcji MustStrToSth, ktry w
przypadku niepowodzenia rzuca wyjtek.

Klasa Format (wraz z przeadowanym dla niej operatorem %) robi za sprintf dla
acuchw string. Nie jest super szybka, ale jest wygodna w uyciu. Obsuguje
wszystkie te typy, co SthToStr. Sposb uycia (jeli jakitam OutputLine
oczekuje const string&):

	OutputLine( Format("Bd w pliku # w wierszu #") % "plik.txt" % 123 );

Jeli potrzeba zapisa do strumienia lub z innych przyczyn operator string() nie
dziaa, uywamy metody str:

	std::cout << ( Format("Bd w pliku # w wierszu #") % "plik.txt" % 123 ).str();

Jeli chcemy niestandardowe formatowanie podczas konwersji z jakiego typu na
acuch, konwertujemy we wasnym zakresie:

	OutputLine( Format("Bd w pliku # w wierszu #") % "plik.txt" % IntToStr2(123, 5) );

Jeli potrzebujemy znaku '#' i chcemy jako specjalny uy innego znaku:

	OutputLine( Format("Bd # % w pliku %", '%') % 123 % "plik.txt" );


Inteligentne wskaniki
================================================================================

Modu zawiera wasn, elastyczn i do potn, acz prost implementacj
inteligentnych wskanikw.


Sposb uycia
--------------------------------------------------------------------------------

S cztery rodzaje wskanikw:

- Przechowujce wskanik typu T* - do wskanikw:
  - scoped_ptr
    Zwyky posiadajcy wasno, zwalnia w destruktorze, niekopiowalny.
  - shared_ptr
    Zliczajcy referencje.
- Przechowujce bezporednio warto typu T - do uchwytw:
  - scoped_handle
    Zwyky posiadajcy wasno, zwalnia w destruktorze, niekopiowalny.
  - shared_handle
    Zliczajcy referencje.

S trzy polityki zwalniania dla wskanikw:

- DeletePolicy (domylna)
  Wywouje: delete x;
- DeleteArrayPolicy - do tablic
  Wywouje: delete [] x;
- ReleasePolicy - do zasobw takich jak obiekty COM
  Wywouje: x->Release();

Oraz dwie dla uchwytw [tylko Windows]:

- CloseHandlePolicy - wywouje CloseHandle(x);
- DeleteObjectPolicy - wywouje DeleteObject(x);

Mona te pisa wasne polityki zwalniania. Przykady:
- dla wskanikw:
    class ReleasePolicy { public: template <typename T> static void Destroy(T *p) { if (p) p->Release(); } };
- dla uchwytw:
    class DeleteObjectPolicy { public: template <typename T> static void Destroy(T p) { if (p != NULL) DeleteObject(p); } };

Przykady klas wskanikw:

- Wskanik z wasnoci, sam kasuje, niekopiowalny:
    scoped_ptr<Klasa> p1;
- Wskanik ze zliczaniem referencji:
    shared_ptr<Klasa> p2;
- Wskanik do tablicy (usuwany delete[]), niekopiowalny:
    scoped_ptr<Klasa, DeleteArrayPolicy> p3;
- Wskanik do obiektu COM ze zliczaniem referencji:
    shared_ptr<IDirect3DTexture9, ReleasePolicy> p4;
- Uchwyt do otwartego pliku Windows API:
    typedef scoped_handle<HANDLE, CloseHandlePolicy> close_handle;
    close_handle plik(NULL);

Sposb uycia scoped_ptr:

- Konstruktor domylny ustawia wskanik pusty (NULL)
    scoped_ptr<Klasa> p1;
- Konstruktor inicjalizujcy (tylko explicit):
    scoped_ptr<Klasa> p1(NULL);
    scoped_ptr<Klasa> p2(new Klasa());
- Wyzerowanie wskanika (jeli trzeba, sam zwolni obiekt):
    p1.reset();
    p1.reset(NULL);
- Ustawienie wskanika na nowy obiekt (jeli trzeba, sam zwolni stary):
    p1.reset(new Klasa());
- Odwoanie si pod wskanik:
    Klasa obj2 = *p1;
    p1->MetodaKlasy();
- Otrzymanie prawdziwego wskanika:
    Klasa *RealPtr = p1.get();
- Porwnywanie wskanikw:
    if (p1 == NULL) { }
    if (RealPtr == p1) { }
- Zamiana:
    p1.swap(p2);
    swap(p1, p2);
- Odwoanie si do elementu tablicy wskazywanej przez wskanik:
    scoped_ptr<int, DeleteArrayPolicy> tablica(new int[1024]);
    tablica[0] = 1;

Sposb uycia shared_ptr:

- Wspiera to samo co scoped_ptr plus dodatkowo...
- Skopiowanie wskanika do drugiego:
  Dziaa take dla klas sparametryzowanych typem klasy nieidentycznym, ale
  dajcym si skonwertowa.
    shared_ptr<Klasa> p1;
    shared_ptr<Klasa> p2 = p1;
    p2 = p1;
    p2.reset(p1);
- Porwnanie dwch wskanikw:
    if (p1 == p2) { }

Sposb uycia scoped_handle i shared_handle:
Jak odpowiednio scoped_ptr lub shared_ptr, ale:
- Nie posiada operatorw: * -> []
  Trzeba pobiera jego warto za pomoc metody get.
- Nie posiada bezparametrowego konstruktora ani operatora przypisania, eby nie
  oczekiwa po typie wskanika e posiada domyln warto zerow oznaczajc
  warto pust. Dlatego trzeba pisa na przykad tak:
    scoped_handle<HANDLE, CloseHandlePolicy> p1(NULL);
    p1.reset(NULL);


Szczegy
--------------------------------------------------------------------------------

Inteligetne wskaniki s potrzebne, zwaszcza do unikania wyciekw pamici kiedy
uywamy wyjtkw. Do napisania wasnych zmotywowaa mnie ch uwolnienia si od
biblioteki Boost. Pisanie takich wskanikw nie jest trudne, ale wie si z
podjciem szeregu trudnych decyzji projektowych. Podjem nastpujce:

- Rne sposoby zwalniania: parametryzacja szablonu specjalnym Policy
- Rodzaje wasnoci:
  - niekopiowalny scoped_ptr
  - zliczajcy referencje shared_ptr
- Implementacja zliczania referencji: wskanik przechowuje:
  - wskanik do danych
  - wskanik do alokowanego na stercie licznika
- Nie-explicit konstruktor oraz operator pobierajcy T* : NIE
- Operator * i -> zamiast samej metody get: TAK
- Funkcje takie jak get czy reset: jako metody, nie funkcje globalne
- Przeciony operator [] do indeksowania tablic: po namyle jednak TAK
- Arytmetyka wskanikw: NIE
- Konwersje z wskanikw do innych typw: TAK
- Operatory == != : TAK
- Operatory < > <= >= : NIE
- Operator & : NIE
- Kontrola niezerowoci wskanika przy * i -> : TAK, assert
- Wskanik do staej, stay wskanik: OLA, nic z tym nie robi
- Bezpieczestwo wtkowe: OLA, nic z tym nie robi
- Moliwo przechowywania czego innego ni normalnego wskanika T* : TAK, ale
  jako osobne klasy, bez uoglniania tego z uyciem Policy
- Zapobieganie UB-kowi przy destrukcji niezdefiniowanej klasy: TAK, sztuczka
  z Boost checked_delete.hpp


Singleton
================================================================================

Szablon klasy Singleton to klasa bazowa do implementacji wzorca projektowego
singletonu, czyli klasy, ktrej gwny (najczciej jedyny) obiekt jest tworzony
automatycznie podczas pierwszego uycia.

Deklarujemy tak:

	class MyClass : public Singleton<MyClass>
	{
		int MyMethod(int x);
	};

Uywamy tak:

	int i = MyClass::GetInstance().MyMethod(123);

Obiekt powstanie przy pierwszym uyciu i, jeli kiedykolwiek powsta, zostanie
na kocu programu automatycznie usunity (wywoa si destruktor).


Parser wiersza polece
================================================================================

Klasa CmdLineParser oferuje parsowanie parametrw przekazanych do programu z
wiersza polece. Jest troch podobna do funkcji getopt z Linuksa.

Cechy
--------------------------------------------------------------------------------

- Przenona, jak cay CommonLib, a w przeciwiestwie do linuksowej getopt.
- Obsuguje zarwno wiersz polece z main(int argc, char **argv), jak i z
  WinMain(HINSTANCE, HINSTANCE, char *CmdLine, int).
- Obsuguje opcje krtkie (jednoznakowe) i dugie (wieloznakowe), w formatach:
  > Linuksa:  -a -b -c -abc --duga -lARG -l ARG -l=ARG
  > Windowsa: /a /b /c      /duga  /lARG /l ARG /l=ARG
- Prosta w uyciu.
- Nie jest maksymalnie szybka.

Sposb uycia
--------------------------------------------------------------------------------

1. Utworzy obiekt klasy CmdLineParser
   Jako parametry do odpowiedniego konstruktora poda argumenty wiersza polece
   otrzymane w funkcji main lub WinMain. W czasie parsowania nie mog si
   zmienia.
2. Zarejestrowa dopuszczalne opcje metod RegisterOpt. Kada opcja ma:
   - Identyfikator liczbowy - powinien by wikszy od 0.
   - Tre - jednoznakow (opcja krtka) lub wieloznakow (opcja duga)
   - Flag, czy oczekuje parametru (dodatkowego acucha za opcj)
3. Pobiera kolejne informacje metod ReadNext a do otrzymania RESULT_END lub
   RESULT_ERROR.

Skadnia
--------------------------------------------------------------------------------

Uycie parsera polega na pobieraniu kolejnych informacji. Moliwe wartoci:

- RESULT_END - informacji nie pobrano, koniec wiersza polece
- RESULT_ERROR - informacji nie pobrano, bd skadni
- RESULT_PARAMETER - pobrano goy parametr bez opcji
  Moesz odczyta tre parametru metod GetParameter.
- RESULT_OPT - pobrano krtk lub dug opcj
  Moesz odczyta identyfikator opcji metod GetOptId.
  Jeli opcja przyjmuje parametr, moesz odczyta tre parametru metod
  GetParameter.

Na przykad jeli 'a', 'b' i 'c' to opcje krtkie, z ktrych 'c' oczekuje
parametru, dopuszczalne s m.in. takie konstrukcje:

  -a -b -c parametr
  -abc parametr
  -a -b -c=parametr
  -ab -c"parametr ze spacj"
  "-abcparametr ze spacj"
  /a /b /c parametr
  /a /b /c="parametr ze spacj"
  /a /b "/cparametr ze spacj"

Jeli natomiast "AA" i "BBB" to opcje dugie, z czego ta druga oczekuje
parametru, dopuszczalne s m.in. takie konstrukcje:

  --AA --BB parametr
  --AA --BB=parametr
  /AA /BB="parametr ze spacj"
  --AA /BB "parametr ze spacj"

Kolejno opcji nie jest w aden sposb kontrolowania, podobnie jak ich obecno
czy powtarzanie si wiele razy. To ley ju w gestii uytkownika - parser tylko
odczytuje i zwraca kolejne napotkane informacje.

Przykad
--------------------------------------------------------------------------------

Obsugiwana skadnia jest skomplikowana i oparta na dogbnych badaniach
zachowania wiersza polece Windowsa i Linuksa. Niektre moliwoci przedstawia
ten przykad. Jeli zarejestrowane s opcje:

  RegisterOpt(1, 'a', false);
  RegisterOpt(2, 'b', false);
  RegisterOpt(3, 'c', true);
  RegisterOpt(11, "AA", false);
  RegisterOpt(12, "BBB", true);

Wiersz polece wyglda tak:

  -a -b -c param -abc="param" "-cparam" /AA --AA "/BBB"=param DUPA --BBB "param"

Wwczas wynikiem kolejnych wywoa ReadNext jest:

  Result=RESULT_OPT,       Id=1,  Param=""
  Result=RESULT_OPT,       Id=2,  Param=""
  Result=RESULT_OPT,       Id=3,  Param="param"
  Result=RESULT_OPT,       Id=1,  Param=""
  Result=RESULT_OPT,       Id=2,  Param=""
  Result=RESULT_OPT,       Id=3,  Param="param"
  Result=RESULT_OPT,       Id=3,  Param="param"
  Result=RESULT_OPT,       Id=11, Param=""
  Result=RESULT_OPT,       Id=11, Param=""
  Result=RESULT_OPT,       Id=12, Param="param"
  Result=RESULT_PARAMETER, Id=0,  Param="DUPA"
  Result=RESULT_OPT,       Id=12, Param="param"
  Result=RESULT_END,       Id=0,  Param=""

