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

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * Copyright (c) 1993, 1994 Chris Provenzano. 
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * Chris Torek.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  * This product includes software developed by the University of
  20.  * California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. /*static char *sccsid = "from: @(#)fgetline.c 5.2 (Berkeley) 5/4/91";*/
  39. static char *rcsid = "$Id$";
  40. #endif /* LIBC_SCCS and not lint */
  41. #include <pthread.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include "local.h"
  46. /*
  47.  * Expand the line buffer.  Return -1 on error.
  48.  * The `new size' does not account for a terminating '',
  49.  * so we add 1 here.
  50.  */
  51. __slbexpand(fp, newsize)
  52. FILE *fp;
  53. size_t newsize;
  54. {
  55. void *p;
  56. if (fp->_lb._size >= ++newsize)
  57. return (0);
  58. if ((p = realloc(fp->_lb._base, newsize)) == NULL)
  59. return (-1);
  60. fp->_lb._base = p;
  61. fp->_lb._size = newsize;
  62. return (0);
  63. }
  64. /*
  65.  * Get an input line.  The returned pointer often (but not always)
  66.  * points into a stdio buffer.  Fgetline smashes the newline (if any)
  67.  * in the stdio buffer; callers must not use it on streams that
  68.  * have `magic' setvbuf() games happening.
  69.  */
  70. char *
  71. fgetline(fp, lenp)
  72. register FILE *fp;
  73. size_t *lenp;
  74. {
  75. register unsigned char *p;
  76. register size_t len;
  77. size_t off;
  78. flockfile(fp);
  79. /* make sure there is input */
  80. if (fp->_r <= 0 && __srefill(fp)) {
  81. if (lenp != NULL)
  82. *lenp = 0;
  83. funlockfile(fp);
  84. return (NULL);
  85. }
  86. /* look for a newline in the input */
  87. if ((p = memchr((void *)fp->_p, 'n', fp->_r)) != NULL) {
  88. register char *ret;
  89. /*
  90.  * Found one.  Flag buffer as modified to keep
  91.  * fseek from `optimising' a backward seek, since
  92.  * the newline is about to be trashed.  (We should
  93.  * be able to get away with doing this only if
  94.  * p is not pointing into an ungetc buffer, since
  95.  * fseek discards ungetc data, but this is the
  96.  * usual case anyway.)
  97.  */
  98. ret = (char *)fp->_p;
  99. len = p - fp->_p;
  100. fp->_flags |= __SMOD;
  101. *p = 0;
  102. fp->_r -= len + 1;
  103. fp->_p = p + 1;
  104. if (lenp != NULL)
  105. *lenp = len;
  106. funlockfile(fp);
  107. return (ret);
  108. }
  109. /*
  110.  * We have to copy the current buffered data to the line buffer.
  111.  *
  112.  * OPTIMISTIC is length that we (optimistically)
  113.  * expect will accomodate the `rest' of the string,
  114.  * on each trip through the loop below.
  115.  */
  116. #define OPTIMISTIC 80
  117. for (len = fp->_r, off = 0;; len += fp->_r) {
  118. register size_t diff;
  119. /*
  120.  * Make sure there is room for more bytes.
  121.  * Copy data from file buffer to line buffer,
  122.  * refill file and look for newline.  The
  123.  * loop stops only when we find a newline.
  124.  */
  125. if (__slbexpand(fp, len + OPTIMISTIC))
  126. goto error;
  127. (void) memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, 
  128.     len - off);
  129. off = len;
  130. if (__srefill(fp))
  131. break; /* EOF or error: return partial line */
  132. if ((p = memchr((void *)fp->_p, 'n', fp->_r)) == NULL)
  133. continue;
  134. /* got it: finish up the line (like code above) */
  135. fp->_flags |= __SMOD; /* soon */
  136. diff = p - fp->_p;
  137. len += diff;
  138. if (__slbexpand(fp, len))
  139. goto error;
  140. (void) memcpy((void *)(fp->_lb._base + off), (void *)fp->_p, diff);
  141. fp->_r -= diff + 1;
  142. fp->_p = p + 1;
  143. break;
  144. }
  145. if (lenp != NULL)
  146. *lenp = len;
  147. fp->_lb._base[len] = 0;
  148. funlockfile(fp);
  149. return ((char *)fp->_lb._base);
  150. error:
  151. if (lenp != NULL)
  152. *lenp = 0; /* ??? */
  153. funlockfile(fp);
  154. return (NULL); /* ??? */
  155. }