Text Parsen



  • Guten Tag liebes Forum!

    Ich habe ein mittleres Problem. Und zwar schreibe ich eine Funktion im Windows Drucker System um. Dazu verwende ich routinen aus dem Windows DDK. Mein Problem ist einfach, dass ich noch nicht lange mit C schreibe.

    Die Funktion wird vom Spooler mehrmals mit einem Buffer und dessen größe aufgerufen. In diesem Buffer steht ein PostScript Text. Dieser Buffer ist ein einfaches Byte Array und ich bekomme den LPBYTE und die größe cbBuf.

    LangMonWritePort(
        IN  HANDLE  hPort,
        IN  LPBYTE  pBuffer,
        IN  DWORD   cbBuf,
        IN  LPDWORD pcbWritten
    )
    

    Nun möchte ich diesen Buffer durchsuchen und Teilen. Ich muss so lange bis ich zb. "%%Page:" gefunden habe, den Buffer als Teil zwischenspeichern (Prolog). Die Position von "%%Page:" muss ich auch speichern, und zwar als ersten Seitenstart.
    Dann muss ich weiter suchen bis ich ein "%%PageTrailer" gefunden habe.
    Dann muss ich den Prolog, den buffer ab %%Page: bis %%PageTrailer und noch zusätzlich einen kleinen String wegschreiben. Das ganze so lange wiederholen bis ich kein %%Page: mehr finden kann.

    Im groben und ganzen soll diese Funktion einen Postscript Druckjob zerteilen in Prolog(header), N Seiten, und Footer. Die Funktion soll dann für jede Seite einzelnd Header, Seite X und Footer wegschreiben.

    Kann mir hier jemand unter die Arme greifen? Ich checks echt überhaupt nicht. 😞

    BOOL
    WINAPI
    LangMonWritePort(
        IN  HANDLE  hPort,
        IN  LPBYTE  pBuffer,
        IN  DWORD   cbBuf,
        IN  LPDWORD pcbWritten
    )
    /*++
    
    Routine Description:
        Language monitor WritePort
    
    Arguments:
        hPort           : Port handle
        pBuffer         : Data Buffer
        cbBuf           : Buffer size
        pcbRead         : Pointer to the variable to return written count
    
    Return Value:
        TRUE on success, FALSE on error
    
    --*/
    {
        PINIPORT    pIniPort		= (PINIPORT)((INIPORT *)hPort);
        BOOL        ret				= FALSE;
    	LPBYTE		pBufferTemp		= NULL;
    	FILE		*pPimml			= NULL;
    
            /* ???? */
    
    	ret = (*pIniPort->fn.pfnWritePort)(pIniPort->hPort, pBuffer, cbBuf, pcbWritten);
    
    	if ( ret ) {
    		pIniPort->status &= ~PP_WRITE_ERROR;
    	} else {
    	    pIniPort->status |= PP_WRITE_ERROR;
    	}
    
        return ret;
    }
    


  • Nun Du sagtest diese Funktion wird vom Spooler aufgerufen!

    Ich denke dann könntest Du so vorgehen:

    Wenn der Spooler die Funktion aufruft
    dann sollte man über diese ZeigerVariablen

    IN  LPDWORD pcbWritten
    

    abfragen können wieviele Bytes in den Buffer geschreiben
    worden sind! Dann weisst Du das der Buffer zumindest Daten enthält!
    Und somit lohnt es in dem Buffer nach Deinen Schlüsselwörtern:

    Page

    sowie

    PageTrailer

    zu suchen! Wegen der Prozentzeichen (% oder %%) gehe ich davon aus das
    es sich um Platzhalter fuer eine dezimal Seitenzahl handelt etc. !

    Um die Schlüsselwörter zu suchen kopierst Du für
    das Schlüsselwort Page 4 + 1 Byte (Schlüsselwortgrösse) aus den Puffer in ein char - array
    und vergleichst dann den Inhalt des Array mit einem Schlüsselwort z.B "Page"!

    strcmp(array,"Page");
    

    Wenn der Inhalt des Feldes "array" mit dem Sclüsselwort "Page" übereinstimmt
    gibt

    stcmp(..., ...);
    

    den Integer - Wert 0 zurueck was Dir signalisieren würde das Du eines deiner Schlüsselwörter gefunden hast!

    Wenn nicht gefunden (return von

    strcmp(..., ...)
    

    ist immer ungleich 0) eine Offsetvariable (

    int idx
    

    ) um 1 hochzählen (

    idx++;
    

    )
    und wieder 4 + 1 Byte ruaszukopieren um Wieder zu vergeichen
    diese Vergleiche kannst du solange machen Wie Differenz (Grösse Datenbuffer) - Offsetvariable >= 5 ist (Schlüsselwortgrösse) ist! Diesen ich sag mal Pseudocode musst Du in einer Schleife ablaufen lassen!

    Analog machst Du das beim Schlüsselwort PageTrailer vorgehen,
    aber Achtung hier Ist das Schlüsselwort länger! Zähle einfach die anzahl der Buchstaben und addiere 1 dazu den jede Zeichenkette in C/C++ endet mit "\0" .

    Somit findest Du die markanten Stellen die im Spoller stehen!
    Diese Richtung würde ich einschlagen!

    Das char - Array

    char array[12]
    

    kannst Du bei der Deklaration so gross machen
    das beide Schlüsselwörter von der Länge reinpassen ( richte dich nach dem längsten Schlüsselwort in deinem Fall PageTrailer)!

    Das wäre mein Ansatz 👍 den ich gehen würde!
    für die Vergleichsfunktion

    strcmp(char *, char *);
    

    musst Du die Header

    #include <string.h>
    

    includieren!

    P.S.: Ich hoffe ich konnte Dir zu nem Denkanstoss verhelfen 😉

    Gruss sclearscreen 🙂



  • Eine andere Möglichkeit wäre wenn Du Dich mit Regulären Ausdrücken auskennst,
    mit einem Parsergenerator ( ala lex was aber unter LINUX/UNIX läuft )

    fuer dies Schlüsselwörter -> Reguläre Ausdrücke zu bilden (sind Muster) !

    In dem Parsergenerator kann man auf solche Muster mit Aktionen reagieren.
    Der generierte Quelltext ist soweit ich denke Standardkonform, das du den Quelltext
    soweit Du als Wirtssprache C gewählt hast problemos weils ne Textdatei ist nach Windows portieren!

    Lex generiert eine C - Quelltextdatei yy.lex.c in dieser Quelltextdatei wird
    die Funktion

    yylex()
    

    generiert die durch die Regulärer Ausdrueck
    die Du definieren kannst, genau auf dein Problem gemünzt ist.

    Eine lex - Programm besteht aus

    einem Definitionsteil: Wo die regulären Ausdrücke (Muster) definiert werden

    sowie ein Regelteil: Wo der Nutzer fuer jedes Muster mit beliebigen Anweisungen
    reagieren kann

    Mit freundlichen Grüssen sclearscreen 🙂 👍

    Das wäre eine zweite lösungsmöglichkeit



  • für lexx, Bison und yacc gibt es auch Windows ports. Ist mit Sicherheit eine sehr sinnvoller Ansatz


Anmelden zum Antworten