Ορισμένες φορές χρειάζεται να ανακτήσουμε το σχεδιασμό ενός
συστήματος από την υλοποίησή του.
Η διαδιακασία αυτή καλείται
αντίστροφος σχεδιασμός (reverse engineering)
και απαιτείται όταν δεν υπάρχει ο αρχικός σχεδιασμός ή αυτός δεν
έχει συντηρηθεί κατά τη διάρκεια ζωής του έργου.
Για το παρακάτω σύνολο από αρχεία C++
που δηλώνουν αντίστοιχες κλάσεις
να σχεδιάσετε σε UML ένα διάγραμμα που να απεικονίζει την κάθε κλάση
και τη σχέση της με τις υπόλοιπες.
(Τα αρχεία αυτά υλοποιούν ένα σύστημα μετατροπής χαρακτήρων ανάμεσα σε διάφορα
πρότυπα κωδικοποίησης, μεταγραφής και μεταγραμματισμού.)
Προσοχή: για την διαδικασία του αντίστροφου σχεδιασμού δεν απατείται
η πλήρης κατανόηση του κώδικα.
filter.h
#ifndef FILTER_
#define FILTER_
class filter {
protected:
filter *input;
public:
virtual int getcharacter() = 0;
void setinput(filter *i) {input = i;};
};
#endif
htmll1.h
#ifndef HTMLL1_
#define HTMLL1_
#include "filter.h"
#include "queue.h"
class htmll1: public filter, public queue {
private:
void fillbuff(); // Fill the queue buffer
public:
int getcharacter() { return (queue::getcharacter()); };
};
#endif
lex.h
#ifndef LEX_
#define LEX_
#include "filter.h"
#include "queue.h"
class lex: public filter, public queue {
private:
void (*lexfun)(lex *lf);
void fillbuff() { lexfun(this); }; // Fill the queue buffer
public:
lex(void (*lf)(lex *l)) { lexfun = lf; };
inline int getinputcharacter() { return input->getcharacter(); };
int getcharacter() { return (queue::getcharacter()); };
};
#endif
map.h
#ifndef MAP_
#define MAP_
#include "filter.h"
class map: public filter {
private:
int mapsize; // Size of character map
int *charmap; // Map from source to target
char default_char; // Default map character
public:
map(char *source, char *target, char dflt);
int getcharacter();
};
#endif
queue.h
#ifndef QUEUE_
#define QUEUE_
#include "filter.h"
class queue {
private:
int *q; // Output queue
int qlen; // Characters in output queue
int qhead;
int qtail;
virtual void fillbuff() = 0; // Fill the queue buffer
public:
void nq(int c); // Add a character to the output queue
unsigned int getcharacter(); // Get a character from the output queue
queue(const int qlen = 100);
~queue() { delete[] q; };
};
#endif
stdinput.h
#ifndef STDINPUT_
#define STDINPUT_
#include "filter.h"
#include <iostream.h>
class stdinput: public filter {
public:
int getcharacter()
{
unsigned char c;
cin.read(&c, 1);
return (cin.eof() ? EOF : c);
};
};
#endif
translit.h
#ifndef TRANSLIT_
#define TRANSLIT_
#include "filter.h"
#include "queue.h"
class translit: public filter, public queue {
private:
void fillbuff(); // Fill the queue buffer
public:
int getcharacter() { return (queue::getcharacter()); };
};
#endif
ucs2i.h
#ifndef UCS2I_
#define UCS2I_
#include "filter.h"
class ucs2i: public filter {
public:
int getcharacter()
{
int c1, c2;
c1 = input->getcharacter();
c2 = input->getcharacter();
return ((c1 << 8) | c2);
}
};
#endif
ucs2o.h
#ifndef UCS2O_
#define UCS2O_
#include "filter.h"
#include "queue.h"
class ucs2o: public filter, public queue {
private:
void fillbuff() // Fill the queue buffer
{
unsigned int c;
c = input->getcharacter();
nq(c >> 8);
nq(c & 0xff);
}
public:
int getcharacter() { return (queue::getcharacter()); };
};
#endif
utf7.h
#ifndef UTF7_
#define UTF7_
// See RFC 1642
class utf7 {
protected:
static char base64[];
static short invbase64[128];
static char direct[];
static char optional[];
static char spaces[]; /* space, tab, return, line feed */
static char mustshiftsafe[128];
static char mustshiftopt[128];
static const int SHIFT_IN;
static const int SHIFT_OUT;
unsigned long BITbuffer;
unsigned long buffertemp;
int bufferbits;
inline void write_n_bits(int x, int n)
{
BITbuffer |= ((x & ~(-1L<<n)) << (32-n-bufferbits));
bufferbits += n;
}
inline int read_n_bits(int n)
{
buffertemp = (BITbuffer >> (32-n));
BITbuffer <<= n;
bufferbits -= n;
return (buffertemp);
}
public:
utf7();
};
#endif
utf7i.h
#ifndef UTF7I_
#define UTF7I_
#include "filter.h"
#include "queue.h"
#include "utf7.h"
// See RFC 1642
class utf7i: public filter, public queue, public utf7 {
private:
void fillbuff();
int shifted, first, wroteone;
public:
utf7i() { shifted = first = wroteone = 0; };
int getcharacter() { return (queue::getcharacter()); };
};
#endif
utf7o.h
#ifndef UTF7O_
#define UTF7O_
#include "filter.h"
#include "queue.h"
#include "utf7.h"
// See RFC 1642
class utf7o: public filter, public queue, public utf7 {
private:
char *mustshift;
int shifted, needshift, done;
void fillbuff();
public:
int getcharacter() { return (queue::getcharacter()); };
void optional(bool opt);
utf7o()
{
mustshift = mustshiftopt;
shifted = needshift = done = 0;
}
};
#endif
utf8i.h
#ifndef UTF8I_
#define UTF8I_
#include "filter.h"
class utf8i: public filter {
public:
int getcharacter()
{
int c1, c2, c3, c4;
int cout;
c1 = input->getcharacter();
if ((c1 & 0x80) == 0) {
cout = c1;
} else if ((c1 & 0xe0) == 0xc0) {
c2 = input->getcharacter();
cout = (c2 & 0x3f) | ((c1 & 0x1f) << 6);
} else if ((c1 & 0xf0) == 0xe0) {
c2 = input->getcharacter();
c3 = input->getcharacter();
cout = ((c1 & 0xf) << 12) |
((c2 & 0x3f) << 6) |
(c3 & 0x3f);
} else {
error("UTF-8 input: UCS characters above 0xffff are not supported\n");
}
return (cout);
}
};
#endif
utf8o.h
#ifndef UTF8O_
#define UTF8O_
#include "filter.h"
#include "queue.h"
class utf8o: public filter, public queue {
private:
void fillbuff() // Fill the queue buffer
{
unsigned int c;
c = input->getcharacter();
if (c < 0x80) {
nq(c);
} else if (c < 0x800) { // bbb bbbb bbbb
nq(0xC0 | c>>6); // 110b bbbb
nq(0x80 | c & 0x3F); // 10bb bbbb
} else if (c < 0x10000) { // bbbb bbbb bbbb bbbb
nq(0xE0 | c>>12); // 1110 bbbb
nq(0x80 | c>>6 & 0x3F); // 10bb bbbb
nq(0x80 | c & 0x3F); // 10bb bbbb
} else {
error("UCS characters above 0xffff are not supported\n");
}
}
public:
int getcharacter() { return (queue::getcharacter()); };
};
#endif