The world's most popular open source database
00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* readline for batch mode */ 00018 00019 #include <my_global.h> 00020 #include <my_sys.h> 00021 #include <m_string.h> 00022 #include "my_readline.h" 00023 00024 static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size, 00025 ulong max_size); 00026 static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str); 00027 static uint fill_buffer(LINE_BUFFER *buffer); 00028 static char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length); 00029 00030 00031 LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) 00032 { 00033 LINE_BUFFER *line_buff; 00034 if (!(line_buff=(LINE_BUFFER*) 00035 my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL)))) 00036 return 0; 00037 if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size)) 00038 { 00039 my_free((char*) line_buff,MYF(0)); 00040 return 0; 00041 } 00042 return line_buff; 00043 } 00044 00045 00046 char *batch_readline(LINE_BUFFER *line_buff) 00047 { 00048 char *pos; 00049 ulong out_length; 00050 00051 if (!(pos=intern_read_line(line_buff,&out_length))) 00052 return 0; 00053 if (out_length && pos[out_length-1] == '\n') 00054 out_length--; /* Remove '\n' */ 00055 line_buff->read_length=out_length; 00056 pos[out_length]=0; 00057 return pos; 00058 } 00059 00060 00061 void batch_readline_end(LINE_BUFFER *line_buff) 00062 { 00063 if (line_buff) 00064 { 00065 my_free((gptr) line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR)); 00066 my_free((char*) line_buff,MYF(0)); 00067 } 00068 } 00069 00070 00071 LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, my_string str) 00072 { 00073 if (!line_buff) 00074 if (!(line_buff=(LINE_BUFFER*) 00075 my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL)))) 00076 return 0; 00077 if (init_line_buffer_from_string(line_buff,str)) 00078 { 00079 my_free((char*) line_buff,MYF(0)); 00080 return 0; 00081 } 00082 return line_buff; 00083 } 00084 00085 00086 /***************************************************************************** 00087 Functions to handle buffered readings of lines from a stream 00088 ******************************************************************************/ 00089 00090 static bool 00091 init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer) 00092 { 00093 buffer->file=file; 00094 buffer->bufread=size; 00095 buffer->max_size=max_buffer; 00096 if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1, 00097 MYF(MY_WME | MY_FAE)))) 00098 return 1; 00099 buffer->end_of_line=buffer->end=buffer->buffer; 00100 buffer->buffer[0]=0; /* For easy start test */ 00101 return 0; 00102 } 00103 00104 /* 00105 init_line_buffer_from_string can be called on the same buffer 00106 several times. the resulting buffer will contain a 00107 concatenation of all strings separated by spaces 00108 */ 00109 static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str) 00110 { 00111 uint old_length=(uint)(buffer->end - buffer->buffer); 00112 uint length= (uint) strlen(str); 00113 if (!(buffer->buffer= buffer->start_of_line= buffer->end_of_line= 00114 (char*)my_realloc(buffer->buffer, old_length+length+2, 00115 MYF(MY_FAE|MY_ALLOW_ZERO_PTR)))) 00116 return 1; 00117 buffer->end= buffer->buffer + old_length; 00118 if (old_length) 00119 buffer->end[-1]=' '; 00120 memcpy(buffer->end, str, length); 00121 buffer->end[length]= '\n'; 00122 buffer->end[length+1]= 0; 00123 buffer->end+= length+1; 00124 buffer->eof=1; 00125 buffer->max_size=1; 00126 return 0; 00127 } 00128 00129 00130 /* 00131 Fill the buffer retaining the last n bytes at the beginning of the 00132 newly filled buffer (for backward context). Returns the number of new 00133 bytes read from disk. 00134 */ 00135 00136 static uint fill_buffer(LINE_BUFFER *buffer) 00137 { 00138 uint read_count; 00139 uint bufbytes= (uint) (buffer->end - buffer->start_of_line); 00140 00141 if (buffer->eof) 00142 return 0; /* Everything read */ 00143 00144 /* See if we need to grow the buffer. */ 00145 00146 for (;;) 00147 { 00148 uint start_offset=(uint) (buffer->start_of_line - buffer->buffer); 00149 read_count=(buffer->bufread - bufbytes)/IO_SIZE; 00150 if ((read_count*=IO_SIZE)) 00151 break; 00152 buffer->bufread *= 2; 00153 if (!(buffer->buffer = (char*) my_realloc(buffer->buffer, 00154 buffer->bufread+1, 00155 MYF(MY_WME | MY_FAE)))) 00156 return (uint) -1; 00157 buffer->start_of_line=buffer->buffer+start_offset; 00158 buffer->end=buffer->buffer+bufbytes; 00159 } 00160 00161 /* Shift stuff down. */ 00162 if (buffer->start_of_line != buffer->buffer) 00163 { 00164 bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes); 00165 buffer->end=buffer->buffer+bufbytes; 00166 } 00167 00168 /* Read in new stuff. */ 00169 if ((read_count= my_read(buffer->file, (byte*) buffer->end, read_count, 00170 MYF(MY_WME))) == MY_FILE_ERROR) 00171 return read_count; 00172 00173 DBUG_PRINT("fill_buff", ("Got %d bytes", read_count)); 00174 00175 /* Kludge to pretend every nonempty file ends with a newline. */ 00176 if (!read_count && bufbytes && buffer->end[-1] != '\n') 00177 { 00178 buffer->eof = read_count = 1; 00179 *buffer->end = '\n'; 00180 } 00181 buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes; 00182 buffer->end+=read_count; 00183 *buffer->end=0; /* Sentinel */ 00184 return read_count; 00185 } 00186 00187 00188 00189 char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length) 00190 { 00191 char *pos; 00192 uint length; 00193 DBUG_ENTER("intern_read_line"); 00194 00195 buffer->start_of_line=buffer->end_of_line; 00196 for (;;) 00197 { 00198 pos=buffer->end_of_line; 00199 while (*pos != '\n' && *pos) 00200 pos++; 00201 if (pos == buffer->end) 00202 { 00203 if ((uint) (pos - buffer->start_of_line) < buffer->max_size) 00204 { 00205 if (!(length=fill_buffer(buffer)) || length == (uint) -1) 00206 DBUG_RETURN(0); 00207 continue; 00208 } 00209 pos--; /* break line here */ 00210 } 00211 buffer->end_of_line=pos+1; 00212 *out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line); 00213 DBUG_RETURN(buffer->start_of_line); 00214 } 00215 }
1.4.7

