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


  • Mod

    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


  • Mod

    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 eigenes FILE* 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 Fall fmemopen (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 noch asprintf (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.


Anmelden zum Antworten