std.edi.core
EDIFACT-Interchange-Engine — das Fundament aller std.edi.*-Units. Implementiert die vollständige Umschlag-Hierarchie (UNA / UNB / UNZ / UNG / UNE / UNH / UNT), den Segment-Tokenizer mit Escape-Behandlung, laufende Sequenznummern und Duplikatserkennung pro Partner.
Alle anderen EDI-Units importieren std.edi.core und setzen die hier definierten Structs und Konstanten voraus.
import std.edi.core;
// 1. Kontext allozieren und initialisieren
var ctx: int64 := alloc(EDI_CTX_SIZE);
EdiCtxInit(ctx);
// Absender / Empfänger setzen (Zeiger in eigene Puffer, kein Copy)
poke64(ctx + EDI_CTX_SENDER, "MYCOMPANY" as int64);
poke64(ctx + EDI_CTX_SNDLEN, 9);
poke64(ctx + EDI_CTX_RCVR, "PARTNER01" as int64);
poke64(ctx + EDI_CTX_RCVLEN, 9);
// 2. State für Sequenznummern / Duplikatserkennung
var state: int64 := alloc(EDI_STATE_SIZE);
EdiStateInit(state);
// 3. UNB-Header schreiben
var out: int64 := alloc(65536);
var pos: int64 := EdiUnbWrite(ctx, out, 65536);
free(out, 65536);
free(state, EDI_STATE_SIZE);
free(ctx, EDI_CTX_SIZE);
Imports
Konstanten & Standardtrennzeichen
Wenn kein UNA-Segment vorhanden ist, gelten folgende Standardwerte (UNOA-Zeichensatz):
| Konstante | Wert | Bedeutung |
EDI_DEF_COMP | : (58) | Komponenten-Trenner |
EDI_DEF_DATA | + (43) | Datenelement-Trenner |
EDI_DEF_DEC | . (46) | Dezimalzeichen |
EDI_DEF_REL | ? (63) | Release-Zeichen (Escape) |
EDI_DEF_SEG | (39) | Segmentabschluss |
Zeichensatz-Codes:
| Konstante | Bedeutung |
EDI_CHARSET_UNOA | A–Z, 0–9 + wenige Sonderzeichen |
EDI_CHARSET_UNOB | Latin-1 / ISO 8859-1 |
EDI_CHARSET_UNOC | UTF-8 |
Fehlercodes:
| Konstante | Bedeutung |
EDI_OK | Kein Fehler |
EDI_ERR_TRUNC | Puffer zu klein |
EDI_ERR_NOUNA | Kein UNA-Segment gefunden |
EDI_ERR_SYNTAX | Syntaxfehler im Segment |
EDI_ERR_DUP | Doppelte Interchange-Referenz erkannt |
EDI_ERR_OVERFLOW | Zu viele Partner-Slots belegt |
EDI_ERR_PARTNER | Partner nicht gefunden |
Structs
Alle Structs werden vom Caller alloziert. Größen sind über Konstanten verfügbar.
EdiUna (EDI_UNA_SIZE = 48 Bytes)
Hält die Trennzeichen aus dem UNA-Segment oder die Standardwerte.
| Offset-Konstante | Offset | Inhalt |
EDI_UNA_COMP | 0 | Komponenten-Trenner (int64) |
EDI_UNA_DATA | 8 | Datenelement-Trenner (int64) |
EDI_UNA_DEC | 16 | Dezimalzeichen (int64) |
EDI_UNA_REL | 24 | Release-Zeichen (int64) |
EDI_UNA_RES | 32 | Reserviert (int64) |
EDI_UNA_SEG | 40 | Segmentabschluss (int64) |
EdiCtx — Interchange-Kontext (EDI_CTX_SIZE = 128 Bytes)
| Offset-Konstante | Inhalt |
EDI_CTX_SENDER / EDI_CTX_SNDLEN | Absender-ID (Zeiger + Länge) |
EDI_CTX_RCVR / EDI_CTX_RCVLEN | Empfänger-ID (Zeiger + Länge) |
EDI_CTX_ICREF / EDI_CTX_ICREFLEN | Interchange-Referenz (ICR) |
EDI_CTX_DATE / EDI_CTX_TIME | Datum (YYYYMMDD oder YYMMDD) / Zeit (HHMM) |
EDI_CTX_CHARSET | Zeichensatz-Code (UNOA/UNOB/UNOC) |
EDI_CTX_TESTFLAG | 0 = Produktion, 1 = Testmodus |
EDI_CTX_COMP / DATA / DEC / REL / SEG | Trennzeichen (0 = Standard) |
EDI_CTX_MSGCOUNT | Anzahl Nachrichten im Interchange |
EdiSegCtx — Segment-Iterator (EDI_SEGCTX_SIZE = 40 Bytes)
Hält die aktuelle Position im Lesepuffer. Wird von EdiSegCtxInit initialisiert und von EdiSegmentNext fortgeschrieben.
EdiSeg — Segment-Ergebnis (EDI_SEG_SIZE = 16 Bytes)
| Offset-Konstante | Inhalt |
EDI_SEG_PTR | Zeiger in den Originalpuffer (Zero-Copy) |
EDI_SEG_LEN | Byte-Länge ohne Segmentabschluss |
EdiElem — Element/Komponenten-Slot (EDI_ELEM_SIZE = 16 Bytes)
| Offset-Konstante | Inhalt |
EDI_ELEM_PTR | Zeiger in den Originalpuffer |
EDI_ELEM_LEN | Byte-Länge des Elements/der Komponente |
EdiState — Partner-State (EDI_STATE_SIZE = 16 776 Bytes)
Speichert pro Partner (max. 16) die laufende Sequenznummer und einen Ring-Buffer von 128 ICR-Hashes zur Duplikatserkennung.
Funktionen
Initialisierung
| Signatur | Beschreibung |
EdiCtxInit(ctx: int64): void | Nullt alle Felder des Interchange-Kontexts |
EdiStateInit(state: int64): void | Nullt alle Felder des Partner-State |
UNA lesen / schreiben
| Signatur | Beschreibung |
EdiUnaRead(buf: int64, bufLen: int64, out: int64): int64 | Liest UNA-Segment aus buf; füllt out (EDI_UNA_SIZE). Kein UNA → Standardwerte. Gibt EDI_OK zurück. |
EdiUnaWrite(ctx: int64, out: int64, outMax: int64): int64 | Schreibt UNA-Segment mit den im Kontext gesetzten Trennzeichen; gibt geschriebene Bytes zurück. |
Segment-Tokenizer
| Signatur | Beschreibung |
EdiSegCtxInit(sctx: int64, una: int64, startPos: int64): void | Initialisiert Iterator ab Byte-Position startPos mit Trennzeichen aus una |
EdiSegmentNext(buf: int64, bufLen: int64, sctx: int64, seg: int64): int64 | Holt nächstes Segment. Gibt 1 (gefunden) oder 0 (Ende) zurück. Zeiger in seg zeigen in buf (Zero-Copy). |
EdiElementSplit(seg: int64, out: int64, maxOut: int64): int64 | Spaltet Segment in Datenelemente auf; befüllt out-Array (je EDI_ELEM_SIZE). Gibt Anzahl zurück. |
EdiComponentSplit(ptr: int64, len: int64, out: int64, maxOut: int64): int64 | Spaltet ein Datenelement in Komponenten auf. Gibt Anzahl zurück. |
EdiUnescape(src: int64, srcLen: int64, dst: int64, dstMax: int64): int64 | Entfernt Release-Zeichen (?) aus einem String. Gibt Länge des Ergebnisses zurück. |
UNB / UNZ — Interchange-Umschlag
| Signatur | Beschreibung |
EdiUnbRead(buf: int64, bufLen: int64, ctx: int64): int64 | Parst UNB-Segment; füllt Absender/Empfänger/ICR/Datum ins ctx. Gibt EDI_OK oder Fehlercode. |
EdiUnbWrite(ctx: int64, out: int64, outMax: int64): int64 | Schreibt UNB-Segment; gibt geschriebene Bytes zurück. |
EdiUnzWrite(ctx: int64, msgCount: int64, out: int64, outMax: int64): int64 | Schreibt UNZ-Trailer (Interchange-Ende). |
UNG / UNE — Gruppen-Umschlag
| Signatur | Beschreibung |
EdiUngWrite(ctx: int64, msgType: int64, grpRef: int64, out: int64, outMax: int64): int64 | Schreibt UNG-Gruppen-Header |
EdiUneWrite(ctx: int64, msgCount: int64, grpRef: int64, out: int64, outMax: int64): int64 | Schreibt UNE-Gruppen-Trailer |
UNH / UNT — Nachrichten-Umschlag
| Signatur | Beschreibung |
EdiUnhWrite(ctx: int64, msgRef: int64, msgType: int64, out: int64, outMax: int64): int64 | Schreibt UNH-Nachrichten-Header |
EdiUntWrite(ctx: int64, segCount: int64, msgRef: int64, out: int64, outMax: int64): int64 | Schreibt UNT-Nachrichten-Trailer |
Sequenznummern & Duplikatserkennung
| Signatur | Beschreibung |
EdiSeqNext(state: int64, partnerKey: int64): int64 | Erhöht Sequenznummer für diesen Partner; gibt nächste Nummer zurück |
EdiDuplicateCheck(state: int64, partnerKey: int64, icRef: int64): int64 | Prüft ob ICR bereits bekannt; gibt 1 (Duplikat) oder 0 (neu). Trägt neue ICRs automatisch ein (Ring-Buffer mit 128 Einträgen). |
Codebeispiel — Eingehende Nachricht parsen
import std.edi.core;
fn parseEdi(buf: int64, bufLen: int64): void {
// 1. UNA-Trennzeichen ermitteln (oder Standardwerte)
var una: int64 := alloc(EDI_UNA_SIZE);
EdiUnaRead(buf, bufLen, una);
// UNB steht nach UNA (9 Bytes) oder am Anfang
var startPos: int64 := 0;
if (peek8(buf) == 85 && peek8(buf+1) == 78 && peek8(buf+2) == 65) {
startPos := 9;
}
// 2. Segment-Iterator initialisieren
var sctx: int64 := alloc(EDI_SEGCTX_SIZE);
EdiSegCtxInit(sctx, una, startPos);
var seg: int64 := alloc(EDI_SEG_SIZE);
var elems: int64 := alloc(16 * EDI_ELEM_SIZE);
var done: int64 := 0;
while (done == 0) {
var r: int64 := EdiSegmentNext(buf, bufLen, sctx, seg);
if (r == 0) {
done := 1;
} else {
var n: int64 := EdiElementSplit(seg, elems, 16);
// Segment-Tag aus erstem Element auslesen
var tag: int64 := peek64(seg + EDI_SEG_PTR);
PrintLn("Segment: " + (tag as pchar));
}
}
free(elems, 16 * EDI_ELEM_SIZE);
free(seg, EDI_SEG_SIZE);
free(sctx, EDI_SEGCTX_SIZE);
free(una, EDI_UNA_SIZE);
}
Hinweise
Zero-Copy-Parsing: EdiSegmentNext, EdiElementSplit und EdiComponentSplit setzen Zeiger in den Originalpuffer — keine Kopien. Der Puffer muss während der gesamten Verarbeitung gültig bleiben.
Caller alloziert: Alle Structs (UNA, CTX, SEGCTX, SEG, Elem-Arrays) werden vom Caller alloziert und freigegeben. Die Größenkonstanten (EDI_*_SIZE) geben die benötigte Byte-Anzahl an.
Escape-Behandlung: EdiSegmentNext behandelt das Release-Zeichen (Standard: ?) korrekt — es schützt das darauffolgende Trennzeichen vor Interpretation. Explizite Daten müssen danach durch EdiUnescape bereinigt werden.
Duplikatserkennung: EdiDuplicateCheck nutzt einen Ring-Buffer mit 128 Hash-Einträgen pro Partner. Bei mehr als 128 ICRs pro Partner kann ein alter ICR wieder als „neu“ erscheinen.
Quelldatei
| Unit | Datei |
std.edi.core | std/edi/core.lyx |
Letzte Aktualisierung: 2026-06-16