-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathggets.cpp
More file actions
212 lines (176 loc) · 6.25 KB
/
ggets.cpp
File metadata and controls
212 lines (176 loc) · 6.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/* File ggets.c - goodgets is a safe alternative to gets */
/* By C.B. Falconer. Public domain 2002-06-22 */
/* attribution appreciated. */
/* Revised 2002-06-26 New prototype.
2002-06-27 Incomplete final lines
2006-03-29 This version "templatised" for
Unicode and made to use "new/delete"
by David Pritchard
*/
/* fggets and ggets [which is fggets(ln, stdin)] set *ln to
a buffer filled with the next complete line from the text
stream f. The storage has been allocated within fggets,
and is normally reduced to be an exact fit. The trailing
\n has been removed, so the resultant line is ready for
dumping with puts. The buffer will be as large as is
required to hold the complete line.
Note: this means a final file line without a \n terminator
has an effective \n appended, as EOF occurs within the read.
If no error occurs fggets returns 0. If an EOF occurs on
the input file, EOF is returned. For memory allocation
errors some positive value is returned. In this case *ln
may point to a partial line. For other errors memory is
freed and *ln is set to NULL.
Freeing of assigned storage is the callers responsibility
*/
#include "stdafx.h"
#include <stdio.h>
#include <string.h> /* strchr */
#include <stdlib.h>
//#include "ggets.h"
// Adapted from code by Ana Sayfa. Thanks also to Dave Kondrad.
template<class TTCHAR>
TTCHAR *ReallocString(TTCHAR *ptr, size_t newsize, size_t oldsize, IN OUT bool& bOwnBuffer) /*size_t unsigned int*/
{
// Only reallocate if needed
if (newsize > oldsize)
{
TTCHAR* pTemp = NULL;
// Declare the new string and zero it out
pTemp = new TTCHAR[newsize] ;
memset(pTemp, '\0', newsize*sizeof(TTCHAR));
// Copy the old string if there is one
if (ptr)
{
// Ensure we only copy up to the size of the new buffer
memcpy(pTemp, ptr, min(oldsize*sizeof(TTCHAR), newsize*sizeof(TTCHAR)));
// Don't delete a default buffer we didn't create
if (bOwnBuffer)
{
if(oldsize > 1)
{
delete [] ptr;
}
else
{
delete ptr;
}
}
}
// We own it now!
bOwnBuffer = true;
return pTemp;
}
return ptr;
}
// Encapsulate multibyte and Unicode versions of fgets in functions with same
// name. Use this function in our template fggets function and when TTCHAR is
// resolved the correct one will be called
char *GetFileString( char *string, int n, FILE *stream )
{
return fgets( string, n, stream );
}
wchar_t *GetFileString( wchar_t *string, int n, FILE *stream )
{
return fgetws( string, n, stream );
}
// Same with strchr
char *FindCharInString( const char *string, int c )
{
// This *should* work OK even with UTF-8, since we're only searching for
// '\n' in practice. Careful if you try to use this for anything other
// than ASCII characters.
return (char*)_mbschr( (const unsigned char *)string, c );
}
wchar_t *FindCharInString( const wchar_t *string, wint_t c )
{
return (wchar_t *)wcschr( string, c );
}
#define INITSIZE 112 /* power of 2 minus 16, helps malloc */
#define DELTASIZE (INITSIZE + 16)
// DP 29/03/2006 Modified to "templatise" it so it will work with Unicode and MB
// DP 24/06/2006 Now accepts default buffer to avoid the need for dynamic memory allocation
template<class TTCHAR>
int fggets(TTCHAR* *ln, FILE *f, IN OUT bool& bOwnBuffer, IN const int nDefaultBufferSizeChars)
// int fggets(CTemplateSmartPtrArray<TTCHAR>& spln, FILE *f, const int nDefaultBufferSizeChars)
{
int cursize, rdsize, nOldSize;
TTCHAR *buffer, *temp, *rdpoint, *crlocn;
bOwnBuffer = false;
ASSERT(*ln != NULL || nDefaultBufferSizeChars==0);
// DP 24/06/2007: Allow default buffer to be passed in for reading. Avoids need for "new"s/"delete"s in 99% of cases
if (nDefaultBufferSizeChars == 0 || *ln == NULL)
{
// DP 29/3/2006: Changed to use new
buffer = new TTCHAR[INITSIZE];
if (NULL == buffer)
return FGGETS_NOMEM;
// DP 24/06/2007: Signal that we own the buffer now
bOwnBuffer = true;
}
else
{
buffer = *ln;
}
*ln = NULL; /* default */
// if (NULL == (buffer = (char*)malloc(INITSIZE)))
// DP 29/3/2006: Added oldsize variable
// Initialise original size to default buffer size or INITSIZE, whichever applies
cursize = rdsize = nOldSize = (nDefaultBufferSizeChars==0 ? INITSIZE:nDefaultBufferSizeChars);
rdpoint = buffer;
*buffer = '\0';
// if (NULL == fgets(rdpoint, rdsize, f))
if (NULL == GetFileString(rdpoint, rdsize, f))
{
// free(buffer);
// DP 29/3/2006: Changed to use delete
if (bOwnBuffer)
{
delete buffer;
}
return EOF;
}
/* initial read succeeded, now decide about expansion */
// while (NULL == (crlocn = strchr(rdpoint, '\n')))
while (NULL == (crlocn = FindCharInString(rdpoint, '\n')))
{
/* line is not completed, expand */
// DP 29/3/2006: Save current buffer size
nOldSize = cursize;
/* set up cursize, rdpoint and rdsize, expand buffer */
rdsize = DELTASIZE + 1; /* allow for a final '\0' */
cursize += DELTASIZE;
// if (NULL == (temp = (char*)realloc(buffer, (size_t)cursize))) {
// DP 29/3/2006: Changed to use custom realloc
if (NULL == (temp = ReallocString<TTCHAR>(buffer, (size_t)cursize, (size_t)nOldSize, bOwnBuffer)))
{
/* ran out of memory */
*ln = buffer; /* partial line, next call may fail */
return FGGETS_NOMEM;
}
buffer = temp;
/* Read into the '\0' up */
rdpoint = buffer + (cursize - DELTASIZE - 1);
/* get the next piece of this line */
// if (NULL == fgets(rdpoint, rdsize, f)) {
if (NULL == GetFileString(rdpoint, rdsize, f))
{
/* early EOF encountered */
// crlocn = strchr(buffer, '\0');
crlocn = FindCharInString(buffer, '\0');
break;
}
} /* while line not complete */
*crlocn = '\0'; /* mark line end, strip \n */
rdsize = (int)(crlocn - buffer);
// if (NULL == (temp = (char*)realloc(buffer, (size_t)rdsize + 1))) {
// DP 29/3/2006: Changed to use custom realloc
if (NULL == (temp = ReallocString<TTCHAR>(buffer, (size_t)rdsize + 1, (size_t)cursize, bOwnBuffer)))
{
*ln = buffer; /* without reducing it */
return FGGETS_OK;
}
*ln = temp;
return FGGETS_OK;
} /* fggets */
/* End of ggets.c */