readline.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* readline for batch mode */
  14. #include <my_global.h>
  15. #include <my_sys.h>
  16. #include <m_string.h>
  17. #include "my_readline.h"
  18. static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
  19.     ulong max_size);
  20. static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str);
  21. static uint fill_buffer(LINE_BUFFER *buffer);
  22. static char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length);
  23. LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
  24. {
  25.   LINE_BUFFER *line_buff;
  26.   if (!(line_buff=(LINE_BUFFER*)
  27.         my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
  28.     return 0;
  29.   if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
  30.   {
  31.     my_free((char*) line_buff,MYF(0));
  32.     return 0;
  33.   }
  34.   return line_buff;
  35. }
  36. char *batch_readline(LINE_BUFFER *line_buff)
  37. {
  38.   char *pos;
  39.   ulong out_length;
  40.   if (!(pos=intern_read_line(line_buff,&out_length)))
  41.     return 0;
  42.   if (out_length && pos[out_length-1] == 'n')
  43.     out_length--; /* Remove 'n' */
  44.   line_buff->read_length=out_length;
  45.   pos[out_length]=0;
  46.   return pos;
  47. }
  48. void batch_readline_end(LINE_BUFFER *line_buff)
  49. {
  50.   if (line_buff)
  51.   {
  52.     my_free((gptr) line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR));
  53.     my_free((char*) line_buff,MYF(0));
  54.   }
  55. }
  56. LINE_BUFFER *batch_readline_command(LINE_BUFFER *line_buff, my_string str)
  57. {
  58.   if (!line_buff)
  59.     if (!(line_buff=(LINE_BUFFER*)
  60.           my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL))))
  61.       return 0;
  62.   if (init_line_buffer_from_string(line_buff,str))
  63.   {
  64.     my_free((char*) line_buff,MYF(0));
  65.     return 0;
  66.   }
  67.   return line_buff;
  68. }
  69. /*****************************************************************************
  70.       Functions to handle buffered readings of lines from a stream
  71. ******************************************************************************/
  72. static bool
  73. init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
  74. {
  75.   buffer->file=file;
  76.   buffer->bufread=size;
  77.   buffer->max_size=max_buffer;
  78.   if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1,
  79.    MYF(MY_WME | MY_FAE))))
  80.     return 1;
  81.   buffer->end_of_line=buffer->end=buffer->buffer;
  82.   buffer->buffer[0]=0; /* For easy start test */
  83.   return 0;
  84. }
  85. /*
  86.   init_line_buffer_from_string can be called on the same buffer
  87.   several times. the resulting buffer will contain a
  88.   concatenation of all strings separated by spaces
  89. */
  90. static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str)
  91. {
  92.   uint old_length=(uint)(buffer->end - buffer->buffer);
  93.   uint length= (uint) strlen(str);
  94.   if (!(buffer->buffer= buffer->start_of_line= buffer->end_of_line=
  95. (char*)my_realloc(buffer->buffer, old_length+length+2,
  96.                           MYF(MY_FAE|MY_ALLOW_ZERO_PTR))))
  97.     return 1;
  98.   buffer->end= buffer->buffer + old_length;
  99.   if (old_length)
  100.     buffer->end[-1]=' ';
  101.   memcpy(buffer->end, str, length);
  102.   buffer->end[length]= 'n';
  103.   buffer->end[length+1]= 0;
  104.   buffer->end+= length+1;
  105.   buffer->eof=1;
  106.   buffer->max_size=1;
  107.   return 0;
  108. }
  109. /*
  110.   Fill the buffer retaining the last n bytes at the beginning of the
  111.   newly filled buffer (for backward context). Returns the number of new
  112.   bytes read from disk.
  113. */
  114. static uint fill_buffer(LINE_BUFFER *buffer)
  115. {
  116.   uint read_count;
  117.   uint bufbytes= (uint) (buffer->end - buffer->start_of_line);
  118.   if (buffer->eof)
  119.     return 0; /* Everything read */
  120.   /* See if we need to grow the buffer. */
  121.   for (;;)
  122.   {
  123.     uint start_offset=(uint) (buffer->start_of_line - buffer->buffer);
  124.     read_count=(buffer->bufread - bufbytes)/IO_SIZE;
  125.     if ((read_count*=IO_SIZE))
  126.       break;
  127.     buffer->bufread *= 2;
  128.     if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
  129.       buffer->bufread+1,
  130.       MYF(MY_WME | MY_FAE))))
  131.       return (uint) -1;
  132.     buffer->start_of_line=buffer->buffer+start_offset;
  133.     buffer->end=buffer->buffer+bufbytes;
  134.   }
  135.   /* Shift stuff down. */
  136.   if (buffer->start_of_line != buffer->buffer)
  137.   {
  138.     bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes);
  139.     buffer->end=buffer->buffer+bufbytes;
  140.   }
  141.   /* Read in new stuff. */
  142.   if ((read_count= my_read(buffer->file, (byte*) buffer->end, read_count,
  143.    MYF(MY_WME))) == MY_FILE_ERROR)
  144.     return read_count;
  145.   DBUG_PRINT("fill_buff", ("Got %d bytes", read_count));
  146.   /* Kludge to pretend every nonempty file ends with a newline. */
  147.   if (!read_count && bufbytes && buffer->end[-1] != 'n')
  148.   {
  149.     buffer->eof = read_count = 1;
  150.     *buffer->end = 'n';
  151.   }
  152.   buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes;
  153.   buffer->end+=read_count;
  154.   *buffer->end=0; /* Sentinel */
  155.   return read_count;
  156. }
  157. char *intern_read_line(LINE_BUFFER *buffer,ulong *out_length)
  158. {
  159.   char *pos;
  160.   uint length;
  161.   DBUG_ENTER("intern_read_line");
  162.   buffer->start_of_line=buffer->end_of_line;
  163.   for (;;)
  164.   {
  165.     pos=buffer->end_of_line;
  166.     while (*pos != 'n' && *pos)
  167.       pos++;
  168.     if (pos == buffer->end)
  169.     {
  170.       if ((uint) (pos - buffer->start_of_line) < buffer->max_size)
  171.       {
  172. if (!(length=fill_buffer(buffer)) || length == (uint) -1)
  173.   DBUG_RETURN(0);
  174. continue;
  175.       }
  176.       pos--; /* break line here */
  177.     }
  178.     buffer->end_of_line=pos+1;
  179.     *out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line);
  180.     DBUG_RETURN(buffer->start_of_line);
  181.   }
  182. }