27.11.2012 Views

Working with the various stream classes in POCO. - POCO C++ ...

Working with the various stream classes in POCO. - POCO C++ ...

Working with the various stream classes in POCO. - POCO C++ ...

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Streams<br />

<strong>Work<strong>in</strong>g</strong> <strong>with</strong> <strong>the</strong> <strong>various</strong> <strong>stream</strong> <strong>classes</strong> <strong>in</strong> <strong>POCO</strong>.


Overview<br />

> Encod<strong>in</strong>g and Decod<strong>in</strong>g (Base64, HexB<strong>in</strong>ary)<br />

> Data Compression <strong>with</strong> zlib<br />

> B<strong>in</strong>ary I/O<br />

> Utility Streams<br />

(Count<strong>in</strong>gStream, L<strong>in</strong>eEnd<strong>in</strong>gConverter, TeeStream, NullStream)<br />

> FileStream<br />

> Creat<strong>in</strong>g Your Own Streams


The <strong>POCO</strong> Stream Classes<br />

> <strong>POCO</strong> provides a variety of <strong>stream</strong> <strong>classes</strong>, compatible <strong>with</strong><br />

standard <strong>C++</strong> IOStreams.<br />

> Most <strong>POCO</strong> <strong>stream</strong> <strong>classes</strong> are implemented as filters, which<br />

means that <strong>the</strong>y do not write to or read from a device, but ra<strong>the</strong>r<br />

from ano<strong>the</strong>r <strong>stream</strong> <strong>the</strong>y are connected to.<br />

> A few utility <strong>classes</strong> <strong>in</strong> <strong>POCO</strong> make it easy for you to create your<br />

own <strong>stream</strong> buffer and <strong>stream</strong> <strong>classes</strong>.


Encod<strong>in</strong>g and Decod<strong>in</strong>g<br />

> <strong>POCO</strong> provides filter <strong>stream</strong> <strong>classes</strong> for encod<strong>in</strong>g and decod<strong>in</strong>g<br />

data <strong>in</strong> Base64 and HexB<strong>in</strong>ary format.<br />

> Both Base64 and HexB<strong>in</strong>ary can be used to encode arbitrary<br />

b<strong>in</strong>ary data us<strong>in</strong>g only pr<strong>in</strong>table ASCII characters.<br />

> Base64 uses digits, upper and lowercase characters, as well as '+'<br />

and '-' to encode groups of 6 bits. The encoded data takes by a<br />

factor 1.33 as much space as <strong>the</strong> orig<strong>in</strong>al data.<br />

> HexB<strong>in</strong>ary uses digits and <strong>the</strong> characters 'A' to 'F' to encode<br />

groups of 4 bit. The encoded data takes twice <strong>the</strong> space.<br />

> See RFC 4648 for details.


Encod<strong>in</strong>g and Decod<strong>in</strong>g (cont'd)<br />

> Poco::Base64Encoder #<strong>in</strong>clude "Poco/Base64Encoder.h"<br />

Poco::HexB<strong>in</strong>aryEncoder #<strong>in</strong>clude "Poco/HexB<strong>in</strong>aryEncoder.h"<br />

are output <strong>stream</strong>s that must be constructed <strong>with</strong> ano<strong>the</strong>r<br />

output <strong>stream</strong>, where Base64/HexB<strong>in</strong>ary-encoded data is<br />

written to.<br />

> Poco::Base64Decoder #<strong>in</strong>clude "Poco/Base64Decoder.h"<br />

Poco::HexB<strong>in</strong>aryDecoder #<strong>in</strong>clude "Poco/HexB<strong>in</strong>aryDecoder.h"<br />

are <strong>in</strong>put <strong>stream</strong>s that must be constructed <strong>with</strong> ano<strong>the</strong>r <strong>in</strong>put<br />

<strong>stream</strong>, where Base64/HexB<strong>in</strong>ary-encoded data is read from.


#<strong>in</strong>clude "Poco/Base64Encoder.h"<br />

#<strong>in</strong>clude <br />

us<strong>in</strong>g Poco::Base64Encoder;<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char** argv)<br />

{<br />

Base64Encoder encoder(std::cout);<br />

}<br />

encoder


ZLib Compression<br />

> <strong>POCO</strong> provides filter <strong>stream</strong> wrappers for zlib, support<strong>in</strong>g<br />

"deflate" and "gzip" style compression.<br />

> Input and output <strong>stream</strong>s are provided for compression<br />

(deflat<strong>in</strong>g) and expansion (<strong>in</strong>flat<strong>in</strong>g).<br />

> Four <strong>stream</strong> <strong>classes</strong> (two <strong>in</strong>put <strong>stream</strong>s and two output <strong>stream</strong>s)<br />

are available.


ZLib Stream Classes<br />

raw<br />

data<br />

Deflat<strong>in</strong>gOutputStream o<strong>stream</strong><br />

i<strong>stream</strong><br />

Deflat<strong>in</strong>gInputStream<br />

Inflat<strong>in</strong>gInputStream i<strong>stream</strong><br />

o<strong>stream</strong> Inflat<strong>in</strong>gOutputStream<br />

compressed<br />

data


ZLib Stream Classes (cont'd)<br />

> Deflat<strong>in</strong>g Streams<br />

> #<strong>in</strong>clude "Poco/Deflat<strong>in</strong>gStream.h"<br />

> Poco::Deflat<strong>in</strong>gInputStream<br />

> Poco::Deflat<strong>in</strong>gOutputStream<br />

> Inflat<strong>in</strong>g Streams<br />

> #<strong>in</strong>clude "Poco/Inflat<strong>in</strong>gStream.h"<br />

> Poco::Inflat<strong>in</strong>gInputStream<br />

> Poco::Inflat<strong>in</strong>gOutputStream


ZLib Stream Classes (cont'd)<br />

> Poco::Deflat<strong>in</strong>gInputStream<br />

Poco::Deflat<strong>in</strong>gOutputStream<br />

is constructed <strong>with</strong> ano<strong>the</strong>r <strong>in</strong>put/output <strong>stream</strong> and an optional<br />

argument specify<strong>in</strong>g <strong>the</strong> compression type:<br />

Poco::Deflat<strong>in</strong>gStreamBuf::STREAM_ZLIB (deflate/zlib type)<br />

Poco::Deflat<strong>in</strong>gStreamBuf::STREAM_GZIP (gzip type)<br />

> Poco::Inflat<strong>in</strong>gInputStream<br />

Poco::Inflat<strong>in</strong>gOutputStream<br />

is constructed <strong>with</strong> ano<strong>the</strong>r <strong>in</strong>put/output <strong>stream</strong> and an optional<br />

argument specify<strong>in</strong>g <strong>the</strong> compression type:<br />

Poco::Inflat<strong>in</strong>gStreamBuf::STREAM_ZLIB (deflate/zlib type)<br />

Poco::Inflat<strong>in</strong>gStreamBuf::STREAM_GZIP (gzip type)


#<strong>in</strong>clude "Poco/Deflat<strong>in</strong>gStream.h"<br />

#<strong>in</strong>clude <br />

us<strong>in</strong>g Poco::Deflat<strong>in</strong>gOutputStream;<br />

us<strong>in</strong>g Poco::Deflat<strong>in</strong>gStreamBuf;<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char** argv)<br />

{<br />

std::of<strong>stream</strong> ostr("test.gz", std::ios::b<strong>in</strong>ary);<br />

Deflat<strong>in</strong>gOutputStream deflater(ostr, Deflat<strong>in</strong>gStreamBuf::STREAM_GZIP);<br />

}<br />

deflater


Count<strong>in</strong>g Streams<br />

> Poco::Count<strong>in</strong>gInputStream and Poco::Count<strong>in</strong>gOutputStream<br />

count <strong>the</strong> number of characters and l<strong>in</strong>es <strong>in</strong> a file. They also keep<br />

track of <strong>the</strong> current l<strong>in</strong>e number and column position.<br />

> #<strong>in</strong>clude "Poco/Count<strong>in</strong>gStream.h"


L<strong>in</strong>e End<strong>in</strong>g Conversion<br />

> Poco::InputL<strong>in</strong>eEnd<strong>in</strong>gConverter and<br />

Poco::OutputL<strong>in</strong>eEnd<strong>in</strong>gConverter converts l<strong>in</strong>e end<strong>in</strong>gs <strong>in</strong> text<br />

files between Unix (LF), DOS/W<strong>in</strong>dows (CRLF) and Mac<strong>in</strong>tosh (CR)<br />

format.<br />

> #<strong>in</strong>clude "Poco/L<strong>in</strong>eEnd<strong>in</strong>gConverter.h"<br />

> Poco::L<strong>in</strong>eEnd<strong>in</strong>g def<strong>in</strong>es l<strong>in</strong>e end<strong>in</strong>g formats:<br />

NEWLINE_DEFAULT (<strong>the</strong> default for <strong>the</strong> current platform)<br />

NEWLINE_CR (Mac<strong>in</strong>tosh l<strong>in</strong>e end<strong>in</strong>gs)<br />

NEWLINE_CRLF (DOS/W<strong>in</strong>dows l<strong>in</strong>e end<strong>in</strong>gs)<br />

NEWLINE_LF (Unix l<strong>in</strong>e end<strong>in</strong>gs)


Splitt<strong>in</strong>g Streams<br />

> Poco::TeeInputStream and Poco::TeeOutputStream copy all<br />

characters go<strong>in</strong>g through <strong>the</strong>m (read or written) to one or more<br />

output <strong>stream</strong>s.<br />

> #<strong>in</strong>clude "Poco/TeeStream.h"<br />

> These <strong>stream</strong>s are quite useful for debugg<strong>in</strong>g purposes.<br />

> void addStream(std::o<strong>stream</strong>& ostr)<br />

adds an output <strong>stream</strong> to a Poco::TeeInputStream or<br />

Poco::TeeOutputStream.


#<strong>in</strong>clude "Poco/TeeStream.h"<br />

#<strong>in</strong>clude <br />

#<strong>in</strong>clude <br />

us<strong>in</strong>g Poco::TeeOutputStream;<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char** argv)<br />

{<br />

TeeOutputStream tee(std::cout);<br />

}<br />

std::of<strong>stream</strong> fstr("output.txt");<br />

tee.addStream(fstr);<br />

tee


The Null Stream<br />

> Poco::NullOutputStream discards all data written to it.<br />

> Poco::NullInputStream signals end-of-file for every read<br />

operation.<br />

> #<strong>in</strong>clude "Poco/NullStream.h"


Writ<strong>in</strong>g and Read<strong>in</strong>g B<strong>in</strong>ary Data<br />

> Poco::B<strong>in</strong>aryWriter is used to write <strong>the</strong> value of basic types <strong>in</strong><br />

b<strong>in</strong>ary form to an output <strong>stream</strong>, us<strong>in</strong>g a <strong>stream</strong>-like <strong>in</strong>terface.<br />

> #<strong>in</strong>clude "Poco/B<strong>in</strong>aryWriter.h"<br />

> Poco::B<strong>in</strong>aryReader is used to read basic types <strong>in</strong> b<strong>in</strong>ary form<br />

(produced by a Poco::B<strong>in</strong>aryWriter) from an <strong>in</strong>put <strong>stream</strong>.<br />

> #<strong>in</strong>clude "Poco/B<strong>in</strong>aryReader.h"<br />

> Both support big endian and little endian byte order for writ<strong>in</strong>g<br />

and read<strong>in</strong>g, as well as automatic byte order conversions.<br />

> These <strong>classes</strong> are useful for exchang<strong>in</strong>g b<strong>in</strong>ary data between<br />

systems <strong>with</strong> a different architecture.


The B<strong>in</strong>aryWriter Class<br />

> Poco::B<strong>in</strong>aryWriter supports <strong>stream</strong> <strong>in</strong>sertion operators ( The value is written out seven bits at a time, start<strong>in</strong>g <strong>with</strong> <strong>the</strong><br />

seven least significant bits.<br />

> The most significant bit of a byte <strong>in</strong>dicates whe<strong>the</strong>r <strong>the</strong>re are<br />

more bytes com<strong>in</strong>g.<br />

> A value that fits <strong>in</strong>to seven bits takes one storage byte.<br />

> For a 32-bit value, at most five bytes are used.


The B<strong>in</strong>aryWriter Class (cont'd)<br />

> void write7BitEncoded(UInt32 value)<br />

void write7BitEncoded(UInt64 value)<br />

writes an unsigned <strong>in</strong>teger <strong>in</strong> <strong>the</strong> compact 7 bit encoded format<br />

to <strong>the</strong> underly<strong>in</strong>g output <strong>stream</strong><br />

> void writeRaw(const std::str<strong>in</strong>g& rawData)<br />

writes rawData as is to <strong>the</strong> underly<strong>in</strong>g <strong>stream</strong><br />

> void writeBOM()<br />

writes a byte order mark (<strong>the</strong> 16 bit value 0xFEFF <strong>in</strong> host byte<br />

order) to <strong>the</strong> <strong>stream</strong>. A B<strong>in</strong>aryReader uses <strong>the</strong> BOM to<br />

automatically enable byte order conversion, if required.


B<strong>in</strong>aryWriter and Byte Order<br />

> A B<strong>in</strong>aryWriter is constructed <strong>with</strong> an output <strong>stream</strong>, and an<br />

optional byte order argument.<br />

> The byte order can be one of <strong>the</strong> follow<strong>in</strong>g:<br />

> NATIVE_BYTE_ORDER (default)<br />

> BIG_ENDIAN_BYTE_ORDER<br />

> NETWORK_BYTE_ORDER<br />

> LITTLE_ENDIAN_BYTE_ORDER


B<strong>in</strong>aryWriter Stream State<br />

> Poco::B<strong>in</strong>aryWriter provides convenience functions to determ<strong>in</strong>e<br />

or change <strong>the</strong> state of <strong>the</strong> underly<strong>in</strong>g output <strong>stream</strong>.<br />

> void flush()<br />

flushes <strong>the</strong> underly<strong>in</strong>g <strong>stream</strong><br />

> bool good()<br />

returns true if <strong>the</strong> <strong>stream</strong> is okay<br />

> bool fail()<br />

returns <strong>the</strong> state of <strong>the</strong> <strong>stream</strong>'s fail bit<br />

> bool bad()<br />

returns <strong>the</strong> state of <strong>the</strong> <strong>stream</strong>'s bad bit


The B<strong>in</strong>aryReader Class<br />

> Poco::B<strong>in</strong>aryReader provides <strong>stream</strong> extraction operators (>>) for<br />

all built-<strong>in</strong> <strong>C++</strong> types, as well as std::str<strong>in</strong>g.<br />

> void read7BitEncoded(UInt32& value)<br />

void read7BitEncoded(UInt64& value)<br />

read an <strong>in</strong>teger stored <strong>in</strong> 7 bit compressed format<br />

> void readRaw(<strong>in</strong>t length, std::str<strong>in</strong>g& value)<br />

reads length bytes of raw data <strong>in</strong>to value<br />

> void readBOM()<br />

reads a byte order mark and enables or disables automatic byte<br />

order conversion for all data read <strong>in</strong> <strong>the</strong> future


The B<strong>in</strong>aryReader Class (cont'd)<br />

> bool good()<br />

returns true if <strong>the</strong> <strong>stream</strong> is okay<br />

> bool fail()<br />

returns <strong>the</strong> state of <strong>the</strong> <strong>stream</strong>'s fail bit<br />

> bool bad()<br />

returns <strong>the</strong> state of <strong>the</strong> <strong>stream</strong>'s bad bit<br />

> bool eof()<br />

returns <strong>the</strong> state of <strong>the</strong> <strong>stream</strong>'s eof bit


#<strong>in</strong>clude "Poco/B<strong>in</strong>aryWriter.h"<br />

#<strong>in</strong>clude <br />

us<strong>in</strong>g Poco::B<strong>in</strong>aryWriter;<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char** argv)<br />

{<br />

std::of<strong>stream</strong> ostr("b<strong>in</strong>ary.dat", std::ios::b<strong>in</strong>ary);<br />

B<strong>in</strong>aryWriter writer(ostr);<br />

}<br />

writer.writeBOM();<br />

writer


#<strong>in</strong>clude "Poco/B<strong>in</strong>aryReader.h"<br />

#<strong>in</strong>clude <br />

us<strong>in</strong>g Poco::B<strong>in</strong>aryReader;<br />

<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char** argv)<br />

{<br />

std::if<strong>stream</strong> istr("b<strong>in</strong>ary.dat", std::ios::b<strong>in</strong>ary);<br />

B<strong>in</strong>aryReader reader(istr);<br />

}<br />

reader.readBOM();<br />

std::str<strong>in</strong>g hello;<br />

<strong>in</strong>t i;<br />

bool b;<br />

reader >> hello >> i;<br />

reader.read7BitEncoded(i);<br />

reader >> b;<br />

return 0;


Cross-Platform Considerations<br />

> Poco::B<strong>in</strong>aryWriter and Poco::B<strong>in</strong>aryReader can be used to<br />

exchange data between systems <strong>with</strong> different architectures.<br />

> Ei<strong>the</strong>r write <strong>the</strong> data <strong>in</strong> a fixed byte order (e.g., big endian), or use<br />

a byte order mark and write <strong>in</strong> native byte order.<br />

> Be careful <strong>with</strong> <strong>in</strong>tegers. Prefer Poco::UIntXX and Poco::IntXX to<br />

(unsigned) short, (unsigned) <strong>in</strong>t and (unsigned) long.<br />

> For textual data, ensure that a common encod<strong>in</strong>g (e.g., Lat<strong>in</strong>-1 or<br />

UTF-8) is used.


File Streams<br />

> <strong>POCO</strong> provides <strong>stream</strong> <strong>classes</strong> for read<strong>in</strong>g and writ<strong>in</strong>g files:<br />

FileStream, FileInputStream, FileOutputStream<br />

> #<strong>in</strong>clude "Poco/FileStream.h"<br />

> On W<strong>in</strong>dows platforms, <strong>the</strong> path passed to a File Stream is UTF-8<br />

encoded.<br />

> No l<strong>in</strong>e end<strong>in</strong>g conversion is performed. File <strong>stream</strong>s are always<br />

open <strong>in</strong> b<strong>in</strong>ary mode. Seek<strong>in</strong>g is supported.<br />

> Use InputL<strong>in</strong>eEnd<strong>in</strong>gConverter or OutputL<strong>in</strong>eEnd<strong>in</strong>gConverter if<br />

you need CR-LF conversion.


Writ<strong>in</strong>g Your Own Stream Classes<br />

> <strong>POCO</strong> provides <strong>stream</strong> buffer class templates that simplify <strong>the</strong><br />

implementation of custom <strong>stream</strong> <strong>classes</strong>.<br />

> Streams are implemented by first creat<strong>in</strong>g a <strong>stream</strong> buffer class<br />

(<strong>stream</strong>buf), and <strong>the</strong>n add<strong>in</strong>g IOS, i<strong>stream</strong> and o<strong>stream</strong> <strong>classes</strong>.<br />

> The follow<strong>in</strong>g <strong>stream</strong> buffer class templates are available:<br />

> Poco::BasicUnbufferedStreamBuf<br />

> Poco::BasicBufferedStreamBuf<br />

> Poco::BasicBufferedBidirectionalStreamBuf


UnbufferedStreamBuf<br />

> Poco::BasicUnbufferedStreamBuf is a class template that must be<br />

<strong>in</strong>stantiated for a character type.<br />

> Poco::UnbufferedStreamBuf is an <strong>in</strong>stantiation of<br />

Poco::BasicUnbufferedStreamBuf for char.<br />

> #<strong>in</strong>clude "Poco/UnbufferedStreamBuf.h"<br />

> Poco::UnbufferedStreamBuf is <strong>the</strong> simplest way to implement a<br />

custom <strong>stream</strong>. It does not do any buffer<strong>in</strong>g.


UnbufferedStreamBuf (cont'd)<br />

> Sub<strong>classes</strong> must override <strong>the</strong> follow<strong>in</strong>g member functions:<br />

> <strong>in</strong>t readFromDevice()<br />

reads and returns a s<strong>in</strong>gle (unsigned) byte. Returns<br />

char_traits::eof() (-1) if no more data is available.<br />

NOTE: Never return a char value directly, as char might be<br />

signed. Always use <strong>in</strong>t charToInt(char c) to convert <strong>the</strong><br />

!<br />

character to an <strong>in</strong>teger.<br />

> <strong>in</strong>t writeToDevice(char c)<br />

writes a s<strong>in</strong>gle byte. Returns <strong>the</strong> byte (as <strong>in</strong>teger) if successful,<br />

o<strong>the</strong>rwise char_traits::eof() (-1).


#<strong>in</strong>clude "Poco/UnbufferedStreamBuf.h"<br />

#<strong>in</strong>clude <br />

#<strong>in</strong>clude <br />

class UpperStreamBuf: public UnbufferedStreamBuf<br />

{<br />

public:<br />

UpperStreamBuf(std::o<strong>stream</strong>& ostr): _ostr(ostr)<br />

{<br />

}<br />

protected:<br />

<strong>in</strong>t writeToDevice(char c)<br />

{<br />

_ostr.put(toupper(c));<br />

return charToInt(c);<br />

}<br />

private:<br />

std::o<strong>stream</strong>& _ostr;<br />

};


class UpperIOS: public virtual std::ios<br />

{<br />

public:<br />

UpperIOS(std::o<strong>stream</strong>& ostr): _buf(ostr)<br />

{<br />

poco_ios_<strong>in</strong>it(&_buf);<br />

}<br />

protected:<br />

UpperStreamBuf _buf;<br />

};<br />

class UpperOutputStream: public UpperIOS, public std::o<strong>stream</strong><br />

{<br />

public:<br />

UpperOutputStream(std::o<strong>stream</strong>& ostr):<br />

UpperIOS(ostr),<br />

std::o<strong>stream</strong>(&_buf)<br />

{<br />

}<br />

};


<strong>in</strong>t ma<strong>in</strong>(<strong>in</strong>t argc, char** argv)<br />

{<br />

UpperOutputStream upper(std::cout);<br />

}<br />

upper


Buffered Streams<br />

> Poco::BasicBufferedStreamBuf is a class template that must be<br />

<strong>in</strong>stantiated for a character type.<br />

> Poco::BufferedStreamBuf is an <strong>in</strong>stantiation of<br />

Poco::BasicBufferedStreamBuf for char.<br />

> #<strong>in</strong>clude "Poco/BufferedStreamBuf.h"<br />

> An <strong>in</strong>stance of Poco::BufferedStreamBuf supports ei<strong>the</strong>r read<strong>in</strong>g<br />

or writ<strong>in</strong>g, but not both.<br />

> Poco::BasicBufferedBidirectionalStreamBuf supports read<strong>in</strong>g and<br />

writ<strong>in</strong>g. Internally, it ma<strong>in</strong>ta<strong>in</strong>s two buffers.<br />

> #<strong>in</strong>clude "Poco/BufferedBidirectionalStreamBuf.h"


Buffered Streams (cont'd)<br />

> Sub<strong>classes</strong> of Buffered[Bidirectional]StreamBuf must override <strong>the</strong><br />

follow<strong>in</strong>g member functions:<br />

> <strong>in</strong>t readFromDevice(char* buffer, std::<strong>stream</strong>size length)<br />

read up to length characters and place <strong>the</strong>m <strong>in</strong> buffer. Return<br />

<strong>the</strong> number of characters read, or -1 if someth<strong>in</strong>g went wrong.<br />

> <strong>in</strong>t writeToDevice(const char* buffer, std::<strong>stream</strong>size length)<br />

write length bytes start<strong>in</strong>g from buffer and return <strong>the</strong> number<br />

of bytes written, or -1 if someth<strong>in</strong>g went wrong.


Stream Buffers and Exceptions<br />

> Exceptions thrown by <strong>stream</strong> buffers will normally be catched by<br />

<strong>the</strong> <strong>stream</strong> class and result <strong>in</strong> <strong>the</strong> <strong>stream</strong>'s bad bit be<strong>in</strong>g set. The<br />

exception will not propagate; <strong>in</strong>stead, <strong>the</strong> <strong>stream</strong>'s bad bit will be<br />

set.<br />

> This behavior of a <strong>stream</strong> can be changed by call<strong>in</strong>g <strong>the</strong><br />

exceptions() member function of a <strong>stream</strong> <strong>with</strong> true as argument.


Copyright © 2006-2010 by Applied Informatics Software Eng<strong>in</strong>eer<strong>in</strong>g GmbH.<br />

Some rights reserved.<br />

www.app<strong>in</strong>f.com | <strong>in</strong>fo@app<strong>in</strong>f.com<br />

T +43 4253 32596 | F +43 4253 32096

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!