/* lineio.c - Don Yang (uguu.org) 03/10/04 */ /*@ -branchstate -globstate -usedef -compdef @*/ #include #include #include #include static FILE *Infile, *Outfile; static size_t LineCount, MaxLineSize; static int Process(FILE *infile); static int ProcessLine(char *line, size_t size); /* Test driver */ int main(int argc, char **argv) { LineCount = MaxLineSize = 0; Infile = stdin; Outfile = stdout; if( argc > 1 ) { if( (Infile = fopen(argv[1], "rb")) == NULL ) return printf("Can not open %s\n", argv[1]); if( argc > 2 ) { if( (Outfile = fopen(argv[2], "wb+")) == NULL ) { (void)fclose(Infile); return printf("Can not create %s\n", argv[2]); } } } (void)Process(Infile); fprintf(stderr, "%u lines, longest line = %u characters\n", (unsigned)LineCount, (unsigned)MaxLineSize); (void)fclose(Infile); (void)fclose(Outfile); return 0; } /* Line parsing loop */ static int Process(FILE *infile) { size_t maxsize, buffersize, start, end, eof, grow, i; char *buffer, *p; if( (buffer = (char*)malloc(maxsize = 0x100)) == NULL ) { (void)puts("not enough memory"); return 1; } buffersize = eof = start = 0; for(;;) { /* Fill buffer */ if( buffersize < maxsize ) { i = fread(buffer + buffersize, 1, maxsize - buffersize, infile); if( i < maxsize - buffersize ) eof = 1; buffersize += i; } /* Tokenize buffer */ for(start = grow = 0; start < buffersize; start = end) { grow = 1; p = buffer + start; for(end = start; end < buffersize; end++) { if( *p == '\n' ) { (void)ProcessLine(buffer + start, ++end - start); grow = 0; break; } else if( *p == '\r' ) { if( ++end < buffersize ) { if( *++p == '\n' ) end++; (void)ProcessLine(buffer + start, end - start); grow = 0; } break; } p++; } if( grow != 0 ) break; } if( eof != 0 ) break; if( start > 0 ) { /* Shift partial line */ p = buffer; for(i = 0; i < buffersize - start; i++) { *p = *(p + start); p++; } buffersize -= start; start = 0; } else { /* Expand buffer */ if( (p = (char*)malloc(maxsize * 2)) == NULL ) { free(buffer); (void)puts("not enough memory"); return 1; } memcpy(p, buffer, buffersize); free(buffer); buffer = p; maxsize *= 2; } } /* Last line */ if( buffersize > start ) (void)ProcessLine(buffer + start, buffersize - start); free(buffer); return 0; } /* Test stub */ static int ProcessLine(char *line, size_t size) { size_t i; assert(size > 0); (void)fwrite(line, size, 1, Outfile); for(i = 0; i < 2 && size > 0; i++) { if( line[size - 1] == '\n' || line[size - 1] == '\r' ) size--; } LineCount++; if( MaxLineSize < size ) MaxLineSize = size; return 0; }