mirror of
https://github.com/irssi/irssi.git
synced 2026-08-10 20:33:46 +02:00
..adding new files..
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@171 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
d01b094151
commit
c95034c6de
206 changed files with 31247 additions and 0 deletions
147
src/core/line-split.c
Normal file
147
src/core/line-split.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
line-split.c : irssi
|
||||
|
||||
Copyright (C) 1999-2000 Timo Sirainen
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
/* Maximum line length - split to two lines if it's longer than this.
|
||||
|
||||
This is mostly to prevent excessive memory usage. Like if someone DCC
|
||||
chats you, you both have very fast connections and the other side sends
|
||||
you 100 megs of text without any line feeds -> irssi will (try to)
|
||||
allocate 128M of memory for the line and will eventually crash when it
|
||||
can't allocate any more memory. If the line is split at every 64k the
|
||||
text buffer will free the old lines and the memory usage never gets
|
||||
too high. */
|
||||
#define MAX_CHARS_IN_LINE 65536
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
int alloc;
|
||||
int remove;
|
||||
char *str;
|
||||
} LINEBUF_REC;
|
||||
|
||||
static inline int nearest_power(int num)
|
||||
{
|
||||
int n = 1;
|
||||
|
||||
while (n < num) n <<= 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
static void linebuf_append(LINEBUF_REC *rec, const char *data, int len)
|
||||
{
|
||||
if (rec->len+len > rec->alloc) {
|
||||
rec->alloc = nearest_power(rec->len+len);;
|
||||
rec->str = rec->str == NULL ? g_malloc(rec->alloc) :
|
||||
g_realloc(rec->str, rec->alloc);
|
||||
}
|
||||
|
||||
memcpy(rec->str + rec->len, data, len);
|
||||
rec->len += len;
|
||||
}
|
||||
|
||||
static char *linebuf_find(LINEBUF_REC *rec, char chr)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < rec->len; n++)
|
||||
if (rec->str[n] == chr) return rec->str+n;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int remove_newline(LINEBUF_REC *rec)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = linebuf_find(rec, '\n');
|
||||
if (ptr == NULL) {
|
||||
/* LF wasn't found, wait for more data.. */
|
||||
if (rec->len < MAX_CHARS_IN_LINE)
|
||||
return 0;
|
||||
|
||||
/* line buffer is too big - force a newline. */
|
||||
linebuf_append(rec, "\n", 1);
|
||||
ptr = rec->str+rec->len-1;
|
||||
}
|
||||
|
||||
rec->remove = (int) (ptr-rec->str)+1;
|
||||
if (ptr != rec->str && ptr[-1] == '\r') {
|
||||
/* remove CR too. */
|
||||
ptr--;
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* line-split `data'. Initially `*buffer' should contain NULL. */
|
||||
int line_split(const char *data, int len, char **output, LINEBUF_REC **buffer)
|
||||
{
|
||||
LINEBUF_REC *rec;
|
||||
|
||||
g_return_val_if_fail(data != NULL, -1);
|
||||
g_return_val_if_fail(output != NULL, -1);
|
||||
g_return_val_if_fail(buffer != NULL, -1);
|
||||
|
||||
if (*buffer == NULL)
|
||||
*buffer = g_new0(LINEBUF_REC, 1);
|
||||
rec = *buffer;
|
||||
|
||||
if (rec->remove > 0) {
|
||||
rec->len = rec->len - rec->remove;
|
||||
memcpy(rec->str, rec->str+rec->remove, rec->len);
|
||||
rec->remove = 0;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
linebuf_append(rec, data, len);
|
||||
else if (len < 0) {
|
||||
/* connection closed.. */
|
||||
if (rec->len == 0)
|
||||
return -1;
|
||||
|
||||
/* no new data got but still something in buffer.. */
|
||||
len = 0;
|
||||
if (linebuf_find(rec, '\n') == NULL) {
|
||||
/* connection closed and last line is missing \n ..
|
||||
just add it so we can see if it had anything useful.. */
|
||||
linebuf_append(rec, "\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
*output = rec->str;
|
||||
return remove_newline(rec);
|
||||
}
|
||||
|
||||
void line_split_free(LINEBUF_REC *buffer)
|
||||
{
|
||||
if (buffer != NULL) {
|
||||
if (buffer->str != NULL) g_free(buffer->str);
|
||||
g_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return 1 if there is no data in the buffer */
|
||||
int line_split_is_empty(LINEBUF_REC *buffer)
|
||||
{
|
||||
return buffer->len == 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue