forked from BSB-WS23/mpstubs
Skeleton
This commit is contained in:
commit
5bfe56aafd
|
@ -0,0 +1,2 @@
|
||||||
|
.build*
|
||||||
|
.solution
|
|
@ -0,0 +1,32 @@
|
||||||
|
# This is a configuration file for GitLab Continuous Integration (CI).
|
||||||
|
#
|
||||||
|
# At each "push", GitLab will use this file (named '.gitlab-ci.yml') to start
|
||||||
|
# a docker container with the image of a Linux distribution (in this case
|
||||||
|
# Ubuntu Focal) with an already installed build tool chain and compile the
|
||||||
|
# source in the git repository.
|
||||||
|
# The status (indicated by the exit code of 'make') is clearly visible on the
|
||||||
|
# project page of your repository in GitLab:
|
||||||
|
# If a commit contains an invalid (untranslatable) state, an error (red 'x')
|
||||||
|
# is displayed and the author is notified by mail.
|
||||||
|
#
|
||||||
|
# Please note: This will only test the build of your operating system,
|
||||||
|
# but not the [correct] functionality!
|
||||||
|
#
|
||||||
|
#Further information: https://docs.gitlab.com/ee/ci/
|
||||||
|
|
||||||
|
GCC-Build:
|
||||||
|
image: inf4/stubs:gcc-x64
|
||||||
|
script:
|
||||||
|
- if [ -f Makefile ] ; then make clean ; make ; fi
|
||||||
|
|
||||||
|
# Optional: Use Clang 11
|
||||||
|
#Clang-Build:
|
||||||
|
# image: inf4/stubs:clang-x64
|
||||||
|
# script:
|
||||||
|
# - make clean ; make CXX=clang++-11
|
||||||
|
|
||||||
|
# Check style guide using cpplint
|
||||||
|
linter:
|
||||||
|
image: inf4/stubs:cpplint
|
||||||
|
script:
|
||||||
|
- if [ -f Makefile ] ; then make clean ; make lint ; fi
|
|
@ -0,0 +1,16 @@
|
||||||
|
# StuBS Coding Style Checker
|
||||||
|
#
|
||||||
|
# Wir orientieren uns grob an den Google C++ Style Guide ( http://google.github.io/styleguide/cppguide.html )
|
||||||
|
# mit primär folgenden Änderungen/Anpassungen:
|
||||||
|
#
|
||||||
|
# - Tabs statt Leerzeichen. Spart Bytes ;)
|
||||||
|
# - Zeilenlänge ist 120
|
||||||
|
# - Keine Angaben zum Copyright
|
||||||
|
# - Aufgrund des Aufgabenbuildsystems sind neue / leere Zeilen leider nicht immer vermeidbar
|
||||||
|
#
|
||||||
|
# Zum Prüfen empfiehlt sich beispielsweise das Pythonscript CPPLINT.py ( https://github.com/cpplint/cpplint )
|
||||||
|
# welches mit dieser Konfigurationsdatei arbeiten kann.
|
||||||
|
#
|
||||||
|
set noparent
|
||||||
|
filter=-whitespace/tab,-legal/copyright,-runtime/int,-runtime/threadsafe_fn,-readability/todo,-build/include_subdir,-runtime/references,-build/include_what_you_use,-whitespace/blank_line
|
||||||
|
linelength=120
|
|
@ -0,0 +1,10 @@
|
||||||
|
Copyright 1998-2002 Institut für Verteilte Systeme (IVS), Otto-von-Guericke-Universität Magdeburg
|
||||||
|
Copyright 2002-2022 Lehrstuhl für Informatik 4, Friedrich-Alexander-Universität Erlangen-Nürnberg
|
||||||
|
|
||||||
|
Diese Vorlage dient als Grundlage für Lehrveranstaltungen und darf nicht ohne vorherige, schriftliche Erlaubnis der Urheberrechtsinhaber veröffentlicht oder weitergegeben werden.
|
||||||
|
Es ist erlaubt und wünschenswert, diese Vorlage als Inspiration für eigene Projekte zu verwenden, es wird allerdings erbeten, dass die Vorgabe nicht mit deiner Lösung veröffentlicht wird.
|
||||||
|
Wir, als Lehrende, möchten alle teilnehmenden Studierenden dazu ermutigen eine eigene Lösung zu erstellen; eine veröffentlichte Lösung ist ein Anreiz zum Abschreiben, den wir gerne vermeiden möchten.
|
||||||
|
|
||||||
|
This skeleton is provided as a foundation for educational purposes and therefore MUST NOT BE DISTRIBUTED OR PUBLISHED without prior, written consent of the copyright holders.
|
||||||
|
You are free to use this skeleton as inspiration for your projects, but, please, do not publish it along with your solution.
|
||||||
|
We, as lecturers, want to encourage every participating student to write a solution themself; a public solution is an allurement to copying we want to avoid.
|
|
@ -0,0 +1,42 @@
|
||||||
|
MPStuBS - Multiprozessor Studenten Betriebssystem
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
Coding Guidelines
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Similar to [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) but with following exceptions:
|
||||||
|
- No license boilerplate
|
||||||
|
- *Tabs* instead of *Spaces*
|
||||||
|
- Line length of 120 characters
|
||||||
|
- `#pragma once` instead of `#include` guards
|
||||||
|
|
||||||
|
The code should be *self-documenting*, don't state the obvious!
|
||||||
|
However, this does not make comments superfluous:
|
||||||
|
Since good naming is sometimes not enough, more advanced parts need to be documented,
|
||||||
|
so any operating system developer should be able to easily understand your code.
|
||||||
|
|
||||||
|
### Naming Convention
|
||||||
|
|
||||||
|
- **Variables**: lowercase with underscore
|
||||||
|
|
||||||
|
char* variable_name;
|
||||||
|
|
||||||
|
- **Constants** (and **enum** values): uppercase with underscore
|
||||||
|
|
||||||
|
const int CONST_VALUE = 42;
|
||||||
|
|
||||||
|
- **Type Names** (`class`/`struct`/`namespace`/`enum`): Capital letter, camel case
|
||||||
|
|
||||||
|
class SomeClassName;
|
||||||
|
|
||||||
|
- **Methods/Functions** (C++): start with lowercase letter, then camel case
|
||||||
|
|
||||||
|
void someFunctionName();
|
||||||
|
|
||||||
|
- **extern "C" Functions**: lowercase with underscore (like variables).
|
||||||
|
|
||||||
|
void interrupt_handler(int vector);
|
||||||
|
|
||||||
|
- **File Names**: lowercase, main type name, underscores only if is a sub type
|
||||||
|
|
||||||
|
folder/classname.cc
|
|
@ -0,0 +1 @@
|
||||||
|
#include "outputstream.h"
|
|
@ -0,0 +1,237 @@
|
||||||
|
/*! \file
|
||||||
|
* \brief This file contains the \ref OutputStream
|
||||||
|
*
|
||||||
|
* Along with the class OutputStream itself, this file contains definitions for the
|
||||||
|
* manipulators \ref hex, \ref dec, \ref oct, and \ref bin, which are used for
|
||||||
|
* changing the radix, and \ref endl for signaling the end of the current line.
|
||||||
|
* \ingroup io
|
||||||
|
*
|
||||||
|
* \par Manipulators
|
||||||
|
* To simplify formatting text and numbers using the class OutputStream, we define
|
||||||
|
* so-called manipulators.
|
||||||
|
* For example, the expression
|
||||||
|
* <tt>kout << "a = " << dec << a << " is hexadecimal " << hex << a << endl;</tt>
|
||||||
|
* should, at first, print the value stored in decimal and then in hexadecimal
|
||||||
|
* form, followed by a line break.
|
||||||
|
* The intended properties can be realized by implementing \ref hex, \ref dec, \ref oct, \ref bin,
|
||||||
|
* and \ref endl as functions (i.e., they are, in particular, not methods of \ref OutputStream)
|
||||||
|
* that take (as first parameter) and return a reference to an OutputStream object.
|
||||||
|
* When compiling the expression show above, the method
|
||||||
|
* <tt>OutputStream& OutputStream::operator<< ((*f*) (OutputStream&))</tt>
|
||||||
|
* is chosen when one of the functions \ref hex, \ref dec, \ref oct, \ref bin, or \ref endl
|
||||||
|
* is streamed an \ref OutputStream, which finally will execute the passed function.
|
||||||
|
*
|
||||||
|
* \note The term manipulator originates from the book
|
||||||
|
* [The C++ Programming Language](http://www.stroustrup.com/4th.html)
|
||||||
|
* by Bjarne Stroustrup. Refer to this book for further explanations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stringbuffer.h"
|
||||||
|
|
||||||
|
/*! \brief The class OutputStream corresponds, essentially, to the class ostream
|
||||||
|
* from the C++ IO-Stream library.
|
||||||
|
*
|
||||||
|
* As relying on the method \ref Stringbuffer::put() is quite cumbersome when
|
||||||
|
* not only printing single characters, but numbers and whole strings, the
|
||||||
|
* class OutputStream provides a convenient way of composing output of variables of
|
||||||
|
* varying data types.
|
||||||
|
* Therefore, OutputStream implements shift operators `operator<<`` for various
|
||||||
|
* data types (similar to those known from the C++ IO-Stream library)
|
||||||
|
*
|
||||||
|
* For further convenience, OutputStream also allows printing integral numbers in
|
||||||
|
* decimal, binary, octal, and hexadecimal format.
|
||||||
|
* Remember that, for negative numbers, the sign is only printed when using the
|
||||||
|
* decimal number system; for binary, octal, and hex, the number is printed as
|
||||||
|
* stored in the machine word without interpreting the sign.
|
||||||
|
* For Intel CPUs, two's complement is used for storing negative values, `-1`,
|
||||||
|
* for example, will print hex `FFFFFFFF` and octal `37777777777`.
|
||||||
|
*
|
||||||
|
* OutputStream's public methods/operators all return a reference to the object
|
||||||
|
* they are called on (i.e. `*this`). Returning `*this` allows chaining those
|
||||||
|
* stream operators in a single expression, such as
|
||||||
|
* <tt>kout << "a = " << a</tt>;
|
||||||
|
*
|
||||||
|
* At this point in time, OutputStream implements `operator<<` for chars, strings
|
||||||
|
* and whole numbers. An additional `operator<<` allows using manipulators
|
||||||
|
* whose detailed description is given below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class OutputStream {
|
||||||
|
OutputStream(const OutputStream&) = delete;
|
||||||
|
OutputStream& operator=(const OutputStream&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*! \brief Number system used for printing integral numbers (one of 2,
|
||||||
|
* 8, 10, or 16)
|
||||||
|
*/
|
||||||
|
int base;
|
||||||
|
|
||||||
|
/*! \brief Default constructor. Initial number system is decimal.
|
||||||
|
*
|
||||||
|
* \todo Implement Constructor
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
OutputStream() {}
|
||||||
|
|
||||||
|
/*! \brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~OutputStream() {}
|
||||||
|
|
||||||
|
/*! \brief Clears the buffer.
|
||||||
|
*
|
||||||
|
* Pure virtual method that must be implemented by derived
|
||||||
|
* (non-abstract) classes.
|
||||||
|
* Formatting of the buffer contents can be implemented differently by
|
||||||
|
* different derived classes
|
||||||
|
*/
|
||||||
|
virtual void flush() = 0;
|
||||||
|
|
||||||
|
/*! \brief Print a single character
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param c Character to be printed
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (char c);
|
||||||
|
|
||||||
|
/*! \brief Print a single character
|
||||||
|
* \note In C, there are no "characters" in that sense, but only
|
||||||
|
* integers. A `char`, therefore, is a 8 bit number with the most
|
||||||
|
* significant bit (optionally) representing a sign.
|
||||||
|
* Depending on whether signed or not, the value ranges are [-128, 127]
|
||||||
|
* or [0; 255]. For GCC, a `char` is a `signed char`.
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param c Character to be printed
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (unsigned char c);
|
||||||
|
|
||||||
|
/*! \brief Printing a null-terminated string
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param string String to be printed
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (const char* string);
|
||||||
|
|
||||||
|
/*! \brief Print a boolean value
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param b Boolean to be printed
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (bool b);
|
||||||
|
|
||||||
|
/*! \brief Print an integral number in radix `base`
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param ival Number to be printed
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (short ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (unsigned short ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (int ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (unsigned int ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (long ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (unsigned long ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (long long ival);
|
||||||
|
|
||||||
|
/// \copydoc OutputStream::operator<<(short)
|
||||||
|
OutputStream& operator << (unsigned long long ival);
|
||||||
|
|
||||||
|
/*! \brief Print a pointer as hexadecimal number
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param ptr Pointer to be printed
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (const void* ptr);
|
||||||
|
|
||||||
|
/*! \brief Calls one of the manipulator functions.
|
||||||
|
*
|
||||||
|
* Method that calls the manipulator functions defined below, which
|
||||||
|
* allow modifying the stream's behavior by, for instance, changing the
|
||||||
|
* number system.
|
||||||
|
*
|
||||||
|
* \todo Implement Operator
|
||||||
|
*
|
||||||
|
* \param f Manipulator function to be called
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& operator << (OutputStream& (*f) (OutputStream&));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief Enforces a buffer flush.
|
||||||
|
*
|
||||||
|
* \todo Implement Manipulator
|
||||||
|
*
|
||||||
|
* \param os Reference to stream to be flushed.
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& flush(OutputStream& os);
|
||||||
|
|
||||||
|
/*! \brief Prints a newline character to the stream and issues a buffer flush.
|
||||||
|
*
|
||||||
|
* \todo Implement Manipulator
|
||||||
|
*
|
||||||
|
* \param os Reference to stream to be modified.
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& endl(OutputStream& os);
|
||||||
|
|
||||||
|
/*! \brief Print subsequent numbers in binary form.
|
||||||
|
*
|
||||||
|
* \todo Implement Manipulator
|
||||||
|
*
|
||||||
|
* \param os Reference to stream to be modified.
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& bin(OutputStream& os);
|
||||||
|
|
||||||
|
/*! \brief Print subsequent numbers in octal form.
|
||||||
|
*
|
||||||
|
* \todo Implement Manipulator
|
||||||
|
*
|
||||||
|
* \param os Reference to stream to be modified.
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& oct(OutputStream& os);
|
||||||
|
|
||||||
|
/*! \brief Print subsequent numbers in decimal form.
|
||||||
|
*
|
||||||
|
* \todo Implement Manipulator
|
||||||
|
*
|
||||||
|
* \param os Reference to stream to be modified.
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& dec(OutputStream& os);
|
||||||
|
|
||||||
|
/*! \brief Print subsequent numbers in hex form.
|
||||||
|
*
|
||||||
|
* \todo Implement Manipulator
|
||||||
|
*
|
||||||
|
* \param os Reference to stream to be modified.
|
||||||
|
* \return Reference to OutputStream os; allows operator chaining.
|
||||||
|
*/
|
||||||
|
OutputStream& hex(OutputStream& os);
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "stringbuffer.h"
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*! \file
|
||||||
|
* \brief \ref Stringbuffer composes single characters into a buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*! \brief The class Stringbuffer composes single characters into a longer text that can be processed on block.
|
||||||
|
*
|
||||||
|
* To make Stringbuffer as versatile as possible, the class does make
|
||||||
|
* assumptions about neither the underlying hardware, nor the meaning of
|
||||||
|
* "processing". When flush() is called (i.e., either on explicit request or
|
||||||
|
* once the buffer is full). To be hardware independent, flush() is to be
|
||||||
|
* implemented by the derived classes.
|
||||||
|
*
|
||||||
|
* \par Hints for Implementation
|
||||||
|
* Use a buffer of fixed size for caching characters, which should be
|
||||||
|
* accessible by derived classes.
|
||||||
|
* Keep in mind that the derived implementation of flush() will need to know
|
||||||
|
* about numbers of characters in the buffer.
|
||||||
|
*
|
||||||
|
* \par Notes
|
||||||
|
* Reason for the existence of this class is that generating longer texts is
|
||||||
|
* often implemented by assembly of small fragments (such as single characters
|
||||||
|
* or numbers).
|
||||||
|
* However, writing such small fragments directly to (for example) screen is
|
||||||
|
* quite inefficient (e.g., due to the use of IO ports, syscalls, or locks) and
|
||||||
|
* can be improved drastically by delaying the output step until the assembly
|
||||||
|
* is finished (or the buffer runs full).
|
||||||
|
*/
|
||||||
|
class Stringbuffer {
|
||||||
|
// Prevent copies and assignments
|
||||||
|
Stringbuffer(const Stringbuffer&) = delete;
|
||||||
|
Stringbuffer& operator=(const Stringbuffer&) = delete;
|
||||||
|
|
||||||
|
// All variables and methods are protected in this class,
|
||||||
|
// as the derived classes need direct access to be buffer,
|
||||||
|
// the constructor, the destructor, and the method put.
|
||||||
|
// flush() is to be implemented either way and may be redefined
|
||||||
|
// as public.
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// buffer containing characters that will be printed upon flush()
|
||||||
|
char buffer[80];
|
||||||
|
/// current position in the buffer
|
||||||
|
long unsigned pos;
|
||||||
|
|
||||||
|
/*! \brief Constructor; Marks the buffer as empty
|
||||||
|
*
|
||||||
|
* \todo Complete Constructor
|
||||||
|
*/
|
||||||
|
Stringbuffer() { }
|
||||||
|
|
||||||
|
/*! \brief Inserts a character into the buffer.
|
||||||
|
*
|
||||||
|
* Once the buffer is full, a call to flush() will be issued and
|
||||||
|
* thereby clearing the buffer.
|
||||||
|
*
|
||||||
|
* \todo Implement Method
|
||||||
|
*
|
||||||
|
* \param c Char to be added
|
||||||
|
*/
|
||||||
|
void put(char c);
|
||||||
|
|
||||||
|
/*! \brief Flush the buffer contents
|
||||||
|
*
|
||||||
|
* This method is to be defined in derived classes, as only those know
|
||||||
|
* how to print characters.
|
||||||
|
* flush() is required to reset the position pos.
|
||||||
|
*/
|
||||||
|
virtual void flush() = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*! \brief Destructor (nothing to do here)
|
||||||
|
*/
|
||||||
|
virtual ~Stringbuffer() { }
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
VERBOSE = @
|
||||||
|
OBJDIR = build
|
||||||
|
CXX = g++
|
||||||
|
MKDIR = mkdir
|
||||||
|
CC_SOURCES = ../test-stream/console_out.cc ../test-stream/test.cc ../test-stream/file_out.cc ../object/outputstream.cc ../object/stringbuffer.cc
|
||||||
|
CXXFLAGS = -std=c++11 -m64 -I../object -I.
|
||||||
|
TARGET = $(OBJDIR)/test
|
||||||
|
|
||||||
|
all: run
|
||||||
|
|
||||||
|
run: $(TARGET)
|
||||||
|
@./$<
|
||||||
|
|
||||||
|
$(TARGET): $(CC_SOURCES)
|
||||||
|
$(VERBOSE) $(MKDIR) -p $(OBJDIR)
|
||||||
|
$(VERBOSE) $(CXX) -o $@ $(CXXFLAGS) $^
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "RM $(OBJDIR)"
|
||||||
|
$(VERBOSE) rm -rf $(OBJDIR)
|
||||||
|
|
||||||
|
.PHONY: all run clean
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "console_out.h"
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*! \file
|
||||||
|
* \brief \ref ConsoleOut "Console" \ref OutputStream "output" (for the voluntary C++ exercise only)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "outputstream.h"
|
||||||
|
|
||||||
|
/*! \brief Write text on console (`STDOUT`)
|
||||||
|
*
|
||||||
|
* This class allows writing to the console similar to `std::cout` from the standard C++ library.
|
||||||
|
* The class is derived from \ref OutputStream.
|
||||||
|
*/
|
||||||
|
class ConsoleOut : public OutputStream {
|
||||||
|
// Prevent copies and assignments
|
||||||
|
ConsoleOut(const ConsoleOut&) = delete;
|
||||||
|
ConsoleOut& operator=(const ConsoleOut&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*! \brief Constructor
|
||||||
|
*
|
||||||
|
* \todo Implement constructor
|
||||||
|
*/
|
||||||
|
ConsoleOut();
|
||||||
|
|
||||||
|
/*! \brief Output the string on the screen.
|
||||||
|
*
|
||||||
|
* The implementation should solely use `putchar()`
|
||||||
|
*
|
||||||
|
* \todo Implement virtual method
|
||||||
|
*/
|
||||||
|
virtual void flush() override; //NOLINT
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "file_out.h"
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*! \file
|
||||||
|
* \brief \ref FileOut "File" \ref OutputStream "output" (for the voluntary C++ exercise only)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "outputstream.h"
|
||||||
|
|
||||||
|
/*! \brief Write text into file
|
||||||
|
*
|
||||||
|
* This class allows a comfortable output to a file only by using the elementary
|
||||||
|
* system calls `open()` / `write()` / `close()` and (optional) `fsync()`.
|
||||||
|
* The class is derived from \ref OutputStream.
|
||||||
|
*/
|
||||||
|
class FileOut : public OutputStream {
|
||||||
|
// TODO: Add (private) attributes, if required
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*! \brief Constructor
|
||||||
|
*
|
||||||
|
* Opens the file for writing using the system call `open()`.
|
||||||
|
* \param path Path to the output file
|
||||||
|
*
|
||||||
|
* \todo Implement constructor
|
||||||
|
*/
|
||||||
|
explicit FileOut(const char * path);
|
||||||
|
|
||||||
|
/*! \brief Destructor
|
||||||
|
*
|
||||||
|
* Close the output file (using the system call `close()`)
|
||||||
|
*
|
||||||
|
* \todo Implement destructor
|
||||||
|
*/
|
||||||
|
virtual ~FileOut();
|
||||||
|
|
||||||
|
/*! \brief Get path of the output file
|
||||||
|
*
|
||||||
|
* \return Path to output file (as defined in constructor)
|
||||||
|
*
|
||||||
|
* \todo Implement Method
|
||||||
|
*/
|
||||||
|
const char * getPath();
|
||||||
|
|
||||||
|
/*! \brief Number of output files which are currently opened (with this class)
|
||||||
|
*
|
||||||
|
* \return Number of active files
|
||||||
|
*
|
||||||
|
* \todo Implement Method
|
||||||
|
*/
|
||||||
|
static int count();
|
||||||
|
|
||||||
|
/*! \brief Write the string to the open file.
|
||||||
|
*
|
||||||
|
* The implementation should only use the system calls `write()` and `fsync()`.
|
||||||
|
*
|
||||||
|
* \todo Implement virtual Method
|
||||||
|
*/
|
||||||
|
virtual void flush() override; //NOLINT
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "console_out.h"
|
||||||
|
#include "file_out.h"
|
||||||
|
|
||||||
|
ConsoleOut cout;
|
||||||
|
FileOut foo("foo.txt");
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
cout << "Console Test <stream result> -> <expected>" << endl;
|
||||||
|
cout << " bool: " << true << " -> true" << endl;
|
||||||
|
cout << " zero: " << 0 << " -> 0" << endl;
|
||||||
|
cout << " binary: " << bin << 42 << dec << " -> 0b101010" << endl;
|
||||||
|
cout << " octal: " << oct << 42 << dec << " -> 052" << endl;
|
||||||
|
cout << " hex: " << hex << 42 << dec << " -> 0x2a" << endl;
|
||||||
|
cout << " uint64_t max: " << ~((unsigned long long)0) << " -> 18446744073709551615" << endl;
|
||||||
|
cout << " int64_t max: " << ~(1ll<<63) << " -> 9223372036854775807" << endl;
|
||||||
|
cout << " int64_t min: " << (1ll<<63) << " -> -9223372036854775808" << endl;
|
||||||
|
cout << " some int64_t: " << (-1234567890123456789) << " -> -1234567890123456789" << endl;
|
||||||
|
cout << " some int64_t: " << (1234567890123456789) << " -> 1234567890123456789" << endl;
|
||||||
|
cout << " pointer: " << reinterpret_cast<void*>(1994473406541717165ull) << " -> 0x1badcafefee1dead" << endl;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
cout << "File Test" << endl
|
||||||
|
<< " currently open: " << FileOut::count() << endl
|
||||||
|
<< " writing into '" << foo.getPath() << "'..." << endl;
|
||||||
|
foo << "C makes it easy to shoot yourself in the foot;" << endl;
|
||||||
|
foo << "C++ makes it harder, but when you do it blows your whole leg off." << endl;
|
||||||
|
{
|
||||||
|
FileOut bar("bar.txt");
|
||||||
|
cout << " opened the " << FileOut::count() << ". file, " << endl;
|
||||||
|
cout << " writing into '" << bar.getPath() << "'..." << endl;
|
||||||
|
bar << "Anyone who claims to have the perfect programming language is either a fool or a salesman or both" << endl;
|
||||||
|
}
|
||||||
|
cout << " having only " << FileOut::count() << " file opened since the other is out of scope" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue