return n;
}
+int kgetline(kstring_t *s, kgets_func *fgets_fn, void *fp)
+{
+ size_t l0 = s->l;
+
+ while (s->l == l0 || s->s[s->l-1] != '\n') {
+ if (s->m - s->l < 200) ks_resize(s, s->m + 200);
+ if (fgets_fn(s->s + s->l, s->m - s->l, fp) == NULL) break;
+ s->l += strlen(s->s + s->l);
+ }
+
+ if (s->l == l0) return EOF;
+
+ if (s->l > l0 && s->s[s->l-1] == '\n') {
+ s->l--;
+ if (s->l > l0 && s->s[s->l-1] == '\r') s->l--;
+ }
+ s->s[s->l] = '\0';
+ return 0;
+}
+
/**********************
* Boyer-Moore search *
**********************/
* if sep is not changed. */
char *kstrtok(const char *str, const char *sep, ks_tokaux_t *aux);
+ /* kgetline() uses the supplied fgets()-like function to read a "\n"-
+ * or "\r\n"-terminated line from fp. The line read is appended to the
+ * kstring without its terminator and 0 is returned; EOF is returned at
+ * EOF or on error (determined by querying fp, as per fgets()). */
+ typedef char *kgets_func(char *, int, void *);
+ int kgetline(kstring_t *s, kgets_func *fgets, void *fp);
+
#ifdef __cplusplus
}
#endif
#include <limits.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
check("kputl()", ks, buf);
}
-int main()
+static char *mem_gets(char *buf, int buflen, void *vtextp)
+{
+ const char **textp = (const char **) vtextp;
+
+ const char *nl = strchr(*textp, '\n');
+ size_t n = nl? nl - *textp + 1 : strlen(*textp);
+
+ if (n == 0) return NULL;
+
+ if (n > buflen-1) n = buflen-1;
+ memcpy(buf, *textp, n);
+ buf[n] = '\0';
+ *textp += n;
+ return buf;
+}
+
+void test_kgetline(kstring_t *ks, const char *text, ...)
+{
+ const char *exp;
+ va_list arg;
+
+ va_start(arg, text);
+ while ((exp = va_arg(arg, const char *)) != NULL) {
+ ks->l = 0;
+ if (kgetline(ks, mem_gets, &text) != 0) kputs("EOF", ks);
+ check("kgetline()", ks, exp);
+ }
+ va_end(arg);
+
+ ks->l = 0;
+ if (kgetline(ks, mem_gets, &text) == 0) check("kgetline()", ks, "EOF");
+}
+
+int main(int argc, char **argv)
{
kstring_t ks;
test_kputl(&ks, -LONG_MAX);
test_kputl(&ks, LONG_MIN);
+ test_kgetline(&ks, "", NULL);
+ test_kgetline(&ks, "apple", "apple", NULL);
+ test_kgetline(&ks, "banana\n", "banana", NULL);
+ test_kgetline(&ks, "carrot\r\n", "carrot", NULL);
+ test_kgetline(&ks, "\n", "", NULL);
+ test_kgetline(&ks, "\n\n", "", "", NULL);
+ test_kgetline(&ks, "foo\nbar", "foo", "bar", NULL);
+ test_kgetline(&ks, "foo\nbar\n", "foo", "bar", NULL);
+ test_kgetline(&ks,
+ "abcdefghijklmnopqrstuvwxyz0123456789\nABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
+ "abcdefghijklmnopqrstuvwxyz0123456789",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL);
+
+ if (argc > 1) {
+ FILE *f = fopen(argv[1], "r");
+ if (f) {
+ for (ks.l = 0; kgetline(&ks, (kgets_func *)fgets, f) == 0; ks.l = 0)
+ puts(ks.s);
+ fclose(f);
+ }
+ }
+
free(ks.s);
if (nfail > 0) {