diff --git a/tutorial/CoreTutorial/Serialize.cpp b/tutorial/CoreTutorial/Serialize.cpp index dea03c1dd..773bdc4b8 100644 --- a/tutorial/CoreTutorial/Serialize.cpp +++ b/tutorial/CoreTutorial/Serialize.cpp @@ -4,6 +4,17 @@ void Serialize() { /// .Binary serialization + /// Serialization is a mechanism that converts structured data to/from binary stream. In + /// U++, loading and storing of data is performed by single code, in most cases represented + /// by method `Serialize`. Serialization is performed directly with basic `Stream`. To this + /// end, `Stream` features a single boolean representing the direction of serialization + /// process. The direction can be checked using `IsLoading` and `IsStoring` methods and + /// changed with `SetStoring` and `SetLoading` methods. Direction is usually set properly + /// by derived classes (e.g. FileOut sets it to storing, FileIn to loading). + /// + /// Shortcut to calling `Serialize` method is `operator%`, which is templated overload that + /// calls `Serialize` for given variable (primitive types have direct overload in `Stream` class): + StringStream ss; int x = 123; @@ -21,7 +32,7 @@ void Serialize() DUMP(x2); DUMP(h2); - /// + /// ss2.Seek(0); ss2.LoadThrowing(); @@ -41,6 +52,7 @@ void Serialize() void Serialize(Stream& s) { int version = 0; s / version; // allow backward compatibility in the future + s.Magic(31415); s % number % color; } }; @@ -74,4 +86,6 @@ void Serialize() LoadFromString(foo3, data); DUMP(foo3.number); DUMP(foo3.color); -} \ No newline at end of file + + /// +} diff --git a/tutorial/CoreTutorial/SpecialStream.cpp b/tutorial/CoreTutorial/SpecialStream.cpp index 7ea7639f5..607b5b0f8 100644 --- a/tutorial/CoreTutorial/SpecialStream.cpp +++ b/tutorial/CoreTutorial/SpecialStream.cpp @@ -3,20 +3,28 @@ void SpecialStream() { /// .Special streams + + /// `SizeStream` counts the number of bytes written to the stream: + SizeStream szs; szs << "1234567"; DUMP(szs.GetSize()); - /// + /// `CompareStream` can be used to compare the content of some stream with data written to + /// `CompareStream`: StringStream in("123456"); CompareStream cs(in); cs.Put("12345"); DUMP(cs.IsEqual()); + + /// + cs.Put("7"); DUMP(cs.IsEqual()); - /// + /// `OutStream` buffers output data to bigger blocks, then outputs them via `Out` virtual + /// method: struct MyOutStream : OutStream { virtual void Out(const void *data, dword size) { @@ -28,7 +36,7 @@ void SpecialStream() os << "This is a test " << 12345; os.Close(); - /// + /// `TeeStream` send output data to two separate streams: StringStream ss1; StringStream ss2; @@ -38,7 +46,7 @@ void SpecialStream() DUMP(ss1.GetResult()); DUMP(ss2.GetResult()); - /// + /// `MemReadStream` can be used to convert read-only memory block to stream data: static const char s[] = "Some line\nAnother line"; MemReadStream ms(s, sizeof(os)); diff --git a/tutorial/CoreTutorial/Stream.cpp b/tutorial/CoreTutorial/Stream.cpp index e36d6919c..834d4efd6 100644 --- a/tutorial/CoreTutorial/Stream.cpp +++ b/tutorial/CoreTutorial/Stream.cpp @@ -13,8 +13,8 @@ void Stream() return; } - /// The most basic operations of streams are Put and Get. Get works in the same ways as - /// good old C getc - it returns negative number on eof or error: + /// The most basic operations of streams are `Put` and `Get`. `Get` works in the same ways + /// as good old C getc - it returns negative number on eof or error: String h; int c; @@ -26,28 +26,47 @@ void Stream() /// but they have some unique features. U++ does not distinguish between 'text' and /// 'binary' mode streams, methods are well suited to work with both in common mode. - /// GetLine returns String of single line read (lines separator being '\n', '\r' is + /// `GetLine` returns `String` of single line read (lines separator being '\n', '\r' is /// ignored): in.Seek(0); while(!in.IsEof()) DUMP(in.GetLine()); + + /// `Peek` can be used to look at the next character without actually moving on to the next + /// one: + + in.Seek(0); + DDUMP((char)in.Peek()); + DDUMP(in.GetLine()); - /// Get method reads at most specified number of bytes from the stream and returns them as - /// String: + /// `Get` method reads at most specified number of bytes from the stream and returns them as + /// `String`: in.Seek(0); DUMP(in.Get(10)); + /// If there is not enough characters in the Stream as required by Get, everything till EOF + /// is returned: in.Seek(0); DUMP(in.Get(999999).GetCount()); + + /// In contrast, `GetAll` method fails when there is not enough characters in the Stream and + /// returns Void `String` if Stream is not in `LoadThrowing` mode: in.Seek(0); h = in.GetAll(100); DUMP(h.GetCount()); + + /// + h = in.GetAll(999999); DUMP(h.IsVoid()); + + /// In `LoadThrowing` mode, `Stream` throws `LoadingError` exception when there is problem with + /// input `Stream`: + in.LoadThrowing(); try { in.GetAll(999999); @@ -55,8 +74,10 @@ void Stream() catch(LoadingError) { LOG("Loading error"); } + + /// Template variant of `Stream::operator<<` is using `AsString` to convert data to text: - String fn = GetHomeDirFile("test"); + String fn = GetHomeDirFile("test.txt"); FileOut out(fn); if(!out) { LOG("Failed to open the file"); @@ -64,27 +85,39 @@ void Stream() } out << "Some number " << 321 << " and Point " << Point(1, 2); out.Close(); + + /// When writing to the `Stream`, the good way to check for errors is to write all data, + /// close the stream and then check for `IsError`: + if(out.IsError()) { // check whether file was properly written LOG("Error"); return; } DUMP(LoadFile(fn)); + /// `FileAppend` can be used to append data to the file: + FileAppend out2(fn); out2 << "\nSomething more"; out2.Close(); DUMP(LoadFile(fn)); + /// Important and often used type of `Stream` is `StringStream` which works with `String` as + /// input/output. + + /// `Stream` also provides methods to store/load primitive types, in both + /// little-endian and big-endian modes: + StringStream ss; ss.Put32le(0x12345678); ss.Put32be(0x12345678); - - StringStream ss2(ss.GetResult()); - DUMP(ss.Get32le()); - DUMP(ss.Get32be()); DUMPHEX(ss.GetResult()); - - /// -} \ No newline at end of file + + StringStream ss2(ss.GetResult()); + DUMPHEX(ss2.Get32le()); + DUMPHEX(ss2.Get32be()); + + /// +} diff --git a/tutorial/CoreTutorial/Tutorial.cpp b/tutorial/CoreTutorial/Tutorial.cpp index 235122933..f49ee40d6 100644 --- a/tutorial/CoreTutorial/Tutorial.cpp +++ b/tutorial/CoreTutorial/Tutorial.cpp @@ -12,7 +12,7 @@ String qtf = "[b83;*6 $$2,3#07864147445237544204411237157677:title]" "[b42;a42 $$3,3#45413000475342174754091244180557:text]" "[l100;C@5*;1 $$4,4#20902679421464641399138805415013:code]" -"[l100;*C$7;2 $$5,5#07531550463529505371228428965313:log]" +"[l100;*C$7;1 $$5,5#07531550463529505371228428965313:log]" "[H6;b73;*7 $$6,3#07864147445237544204111237153677:section]" ; diff --git a/tutorial/CoreTutorial/test.txt b/tutorial/CoreTutorial/test.txt index 76602ea22..a9baac6ca 100644 --- a/tutorial/CoreTutorial/test.txt +++ b/tutorial/CoreTutorial/test.txt @@ -1,6 +1,8 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit -esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat -non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. \ No newline at end of file +Lorem ipsum dolor sit amet, consectetur adipiscing elit, +sed do eiusmod tempor incididunt ut labore et dolore magna +aliqua. Ut enim ad minim veniam, quis nostrud exercitation +ullamco laboris nisi ut aliquip ex ea commodo consequat. +Duis aute irure dolor in reprehenderit in voluptate velit +esse cillum dolore eu fugiat nulla pariatur. Excepteur +sint occaecat cupidatat non proident, sunt in culpa qui +officia deserunt mollit anim id est laborum. \ No newline at end of file