//
// Sławomir Słoma 
//
// Biblioteka Boost::crc
//
// Przedstawiony poniżej program prezentuje możliowści
// jakie oferują klasy z biblioteki boost:crc.
//
// 
//
//

#include <boost/crc.hpp>      // for boost::crc_basic, boost::crc_optimal
#include <boost/cstdint.hpp>  // for boost::uint16_t

#include <algorithm>  //  std::for_each
#include <cassert>    //  assert
#include <cstddef>    //  std::size_t
#include <iostream>   //  std::cout
#include <ostream>    //  std::endl


// Funkcja main:
int main ( int argc , char const *  argv[] )
{
    // Dane wejsciowe - "123456789" w ASCII
    unsigned char const  dane_wejsciowe[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
     0x38, 0x39 };
    std::size_t const    dlugosc_danych = sizeof( dane_wejsciowe ) / sizeof( dane_wejsciowe[0] );

    // Oczekiwany wynik dla naszych danych wejsciowych:
    boost::uint16_t const  oczekiwany = 0x29B1; //unsigned int

    // Parametry szablonu klasy crc_optimal
	// Truncated polynominal - wielomian dzielący który ma zostać zastosowany w algorytmie CRC
	// Initial reminder - wartość początkowa algorytmu CRC (domyślnie 0)
	// Final XOR value - wartość z jaka ma być XOR-owany wynik przed zwóceniem użytkownikowi
	// Reflected input - ustawia czy przed rozpoczęciem algorytmu bity wejściowe maja zostać odbite
	//					 wzgledem środka bajtu
	// Reflected (remainder) output - ustawia czy dane wyjściowe maja zostać odbite przed rozpoczęciem
	//								  operacji XOR-owania
	//
	// wszystkie parametry można pobrać w czesie działania programu dzieki odpowiednimi metodami get
	// np. get_truncated_polynominal

	// Dozwolone operacje:
	//
	
	// void process_bit( bool bit ); - dostarcza pojedyncze bity do obliczenia sumy kontrolnej CRC 
	//								   metoda ta jest zaimplementowana jedynie dla powolnego algorytmu obliczania CRC

	// void process_bits( unsigned char bits, - metoda pozwala na dostarczenie 'bit_count' ilosci bitow z ktorych ma
	//	std::size_t bit_count );				zostac obliczona suma kontrolna. Metoda ta jest zaimplementowana tylko 
	//											dla powolnego algorytmu obliczania CRC

	// void process_byte( unsigned char byte ); - dostarcza pojedyncze bajty do obliczania sumy CRC. Jezeli odbicie
	//											  nie jest wymagane bajty sa przetwarzane od najbardziej do najmniej 
	//											  znaczacych

	// void process_block( void const *bytes_begin, - przetwarza blok bajtow. Bajty przetwarzane sa od bytes_begin do
	//	void const *bytes_end );					  do bytes_end
	//
	
	// void process_bytes( void const *buffer, - przetwarza 'byte_count' bajtów zaczynając od 'buffer'
	//	std::size_t byte_count );
	//

	// value_type checksum() const; - zwraca obliczoną do tej pory wartość sumy kontrolnej

	// void operator ()( unsigned char byte ); - przeciążenie operatora() - wywołuje process_byte, zdefiniowane
	//																		tylko dla szybkiej klasy

	// value_type operator ()() const; - wywoluje checksum() zdefiniowane tylko dla szybkiej klasy



	// deklaracja obiektu klasy teoretyczniej (rozmiar 16bitow):
    boost::crc_basic<16>  crc_ccitt1( 0x1021, 0xFFFF, 0, false, false );
    
	// obliczenie wyniku:
	crc_ccitt1.process_bytes( dane_wejsciowe, dlugosc_danych );

	assert( crc_ccitt1.checksum() == oczekiwany ); //makro assert przerywa działanie programu w przypadku gdy wynik
												 // będzie nieprawidłowy

    // deklaracja obiektu klasy teoretyczniej (rozmiar 16bitow):
    boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false>  crc_ccitt2;
	// obliczenie wyniku:
    crc_ccitt2 = std::for_each( dane_wejsciowe, dane_wejsciowe + dlugosc_danych, crc_ccitt2 );

    assert( crc_ccitt2() == oczekiwany );

    std::cout << "Wszystkie testy udane" << std::endl;

	// Biblioteka boost::crc dostarcza 4 predefiniowane przykładowe typy CRC:
	
	// crc_16_type
	// crc_32_type
	// crc_ccitt_type
	// crc_xmodem_type
	
	// które reprezentuja powszechnie używane wersje CRC

	// Dodatkowo biblioteka boost::crc dostarcza wzorce funkcji crc:
	//
	// template < std::size_t Bits, impl_def TruncPoly,
	//	impl_def InitRem, impl_def FinalXor,
	//	bool ReflectIn, bool ReflectRem >
	//	typename boost::uint_t<Bits>::fast
	//	boost::crc( void const *buffer, std::size_t byte_count );
	//
	// powyższa funkcja zwraca taki sam wynik jak przy wykorzystaniu obiektu klasy crc_optimal

	// i 2 funkcji augmented_crc:
	
	// template < std::size_t Bits, impl_def TruncPoly >
	//	typename boost::uint_t<Bits>::fast
	//	boost::augmented_crc( void const *buffer, std::size_t byte_count,
	//	typename boost::uint_t<Bits>::fast initial_remainder );

	// template < std::size_t Bits, impl_def TruncPoly >
	// typename boost::uint_t<Bits>::fast
	// boost::augmented_crc( void const *buffer, std::size_t byte_count );

	// funkcje augmented_crc w inny sposób obliczają wynik - kolejność dzielenia jest odwrotna
    
	return 0;

}
