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

  • std.alloc

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