ec.h raw

   1  /*
   2   * Copyright (c) 1993-1994 by Xerox Corporation.  All rights reserved.
   3   *
   4   * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
   5   * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
   6   *
   7   * Permission is hereby granted to use or copy this program
   8   * for any purpose, provided the above notices are retained on all copies.
   9   * Permission to modify the code and to distribute modified code is granted,
  10   * provided the above notices are retained, and a notice that the code was
  11   * modified is included with the above copyright notice.
  12   */
  13  
  14  #ifndef EC_H
  15  #define EC_H
  16  
  17  #ifndef CORD_H
  18  #  include "cord.h"
  19  #endif
  20  
  21  #ifdef __cplusplus
  22  extern "C" {
  23  #endif
  24  
  25  /*
  26   * Extensible cords are strings that may be destructively appended to.
  27   * They allow fast construction of cords from characters that are being
  28   * read from a stream.
  29   *
  30   * A client might look like:
  31   * ```
  32   *   CORD_ec x;
  33   *   CORD result;
  34   *   char c;
  35   *   FILE *f;
  36   *
  37   *   CORD_ec_init(x);
  38   *   while (...) {
  39   *       c = getc(f);
  40   *       ...
  41   *       CORD_ec_append(x, c);
  42   *   }
  43   *   result = CORD_balance(CORD_ec_to_cord(x));
  44   * ```
  45   *
  46   * If a C string is desired as the final result, the call to `CORD_balance`
  47   * may be replaced by a call to `CORD_to_char_star`.
  48   */
  49  
  50  #ifndef CORD_BUFSZ
  51  #  define CORD_BUFSZ 128
  52  #endif
  53  
  54  /**
  55   * This structure represents the concatenation of `ec_cord` with
  56   * `ec_buf[0 .. ec_bufptr - ec_buf - 1]`.
  57   */
  58  typedef struct CORD_ec_struct {
  59    CORD ec_cord;
  60    char *ec_bufptr;
  61    char ec_buf[CORD_BUFSZ + 1];
  62  } CORD_ec[1];
  63  
  64  /** Flush the buffer part of the extended cord into extensible cord. */
  65  CORD_API void CORD_ec_flush_buf(CORD_ec);
  66  
  67  /** Convert an extensible cord to a cord. */
  68  #define CORD_ec_to_cord(x) (CORD_ec_flush_buf(x), (x)[0].ec_cord)
  69  
  70  /** Initialize an extensible cord. */
  71  #define CORD_ec_init(x) \
  72    ((x)[0].ec_cord = 0, (void)((x)[0].ec_bufptr = (x)[0].ec_buf))
  73  
  74  /** Append a character to an extensible cord. */
  75  #define CORD_ec_append(x, c)                             \
  76    ((void)((x)[0].ec_bufptr == (x)[0].ec_buf + CORD_BUFSZ \
  77                ? (CORD_ec_flush_buf(x), 0)                \
  78                : 0),                                      \
  79     (void)(*(x)[0].ec_bufptr++ = (c)))
  80  
  81  /**
  82   * Append a cord to an extensible cord.  Structure remains shared with
  83   * the original.
  84   */
  85  CORD_API void CORD_ec_append_cord(CORD_ec, CORD);
  86  
  87  #ifdef __cplusplus
  88  } /* extern "C" */
  89  #endif
  90  
  91  #endif /* EC_H */
  92