📄 poruka.cpp
字号:
/*
Klase za rad sa porukama.
*/
#include "Poruka.h"
#include "Korisno.h"
#include "Konfig.h"
#include <iostream>
//*********************************** KPoruka << BEGIN >> ***************************************
// Konstruktori
KPoruka::KPoruka( string cSadrzajPoruke, KFormatPoruke& formatPoruke ) {
KPoruka::format = formatPoruke;
PostaviSadrzaj( cSadrzajPoruke );
}
KPoruka::KPoruka( string cSadrzajPoruke, IDFormataPoruke formatID ){
KFormatPoruke format;
// Ako dati format ne postoji kreiraj poruku sa DEFAULT formatom
if ( !KSpisakFormata::Instance()->DajFormatPoruke( formatID, format ) )
KSpisakFormata::Instance()->DajDefaultFormat( format );
auto_ptr<KPoruka> pPoruka( new KPoruka( cSadrzajPoruke, format ) );
( *this ) = *pPoruka;
}
// Default konstruktor
KPoruka::KPoruka( IDFormataPoruke formatID ){
auto_ptr<KPoruka> pPoruka( new KPoruka( "", formatID ) );
( *this ) = *pPoruka;
}
// Vraca duzinu poruke
int KPoruka::Duzina( void ) const {
return sadrzaj.size();
}
// Vraca sadrzaj poruke
string KPoruka::Sadrzaj( void ){
return KPoruka::sadrzaj;
};
// Vraca format poruke
KFormatPoruke KPoruka::Format( void ) const {
return KPoruka::format;
}
// Procedura postavlja sadrzaj poruke.
void KPoruka::PostaviSadrzaj( string cNoviSadrzaj ) {
KPoruka::sadrzaj = cNoviSadrzaj;
// Postavi pozicije i duzine pojedinih komponenata poruke na 'default' vrednosti.
// Ako dati string ne sadrzi sve komponente, postavlja njihovu poziciju i duzinu na 0.
ResetujPozicijeKomponenata();
}
// Vraca 'true' ako data komponenta poruke postoji u formatu.
// ( ako komponenta postoji u formatu, ne znaci da postoji i u telu poruke )
bool KPoruka::PostojiKomponenta( IDKomponentePoruke ID ){
return format.PostojiKomponenta( ID );
}
// Vraca sadrzaj komponente poruke sa datim ID-om.
string KPoruka::DajKomponentu( IDKomponentePoruke ID ){
unsigned int nPozicija, nDuzina;
if ( format.DajPozicijuKomponente( ID, nPozicija, nDuzina ) )
return sadrzaj.substr( nPozicija, nDuzina );
else
return string( "" );
}
// Postavlja vrednost date komponente poruke.
// Vraca 'false' ako data komponenta nije predvidjena formatom poruke.
bool KPoruka::PostaviKomponentu( IDKomponentePoruke ID, string cSadrzajKomponente ) {
bool izlaz = false;
if ( format.PostojiKomponenta( ID ) ) {
// Pronadji poziciju na koju treba ubaciti novu komponentu
unsigned int nPozicija = 0;
TOpisPoruke opisPoruke;
format.DajOpis( opisPoruke );
TOpisPoruke::iterator o_iter = opisPoruke.begin();
TOpisPoruke::iterator o_iterEnd = opisPoruke.end();
// Prodji kroz sve komponente pre ove koja se ubacuje
while ( o_iter->IDkomponente != ID ){
nPozicija = o_iter->pozicija + o_iter->duzina;
o_iter++;
}
// Ubaci komponentu u poruku ( zameni staru ako je postojala tj. ako je o_iter->duzina>0 ):
unsigned int nStaraDuzina = o_iter->duzina;
unsigned int nNovaDuzina = cSadrzajKomponente.size();
unsigned int nIzaKomponente = nPozicija+nStaraDuzina;
// sadrzaj.replace( nPozicija, nStaraDuzina, cSadrzajKomponente );
// Zbog baga u funkciji replace, koristim obicnu konkatenaciju :
sadrzaj = sadrzaj.substr( 0, nPozicija ) +
cSadrzajKomponente +
sadrzaj.substr( nIzaKomponente, sadrzaj.length() - nIzaKomponente + 1 );
format.PostaviPozicijuKomponente( ID, nPozicija, nNovaDuzina );
// Pomeri pozicije svih komponenata koje se nalaze iza ove koja je sada ubacena
o_iter++;
while ( o_iter != o_iterEnd ) {
if ( !( o_iter->pozicija==0 && o_iter->duzina==0 ) ) // ako komponenta 'postoji'
o_iter->pozicija += ( nNovaDuzina - nStaraDuzina );
o_iter++;
}
izlaz = true;
}
return izlaz;
}
// Postavlja vrednost date komponente poruke na dati bajt ( kopira ga onoliko puta kolika je duzina komponente ).
// Radi samo za komponente cija je duzina poznata ( > 0 ).
// Vraca 'false' ako data komponenta nije predvidjena formatom poruke.
bool KPoruka::PostaviKomponentu( IDKomponentePoruke ID, unsigned char cBajt ){
bool izlaz = false;
// Pronadji duzinu komponente
unsigned int nPozicija, nDuzina;
if ( KSpisakFormata::Instance()->DefaultPozicijaKomponente( format.DajID(), ID, nPozicija, nDuzina ) ) {
if ( nDuzina > 0 ) {
string cPomStr;
cPomStr.assign( nDuzina, cBajt );
return PostaviKomponentu( ID, cPomStr );
}
}
return izlaz;
}
// Sracunava 'checksum' poruke. 'Sumira' sve bajtove poruke sem komponente 'SUMA' ( ako postoji ).
// Checksum vraca u obiku stringa tako da moze odmah da se ubaci u poruku.
string KPoruka::IzracunajSumu( void ) {
unsigned int duzina = sadrzaj.size();
char suma[2] = {0,0};
unsigned int nPocetakSume;
unsigned int nKrajSume;
// Odredi deo stringa koji sadrzi sumu ( deo koji treba preskociti pri sumiranju )
unsigned int nPozicija, nDuzina;
if ( format.DajPozicijuKomponente( KP_SUMA, nPozicija, nDuzina ) ) {
nPocetakSume = nPozicija;
nKrajSume = nPocetakSume + nDuzina;
}
else // ako komponenta SUMA ne postoji u poruci, postavi 'neutralne' vrednosti
{
nPocetakSume = duzina;
nKrajSume = 0;
}
// Sracunaj sumu
for ( unsigned int i=0; i<duzina && !( i>=nPocetakSume && i<=nKrajSume ) ; i++ )
suma[0] = suma[0] ^ sadrzaj[i];
return string( suma );
}
// Proverava sumu poruke. Vraca 'false' ako suma nije dobra ili ako ne postoji.
bool KPoruka::ProveriSumu( void ){
return ( DajKomponentu( KP_SUMA ) == IzracunajSumu() );
}
// Postavlja vrednost komponente 'SUMA' tako da odgovara sadrzaju poruke
// ako komponenta 'SUMA' postoji u poruci.
void KPoruka::PostaviSumu( void ){
PostaviKomponentu( KP_SUMA, IzracunajSumu() );
}
// Postavlja pozicije i duzine komponenata poruke na 'default' vrednosti.
// Ako je poruka kratka ( ne sadrzi sve komponente ), postavlja njihove pozicije i duzine na 0.
void KPoruka::ResetujPozicijeKomponenata( void ){
unsigned int nDuzinaPoruke = sadrzaj.size();
unsigned int nPozicijaKomp;
unsigned int nDuzinaKomp;
unsigned int nDuzinaBezSadrzaja;
TOpisPoruke opisPoruke;
format.DajOpis( opisPoruke );
TOpisPoruke::iterator o_iter = opisPoruke.begin();
TOpisPoruke::iterator o_iterEnd = opisPoruke.end();
IDKomponentePoruke IDkomponente;
if ( KSpisakFormata::Instance()->FormatDefault( format ) )
// Ako se radi o 'default' formatu, pozicija i duzina se setuje na osnovu sadrzaja
format.PostaviPozicijuKomponente( o_iter->IDkomponente, 0, nDuzinaPoruke );
else {
// 1.KORAK : odredi duzine svih komponenata poruke
IDFormataPoruke formatID = format.DajID();
nDuzinaBezSadrzaja = 0;
// 1.a) odredi duzine svih komponenata sem sadrzaja
while ( o_iter != o_iterEnd ) {
// Uzmi 'default' poziciju i duzinu komponente poruke
IDkomponente = o_iter->IDkomponente;
KSpisakFormata::Instance()->DefaultPozicijaKomponente( formatID, IDkomponente,
nPozicijaKomp, nDuzinaKomp );
if ( nPozicijaKomp + nDuzinaKomp > nDuzinaPoruke && nPozicijaKomp <= nDuzinaPoruke )
// Ako je samo deo komponente ulazi u sadrzaj, skrati duzinu
nDuzinaKomp = nDuzinaPoruke - nPozicijaKomp;
else if ( nPozicijaKomp > nDuzinaPoruke )
// Ako komponenta ne postoji ( sadrzaj je kratak ), postavi duzinu na 0
nDuzinaKomp = 0;
format.PostaviPozicijuKomponente( IDkomponente, 0, nDuzinaKomp );
if ( IDkomponente != KP_SADRZAJ ) nDuzinaBezSadrzaja += nDuzinaKomp;
o_iter++;
}
// 1.b) ako postoji koponenta 'SADRZAJ', odredi njenu duzinu kao razliku
// duzine poruke i zbira duzina svih komponenata bez sadrzaja
if ( KSpisakFormata::Instance()->DefaultPozicijaKomponente( formatID, KP_SADRZAJ,
nPozicijaKomp, nDuzinaKomp ) )
format.PostaviPozicijuKomponente( KP_SADRZAJ, 0, nDuzinaPoruke-nDuzinaBezSadrzaja );
// 2. KORAK : podesi duzine poruka ( da odgovaraju velicinama odredjenim u 1. koraku )
o_iter = opisPoruke.begin();
o_iterEnd = opisPoruke.end();
unsigned int nNovaPozicijaKomp = 0;
while ( o_iter != o_iterEnd ) {
IDkomponente = o_iter->IDkomponente;
// Procitaj duzinu komponente
format.DajPozicijuKomponente( IDkomponente, nPozicijaKomp, nDuzinaKomp );
// Postavi novu poziciju komponente
format.PostaviPozicijuKomponente( IDkomponente, nNovaPozicijaKomp, nDuzinaKomp );
// Pripremi poziciju sledece komponente
nNovaPozicijaKomp += nDuzinaKomp;
o_iter++;
}
}
}
// Pomocna procedura : ispisuje sadraj poruke po komponentama na standardni izlaz
void KPoruka::IspisiPoruku( void ) {
TOpisPoruke opisPoruke;
format.DajOpis( opisPoruke );
TOpisPoruke::iterator o_iter = opisPoruke.begin();
TOpisPoruke::iterator o_iterEnd = opisPoruke.end();
cout << "Poruka po komponentama :" << endl;
while ( o_iter != o_iterEnd ) {
string str = DajKomponentu( o_iter->IDkomponente );
cout << o_iter->IDkomponente
<< ": "
<< KKorisno::Instance()->FormatString( str, FS_BCD_ASCII ) << endl;
o_iter++;
}
}
//*********************************** KPoruka << END >> *****************************************
//******************************* TransankcionaPoruka << BEGIN >> *******************************
// Pomocna procedura za konstruktore
void KTransankcionaPoruka::KopirajPoruku( KPoruka* pPoruka ){
KTransankcionaPoruka::sadrzaj = pPoruka->Sadrzaj();
KTransankcionaPoruka::format = pPoruka->Format();
}
// Konstruktor za formiranje transakcione poruke
KTransankcionaPoruka::KTransankcionaPoruka( string cSadrzajPoruke, KOpisTPoruke opisTP, KFormatPoruke& formatPoruke ){
auto_ptr<KPoruka> pPoruka( new KPoruka( cSadrzajPoruke, formatPoruke ) );
KopirajPoruku( pPoruka.get() );
opisTPoruke.komandaTP = opisTP.komandaTP;
opisTPoruke.duzinaTP = opisTP.duzinaTP;
opisTPoruke.kodirajSadrzaj = opisTP.kodirajSadrzaj;
}
// Konstruktor za formiranje transakcione poruke
KTransankcionaPoruka::KTransankcionaPoruka( string cSadrzajPoruke, KOpisTPoruke opisTP, IDFormataPoruke formatID ){
auto_ptr<KPoruka> pPoruka( new KPoruka( cSadrzajPoruke, formatID ) );
KopirajPoruku( pPoruka.get() );
opisTPoruke.komandaTP = opisTP.komandaTP;
opisTPoruke.duzinaTP = opisTP.duzinaTP;
opisTPoruke.kodirajSadrzaj = opisTP.kodirajSadrzaj;
}
// Konstruktor za formiranje 'prazne' poruke datog formata
KTransankcionaPoruka::KTransankcionaPoruka( KOpisTPoruke opisTP, IDFormataPoruke formatID ){
auto_ptr<KTransankcionaPoruka> pPoruka( new KTransankcionaPoruka( "", opisTP, formatID ) );
( *this ) = *pPoruka;
}
// Konstruktor za formiranje poruke koja treba da se salje : zadaje se samo sadrzaj poruke i format.
KTransankcionaPoruka::KTransankcionaPoruka( string cSadrzajPoruke, IDFormataPoruke formatID ){
auto_ptr<KTransankcionaPoruka> pPoruka( new KTransankcionaPoruka( cSadrzajPoruke,
KOpisTPoruke( KOMANDA_POSALJI, 0, false ),
formatID ) );
( *this ) = *pPoruka;
}
// Konstruktor za formiranje poruke koja treba da se primi : zadaje se samo ocekivana duzina i format.
KTransankcionaPoruka::KTransankcionaPoruka( unsigned int nDuzina, IDFormataPoruke formatID ){
auto_ptr<string> pSadrzaj( new string( "" ) );
auto_ptr<KTransankcionaPoruka> pPoruka( new KTransankcionaPoruka( *pSadrzaj,
KOpisTPoruke( KOMANDA_POSALJI, nDuzina, false ),
formatID ) );
( *this ) = *pPoruka;
}
// Default konstruktor
KTransankcionaPoruka::KTransankcionaPoruka( void ){
auto_ptr<KTransankcionaPoruka> pPoruka( new KTransankcionaPoruka( "" ) );
( *this ) = *pPoruka;
}
// Vraca 'true' ako poruka treba da se posalje na serijski port
bool KTransankcionaPoruka::PorukaZaSlanje( void ) const {
if ( toupper( opisTPoruke.komandaTP[0] )==KOMANDA_POSALJI[0] ) return true;
else return false;
};
// Vraca 'true' ako se ocekuje da poruka stigne sa serijskog porta
bool KTransankcionaPoruka::PrijemnaPoruka( void ) const {
char prvoSlovo = toupper( opisTPoruke.komandaTP[0] );
if ( prvoSlovo==KOMANDA_PRIMI[0] ) return true;
else return false;
};
// Postavlja poruku da bude za slanje
void KTransankcionaPoruka::PostaviZaSlanje( void ){
opisTPoruke.komandaTP = KOMANDA_POSALJI;
}
// Postavlja poruku da bude prijemna
void KTransankcionaPoruka::PostaviZaPrijem( void ){
opisTPoruke.komandaTP = KOMANDA_PRIMI;
}
// Vraca duzinu poruke koja treba da se primi sa serijskog porta.
// ( nije isto kao 'Duzina()' u osnovnoj klasi, jer poruka tek treba da se primi, pa 'Duzina()' moze da vrati 0 )
unsigned int KTransankcionaPoruka::DajDuzinuTP( void ) const {
return opisTPoruke.duzinaTP;
}
// Postavlja duzinu poruke koja se ocekuje sa serijskog porta.
unsigned int KTransankcionaPoruka::PostaviDuzinuTP( unsigned int duz ){
return ( opisTPoruke.duzinaTP = duz );
}
// Ispituje da li se kodira/dekodira sadrzaj poruke ( komponenta poruke KP_SADRZAJ )
bool KTransankcionaPoruka::SadrzajKodiran( void ){
return opisTPoruke.kodirajSadrzaj;
}
//******************************* TransankcionaPoruka << END >> *******************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -