1 /* vifm
2  * Copyright (C) 2001 Ken Steen.
3  * Copyright (C) 2011 xaizek.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include "file_streams.h"
21 
22 #include <stddef.h> /* NULL size_t ssize_t */
23 #include <stdio.h> /* FILE */
24 #include <stdlib.h> /* free() realloc() */
25 #include <string.h> /* strlen() */
26 
27 static int get_char(FILE *fp);
28 
29 char *
read_line(FILE * fp,char buf[])30 read_line(FILE *fp, char buf[])
31 {
32 	enum { PART_BUFFER_LEN = 512 };
33 	char part_buf[PART_BUFFER_LEN];
34 	char *last_allocated_block = NULL;
35 	size_t len = 0;
36 
37 	while(get_line(fp, part_buf, sizeof(part_buf)) != NULL)
38 	{
39 		size_t part_len = strlen(part_buf);
40 		const int eol = (part_len > 0) && (part_buf[part_len - 1] == '\n');
41 		const size_t new_len = len + (part_len - eol);
42 
43 		last_allocated_block = realloc(buf, new_len + 1);
44 		if(last_allocated_block == NULL)
45 		{
46 			break;
47 		}
48 
49 		if(eol)
50 		{
51 			part_buf[--part_len] = '\0';
52 		}
53 
54 		buf = last_allocated_block;
55 		strcpy(buf + len, part_buf);
56 
57 		if(eol)
58 		{
59 			break;
60 		}
61 
62 		len = new_len;
63 	}
64 
65 	if(last_allocated_block == NULL)
66 	{
67 		free(buf);
68 		buf = NULL;
69 	}
70 
71 	return buf;
72 }
73 
74 char *
get_line(FILE * fp,char buf[],size_t bufsz)75 get_line(FILE *fp, char buf[], size_t bufsz)
76 {
77 	int c = '\0';
78 	char *start = buf;
79 
80 	if(bufsz <= 1)
81 	{
82 		return NULL;
83 	}
84 
85 	while(bufsz > 1 && (c = get_char(fp)) != EOF)
86 	{
87 		*buf++ = c;
88 		bufsz--;
89 		if(c == '\n')
90 		{
91 			break;
92 		}
93 	}
94 	*buf = '\0';
95 
96 	return (c == EOF && buf == start) ? NULL : start;
97 }
98 
99 /* Returns next character from file stream. */
100 static int
get_char(FILE * fp)101 get_char(FILE *fp)
102 {
103 	int c = fgetc(fp);
104 	if(c == '\r')
105 	{
106 		int c2 = fgetc(fp);
107 		if(c2 != '\n')
108 			ungetc(c2, fp);
109 		c = '\n';
110 	}
111 	return c;
112 }
113 
114 void
skip_bom(FILE * fp)115 skip_bom(FILE *fp)
116 {
117 	int c;
118 
119 	c = fgetc(fp);
120 	if(c != 0xef)
121 	{
122 		ungetc(c, fp);
123 		return;
124 	}
125 
126 	c = fgetc(fp);
127 	if(c != 0xbb)
128 	{
129 		ungetc(c, fp);
130 		return;
131 	}
132 
133 	c = fgetc(fp);
134 	if(c != 0xbf)
135 	{
136 		ungetc(c, fp);
137 	}
138 }
139 
140 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
141 /* vim: set cinoptions+=t0 filetype=c : */
142