summaryrefslogtreecommitdiff
path: root/client/readline.cc
diff options
context:
space:
mode:
Diffstat (limited to 'client/readline.cc')
-rw-r--r--client/readline.cc216
1 files changed, 216 insertions, 0 deletions
diff --git a/client/readline.cc b/client/readline.cc
new file mode 100644
index 00000000000..95e98cb90c2
--- /dev/null
+++ b/client/readline.cc
@@ -0,0 +1,216 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA */
+
+/* readline for batch mode */
+
+#include <global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include "my_readline.h"
+
+static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
+ ulong max_size);
+static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str);
+static uint fill_buffer(LINE_BUFFER *buffer);
+static char *intern_read_line(LINE_BUFFER *buffer,uint *out_length);
+
+
+LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
+{
+ LINE_BUFFER *line_buff;
+ if (!(line_buff=(LINE_BUFFER*) my_malloc(sizeof(*line_buff),MYF(MY_WME))))
+ return 0;
+ if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
+ {
+ my_free((char*) line_buff,MYF(0));
+ return 0;
+ }
+ return line_buff;
+}
+
+
+char *batch_readline(LINE_BUFFER *line_buff)
+{
+ char *pos;
+ uint out_length;
+
+ if (!(pos=intern_read_line(line_buff,&out_length)))
+ return 0;
+ if (out_length && pos[out_length-1] == '\n')
+ out_length--; /* Remove '\n' */
+ pos[out_length]=0;
+ return pos;
+}
+
+
+void batch_readline_end(LINE_BUFFER *line_buff)
+{
+ if (line_buff)
+ {
+ my_free((gptr) line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((char*) line_buff,MYF(0));
+ }
+}
+
+
+LINE_BUFFER *batch_readline_command(my_string str)
+{
+ LINE_BUFFER *line_buff;
+ if (!(line_buff=(LINE_BUFFER*) my_malloc(sizeof(*line_buff),MYF(MY_WME))))
+ return 0;
+ if (init_line_buffer_from_string(line_buff,str))
+ {
+ my_free((char*) line_buff,MYF(0));
+ return 0;
+ }
+ return line_buff;
+}
+
+
+/*****************************************************************************
+ Functions to handle buffered readings of lines from a stream
+******************************************************************************/
+
+static bool
+init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
+{
+ bzero((char*) buffer,sizeof(buffer[0]));
+ buffer->file=file;
+ buffer->bufread=size;
+ buffer->max_size=max_buffer;
+ if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1,
+ MYF(MY_WME | MY_FAE))))
+ return 1;
+ buffer->end_of_line=buffer->end=buffer->buffer;
+ buffer->buffer[0]=0; /* For easy start test */
+ return 0;
+}
+
+
+static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str)
+{
+ uint length;
+ bzero((char*) buffer,sizeof(buffer[0]));
+ length=strlen(str);
+ if (!(buffer->buffer=buffer->start_of_line=buffer->end_of_line=
+ (char*)my_malloc(length+2,MYF(MY_FAE))))
+ return 1;
+ memcpy(buffer->buffer,str,length);
+ buffer->buffer[length]='\n';
+ buffer->buffer[length+1]=0;
+ buffer->end=buffer->buffer+length+1;
+ buffer->eof=1;
+ buffer->max_size=1;
+ return 0;
+}
+
+
+static void free_line_buffer(LINE_BUFFER *buffer)
+{
+ if (buffer->buffer)
+ {
+ my_free((gptr) buffer->buffer,MYF(0));
+ buffer->buffer=0;
+ }
+}
+
+
+/* Fill the buffer retaining the last n bytes at the beginning of the
+ newly filled buffer (for backward context). Returns the number of new
+ bytes read from disk. */
+
+
+static uint fill_buffer(LINE_BUFFER *buffer)
+{
+ uint read_count;
+ uint bufbytes= (uint) (buffer->end - buffer->start_of_line);
+
+ if (buffer->eof)
+ return 0; /* Everything read */
+
+ /* See if we need to grow the buffer. */
+
+ for (;;)
+ {
+ uint start_offset=(uint) (buffer->start_of_line - buffer->buffer);
+ read_count=(buffer->bufread - bufbytes)/IO_SIZE;
+ if ((read_count*=IO_SIZE))
+ break;
+ buffer->bufread *= 2;
+ if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
+ buffer->bufread+1,
+ MYF(MY_WME | MY_FAE))))
+ return (uint) -1;
+ buffer->start_of_line=buffer->buffer+start_offset;
+ buffer->end=buffer->buffer+bufbytes;
+ }
+
+ /* Shift stuff down. */
+ if (buffer->start_of_line != buffer->buffer)
+ {
+ bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes);
+ buffer->end=buffer->buffer+bufbytes;
+ }
+
+ /* Read in new stuff. */
+ if ((read_count= my_read(buffer->file, (byte*) buffer->end, read_count,
+ MYF(MY_WME))) == MY_FILE_ERROR)
+ return read_count;
+
+ DBUG_PRINT("fill_buff", ("Got %d bytes", read_count));
+
+ /* Kludge to pretend every nonempty file ends with a newline. */
+ if (!read_count && bufbytes && buffer->end[-1] != '\n')
+ {
+ buffer->eof = read_count = 1;
+ *buffer->end = '\n';
+ }
+ buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes;
+ buffer->end+=read_count;
+ *buffer->end=0; /* Sentinel */
+ return read_count;
+}
+
+
+
+char *intern_read_line(LINE_BUFFER *buffer,uint *out_length)
+{
+ char *pos;
+ uint length;
+ DBUG_ENTER("intern_read_line");
+
+ buffer->start_of_line=buffer->end_of_line;
+ for (;;)
+ {
+ pos=buffer->end_of_line;
+ while (*pos != '\n' && *pos)
+ pos++;
+ if (pos == buffer->end)
+ {
+ if ((uint) (pos - buffer->start_of_line) < buffer->max_size)
+ {
+ if (!(length=fill_buffer(buffer)) || length == (uint) -1)
+ DBUG_RETURN(0);
+ continue;
+ }
+ pos--; /* break line here */
+ }
+ buffer->end_of_line=pos+1;
+ *out_length=(uint) (pos + 1 - buffer->eof - buffer->start_of_line);
+ DBUG_RETURN(buffer->start_of_line);
+ }
+}