MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
readline.cc
1 /*
2  Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /* readline for batch mode */
19 
20 #include <my_global.h>
21 #include <my_sys.h>
22 #include <m_string.h>
23 #include <my_dir.h>
24 #include "my_readline.h"
25 
26 static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
27  ulong max_size);
28 static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str);
29 static size_t fill_buffer(LINE_BUFFER *buffer);
30 static char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length);
31 
32 
33 LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
34 {
35  LINE_BUFFER *line_buff;
36  MY_STAT input_file_stat;
37 
38 #ifndef __WIN__
39  if (my_fstat(fileno(file), &input_file_stat, MYF(MY_WME)) ||
40  MY_S_ISDIR(input_file_stat.st_mode) ||
41  MY_S_ISBLK(input_file_stat.st_mode))
42  return 0;
43 #endif
44 
45  if (!(line_buff=(LINE_BUFFER*)
46  my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
47  return 0;
48  if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size))
49  {
50  my_free(line_buff);
51  return 0;
52  }
53  return line_buff;
54 }
55 
56 
57 char *batch_readline(LINE_BUFFER *line_buff, bool binary_mode)
58 {
59  char *pos;
60  ulong out_length;
61 
62  if (!(pos=intern_read_line(line_buff, &out_length)))
63  return 0;
64  if (out_length && pos[out_length-1] == '\n')
65  {
66 #if defined(__WIN__)
67  /*
68  On Windows platforms we also need to remove '\r',
69  unconditionally.
70  */
71 
72  /* Remove '\n' */
73  if (--out_length && pos[out_length-1] == '\r')
74  /* Remove '\r' */
75  out_length--;
76 #else
77  /*
78  On Unix-like platforms we only remove it if we are not
79  on binary mode.
80  */
81 
82  /* Remove '\n' */
83  if (--out_length && !binary_mode && pos[out_length-1] == '\r')
84  /* Remove '\r' */
85  out_length--;
86 #endif
87  }
88  line_buff->read_length=out_length;
89  pos[out_length]=0;
90  DBUG_DUMP("Query: ", (unsigned char *) pos, out_length);
91  return pos;
92 }
93 
94 
95 void batch_readline_end(LINE_BUFFER *line_buff)
96 {
97  if (line_buff)
98  {
99  my_free(line_buff->buffer);
100  my_free(line_buff);
101  }
102 }
103 
104 
105 LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str)
106 {
107  if (!line_buff)
108  if (!(line_buff=(LINE_BUFFER*)
109  my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
110  return 0;
111  if (init_line_buffer_from_string(line_buff,str))
112  {
113  my_free(line_buff);
114  return 0;
115  }
116  return line_buff;
117 }
118 
119 
120 /*****************************************************************************
121  Functions to handle buffered readings of lines from a stream
122 ******************************************************************************/
123 
124 static bool
125 init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
126 {
127  buffer->file=file;
128  buffer->bufread=size;
129  buffer->max_size=max_buffer;
130  if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1,
131  MYF(MY_WME | MY_FAE))))
132  return 1;
133  buffer->end_of_line=buffer->end=buffer->buffer;
134  buffer->buffer[0]=0; /* For easy start test */
135  return 0;
136 }
137 
138 /*
139  init_line_buffer_from_string can be called on the same buffer
140  several times. the resulting buffer will contain a
141  concatenation of all strings separated by spaces
142 */
143 static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str)
144 {
145  uint old_length=(uint)(buffer->end - buffer->buffer);
146  uint length= (uint) strlen(str);
147  if (!(buffer->buffer= buffer->start_of_line= buffer->end_of_line=
148  (char*) my_realloc((uchar*) buffer->buffer, old_length+length+2,
149  MYF(MY_FAE|MY_ALLOW_ZERO_PTR))))
150  return 1;
151  buffer->end= buffer->buffer + old_length;
152  if (old_length)
153  buffer->end[-1]=' ';
154  memcpy(buffer->end, str, length);
155  buffer->end[length]= '\n';
156  buffer->end[length+1]= 0;
157  buffer->end+= length+1;
158  buffer->eof=1;
159  buffer->max_size=1;
160  return 0;
161 }
162 
163 
164 /*
165  Fill the buffer retaining the last n bytes at the beginning of the
166  newly filled buffer (for backward context). Returns the number of new
167  bytes read from disk.
168 */
169 
170 static size_t fill_buffer(LINE_BUFFER *buffer)
171 {
172  size_t read_count;
173  uint bufbytes= (uint) (buffer->end - buffer->start_of_line);
174 
175  if (buffer->eof)
176  return 0; /* Everything read */
177 
178  /* See if we need to grow the buffer. */
179 
180  for (;;)
181  {
182  uint start_offset=(uint) (buffer->start_of_line - buffer->buffer);
183  read_count=(buffer->bufread - bufbytes)/IO_SIZE;
184  if ((read_count*=IO_SIZE))
185  break;
186  if (buffer->bufread * 2 > buffer->max_size)
187  {
188  /*
189  So we must grow the buffer but we cannot due to the max_size limit.
190  Return 0 w/o setting buffer->eof to signal this condition.
191  */
192  return 0;
193  }
194  buffer->bufread *= 2;
195  if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
196  buffer->bufread+1,
197  MYF(MY_WME | MY_FAE))))
198  {
199  buffer->error= my_errno;
200  return (size_t) -1;
201  }
202  buffer->start_of_line=buffer->buffer+start_offset;
203  buffer->end=buffer->buffer+bufbytes;
204  }
205 
206  /* Shift stuff down. */
207  if (buffer->start_of_line != buffer->buffer)
208  {
209  bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes);
210  buffer->end=buffer->buffer+bufbytes;
211  }
212 
213  /* Read in new stuff. */
214  if ((read_count= my_read(buffer->file, (uchar*) buffer->end, read_count,
215  MYF(MY_WME))) == MY_FILE_ERROR)
216  {
217  buffer->error= my_errno;
218  return (size_t) -1;
219  }
220 
221  DBUG_PRINT("fill_buff", ("Got %lu bytes", (ulong) read_count));
222 
223  if (!read_count)
224  {
225  buffer->eof = 1;
226  /* Kludge to pretend every nonempty file ends with a newline. */
227  if (bufbytes && buffer->end[-1] != '\n')
228  {
229  read_count = 1;
230  *buffer->end = '\n';
231  }
232  }
233  buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes;
234  buffer->end+=read_count;
235  *buffer->end=0; /* Sentinel */
236  return read_count;
237 }
238 
239 
240 char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length)
241 {
242  char *pos;
243  size_t length;
244  DBUG_ENTER("intern_read_line");
245 
246  buffer->start_of_line=buffer->end_of_line;
247  for (;;)
248  {
249  pos=buffer->end_of_line;
250  while (*pos != '\n' && pos != buffer->end)
251  pos++;
252  if (pos == buffer->end)
253  {
254  /*
255  fill_buffer() can return NULL on EOF (in which case we abort),
256  on error, or when the internal buffer has hit the size limit.
257  In the latter case return what we have read so far and signal
258  string truncation.
259  */
260  if (!(length= fill_buffer(buffer)))
261  {
262  if (buffer->eof)
263  DBUG_RETURN(0);
264  }
265  else if (length == (size_t) -1)
266  DBUG_RETURN(NULL);
267  else
268  continue;
269  pos--; /* break line here */
270  buffer->truncated= 1;
271  }
272  else
273  buffer->truncated= 0;
274  buffer->end_of_line=pos+1;
275  *out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line);
276 
277  DBUG_DUMP("Query: ", (unsigned char *) buffer->start_of_line, *out_length);
278  DBUG_RETURN(buffer->start_of_line);
279  }
280 }