1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* readline for batch mode */
18
#include <my_global.h>
21
#include "my_readline.h"
23
static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
25
static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
26
static size_t fill_buffer(LINE_BUFFER *buffer);
27
static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated);
30
LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
32
LINE_BUFFER *line_buff;
33
if (!(line_buff=(LINE_BUFFER*)
34
my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
36
if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
38
my_free(line_buff,MYF(0));
45
char *batch_readline(LINE_BUFFER *line_buff, bool *truncated)
49
DBUG_ASSERT(truncated != NULL);
51
if (!(pos=intern_read_line(line_buff,&out_length, truncated)))
53
if (out_length && pos[out_length-1] == '\n')
54
if (--out_length && pos[out_length-1] == '\r') /* Remove '\n' */
55
out_length--; /* Remove '\r' */
56
line_buff->read_length=out_length;
62
void batch_readline_end(LINE_BUFFER *line_buff)
66
my_free(line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR));
67
my_free(line_buff,MYF(0));
72
LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str)
75
if (!(line_buff=(LINE_BUFFER*)
76
my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
78
if (init_line_buffer_from_string(line_buff,str))
80
my_free(line_buff,MYF(0));
87
/*****************************************************************************
88
Functions to handle buffered readings of lines from a stream
89
******************************************************************************/
92
init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
96
buffer->max_size=max_buffer;
97
if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1,
98
MYF(MY_WME | MY_FAE))))
100
buffer->end_of_line=buffer->end=buffer->buffer;
101
buffer->buffer[0]=0; /* For easy start test */
106
init_line_buffer_from_string can be called on the same buffer
107
several times. the resulting buffer will contain a
108
concatenation of all strings separated by spaces
110
static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str)
112
uint old_length=(uint)(buffer->end - buffer->buffer);
113
uint length= (uint) strlen(str);
114
if (!(buffer->buffer= buffer->start_of_line= buffer->end_of_line=
115
(char*) my_realloc((uchar*) buffer->buffer, old_length+length+2,
116
MYF(MY_FAE|MY_ALLOW_ZERO_PTR))))
118
buffer->end= buffer->buffer + old_length;
121
memcpy(buffer->end, str, length);
122
buffer->end[length]= '\n';
123
buffer->end[length+1]= 0;
124
buffer->end+= length+1;
132
Fill the buffer retaining the last n bytes at the beginning of the
133
newly filled buffer (for backward context). Returns the number of new
134
bytes read from disk.
137
static size_t fill_buffer(LINE_BUFFER *buffer)
140
uint bufbytes= (uint) (buffer->end - buffer->start_of_line);
143
return 0; /* Everything read */
145
/* See if we need to grow the buffer. */
149
uint start_offset=(uint) (buffer->start_of_line - buffer->buffer);
150
read_count=(buffer->bufread - bufbytes)/IO_SIZE;
151
if ((read_count*=IO_SIZE))
153
if (buffer->bufread * 2 > buffer->max_size)
156
So we must grow the buffer but we cannot due to the max_size limit.
157
Return 0 w/o setting buffer->eof to signal this condition.
161
buffer->bufread *= 2;
162
if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
164
MYF(MY_WME | MY_FAE))))
166
buffer->start_of_line=buffer->buffer+start_offset;
167
buffer->end=buffer->buffer+bufbytes;
170
/* Shift stuff down. */
171
if (buffer->start_of_line != buffer->buffer)
173
bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes);
174
buffer->end=buffer->buffer+bufbytes;
177
/* Read in new stuff. */
178
if ((read_count= my_read(buffer->file, (uchar*) buffer->end, read_count,
179
MYF(MY_WME))) == MY_FILE_ERROR)
182
DBUG_PRINT("fill_buff", ("Got %lu bytes", (ulong) read_count));
187
/* Kludge to pretend every nonempty file ends with a newline. */
188
if (bufbytes && buffer->end[-1] != '\n')
194
buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes;
195
buffer->end+=read_count;
196
*buffer->end=0; /* Sentinel */
202
char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated)
206
DBUG_ENTER("intern_read_line");
208
buffer->start_of_line=buffer->end_of_line;
211
pos=buffer->end_of_line;
212
while (*pos != '\n' && *pos)
214
if (pos == buffer->end)
217
fill_buffer() can return 0 either on EOF in which case we abort
218
or when the internal buffer has hit the size limit. In the latter case
219
return what we have read so far and signal string truncation.
221
if (!(length=fill_buffer(buffer)) || length == (uint) -1)
228
pos--; /* break line here */
233
buffer->end_of_line=pos+1;
234
*out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line);
235
DBUG_RETURN(buffer->start_of_line);