gobuffer: Move the non string specific bits

Will be used while encoding the CTF sections.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2008-10-02 17:06:01 -03:00
parent 212b994ab5
commit be30be91f5
5 changed files with 206 additions and 108 deletions

View File

@ -31,7 +31,7 @@ find_package(ZLIB REQUIRED)
_set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}${CMAKE_INSTALL_PREFIX}/${__LIB}" "libdir")
set(dwarves_LIB_SRCS dwarves.c strings ctf_loader.c libctf.c dwarf_loader.c)
set(dwarves_LIB_SRCS dwarves.c gobuffer strings ctf_loader.c libctf.c dwarf_loader.c)
add_library(dwarves SHARED ${dwarves_LIB_SRCS})
set_target_properties(dwarves PROPERTIES VERSION 1.0.0 SOVERSION 1)
target_link_libraries(dwarves ${DWARF_LIBRARIES} ${ZLIB_LIBRARIES})

126
gobuffer.c Normal file
View File

@ -0,0 +1,126 @@
/*
Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>
Grow only buffer, add entries but never delete
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
*/
#include "gobuffer.h"
#include <search.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <zlib.h>
#include "dutil.h"
#define GOBUFFER__BCHUNK (8 * 1024)
#define GOBUFFER__ZCHUNK (8 * 1024)
void gobuffer__init(struct gobuffer *self)
{
self->entries = NULL;
self->nr_entries = self->allocated_size = 0;
/* 0 == NULL */
self->index = 1;
}
struct gobuffer *gobuffer__new(void)
{
struct gobuffer *self = malloc(sizeof(*self));
if (self != NULL)
gobuffer__init(self);
return self;
}
void __gobuffer__delete(struct gobuffer *self)
{
free(self->entries);
}
void gobuffer__delete(struct gobuffer *self)
{
__gobuffer__delete(self);
free(self);
}
const void *gobuffer__ptr(const struct gobuffer *self, unsigned int s)
{
return s ? self->entries + s : NULL;
}
unsigned int gobuffer__add(struct gobuffer *self, const void *s,
unsigned int len)
{
const unsigned int rc = self->index;
const unsigned int index = self->index + len;
char *copy;
if (index >= self->allocated_size) {
const unsigned int allocated_size = (self->allocated_size +
GOBUFFER__BCHUNK);
char *entries = realloc(self->entries, allocated_size);
if (entries == NULL)
return 0;
self->allocated_size = allocated_size;
self->entries = entries;
}
++self->nr_entries;
copy = self->entries + rc;
memcpy(copy, s, len);
self->index = index;
return rc;
}
const void *gobuffer__compress(struct gobuffer *self, unsigned int *size)
{
z_stream z = {
.zalloc = Z_NULL,
.zfree = Z_NULL,
.opaque = Z_NULL,
.avail_in = gobuffer__size(self),
.next_in = (Bytef *)gobuffer__entries(self),
};
void *bf = NULL;
unsigned int bf_size = 0;
if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
goto out_free;
do {
const unsigned int new_bf_size = bf_size + GOBUFFER__ZCHUNK;
void *nbf = realloc(bf, new_bf_size);
if (nbf == NULL)
goto out_close_and_free;
bf = nbf;
z.avail_out = GOBUFFER__ZCHUNK;
z.next_out = (Bytef *)bf + bf_size;
bf_size = new_bf_size;
if (deflate(&z, Z_FINISH) == Z_STREAM_ERROR)
goto out_close_and_free;
} while (z.avail_out == 0);
deflateEnd(&z);
*size = bf_size - z.avail_out;
out:
return bf;
out_close_and_free:
deflateEnd(&z);
out_free:
free(bf);
bf = NULL;
goto out;
}

46
gobuffer.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef _GOBUFFER_H_
#define _GOBUFFER_H_ 1
/*
Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
*/
struct gobuffer {
char *entries;
unsigned int nr_entries;
unsigned int index;
unsigned int allocated_size;
};
struct gobuffer *gobuffer__new(void);
void gobuffer__init(struct gobuffer *self);
void gobuffer__delete(struct gobuffer *self);
void __gobuffer__delete(struct gobuffer *self);
unsigned int gobuffer__add(struct gobuffer *self, const void *s,
unsigned int len);
static inline const void *gobuffer__entries(const struct gobuffer *self)
{
return self->entries;
}
static inline unsigned int gobuffer__nr_entries(const struct gobuffer *self)
{
return self->nr_entries;
}
static inline unsigned int gobuffer__size(const struct gobuffer *self)
{
return self->index;
}
const void *gobuffer__ptr(const struct gobuffer *self, unsigned int s);
const void *gobuffer__compress(struct gobuffer *self, unsigned int *size);
#endif /* _GOBUFFER_H_ */

107
strings.c
View File

@ -7,6 +7,7 @@
*/
#include "strings.h"
#include "gobuffer.h"
#include <search.h>
#include <stdint.h>
@ -17,46 +18,19 @@
#include "dutil.h"
#define STRINGS__ZCHUNK (128 * 1024)
#define STRINGS__SCHUNK (8 * 1024)
struct strings {
void *tree;
char *entries;
unsigned int nr_entries;
strings_t index;
strings_t allocated_size;
};
struct strings *strings__new(void)
{
struct strings *self = malloc(sizeof(*self));
if (self != NULL) {
memset(self, 0, sizeof(*self));
/* 0 == NULL */
self->index = 1;
self->tree = NULL;
gobuffer__init(&self->gb);
}
return self;
}
const char *strings__entries(const struct strings *self)
{
return self->entries;
}
unsigned int strings__nr_entries(const struct strings *self)
{
return self->nr_entries;
}
strings_t strings__size(const struct strings *self)
{
return self->index;
}
static void do_nothing(void *ptr __unused)
{
}
@ -64,39 +38,13 @@ static void do_nothing(void *ptr __unused)
void strings__delete(struct strings *self)
{
tdestroy(self->tree, do_nothing);
free(self->entries);
__gobuffer__delete(&self->gb);
free(self);
}
const char *strings__ptr(const struct strings *self, strings_t s)
{
return s ? self->entries + s : NULL;
}
static strings_t strings__insert(struct strings *self, const char *s)
{
const size_t len = strlen(s);
const strings_t rc = self->index;
const strings_t index = self->index + len + 1;
char *copy;
if (index >= self->allocated_size) {
const strings_t allocated_size = (self->allocated_size +
STRINGS__SCHUNK);
char *entries = realloc(self->entries, allocated_size);
if (entries == NULL)
return 0;
self->allocated_size = allocated_size;
self->entries = entries;
}
++self->nr_entries;
copy = self->entries + rc;
memcpy(copy, s, len + 1);
self->index = index;
return rc;
return gobuffer__add(&self->gb, s, strlen(s) + 1);
}
struct search_key {
@ -108,7 +56,7 @@ static int strings__compare(const void *a, const void *b)
{
const struct search_key *key = a;
return strcmp(key->str, key->self->entries + *(strings_t *)&b);
return strcmp(key->str, key->self->gb.entries + *(strings_t *)&b);
}
strings_t strings__add(struct strings *self, const char *str)
@ -140,46 +88,3 @@ strings_t strings__add(struct strings *self, const char *str)
return index;
}
const char *strings__compress(struct strings *self, unsigned int *size)
{
z_stream z = {
.zalloc = Z_NULL,
.zfree = Z_NULL,
.opaque = Z_NULL,
.avail_in = strings__size(self),
.next_in = (Bytef *)strings__entries(self),
};
char *bf = NULL;
unsigned int bf_size = 0;
if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
goto out_free;
do {
const unsigned int new_bf_size = bf_size + STRINGS__ZCHUNK;
char *nbf = realloc(bf, new_bf_size);
if (nbf == NULL)
goto out_close_and_free;
bf = nbf;
z.avail_out = STRINGS__ZCHUNK;
z.next_out = (Bytef *)bf + bf_size;
bf_size = new_bf_size;
if (deflate(&z, Z_FINISH) == Z_STREAM_ERROR)
goto out_close_and_free;
} while (z.avail_out == 0);
deflateEnd(&z);
*size = bf_size - z.avail_out;
out:
return bf;
out_close_and_free:
deflateEnd(&z);
out_free:
free(bf);
bf = NULL;
goto out;
}

View File

@ -8,9 +8,14 @@
published by the Free Software Foundation.
*/
#include "gobuffer.h"
typedef unsigned int strings_t;
struct strings;
struct strings {
void *tree;
struct gobuffer gb;
};
struct strings *strings__new(void);
@ -18,14 +23,30 @@ void strings__delete(struct strings *self);
strings_t strings__add(struct strings *self, const char *str);
const char *strings__ptr(const struct strings *self, strings_t s);
static inline const char *strings__ptr(const struct strings *self, strings_t s)
{
return gobuffer__ptr(&self->gb, s);
}
const char *strings__entries(const struct strings *self);
static inline const char *strings__entries(const struct strings *self)
{
return gobuffer__entries(&self->gb);
}
unsigned int strings__nr_entries(const struct strings *self);
static inline unsigned int strings__nr_entries(const struct strings *self)
{
return gobuffer__nr_entries(&self->gb);
}
strings_t strings__size(const struct strings *self);
static inline strings_t strings__size(const struct strings *self)
{
return gobuffer__size(&self->gb);
}
const char *strings__compress(struct strings *self, unsigned int *size);
static inline const char *strings__compress(struct strings *self,
unsigned int *size)
{
return gobuffer__compress(&self->gb, size);
}
#endif /* _STRINGS_H_ */