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:
parent
212b994ab5
commit
be30be91f5
|
@ -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})
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
107
strings.c
|
@ -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;
|
||||
}
|
||||
|
|
33
strings.h
33
strings.h
|
@ -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_ */
|
||||
|
|
Loading…
Reference in New Issue