fork download
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4.  
  5. /*** Object types */
  6.  
  7. enum e_grow_status {
  8. grow_status_success,
  9. grow_status_invalid_param,
  10. grow_status_too_big,
  11. grow_status_out_of_memory,
  12. grow_status_count
  13. };
  14. typedef enum e_grow_status e_grow_status;
  15.  
  16. /*** Function declarations */
  17.  
  18. e_grow_status realloc_str_buf(
  19. char ** buf_ptr,
  20. unsigned int new_size
  21. );
  22.  
  23. e_grow_status append_buf(
  24. char ** buf_ptr,
  25. char ** tail_ptr,
  26. unsigned int tail_size
  27. );
  28.  
  29. int grow_status_msg(e_grow_status code);
  30.  
  31. /*** Function definitions */
  32.  
  33. int main(void) {
  34. /*
  35.   * We will attempt to grow our storage by this
  36.   * amount, each time we need to grow it
  37.   */
  38. const unsigned int growth = 10;
  39.  
  40. /*
  41.   * This will point to where we put our data.
  42.   * Initially, it points to no storage
  43.   */
  44. char * buf = NULL;
  45.  
  46. /* Where we append data when the buffer is grown */
  47. char * tail;
  48.  
  49. /* Buffer-growing status */
  50. e_grow_status status;
  51.  
  52. /*
  53.   * Keep getting lines of input until there's no
  54.   * more input to be had. We append the new data
  55.   * to the end of the current data
  56.   */
  57. do {
  58. /* Make sure we have some buffer available */
  59. status = append_buf(&buf, &tail, growth);
  60. if (status != grow_status_success) {
  61. /* There was a problem with the buffer */
  62. free(buf);
  63. return grow_status_msg(status);
  64. }
  65.  
  66. /* Read a line of input */
  67. if (!fgets(tail, growth, stdin)) {
  68. /* What is the nature of the problem? */
  69. if (ferror(stdin)) {
  70. /* An unexpected error */
  71. fprintf(stderr, "Unexpected input error!\n");
  72. free(buf);
  73. return EXIT_FAILURE;
  74. }
  75. }
  76.  
  77. /* Do it all again */
  78. continue;
  79. } while (!feof(stdin));
  80.  
  81. /* All done */
  82. "----- All input: -----\n\n%s\n\n"
  83. "----- Final size: %u -----\n",
  84. buf,
  85. (unsigned int) (tail - buf)
  86. );
  87. free(buf);
  88. return EXIT_SUCCESS;
  89. }
  90.  
  91. e_grow_status realloc_str_buf(
  92. char ** buf_ptr,
  93. unsigned int new_size
  94. ) {
  95. /*
  96.   * When we use 'realloc', we don't want to lose
  97.   * track of where '*buf_ptr' currently points, so
  98.   * we use another pointer to capture the result
  99.   */
  100. char * new_buf;
  101.  
  102. /* Check for invalid parameters */
  103. if (!buf_ptr || !new_size) {
  104. return grow_status_invalid_param;
  105. }
  106.  
  107. /* Allocate more storage */
  108. new_buf = realloc(*buf_ptr, new_size);
  109. if (!new_buf) {
  110. /* Problem */
  111. return grow_status_out_of_memory;
  112. }
  113.  
  114. /* Update the caller's pointer */
  115. *buf_ptr = new_buf;
  116.  
  117. return grow_status_success;
  118. }
  119.  
  120. e_grow_status append_buf(
  121. char ** buf_ptr,
  122. char ** tail_ptr,
  123. unsigned int tail_size
  124. ) {
  125. /* The current length of stored data */
  126. unsigned int data_len;
  127.  
  128. /* The next size for a grown buffer */
  129. unsigned int new_size;
  130.  
  131. /* Buffer-growing status */
  132. e_grow_status status;
  133.  
  134. /* Check for invalid parameter */
  135. if (!buf_ptr || !tail_ptr || !tail_size) {
  136. return grow_status_invalid_param;
  137. }
  138.  
  139. /* How much storage is used? */
  140. if (*buf_ptr) {
  141. data_len = strlen(*buf_ptr);
  142. } else {
  143. data_len = 0;
  144. }
  145.  
  146. /* How much total storage do we need? */
  147. new_size = data_len + tail_size;
  148. if (new_size < data_len) {
  149. /* Uh oh, we've wrapped around the maximum size */
  150. return grow_status_too_big;
  151. }
  152.  
  153. /* Allocate 'tail_size' more storage */
  154. status = realloc_str_buf(buf_ptr, new_size);
  155. if (status != grow_status_success) {
  156. /* Problem */
  157. return status;
  158. }
  159.  
  160. /* Tell the caller where the unused storage begins */
  161. *tail_ptr = *buf_ptr + data_len;
  162.  
  163. /*
  164.   * Ensure the tail begins with a null terminator,
  165.   * for the sake of 'strlen' safety
  166.   */
  167. **tail_ptr = 0;
  168.  
  169. return grow_status_success;
  170. }
  171.  
  172. int grow_status_msg(e_grow_status code) {
  173. char * msg;
  174.  
  175. switch (code) {
  176. case grow_status_success:
  177. /* No error */
  178. return EXIT_SUCCESS;
  179.  
  180. case grow_status_invalid_param:
  181. msg = "An invalid parameter was passed!";
  182. break;
  183.  
  184. case grow_status_too_big:
  185. msg = "Buffer too big!";
  186. break;
  187.  
  188. case grow_status_out_of_memory:
  189. msg = "Out of memory!";
  190. break;
  191.  
  192. default:
  193. msg = "Invalid status!";
  194. break;
  195. }
  196.  
  197. fprintf(stderr, "grow_status_msg: %s\n", msg);
  198. return EXIT_FAILURE;
  199. }
Success #stdin #stdout 0.02s 1856KB
stdin
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/*** Object types */

enum e_grow_status {
    grow_status_success,
    grow_status_invalid_param,
    grow_status_too_big,
    grow_status_out_of_memory,
    grow_status_count
  };
typedef enum e_grow_status e_grow_status;

/*** Function declarations */

e_grow_status realloc_str_buf(
    char ** buf_ptr,
    unsigned int new_size
  );

e_grow_status append_buf(
    char ** buf_ptr,
    char ** tail_ptr,
    unsigned int tail_size
  );

int grow_status_msg(e_grow_status code);

/*** Function definitions */

int main(void) {
    /*
     * We will attempt to grow our storage by this
     * amount, each time we need to grow it
     */
    const unsigned int growth = 10;

    /*
     * This will point to where we put our data.
     * Initially, it points to no storage
     */
    char * buf = NULL;

    /* Where we append data when the buffer is grown */
    char * tail;

    /* Buffer-growing status */
    e_grow_status status;

    /*
     * Keep getting lines of input until there's no
     * more input to be had.  We append the new data
     * to the end of the current data
     */
    do {
        /* Make sure we have some buffer available */
        status = append_buf(&buf, &tail, growth);
        if (status != grow_status_success) {
            /* There was a problem with the buffer */
            free(buf);
            return grow_status_msg(status);
          }

        /* Read a line of input */
        if (!fgets(tail, growth, stdin)) {
            /* What is the nature of the problem? */
            if (ferror(stdin)) {
                /* An unexpected error */
                fprintf(stderr, "Unexpected input error!\n");
                free(buf);
                return EXIT_FAILURE;
              }
          }

        /* Do it all again */
        continue;
      } while (!feof(stdin));
        
    /* All done */
    printf(
        "----- All input: -----\n\n%s\n\n"
        "----- Final size: %u -----\n",
        buf,
        (unsigned int) (tail - buf)
      );
    free(buf);
    return EXIT_SUCCESS;
  }

e_grow_status realloc_str_buf(
    char ** buf_ptr,
    unsigned int new_size
  ) {
    /*
     * When we use 'realloc', we don't want to lose
     * track of where '*buf_ptr' currently points, so
     * we use another pointer to capture the result
     */
    char * new_buf;

    /* Check for invalid parameters */
    if (!buf_ptr || !new_size) {
        return grow_status_invalid_param;
      }

    /* Allocate more storage */
    new_buf = realloc(*buf_ptr, new_size);
    if (!new_buf) {
        /* Problem */
        return grow_status_out_of_memory;
      }

    /* Update the caller's pointer */
    *buf_ptr = new_buf;

    return grow_status_success;
  }

e_grow_status append_buf(
    char ** buf_ptr,
    char ** tail_ptr,
    unsigned int tail_size
  ) {
    /* The current length of stored data */
    unsigned int data_len;

    /* The next size for a grown buffer */
    unsigned int new_size;

    /* Buffer-growing status */
    e_grow_status status;

    /* Check for invalid parameter */
    if (!buf_ptr || !tail_ptr || !tail_size) {
        return grow_status_invalid_param;
      }

    /* How much storage is used? */
    if (*buf_ptr) {
        data_len = strlen(*buf_ptr);
      } else {
        data_len = 0;
      }

    /* How much total storage do we need? */
    new_size = data_len + tail_size;
    if (new_size < data_len) {
        /* Uh oh, we've wrapped around the maximum size */
        return grow_status_too_big;
      }

    /* Allocate 'tail_size' more storage */
    status = realloc_str_buf(buf_ptr, new_size);
    if (status != grow_status_success) {
        /* Problem */
        return status;
      }

    /* Tell the caller where the unused storage begins */
    *tail_ptr = *buf_ptr + data_len;

    /*
     * Ensure the tail begins with a null terminator,
     * for the sake of 'strlen' safety
     */
    **tail_ptr = 0;

    return grow_status_success;
  }

int grow_status_msg(e_grow_status code) {
    char * msg;

    switch (code) {
        case grow_status_success:
          /* No error */
          return EXIT_SUCCESS;

        case grow_status_invalid_param:
          msg = "An invalid parameter was passed!";
          break;

        case grow_status_too_big:
          msg = "Buffer too big!";
          break;

        case grow_status_out_of_memory:
          msg = "Out of memory!";
          break;

        default:
          msg = "Invalid status!";
          break;
      }

    fprintf(stderr, "grow_status_msg: %s\n", msg);
    return EXIT_FAILURE;
  }
stdout
----- All input: -----

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/*** Object types */

enum e_grow_status {
    grow_status_success,
    grow_status_invalid_param,
    grow_status_too_big,
    grow_status_out_of_memory,
    grow_status_count
  };
typedef enum e_grow_status e_grow_status;

/*** Function declarations */

e_grow_status realloc_str_buf(
    char ** buf_ptr,
    unsigned int new_size
  );

e_grow_status append_buf(
    char ** buf_ptr,
    char ** tail_ptr,
    unsigned int tail_size
  );

int grow_status_msg(e_grow_status code);

/*** Function definitions */

int main(void) {
    /*
     * We will attempt to grow our storage by this
     * amount, each time we need to grow it
     */
    const unsigned int growth = 10;

    /*
     * This will point to where we put our data.
     * Initially, it points to no storage
     */
    char * buf = NULL;

    /* Where we append data when the buffer is grown */
    char * tail;

    /* Buffer-growing status */
    e_grow_status status;

    /*
     * Keep getting lines of input until there's no
     * more input to be had.  We append the new data
     * to the end of the current data
     */
    do {
        /* Make sure we have some buffer available */
        status = append_buf(&buf, &tail, growth);
        if (status != grow_status_success) {
            /* There was a problem with the buffer */
            free(buf);
            return grow_status_msg(status);
          }

        /* Read a line of input */
        if (!fgets(tail, growth, stdin)) {
            /* What is the nature of the problem? */
            if (ferror(stdin)) {
                /* An unexpected error */
                fprintf(stderr, "Unexpected input error!\n");
                free(buf);
                return EXIT_FAILURE;
              }
          }

        /* Do it all again */
        continue;
      } while (!feof(stdin));
        
    /* All done */
    printf(
        "----- All input: -----\n\n%s\n\n"
        "----- Final size: %u -----\n",
        buf,
        (unsigned int) (tail - buf)
      );
    free(buf);
    return EXIT_SUCCESS;
  }

e_grow_status realloc_str_buf(
    char ** buf_ptr,
    unsigned int new_size
  ) {
    /*
     * When we use 'realloc', we don't want to lose
     * track of where '*buf_ptr' currently points, so
     * we use another pointer to capture the result
     */
    char * new_buf;

    /* Check for invalid parameters */
    if (!buf_ptr || !new_size) {
        return grow_status_invalid_param;
      }

    /* Allocate more storage */
    new_buf = realloc(*buf_ptr, new_size);
    if (!new_buf) {
        /* Problem */
        return grow_status_out_of_memory;
      }

    /* Update the caller's pointer */
    *buf_ptr = new_buf;

    return grow_status_success;
  }

e_grow_status append_buf(
    char ** buf_ptr,
    char ** tail_ptr,
    unsigned int tail_size
  ) {
    /* The current length of stored data */
    unsigned int data_len;

    /* The next size for a grown buffer */
    unsigned int new_size;

    /* Buffer-growing status */
    e_grow_status status;

    /* Check for invalid parameter */
    if (!buf_ptr || !tail_ptr || !tail_size) {
        return grow_status_invalid_param;
      }

    /* How much storage is used? */
    if (*buf_ptr) {
        data_len = strlen(*buf_ptr);
      } else {
        data_len = 0;
      }

    /* How much total storage do we need? */
    new_size = data_len + tail_size;
    if (new_size < data_len) {
        /* Uh oh, we've wrapped around the maximum size */
        return grow_status_too_big;
      }

    /* Allocate 'tail_size' more storage */
    status = realloc_str_buf(buf_ptr, new_size);
    if (status != grow_status_success) {
        /* Problem */
        return status;
      }

    /* Tell the caller where the unused storage begins */
    *tail_ptr = *buf_ptr + data_len;

    /*
     * Ensure the tail begins with a null terminator,
     * for the sake of 'strlen' safety
     */
    **tail_ptr = 0;

    return grow_status_success;
  }

int grow_status_msg(e_grow_status code) {
    char * msg;

    switch (code) {
        case grow_status_success:
          /* No error */
          return EXIT_SUCCESS;

        case grow_status_invalid_param:
          msg = "An invalid parameter was passed!";
          break;

        case grow_status_too_big:
          msg = "Buffer too big!";
          break;

        case grow_status_out_of_memory:
          msg = "Out of memory!";
          break;

        default:
          msg = "Invalid status!";
          break;
      }

    fprintf(stderr, "grow_status_msg: %s\n", msg);
    return EXIT_FAILURE;
  }

----- Final size: 4644 -----