~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to client/readline.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
 
15
 
 
16
/* readline for batch mode */
 
17
 
 
18
#include <my_global.h>
 
19
#include <my_sys.h>
 
20
#include <m_string.h>
 
21
#include "my_readline.h"
 
22
 
 
23
static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
 
24
                            ulong max_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);
 
28
 
 
29
 
 
30
LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
 
31
{
 
32
  LINE_BUFFER *line_buff;
 
33
  if (!(line_buff=(LINE_BUFFER*)
 
34
        my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
 
35
    return 0;
 
36
  if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
 
37
  {
 
38
    my_free(line_buff,MYF(0));
 
39
    return 0;
 
40
  }
 
41
  return line_buff;
 
42
}
 
43
 
 
44
 
 
45
char *batch_readline(LINE_BUFFER *line_buff, bool *truncated)
 
46
{
 
47
  char *pos;
 
48
  ulong out_length;
 
49
  DBUG_ASSERT(truncated != NULL);
 
50
 
 
51
  if (!(pos=intern_read_line(line_buff,&out_length, truncated)))
 
52
    return 0;
 
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;
 
57
  pos[out_length]=0;
 
58
  return pos;
 
59
}
 
60
 
 
61
 
 
62
void batch_readline_end(LINE_BUFFER *line_buff)
 
63
{
 
64
  if (line_buff)
 
65
  {
 
66
    my_free(line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR));
 
67
    my_free(line_buff,MYF(0));
 
68
  }
 
69
}
 
70
 
 
71
 
 
72
LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, char * str)
 
73
{
 
74
  if (!line_buff)
 
75
    if (!(line_buff=(LINE_BUFFER*)
 
76
          my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
 
77
      return 0;
 
78
  if (init_line_buffer_from_string(line_buff,str))
 
79
  {
 
80
    my_free(line_buff,MYF(0));
 
81
    return 0;
 
82
  }
 
83
  return line_buff;
 
84
}
 
85
 
 
86
 
 
87
/*****************************************************************************
 
88
      Functions to handle buffered readings of lines from a stream
 
89
******************************************************************************/
 
90
 
 
91
static bool
 
92
init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
 
93
{
 
94
  buffer->file=file;
 
95
  buffer->bufread=size;
 
96
  buffer->max_size=max_buffer;
 
97
  if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1,
 
98
                                           MYF(MY_WME | MY_FAE))))
 
99
    return 1;
 
100
  buffer->end_of_line=buffer->end=buffer->buffer;
 
101
  buffer->buffer[0]=0;                          /* For easy start test */
 
102
  return 0;
 
103
}
 
104
 
 
105
/*
 
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
 
109
*/
 
110
static bool init_line_buffer_from_string(LINE_BUFFER *buffer,char * str)
 
111
{
 
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))))
 
117
    return 1;
 
118
  buffer->end= buffer->buffer + old_length;
 
119
  if (old_length)
 
120
    buffer->end[-1]=' ';
 
121
  memcpy(buffer->end, str, length);
 
122
  buffer->end[length]= '\n';
 
123
  buffer->end[length+1]= 0;
 
124
  buffer->end+= length+1;
 
125
  buffer->eof=1;
 
126
  buffer->max_size=1;
 
127
  return 0;
 
128
}
 
129
 
 
130
 
 
131
/*
 
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.
 
135
*/
 
136
 
 
137
static size_t fill_buffer(LINE_BUFFER *buffer)
 
138
{
 
139
  size_t read_count;
 
140
  uint bufbytes= (uint) (buffer->end - buffer->start_of_line);
 
141
 
 
142
  if (buffer->eof)
 
143
    return 0;                                   /* Everything read */
 
144
 
 
145
  /* See if we need to grow the buffer. */
 
146
 
 
147
  for (;;)
 
148
  {
 
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))
 
152
      break;
 
153
    if (buffer->bufread * 2 > buffer->max_size)
 
154
    {
 
155
      /*
 
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.
 
158
      */
 
159
      return 0;
 
160
    }
 
161
    buffer->bufread *= 2;
 
162
    if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
 
163
                                              buffer->bufread+1,
 
164
                                              MYF(MY_WME | MY_FAE))))
 
165
      return (uint) -1;
 
166
    buffer->start_of_line=buffer->buffer+start_offset;
 
167
    buffer->end=buffer->buffer+bufbytes;
 
168
  }
 
169
 
 
170
  /* Shift stuff down. */
 
171
  if (buffer->start_of_line != buffer->buffer)
 
172
  {
 
173
    bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes);
 
174
    buffer->end=buffer->buffer+bufbytes;
 
175
  }
 
176
 
 
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)
 
180
    return (size_t) -1;
 
181
 
 
182
  DBUG_PRINT("fill_buff", ("Got %lu bytes", (ulong) read_count));
 
183
 
 
184
  if (!read_count)
 
185
  {
 
186
    buffer->eof = 1;
 
187
    /* Kludge to pretend every nonempty file ends with a newline. */
 
188
    if (bufbytes && buffer->end[-1] != '\n')
 
189
    {
 
190
      read_count = 1;
 
191
      *buffer->end = '\n';
 
192
    }
 
193
  }
 
194
  buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes;
 
195
  buffer->end+=read_count;
 
196
  *buffer->end=0;                               /* Sentinel */
 
197
  return read_count;
 
198
}
 
199
 
 
200
 
 
201
 
 
202
char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length, bool *truncated)
 
203
{
 
204
  char *pos;
 
205
  size_t length;
 
206
  DBUG_ENTER("intern_read_line");
 
207
 
 
208
  buffer->start_of_line=buffer->end_of_line;
 
209
  for (;;)
 
210
  {
 
211
    pos=buffer->end_of_line;
 
212
    while (*pos != '\n' && *pos)
 
213
      pos++;
 
214
    if (pos == buffer->end)
 
215
    {
 
216
      /*
 
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.
 
220
      */
 
221
      if (!(length=fill_buffer(buffer)) || length == (uint) -1)
 
222
      {
 
223
        if (buffer->eof)
 
224
          DBUG_RETURN(0);
 
225
      }
 
226
      else
 
227
        continue;
 
228
      pos--;                                    /* break line here */
 
229
      *truncated= 1;
 
230
    }
 
231
    else
 
232
      *truncated= 0;
 
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);
 
236
  }
 
237
}