Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 21:37

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 18 Beiträge ]  Gehe zu Seite Vorherige  1, 2
Autor Nachricht
 Betreff des Beitrags: Re: EBML… oder was?
BeitragVerfasst: Di Sep 03, 2013 14:51 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Ich möchte hier nochmal kurz ein Update geben, weil aus dem Post im ManiacLab Thread nicht ganz herauskommt, wie structstream nun tatsächlich genutzt wird. Hier ein Beispiel mit ein paar Structs. Unbekannte Typnamen dort sind Enums, das ist nicht weiter wichtig.

Code:
  1. struct RawLevelHeaderData {
  2.     std::string display_name;
  3.  
  4.     uint64_t body_stream_offset;
  5. };
  6.  
  7. struct RawLevelCollectionData {
  8.     std::string display_name;
  9.     std::string description;
  10.  
  11.     std::string author;
  12.     std::string license;
  13.     std::string version;
  14.  
  15.     std::vector<RawLevelHeaderData> level_headers;
  16. };


StructStream hat eine deklarative Sprache auf Basis der C++-Templates, womit man das Datenformat deklariert:
Code:
  1. typedef struct_decl<
  2.     Container,
  3.     id_selector<SSID_LEVEL_HEADER>,
  4.     struct_members<
  5.         member<
  6.             UTF8Record,
  7.             id_selector<SSID_LEVEL_HEADER_DISPLAY_NAME>,
  8.             RawLevelHeaderData,
  9.             std::string,
  10.             &RawLevelHeaderData::display_name>,
  11.         member<
  12.             UInt64Record,
  13.             id_selector<SSID_LEVEL_HEADER_OFFSET>,
  14.             RawLevelHeaderData,
  15.             uint64_t,
  16.             &RawLevelHeaderData::body_stream_offset>
  17.         >
  18.     > RawLevelHeaderDecl;
  19.  
  20. typedef struct_decl<
  21.     Container,
  22.     id_selector<SSID_LEVEL_COLLECTION_HEADER>,
  23.     struct_members<
  24.         member<
  25.             UTF8Record,
  26.             id_selector<SSID_LEVEL_COLLECTION_DISPLAY_NAME>,
  27.             RawLevelCollectionData,
  28.             std::string,
  29.             &RawLevelCollectionData::display_name>,
  30.         member<
  31.             UTF8Record,
  32.             id_selector<SSID_LEVEL_COLLECTION_DESCRIPTION>,
  33.             RawLevelCollectionData,
  34.             std::string,
  35.             &RawLevelCollectionData::description>,
  36.         member<
  37.             UTF8Record,
  38.             id_selector<SSID_LEVEL_COLLECTION_AUTHOR>,
  39.             RawLevelCollectionData,
  40.             std::string,
  41.             &RawLevelCollectionData::author>,
  42.         member<
  43.             UTF8Record,
  44.             id_selector<SSID_LEVEL_COLLECTION_LICENSE>,
  45.             RawLevelCollectionData,
  46.             std::string,
  47.             &RawLevelCollectionData::license>,
  48.         member<
  49.             UTF8Record,
  50.             id_selector<SSID_LEVEL_COLLECTION_VERSION>,
  51.             RawLevelCollectionData,
  52.             std::string,
  53.             &RawLevelCollectionData::version>,
  54.         member_struct<
  55.             RawLevelCollectionData,
  56.             container<
  57.                 RawLevelHeaderDecl,
  58.                 id_selector<SSID_LEVEL_COLLECTION_LEVEL_HEADERS>,
  59.                 std::back_insert_iterator<
  60.                     decltype(RawLevelCollectionData::level_headers)>
  61.                 >,
  62.             &RawLevelCollectionData::level_headers>
  63.         >
  64.     > RawLevelCollectionDecl;
(die SSID_* Identifier sind konstante Integers, die dazu dienen, die Records innerhalb eines Containers zu identifizieren)

Das ganze ist 100% Typesafe. Um dann Daten aus einem Stream einzulesen oder zurückzuschreiben braucht es nur wenige Zeilen. Zum schreiben in einen Stream tut man folgendes:
Code:
  1.     IOIntfHandle io(new PyEngineStream(stream));
  2.     StreamSink sink(new ToBitstream(io));
  3.     serialize_to_sink<RawLevelCollectionDecl>(header, sink);
  4.     sink->end_of_stream();

IOIntfHandle ist ein Typ von StructStream, einen Wrapper für bestehende Streamsysteme zu schreiben ist trivial (es braucht nur read() und write(), optional auch skip(), welches aber in der Basisklasse durch read()s emuliert wird).

StreamSinks sind Objekte, die Node-Ereignisse (ähnlich wie die von einem XML-SAX-Parser) aufnehmen und verarbeiten. Eine ToBitstream-Sink schreibt die passenden Nodes als Binärformat in den gegebenen Stream. serialize_to_sink ist nun der Call, der den Struct anhand der oben gegebenen Deklaration zerpflückt und an die Sink weiterreicht.

Der Preis dieser ganzen Magie ist natürlich, dass die Kompilierungszeit etwas nach oben geht. Allerdings kann man das ganze leicht in eine Compilation Unit auslagern, die sich nur bei Änderungen an der Datenstruktur neu gebaut werden muss.

Ich finde 60 deklarative Zeilen für ein typensicheres Datenformat schon ziemlich gut, ich weiß nicht wie ihr das seht. Wenn man das per Hand aus XML (de-)serialisieren würde, wäre der Aufwand ungleich höher.

Fehlerbehandlung findet über ein wohldefiniertes Set von Exceptions statt. Das kann man anprangern, oder einfach alle in der Serialisierungs/Deserialisiernugsfunktion abfangen und in Errorcodes umwandeln, wenn man drauf steht. Die StructStream-Klassen sind jedenfalls alle Exception-Safe, dagegen teste ich auch.

grüße

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: EBML… oder was?
BeitragVerfasst: Di Sep 03, 2013 17:13 
Offline
DGL Member
Benutzeravatar

Registriert: Di Mai 18, 2004 16:45
Beiträge: 2621
Wohnort: Berlin
Programmiersprache: Go, C/C++
Gefällt mir sehr, wir haben sowas für Netzwerk früher verwendet.
Da hat aber niemand den Code geschrieben, der wurde generiert.
Dazu haben wir xml verwendet, dann mit php bzw. in einem anderem Projekt ein c++ tool, welches die xml liest und daraus den c++ code baut.
QT baut seine stubs auch über das parsen der Klassen-Attribute in extra files und kompiliert die und linkt die mit ins binary.
In den stubs steht dann welche Klassen welche Properties, Methoden und Typen veröffentlicht.
Die benutzten es aber meines Wissens hauptsächlich für RTTI foo und damit auch serialisierung.

Für Radon Framework benutze ich immer structs als Datenblob, lese die Daten ein und Chunk für Chunk, prüfe ich die größe des gelesenden Blocks mit sizeof(struct Bla) und wenn die stimmt und in den Daten noch komplexerer kram gelagert ist, wie Container, dann hab ich Validate Funktionen im struct, die prüfen ob er mit den Daten ohne crash was machen kann. Damit hab ich einige Client-Server gebastelt.

Wenn es weniger wichtig ist dann lade ich sogar nur die Daten vom Medium und addiere auf die MemoryRange typen den pointer des Speicherblocks und speicher das Ergebnis und den Speicherblock in einer C++ Klasse. Also gar keine checks, ledeglich ein paar additionen.
Sowas mach ich auf Daten wie Contentdaten von der Platte, weil meine Asset Pipeline schon alles richtig machen sollte.

Das Ganze kann natürlich nicht beliebige structs an irgendwelchen stellen haben und vom aufbau fehlerfrei sein, dazu müsste ich dann ein System wie deines verwenden.

_________________
"Wer die Freiheit aufgibt um Sicherheit zu gewinnen, der wird am Ende beides verlieren"
Benjamin Franklin

Projekte: https://github.com/tak2004


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: EBML… oder was?
BeitragVerfasst: Di Sep 03, 2013 20:34 
Offline
DGL Member
Benutzeravatar

Registriert: So Sep 26, 2010 12:54
Beiträge: 238
Wohnort: wieder in Berlin
Programmiersprache: Englisch
Erinnert mich ein wenig an die Templates aus dem HexWorkshop32 :) Coole Sache.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 18 Beiträge ]  Gehe zu Seite Vorherige  1, 2
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 35 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.071s | 17 Queries | GZIP : On ]