aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2020-07-05 11:25:46 +0200
committerThomas Schmucker <ts@its1.de>2020-07-05 11:25:46 +0200
commit12b36ad95dc633648b6c93d7626e17a0016b4547 (patch)
treec4fa5d915d19e9e165b7adc94c20c6d3338ba9a5
parenta0fc70b0c6b3860236e783a05aa5d70cfc831669 (diff)
downloadlibcsv-12b36ad95dc633648b6c93d7626e17a0016b4547.tar.gz
libcsv-12b36ad95dc633648b6c93d7626e17a0016b4547.tar.bz2
libcsv-12b36ad95dc633648b6c93d7626e17a0016b4547.zip
erster Versuch einer Dokumentation
-rw-r--r--.gitignore5
-rw-r--r--csv.md197
2 files changed, 202 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e633662..52ff689 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,9 @@ Vegleich.ods
12 12
13*.profdata 13*.profdata
14*.profraw 14*.profraw
15*.md.backup
16*.html
17
18csv-parser.py
19csv-parser.rb
15 20
diff --git a/csv.md b/csv.md
new file mode 100644
index 0000000..63b8d8a
--- /dev/null
+++ b/csv.md
@@ -0,0 +1,197 @@
1# csv - CSV-Dateien parsen
2
3- [x] korrekt
4- [x] einfach
5- [x] intuitiv
6- [x] schnell
7- [x] klein
8- [x] erweiterbar
9- [x] robust
10- [x] einfachst mögliche Lizenz
11
12Kurz: suckless!
13
14## Schnellstart für Ungeduldige
15
161\. Füge die beiden Dateien [csv.c](csv.c) und [csv.h](csv.h) Deinem C/C++ Projekt hinzu.
17
182\. Inkludiere die Headerdatei `csv.h`.
19
20~~~
21#include "csv.h"
22~~~
23
243\. Erstelle und initialisiere ein CSV-Objekt.
25
26~~~
27csv_t csv = { 0 };
28~~~
29
304\. Verarbeite die CSV-Datei
31
32~~~
33for ( int nf; (nf = csv_read(&csv, in)) != EOF; ) { /* eine Zeile aus `in` lesen */
34 for ( int i = 0; i < nf; i++ ) { /* `nf` beinhaltet die Feldanzahl */
35 const char *s = csv_field(&csv, i); /* jedes Feld der Zeile ansprechen */
36 /* ... */
37 }
38}
39~~~
40
41Es sind nur zwei Funktionen notwendig, um die Daten des FILE-Streams `in` vollständig zu verarbeiten:
42`csv_read()` liest eine Zeile aus dem Parameter `in` und liefert die Anzahl der erfolgreich geparsten Felder oder **`EOF`** bei Dateiende.
43`csv_field()` liefert einen (read only) `const char`-Zeiger für das i-te Feld.
44
45Der Speicher für das CSV-Objekt wird automatisch von `csv_read()` beim ersten Aufruf alloziert und wieder freigeben wenn der Stream `in` vollständig gelesen wurde.
46
47## Motivation
48
49Die meisten anderen CSV-Bibliotheken passen nicht:
50
51- falsche Verarbeitung bei eingeklammerten Feldern:
52 C++: getline() -> stringstream -> getline();
53 C: fgets() -> strtok()
54- fehlerhafte Verarbeitung von "problematischen" CSV-Dateien (Linebreaks innerhalb einer Zelle)
55- unvorteilhafte Lizenz (GPL)
56- umständliche API (Callbacks zum Verarbeiten der Inhalte, seltsames Handling am Dateiende)
57- globale Variablen, die den Einsatz in Multi-Threadumgebungen unmöglich machen
58- C++ wenn ich C brauche
59- Java/Python/Rust/Ruby/${YourLanguageHere} wenn ich C brauche
60- Langsam, Aufgebläht
61- schlecht oder gar nicht anpassbar
62
63=> Selber schreiben!
64
65## Tutorial
66
67to be written
68
69## API
70
71### Typen
72
73**Fehlercodes** für die Callbackhandler:
74
75~~~
76typedef enum {
77 CSV_ERR_OK = 0,
78 CSV_ERR_OUT_OF_MEMORY = -1,
79 CSV_ERR_OUT_OF_RANGE = -2,
80 CSV_ERR_IO_READ = -3,
81 CSV_ERR_IO_WRITE = -4
82} csv_err_t;
83~~~
84
85**Optionen** für das Parsen eines CSV-Streams:
86
87~~~
88typedef struct {
89 int field_delimiter;
90 int field_separator;
91
92 void (*cb_error)(csv_err_t, void *);
93 void *cb_error_arg;
94
95 void *(*cb_allocate)(size_t, size_t, void *);
96 void *(*cb_reallocate)(void *, size_t, size_t, void *);
97 void (*cb_free)(void *, size_t, size_t, void *);
98 void *cb_memory_arg;
99} csv_options_t;
100
101extern const csv_options_t csv_default_options;
102~~~
103
104**Contextobjekt** zur Aufnahme der aktuell gelesenen Zeile:
105
106~~~
107typedef struct {
108 csv_options_t *csv_options;
109 /* additional internal fields */
110} csv_t;
111
112~~~
113
114### Funktionen
115
116**Initialisieren**
117
118~~~
119void csv_init(csv_t *csv);
120void csv_init_opt(csv_t *csv, const csv_options_t * const csv_options);
121~~~
122
123**Manuelles Freigeben**
124
125~~~
126void csv_cleanup(csv_t *csv);
127~~~
128
129**Zeilenweises Lesen**
130
131~~~
132int csv_read(csv_t *csv, FILE *in);
133~~~
134
135**Feldzugriff**
136
137~~~
138int csv_nfields(const csv_t * const csv);
139const char * csv_field(const csv_t * const csv, int idx);
140~~~
141
142**Fehlercodes als Textmeldung**
143
144~~~
145const char * csv_err_str(csv_err_t csv_err);
146~~~
147
148## Fehlerbehandlung
149
150to be written
151
152## Anpassungen
153
154Die CSV-Bibliothek kann an verschiedene Bedürfnisse angepasst werden.
155
156### Übersetzungsoptionen
157
158Beim Compilieren der Datei csv.c können die Standardwerte für Feldbegrenzer und Feldtrenner als Makrodefinitionen `CSV_DEFAULT_DELIMITER` und `CSV_DEFAULT_SEPARATOR` voreingestellt werden.
159
160Option Beschreibung Standardwert
161-------------------------- -------------- ---------------------------------
162`CSV_DEFAULT_DELIMITER` Feldbegrenzer `"`
163`CSV_DEFAULT_SEPARATOR` Feldtrenner `,`
164-------------------------- -------------- ---------------------------------
165Table: Makros
166
167Soll beispielsweise das in Deutschland viel häufiger vorkommende Semikolon (`;`) statt einem Komma (`,`) als Trennsymbol zwischen den Feldern einer CSV-Datei benutzt werden sieht der Aufruf zum Compilieren so aus:
168
169~~~
170cc -DCSV_DEFAULT_SEPARATOR="';'" -o csv-german.o -c csv.c
171~~~
172
173Anschließend wird die Datei `csv-german.o` statt `csv.o` zum Projekt dazugelinkt.
174
175Die Headerdatei (`csv.h`) bleibt unverändert.
176
177### Eigener Speicherallozierer
178
179to be written
180
181## Performance
182
183to be written
184
185## Lizenz
186
187In den letzten Jahrzehnten habe ich massiv vom Internet und seinen Inhalten profitiert. Ein gutes Stück meiner Kenntnisse und Fähigkeiten verdanke ich den vielen Foren, Webseiten, Newsgroups und Individuen die Informationen und Software kostenfrei und allgemein zugänglich bereitstellen.
188
189Aus diesem Grund stelle ich meine Software (sofern nicht anders angegeben) unter der freizügigen [Do What the Fuck You Want to Public License](http://www.wtfpl.net) zur Verfügung. Vielleicht findet jemand den Code nützlich oder kann Erkenntnisse daraus gewinnen.
190
191~~~
192Copyright © 2020 Thomas Schmucker
193This work is free. You can redistribute it and/or modify it under the
194terms of the Do What The Fuck You Want To Public License, Version 2,
195as published by Sam Hocevar. See https://www.wtfpl.net/ for more details.
196~~~
197