libgeda
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * libgeda - gEDA's library 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00021 #include <config.h> 00022 00023 #include <stdio.h> 00024 #include <glib.h> 00025 00026 #ifdef HAVE_STRING_H 00027 #include <string.h> 00028 #endif 00029 00030 #ifdef HAVE_LIBDMALLOC 00031 #include <dmalloc.h> 00032 #endif 00033 00034 #include "libgeda_priv.h" 00035 00036 struct _TextBuffer 00037 { 00038 const gchar *buffer; 00039 gsize size; 00040 00041 gchar *line; 00042 gsize linesize; 00043 00044 gsize offset; 00045 }; 00046 00047 #define TEXT_BUFFER_LINE_SIZE 1024 00048 00062 TextBuffer *s_textbuffer_new (const gchar *data, const gint size) 00063 { 00064 TextBuffer *result; 00065 gsize realsize; 00066 00067 g_return_val_if_fail ((data != NULL), 00068 NULL); 00069 00070 if (size < 0) 00071 realsize = strlen(data); 00072 else 00073 realsize = size; 00074 00075 result = g_new0(TextBuffer, 1); 00076 00077 result->buffer = data; 00078 result->size = realsize; 00079 00080 result->linesize = TEXT_BUFFER_LINE_SIZE; 00081 result->line = g_malloc(result->linesize); 00082 00083 return result; 00084 } 00085 00097 TextBuffer *s_textbuffer_free (TextBuffer *tb) 00098 { 00099 if (tb == NULL) return NULL; 00100 00101 g_free (tb->line); 00102 tb->line = NULL; 00103 g_free (tb); 00104 return NULL; 00105 } 00106 00127 const gchar * 00128 s_textbuffer_next (TextBuffer *tb, const gssize count) 00129 { 00130 gboolean eol = FALSE; 00131 gchar c; 00132 gsize len; 00133 00134 g_return_val_if_fail (tb != NULL, NULL); 00135 00136 if (tb->offset >= tb->size) return NULL; 00137 00138 const gchar *src = tb->buffer + tb->offset; 00139 gchar *dest = tb->line; 00140 const gchar *buf_end = tb->buffer + tb->size; 00141 00142 while (1) { 00143 if (src >= buf_end) break; 00144 if (count >= 0 && dest - tb->line >= count) break; 00145 if (count < 0 && eol) break; 00146 00147 /* Expand line buffer, if necessary, leaving space for a null */ 00148 len = dest - tb->line + 2; 00149 if (len >= tb->linesize) { 00150 tb->linesize += TEXT_BUFFER_LINE_SIZE; 00151 tb->line = g_realloc(tb->line, tb->linesize); 00152 } 00153 00154 eol = FALSE; 00155 c = *src; 00156 if (c == '\n') { 00157 *dest = '\n'; 00158 eol = TRUE; 00159 } else if (c == '\r') { 00160 *dest = '\n'; 00161 eol = TRUE; 00162 /* Peek ahead to absorb a '\n' */ 00163 src++; 00164 if (src >= buf_end || *src != '\n') src--; 00165 } else { 00166 *dest = c; 00167 } 00168 00169 src++; 00170 dest++; 00171 } 00172 00173 *dest = 0; 00174 tb->offset = src - tb->buffer; 00175 00176 return tb->line; 00177 } 00192 const gchar * 00193 s_textbuffer_next_line (TextBuffer *tb) 00194 { 00195 return s_textbuffer_next (tb, -1); 00196 }