readline.cc
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:6k
源码类别:

MySQL数据库

开发平台:

Visual C++

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