Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This file is hereby released to the public domain.
- ~aaaaaa123456789, 2015-01-21
- last updated 2015-01-23
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "common.h"
- static char ** get_lines_data(unsigned, const char *, unsigned char *);
- static void flatten_line_pointers(char ***, unsigned);
- static int add_line_count(void *, void *);
- static int array_all_callback(void *, void *);
- struct array_all_struct {
- int (* callback) (void *, void *);
- void * data;
- };
- char * get_line (unsigned char * reachedEOF) {
- char * line = NULL;
- unsigned length = 0;
- int newchar;
- for (newchar = getchar(); (newchar != EOF) && (newchar != '\n'); newchar = getchar()) {
- line = realloc(line, ++ length);
- line[length - 1] = newchar;
- }
- line = realloc(line, length + 1);
- line[length] = 0;
- if (reachedEOF) *reachedEOF = newchar == EOF;
- return line;
- }
- char ** get_lines (unsigned lines, const char * stopper, int single_pointer, unsigned char * reachedEOF) {
- if (reachedEOF) *reachedEOF = 0;
- char ** result = get_lines_data(lines, stopper, reachedEOF);
- if (single_pointer) flatten_line_pointers(&result, count_lines(result));
- return result;
- }
- char * read_all (FILE * stream) {
- char * result;
- unsigned length = read_all_binary(stream, &result);
- if (!result) return NULL;
- result = realloc(result, length + 1);
- result[length] = 0;
- return result;
- }
- unsigned read_all_binary (FILE * stream, char ** result) {
- if (!result) return -1;
- *result = NULL;
- if (!stream) return -2;
- char * data = NULL;
- unsigned length = 0;
- char buffer[16384];
- unsigned short read_length;
- rewind(stream);
- while (!(feof(stream) || ferror(stream))) {
- read_length = fread(buffer, 1, 16384, stream);
- data = realloc(data, length + read_length);
- memcpy(data + length, buffer, read_length);
- length += read_length;
- }
- if (ferror(stream)) {
- free(data);
- return -3;
- }
- *result = data;
- return length;
- }
- void free_lines_array (char ** lines, unsigned size) {
- if (!size) size = -1;
- unsigned line;
- for (line = 0; line < size; line ++) {
- if (!lines[line]) break;
- free(lines[line]);
- }
- free(lines);
- }
- int check_line (char ** line, unsigned expected_size, const char * valid_chars, char replacement, FILE * error_stream, unsigned line_number) {
- int errors = LCERR_OK;
- unsigned pos, length;
- char * current;
- char lnbuf[30];
- if (line_number)
- sprintf(lnbuf, "Line %u", line_number);
- else
- strcpy(lnbuf, "Line");
- if ((valid_chars || expected_size) && (!replacement)) return LCERR_INVALID_REPLACEMENT;
- if (!expected_size) goto size_checked;
- length = strlen(*line);
- if (length > expected_size) {
- if (error_stream) fprintf(error_stream, "%s is %u characters long (expected: %u), truncating\n", lnbuf, length, expected_size);
- *line = realloc(*line, expected_size + 1);
- expected_size[*line] = 0;
- errors |= LCERR_LINE_TOO_LONG;
- } else if (length < expected_size) {
- if (error_stream)
- fprintf(error_stream, "%s is %u characters long (expected: %u), padding with '%c'\n", lnbuf, length, expected_size, replacement);
- *line = realloc(*line, expected_size + 1);
- memset(*line + length, replacement, expected_size - length);
- expected_size[*line] = 0;
- errors |= LCERR_LINE_TOO_SHORT;
- }
- size_checked:
- if (!valid_chars) goto chars_checked;
- for (current = *line, pos = 0; current < (*line + expected_size); current += pos + 1) {
- pos = strspn(current, valid_chars);
- if ((current + pos) >= (*line + expected_size)) break;
- length = current - *line;
- if (error_stream)
- fprintf(error_stream, "%s: spurious character 0x%02x at column %u, inserting '%c'\n", lnbuf, current[pos], pos + length + 1, replacement);
- current[pos] = replacement;
- errors |= LCERR_SPURIOUS_CHARS;
- }
- chars_checked:
- return errors;
- }
- unsigned get_number (void) {
- char * line = get_line(NULL);
- if (!*line) {
- free(line);
- return 0;
- }
- char * end;
- unsigned number = strtoul(line, &end, 10);
- if (*end) number = 0;
- free(line);
- return number;
- }
- int array_each (void * array, unsigned item_size, unsigned count, void * stopper, int (* callback) (void *, void *), void * data) {
- char * current;
- int value;
- if (!array) return 0;
- if (!count) count = -1;
- for (current = array; count; count --, current += item_size) {
- if ((stopper) && (!memcmp(current, stopper, item_size))) return 0;
- value = (*callback)(current, data);
- if (value) return value;
- }
- return 0;
- }
- int array_all (void * array, unsigned item_size, unsigned count, void * stopper, int (* callback) (void *, void *), void * data) {
- struct array_all_struct cbdata = {.callback = callback, .data = data};
- return !array_each(array, item_size, count, stopper, &array_all_callback, &cbdata);
- }
- unsigned count_lines (char ** lines) {
- unsigned count = 0;
- array_each(lines, sizeof(char *), 0, NULL, &add_line_count, &count);
- return count;
- }
- char ** tokenize_string (const char * string, const char * delimiters, int single_pointer) {
- if (!string) return NULL;
- if (!delimiters) delimiters = " \f\n\r\t\v";
- char ** result = malloc(sizeof(char *));
- const char * current = string + strspn(string, delimiters);
- unsigned count = 0;
- unsigned length;
- while (*current) {
- length = strcspn(current, delimiters);
- result[count] = malloc(length + 1);
- memcpy(result[count], current, length);
- result[count][length] = 0;
- result = realloc(result, sizeof(char *) * (count + 2));
- count ++;
- current += length;
- length = strspn(current, delimiters);
- current += length;
- }
- result[count] = NULL;
- if (single_pointer) flatten_line_pointers(&result, count_lines(result));
- return result;
- }
- void * xmalloc (size_t size) {
- if (!size) return NULL;
- void * rv = malloc(size);
- if (!rv) {
- fputs("ERROR: Out of memory.\n", stderr);
- abort();
- }
- return rv;
- }
- void * xrealloc (void * buf, size_t size) {
- void * rv = realloc(buf, size);
- if (!rv) {
- fputs("ERROR: Out of memory.\n", stderr);
- abort();
- }
- return rv;
- }
- static char ** get_lines_data (unsigned lines, const char * stopper, unsigned char * reachedEOF) {
- char ** result = malloc(sizeof(char *));
- unsigned count = 0;
- char * line;
- unsigned char eofstatus = 0;
- if (!reachedEOF) reachedEOF = &eofstatus;
- while (1) {
- if (lines && (count >= lines)) break;
- line = get_line(reachedEOF);
- if (stopper && !strcmp(stopper, line)) {
- free(line);
- break;
- }
- result[count] = line;
- result = realloc(result, sizeof(char *) * (count + 2));
- count ++;
- if (*reachedEOF) break;
- }
- result[count] = NULL;
- return result;
- }
- static void flatten_line_pointers (char *** pointers, unsigned lines) {
- unsigned offset = sizeof(char *) * (lines + 1);
- unsigned line;
- unsigned total = 0;
- for (line = 0; line < lines; line ++) total += strlen(line[*pointers]);
- char ** result = malloc(offset + total + lines);
- char * lineptr = ((char *) result) + offset;
- result[lines] = NULL;
- for (line = 0; line < lines; line ++) {
- offset = strlen(line[*pointers]) + 1;
- memcpy(lineptr, line[*pointers], offset);
- free(line[*pointers]);
- result[line] = lineptr;
- lineptr += offset;
- }
- free(*pointers);
- *pointers = result;
- }
- static int add_line_count (void * line, void * count) {
- if (!*((char **) line)) return 1;
- unsigned * c = count;
- (*c) ++;
- return 0;
- }
- static int array_all_callback (void * item, void * data) {
- return !(((struct array_all_struct *) data -> callback)(item, (struct array_all_struct *) data -> data));
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement