@@@ dvdrip-upload: change settings while i'm stealing someone else's internet
[dvdrip] / lib.h
diff --git a/lib.h b/lib.h
index e9abbaa..7c4a0cb 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -143,6 +143,42 @@ extern PRINTF_LIKE(2, 3) NORETURN
         * exit with status code 2.
         */
 
+/*----- Resizing buffers --------------------------------------------------*/
+
+struct buf {
+  /* A buffer for a string which can grow automatically. */
+
+  char *p;                             /* pointer to the buffer */
+  size_t n, sz;                                /* string length, buffer size */
+};
+#define BUF_INIT { 0, 0, 0 }
+
+static inline void buf_rewind(struct buf *b) { b->n = 0; }
+       /* Throw away the current contents of B so that new stuff gets added
+        * to the beginning.
+        */
+
+static inline void buf_free(struct buf *b)
+  { free(b->p); b->p = 0; b->n = b->sz = 0; }
+       /* Release the memory allocated for B.  The buffer can be reused
+        * immediately and/or freed again safely.
+        */
+
+extern void buf__grow(struct buf *b);
+       /* Make B's buffer larger, so that (at least) one extra byte can be
+        * written to it.  (Internal to `buf_putc'.)
+        */
+
+static inline void buf_putc(struct buf *b, int ch)
+  { if (b->n >= b->sz) buf__grow(b); b->p[b->n++] = ch; }
+       /* Append the character CH to the buffer B. */
+
+static inline void buf_putz(struct buf *b)
+  { if (b->n >= b->sz) buf__grow(b); b->p[b->n] = 0; }
+       /* Append a zero byte to B without increasing the string length, so
+        * that a future `buf_putc' will overwrite it.
+        */
+
 /*----- Resizing vectors --------------------------------------------------*/
 
 #define DEFVEC(vtype, etype)                                           \
@@ -160,14 +196,16 @@ extern PRINTF_LIKE(2, 3) NORETURN
 } while (0)
        /* Free the vector VV.  It's safe to free a vector multiple times. */
 
+extern void *vec__grow(void *p, size_t esz, size_t *sz_inout);
+       /* Extend the buffer P, which currently has space for *SZ_INOUT
+        * elements, each ESZ bytes in size, so that there's space for at
+        * least one one more; return the new buffer address, and update
+        * *SZ_INOUT with the new size.
+        */
+
 #define VEC_PUSH(p, vv) do {                                           \
-  size_t _want;                                                                \
-  if ((vv)->n >= (vv)->sz) {                                           \
-    (vv)->sz = (vv)->sz ? 2*(vv)->sz : 32;                             \
-    _want = (vv)->sz*sizeof(*(vv)->v);                                 \
-    (vv)->v = realloc((vv)->v, _want);                                 \
-    if (!(vv)->v) bail("out of memory allocating %zu bytes", _want);   \
-  }                                                                    \
+  if ((vv)->n >= (vv)->sz)                                             \
+    (vv)->v = vec__grow((vv)->v, sizeof(*(vv)->v), &(vv)->sz);         \
   (p) = &(vv)->v[(vv)->n++];                                           \
 } while (0)
        /* Add an initialized element to the end of vector VV, storing its
@@ -202,6 +240,13 @@ extern void sit(double t);
         * fractional.
         */
 
+extern int read_line(FILE *fp, struct buf *b);
+       /* Read a line from FP, appending it to the buffer B, leaving the
+        * string in B null-terminated (as if by `buf_putz').  Return 0 on
+        * success, or -1 if nothing was read (not even an empty line) before
+        * we encountered end-of-file or a read error.
+        */
+
 extern void carefully_write(int fd, const void *buf, size_t sz);
        /* Write SZ bytes to file descriptor FD, starting at BUF.  Report a
         * fatal error if this fails.  Correctly handles short writes and
@@ -235,7 +280,7 @@ extern off_t device_size(int fd, const char *file, int *blksz_out);
         * device only, store the block size in *BLKSZ_OUT.  (Hence,
         * *BLKSZ_OUT will be left unchanged if FD is open on a regular
         * file.)  If FD refers to any other kind of object then report a
-        * fatal error.
+        * fatal error quoting FILE as the name of the device.
         */
 
 /*----- Progress utilities ------------------------------------------------*/
@@ -256,19 +301,19 @@ extern void hide_banner(void);
 
 /*----- DVD utilities -----------------------------------------------------*/
 
-extern void open_dvd(const char *device, int mode,
-                    int *fd_out, dvd_reader_t **dvd_out);
+extern int open_dvd(const char *device, int mode,
+                   int *fd_out, dvd_reader_t **dvd_out);
        /* Open the DEVICE.  If FD_OUT is not null, then open a file
         * descriptor onto the device, with the given open(2)-style MODE,
         * storing the descriptor in *FD_OUT; if DVD_OUT is not null, then
         * open a `libdvdread' handle onto the devie and store it in
         * *DVD_OUT.  If both are null, then why are you calling this
-        * function?
+        * function?  Returns 0 on success or -1 on failure.
         *
         * If DEVICE refers to an actual block device, and no medium is
         * currently inserted, then put up a banner prompting the user and
-        * wait for a medium to be inserted.  Other problems are reported as
-        * fatal errors.
+        * wait for a medium to be inserted.  Other problems are reported to
+        * stderr.
         */
 
 enum { RAW, IFO, VOB, BUP };