\documentclass[12pt,a4paper,titlepage,oneside]{article} \usepackage[utf8]{inputenc} \usepackage{oop_prot} \usepackage{url} \usepackage{pdfpages} \usepackage{booktabs} \title{Beispiel 1} \author{Manuel Mausz, \matrnr 0728348\\ {\small manuel-tu@mausz.at} } \begin{document} % create titlepage \maketitle \tableofcontents \newpage %------------------------------------------------------------------ %------------------------------------------------------------------ \section{Aufgabenstellung - Beispiel 1} \includegraphics[width=\textwidth,page=1]{../angabe.pdf} \includegraphics[width=\textwidth,page=2]{../angabe.pdf} %------------------------------------------------------------------ %------------------------------------------------------------------ \section{Beispiel 1} \subsection{Design}\label{Design} Abbildung~\ref{fig:classdiagram1} zeigt das Klassendiagramm der Aufgabe. Die Klasse CScriptParser übernimmt das Parsen der per Commandlineparameter übergebenen Scriptdatei als String, wobei dieser bereits im Konstruktor übergeben werden muss. Zum Anstoßen des Parsen dient die Funktion parse(). Der (simple) Parser arbeitet Zeilenbasiert und erwartet pro Zeile einen Funktionsaufruf im Syntax: funktionsname(param1, ... paramX). Schachteln von Funktionen ist nicht erlaubt. Der erste Befehl eines Blocks muss der Befehl ``read'' sein, der Befehl ``write'' beendet einen Block. Alle Funktionsparameter werden zusammen in einer Liste gespeichert und den entsprechenden Funktionen übergeben. Whitespaces und Anführungszeichen werden bereits vorab gelöscht. Tritt ein Fehler während des Parsens auf, werden Instanzen der Klasse \mbox{CSriptError::ParserError} als Exception geworfen. Über die Methode \mbox{getLine()} der Exception kann die aktuelle Zeile der Scriptdatei, die den Fehler erzeugt hat, ausgelesen werden.\\ Da der Scriptbefehl ``read'' und ``write'' einen Dateitypparameter enthält, ist es potentiell möglich verschiedene Dateitypen zu öffnen und zu bearbeiten. Um dies aus der Sicht des Parsers generisch durchzuführen, müssen alle Klassen, die Dateioperationen durchführen können, von der Abstrakten Klasse \mbox{CFile} abgeleitet sein und somit mindestens dessen virtuelle Methoden implementieren. Alle Implementation müssen weiters im Konstruktor die unterstützten Dateitypen in die Membervariable m\_types hinzufügen, damit der Parser die jeweils zuständige Implementation verwenden kann. Die Methode \mbox{callFunc(...)} dient zum Aufruf von dateitypspezifische Scriptfunktionen. Hierzu übergibt der Parser automatisch alle unbekannten Funktionen und dessen Parameter innerhalb eines Block (abgesehen von ``read'' und ``write'') der jeweils zuständigen Instanz. Zur Fehlerbehandlung sollen Implementationen von CFile Instanzen der Klasse \mbox{CFile::FileError} als Exception werfen. Diese werden vom Parser gefangen und in Instanzen der eigenen Exception des Parsers \mbox{CSriptError::ParserError} übersetzt.\\ Die Klasse \mbox{CBitmap} implementiert die Abstrakte Klasse \mbox{CFile} und kann Dateien des Types ``BMP'' (Windows Bitmap) bearbeiten. Beim Lesen der Datei werden rudimentäre Checks des Dateiheaders durchgeführt. Der Speicher der Pixel, wird wie gewünscht dynamisch alloziert. Um aber die verschiedenen möglichen Farbtiefen von Windows Bitmap zu unterstützen, werden die Schreiboperationen auf die Pixeldaten an eine Instanz der je nach Farbtiefe zuständigen Implementation der Abstrakten Klasse \mbox{CPixelFormat} delegiert. Diese Instanz wird während der Analyse des Dateiheaders ebenfalls dynamisch allokiert.\\ Damit Implementationen der abstrakten Klasse \mbox{CPixelFormat} direkt auf die Daten des Windows Bitmap zugreifen können, wird im Konstruktor ein Pointer auf die Instanz von \mbox{CBitmap} übergeben. Über die Public Getter-Methoden von \mbox{CBitmap} erfolgt der direkt Zugriff. Fehlerbehandlung erfolgt Exceptions der Klasse \mbox{CPixelFormat::PixelFormatError}. %================================================================== \begin{figure}[htb] \begin{center} \epsfxsize=0.9\textwidth\epsfbox{ClassDiagram1.png} \end{center} \caption{Klassendiagramm 1} \label{fig:classdiagram1} \end{figure} %================================================================== \subsection{Verwaltung der Ressourcen} Alle Klassen, die im Laufe ihrer Existenz Ressourcen dynamische allozieren, initialisieren die jeweiligen Membervariablen im Konstruktor auf NULL und geben diese, sofern tatsächlich alloziert, im spätestens Destruktor wieder frei.\\ Alle Dateien, die geöffnet werden, werden nach dem Abfangen der Exception auch wieder geschlossen, sofern alle möglichen, auftretenden Exceptions (\mbox{std::bad\_alloc} ausgenommen) auch vorab übersetzt wurden. \subsection{Fehlerbehandlung} Alle Implementationen der abstrakten Klasse \mbox{CPixelFormat} werfen Exceptions der Klasse \mbox{CPixelFormat::PixelFormatError}. Diese werden von \mbox{CBitmap} gefangen und in Exceptions der Klasse \mbox{CFile::FileError} übersetzt, welche wiederum von der Klasse \mbox{CScriptParser} gefangen und in Exceptions der Klasse \mbox{CScriptParser::ParserError} übersetzt werden.\\ Diese Exceptions sowie Exceptions des Typs \mbox{std::exception} werden schlussendlich vom Hauptprogramm gefangen und geben eine entsprechende Fehlermeldung an den Benutzer auf stderr aus. \subsection{Implementierung} Siehe Punkt~\ref{Design} und Abbildung~\ref{fig:classdiagram1} sowie Punkt~\ref{Listings}. Alle Exceptions wurden von \mbox{std::invalid\_argument} abgeleitet und der Konstruktor gemäß den üblichen Konventionen implementiert: %================================================================== \begin{lstlisting}{} ParserError(const std::string& what) : std::invalid_argument(what) {} \end{lstlisting} %================================================================== %------------------------------------------------------------------ %------------------------------------------------------------------ \section{Projektverlauf} \subsection{Probleme und Fallstricke} In der Hoffnung das in der nächsten Aufgabe weitere Funktionen, Dateitypen und/oder Farbtiefen des Windows Bitmaps-Formats verlangt werden, wurden diese sehr generisch implementiert.\\ Ursprünglich wollte ich die jeweilig unterstützen Scriptfunktionen mittels \mbox{std::map} an den Scriptparser zurückgeben, sodass dieser direkt die jeweilige Methode (per Pointer) aufrufen kann. Dies funktioniert jedoch logischerweise nur bei statischen Methoden. Daher die einfacher Methode über die callFunc-Methoden, die die Parameter an die jeweiligen internen Methoden weiterdelegieren. Da sich \mbox{CBitmap} und \mbox{CPixelFormat} gegenseitig referenzieren, müssen die jeweiligen Klassen im Headerfile der anderen Klasse vorab deklariert werden. Andernfalls kann der Compiler die Klasse aufgrund der rekursiven Inklusion nicht finden. \subsection{Arbeitsaufwand} \begin{tabular}{ll} \toprule Entwicklungsschritt / Meilenstein & Arbeitsaufwand in Stunden\\ \midrule Erstes Design & 15 Minuten\\ \hline Implementierung (und leichte Anpassung des Designs) & 1 Tag\\ \hline Dokumentation (Doxygen) und Überprüfung alle\\ Anforderungen gemäß der Programmierrichtlinien & 2 Tage\\ \hline Erstellung des Protokolls & 1 Tag\\ \bottomrule \end{tabular} %------------------------------------------------------------------ %------------------------------------------------------------------ \section{Listings}\label{Listings} \subsection{imgsynth.cpp} \lstinputlisting{../imgsynth/imgsynth.cpp} \newpage \subsection{cscriptparser.h} \lstinputlisting{../imgsynth/cscriptparser.h} \newpage \subsection{cscriptparser.cpp} \lstinputlisting{../imgsynth/cscriptparser.cpp} \newpage \subsection{cfile.h} \lstinputlisting{../imgsynth/cfile.h} \newpage \subsection{cbitmap.h} \lstinputlisting{../imgsynth/cbitmap.h} \newpage \subsection{cbitmap.cpp} \lstinputlisting{../imgsynth/cbitmap.cpp} \newpage \subsection{cpixelformat.h} \lstinputlisting{../imgsynth/cpixelformat.h} \newpage \subsection{cpixelformat\_24.h} \lstinputlisting{../imgsynth/cpixelformat_24.h} \newpage \subsection{cpixelformat\_24.cpp} \lstinputlisting{../imgsynth/cpixelformat_24.cpp} \end{document}