home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / client / readline.cpp < prev    next >
C/C++ Source or Header  |  2000-08-31  |  6KB  |  217 lines

  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.  
  18. /* readline for batch mode */
  19.  
  20. #include <global.h>
  21. #include <my_sys.h>
  22. #include <m_string.h>
  23. #include "my_readline.h"
  24.  
  25. static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,
  26.                 ulong max_size);
  27. static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str);
  28. static uint fill_buffer(LINE_BUFFER *buffer);
  29. static char *intern_read_line(LINE_BUFFER *buffer,uint *out_length);
  30.  
  31.  
  32. LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
  33. {
  34.   LINE_BUFFER *line_buff;
  35.   if (!(line_buff=(LINE_BUFFER*) my_malloc(sizeof(*line_buff),MYF(MY_WME))))
  36.     return 0;
  37.   if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size))
  38.   {
  39.     my_free((char*) line_buff,MYF(0));
  40.     return 0;
  41.   }
  42.   return line_buff;
  43. }
  44.  
  45.  
  46. char *batch_readline(LINE_BUFFER *line_buff)
  47. {
  48.   char *pos;
  49.   uint out_length;
  50.  
  51.   if (!(pos=intern_read_line(line_buff,&out_length)))
  52.     return 0;
  53.   if (out_length && pos[out_length-1] == '\n')
  54.     out_length--;                /* Remove '\n' */
  55.   pos[out_length]=0;
  56.   return pos;
  57. }
  58.  
  59.  
  60. void batch_readline_end(LINE_BUFFER *line_buff)
  61. {
  62.   if (line_buff)
  63.   {
  64.     my_free((gptr) line_buff->buffer,MYF(MY_ALLOW_ZERO_PTR));
  65.     my_free((char*) line_buff,MYF(0));
  66.   }
  67. }
  68.  
  69.  
  70. LINE_BUFFER *batch_readline_command(my_string str)
  71. {
  72.   LINE_BUFFER *line_buff;
  73.   if (!(line_buff=(LINE_BUFFER*) my_malloc(sizeof(*line_buff),MYF(MY_WME))))
  74.     return 0;
  75.   if (init_line_buffer_from_string(line_buff,str))
  76.   {
  77.     my_free((char*) line_buff,MYF(0));
  78.     return 0;
  79.   }
  80.   return line_buff;
  81. }
  82.  
  83.  
  84. /*****************************************************************************
  85.       Functions to handle buffered readings of lines from a stream
  86. ******************************************************************************/
  87.  
  88. static bool
  89. init_line_buffer(LINE_BUFFER *buffer,File file,ulong size,ulong max_buffer)
  90. {
  91.   bzero((char*) buffer,sizeof(buffer[0]));
  92.   buffer->file=file;
  93.   buffer->bufread=size;
  94.   buffer->max_size=max_buffer;
  95.   if (!(buffer->buffer = (char*) my_malloc(buffer->bufread+1,
  96.                        MYF(MY_WME | MY_FAE))))
  97.     return 1;
  98.   buffer->end_of_line=buffer->end=buffer->buffer;
  99.   buffer->buffer[0]=0;                /* For easy start test */
  100.   return 0;
  101. }
  102.  
  103.  
  104. static bool init_line_buffer_from_string(LINE_BUFFER *buffer,my_string str)
  105. {
  106.   uint length;
  107.   bzero((char*) buffer,sizeof(buffer[0]));
  108.   length=(uint) strlen(str);
  109.   if (!(buffer->buffer=buffer->start_of_line=buffer->end_of_line=
  110.     (char*)my_malloc(length+2,MYF(MY_FAE))))
  111.     return 1;
  112.   memcpy(buffer->buffer,str,length);
  113.   buffer->buffer[length]='\n';
  114.   buffer->buffer[length+1]=0;
  115.   buffer->end=buffer->buffer+length+1;
  116.   buffer->eof=1;
  117.   buffer->max_size=1;
  118.   return 0;
  119. }
  120.  
  121.  
  122. static void free_line_buffer(LINE_BUFFER *buffer)
  123. {
  124.   if (buffer->buffer)
  125.   {
  126.     my_free((gptr) buffer->buffer,MYF(0));
  127.     buffer->buffer=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 uint fill_buffer(LINE_BUFFER *buffer)
  138. {
  139.   uint 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.     buffer->bufread *= 2;
  154.     if (!(buffer->buffer = (char*) my_realloc(buffer->buffer,
  155.                           buffer->bufread+1,
  156.                           MYF(MY_WME | MY_FAE))))
  157.       return (uint) -1;
  158.     buffer->start_of_line=buffer->buffer+start_offset;
  159.     buffer->end=buffer->buffer+bufbytes;
  160.   }
  161.  
  162.   /* Shift stuff down. */
  163.   if (buffer->start_of_line != buffer->buffer)
  164.   {
  165.     bmove(buffer->buffer,buffer->start_of_line,(uint) bufbytes);
  166.     buffer->end=buffer->buffer+bufbytes;
  167.   }
  168.  
  169.   /* Read in new stuff. */
  170.   if ((read_count= my_read(buffer->file, (byte*) buffer->end, read_count,
  171.                MYF(MY_WME))) == MY_FILE_ERROR)
  172.     return read_count;
  173.  
  174.   DBUG_PRINT("fill_buff", ("Got %d bytes", read_count));
  175.  
  176.   /* Kludge to pretend every nonempty file ends with a newline. */
  177.   if (!read_count && bufbytes && buffer->end[-1] != '\n')
  178.   {
  179.     buffer->eof = read_count = 1;
  180.     *buffer->end = '\n';
  181.   }
  182.   buffer->end_of_line=(buffer->start_of_line=buffer->buffer)+bufbytes;
  183.   buffer->end+=read_count;
  184.   *buffer->end=0;                /* Sentinel */
  185.   return read_count;
  186. }
  187.  
  188.  
  189.  
  190. char *intern_read_line(LINE_BUFFER *buffer,uint *out_length)
  191. {
  192.   char *pos;
  193.   uint length;
  194.   DBUG_ENTER("intern_read_line");
  195.  
  196.   buffer->start_of_line=buffer->end_of_line;
  197.   for (;;)
  198.   {
  199.     pos=buffer->end_of_line;
  200.     while (*pos != '\n' && *pos)
  201.       pos++;
  202.     if (pos == buffer->end)
  203.     {
  204.       if ((uint) (pos - buffer->start_of_line) < buffer->max_size)
  205.       {
  206.     if (!(length=fill_buffer(buffer)) || length == (uint) -1)
  207.       DBUG_RETURN(0);
  208.     continue;
  209.       }
  210.       pos--;                    /* break line here */
  211.     }
  212.     buffer->end_of_line=pos+1;
  213.     *out_length=(uint) (pos + 1 - buffer->eof - buffer->start_of_line);
  214.     DBUG_RETURN(buffer->start_of_line);
  215.   }
  216. }
  217.