c++ streams aehnlichkeit
-
hola leute
sry fuer den titel, aber ich weiß grad nicht wirklich wie ich den titel nennen sollte.
folgendes problem:
aehnlich dem streambuf und streams von c++ brauch ich was aehnliches in C.
ich muss tabellen auslesen.
entweder aus einer datei, einem socket, von einer webseite usw.
die unterschiedlichen tabellenformate (csv, xml-derivat usw) werden erst zur laufzeit via dll bzw. so dateien geladen. also aehnlich einem plugin system.ganz naiv sollte das ungefaehr so aussehen:
void *source = create_xxxxx_connection(adresse); // xxxxx kann socket, file, http oder sonst was sein; struct callbacks { callbach_func_for_start_new_record new_one; callback_func_for_end_of_record cell; callback_func_for_cell_in_record end_of_rec; }; parse_content(source, callbacks); // die kommt aus der dll bzw. so
der parse_content func soll es also egal sein welche art vpon verbindung erstellt worden ist.
dazu kommt noch das create_xxxxx_connection intern mit nem buffer arbeiten soll, da auch tabellen mit mehreren 100 MB geparst werden muessen und der rechner selber nicht viel hauptspeicher hat.
in C++ wuerde ich dafuer einfach ne eigene streambuf klasse machen und die einem stream zuweisen. aber wie mach ich das am besten in C ?
Meep Meep
-
Wie portabel muss das sein? Für strenges ANSI-C fällt mir keine Methode ein, aber sowohl POSIX und, laut einer schnellen Googlesuche, Windows bieten Möglichkeiten, ein FILE* aus einem eigenen Filedescriptor zu machen.
-
es sollte schon halbwegs portable sein.
das mitnem File wuerde funktionieren fuer sockets, dateien usw. aber z.b. nicht mit ner http seite oder sonst mit einer protocoll-abhaengigen quelle.
z.b. sollte folgendes funktionieren:create_http_connection("www.meineseite.de/mein_dokument.html");
hier soll dann nur der inhalt der html seite der parse_funktion gegeben werden.
die parse funktion muss also mit alles create_xxxxx_connection objekten so arbeiten koennen als wenn es eine datei waere.
ich hoffe das das halbwegs verstaendlich war
-
Meep Meep schrieb:
es sollte schon halbwegs portable sein.
Wenn obiges nicht gut genug ist, dann fällt mir nur noch ein, dass C++ auch ziemlich portabel ist.
Vielleicht hat ja jemand anderes noch eine Idee.
-
Meep Meep schrieb:
es sollte schon halbwegs portable sein.
Was ist an Posix nicht portabel? Posix ist garantiert portabler als dein
create_http_connection
. Für Posix kannst du dir dein eigenesFILE*
schreiben, kein Problem.Ansonsten schreibst du dir halt deine eigene Streamklasse
typedef size_t (*my_read_function)(void*,char*,size_t); typedef struct c_style_streambuf { my_read_function read; } c_style_streambuf; size_t sbread(c_style_streambuf *csb, char *buf, size_t len) { return csb->read(csb, buf, len); } struct c_style_streambuf_that_wrapps_FILE { c_style_streambuf base; FILE *f; }; size_t c_style_streambuf_that_wrapps_FILE_read(void *sb, char *buf, size_t len) { return fread(buf, len, ((c_style_streambuf_that_wrapps_FILE*)sb)->f); } c_style_streambuf* wrap_file(FILE *f) { struct c_style_streambuf_that_wrapps_FILE *c = malloc(sizeof(*c)); c->base.read = c_style_streambuf_that_wrapps_FILE_read; c->f = f; return &c->base; }; void unwrap_file(c_style_streambuf *b) { free(b); }
(ungetestet)
-
Zu nennen wäre da z.B.
open_memstream
(POSIX), und mit Einschränkungen für deinen Fallfmemopen
(dateibasiert).
Leider haben das die Mingw-Leute bis heute nicht geschafft auch für Windows anzubieten, sodass du für Windows evtl. zu cygwin greifen musst.
Alternativ wäre nochasprintf
(nur GCC) für formatierte (String)Streams zu nennen, hier einfach %n verwenden, und auch wieder für Windows was extra basteln, ist aber auch nicht so schwer.
Schwieriger wird schon die Typabhängigkeit deines C-Streams zu realisieren, wenn du dich auf wenige Typen beschränkst, dürfte aber auch das machbar sein.