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 ZeigerVariablenIN 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
gibtstcmp(..., ...);
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 Vergleichsfunktionstrcmp(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 Funktionyylex()
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 kannMit 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