summaryrefslogtreecommitdiffstats
path: root/libopkg/pkg_hash.c
diff options
context:
space:
mode:
authorgraham.gower <graham.gower@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>2009-11-10 22:18:23 (EST)
committer graham.gower <graham.gower@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>2009-11-10 22:18:23 (EST)
commitf547c5906e484a05abb12b2a3f5d704c3cf7b60f (patch)
tree5b638c19bc09ec6902f6b2205e6c9051d11bc970 /libopkg/pkg_hash.c
parent774828dbef307f77e5db18a81edd4afa23af80d9 (diff)
Cleanup parsing of packages.
This diff is loosely based on a patch by Jo-Philipp Wich <google@wwsnet.net> posted in the bugtracker (Issue #24). Peak memory consumption while parsing package lists is dramatically reduced. Thanks to Camille Moncelier for fixing problems after reallocing for long lines. git-svn-id: http://opkg.googlecode.com/svn/trunk@283 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358
Diffstat (limited to 'libopkg/pkg_hash.c')
-rw-r--r--libopkg/pkg_hash.c80
1 files changed, 46 insertions, 34 deletions
diff --git a/libopkg/pkg_hash.c b/libopkg/pkg_hash.c
index cba3599..a445839 100644
--- a/libopkg/pkg_hash.c
+++ b/libopkg/pkg_hash.c
@@ -113,41 +113,53 @@ static char *pkg_get_default_arch(opkg_conf_t *conf)
int pkg_hash_add_from_file(opkg_conf_t *conf, const char *file_name,
pkg_src_t *src, pkg_dest_t *dest, int is_status_file)
{
- hash_table_t *hash = &conf->pkg_hash;
- char **raw;
- char **raw_start;
- pkg_t *pkg;
-
- raw = raw_start = read_raw_pkgs_from_file(file_name);
- if (!raw)
- return -ENOMEM;
-
- while(*raw){ /* don't worry, we'll increment raw in the parsing function */
- pkg = pkg_new();
-
- if (pkg_parse_raw(pkg, &raw, src, dest) == 0) {
- if (!pkg->architecture) {
- char *version_str = pkg_version_str_alloc(pkg);
- pkg->architecture = pkg_get_default_arch(conf);
- opkg_message(conf, OPKG_ERROR, "Package %s version %s has no architecture specified, defaulting to %s.\n",
- pkg->name, version_str, pkg->architecture);
- free(version_str);
- }
- hash_insert_pkg(hash, pkg, is_status_file,conf);
- } else {
- pkg_deinit (pkg);
- free(pkg);
- }
- }
+ hash_table_t *hash = &conf->pkg_hash;
+ pkg_t *pkg;
+ FILE *fp;
+ char *buf;
+ const size_t len = 4096;
+ int ret = 0;
+
+ fp = fopen(file_name, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: fopen(%s): %s\n",
+ __FUNCTION__, file_name, strerror(errno));
+ return -1;
+ }
- /* XXX: CLEANUP: I'd like a cleaner interface for cleaning up
- memory after read_raw_pkgs_from_file */
- raw = raw_start;
- while (*raw) {
- free(*raw++);
- }
- free(raw_start);
- return 0;
+ buf = xmalloc(len);
+
+ do {
+ pkg = pkg_new();
+ pkg->src = src;
+ pkg->dest = dest;
+
+ ret = pkg_parse_from_stream_nomalloc(pkg, fp, PFM_ALL,
+ &buf, len);
+ if (ret) {
+ pkg_deinit (pkg);
+ free(pkg);
+ if (ret == -1)
+ break;
+ continue;
+ }
+
+ if (!pkg->architecture) {
+ char *version_str = pkg_version_str_alloc(pkg);
+ pkg->architecture = pkg_get_default_arch(conf);
+ opkg_message(conf, OPKG_ERROR, "Package %s version %s has no architecture specified, defaulting to %s.\n",
+ pkg->name, version_str, pkg->architecture);
+ free(version_str);
+ }
+
+ hash_insert_pkg(hash, pkg, is_status_file, conf);
+
+ } while (!feof(fp));
+
+ free(buf);
+ fclose(fp);
+
+ return ret;
}
abstract_pkg_t * abstract_pkg_fetch_by_name(hash_table_t * hash, const char * pkg_name)