Просмотр исходного кода

libdpkg: Use a generic pointer to pass the parsed object data around

This will allow code not parsing binary package control files to be
able to easily reuse the parser, by supplying their own object
structure.

Unfortunately this sacrifices the type-safety of the parse_stanza()
and parse_field() functions, but that only affects one variable,
which should be an acceptable tradeoff given the gain in code reuse.
Guillem Jover лет назад: 15
Родитель
Сommit
e84c47aa29
2 измененных файлов с 24 добавлено и 10 удалено
  1. 22 7
      lib/dpkg/parse.c
  2. 2 3
      lib/dpkg/parsedump.h

+ 22 - 7
lib/dpkg/parse.c

@@ -93,13 +93,25 @@ static const struct nickname nicknames[] = {
   { .nick = NULL }
 };
 
+/**
+ * Package object being parsed.
+ *
+ * Structure used to hold the parsed data for the package being constructed,
+ * before it gets properly inserted into the package database.
+ */
+struct pkg_parse_object {
+  struct pkginfo *pkg;
+  struct pkgbin *pkgbin;
+};
+
 /**
  * Parse the field and value into the package being constructed.
  */
 static void
 pkg_parse_field(struct parsedb_state *ps, struct field_state *fs,
-                struct pkginfo *pkg, struct pkgbin *pkgbin)
+                void *parse_obj)
 {
+  struct pkg_parse_object *pkg_obj = parse_obj;
   const struct nickname *nick;
   const struct fieldinfo *fip;
   int *ip;
@@ -125,7 +137,7 @@ pkg_parse_field(struct parsedb_state *ps, struct field_state *fs,
     varbuf_add_buf(&fs->value, fs->valuestart, fs->valuelen);
     varbuf_end_str(&fs->value);
 
-    fip->rcall(pkg, pkgbin, ps, fs->value.buf, fip);
+    fip->rcall(pkg_obj->pkg, pkg_obj->pkgbin, ps, fs->value.buf, fip);
   } else {
     struct arbitraryfield *arp, **larpp;
 
@@ -133,7 +145,7 @@ pkg_parse_field(struct parsedb_state *ps, struct field_state *fs,
       parse_error(ps,
                   _("user-defined field name `%.*s' too short"),
                   fs->fieldlen, fs->fieldstart);
-    larpp = &pkgbin->arbs;
+    larpp = &pkg_obj->pkgbin->arbs;
     while ((arp = *larpp) != NULL) {
       if (!strncasecmp(arp->name, fs->fieldstart, fs->fieldlen))
         parse_error(ps,
@@ -356,8 +368,7 @@ parse_open(struct parsedb_state *ps, const char *filename,
  */
 bool
 parse_stanza(struct parsedb_state *ps, struct field_state *fs,
-             parse_field_func *parse_field,
-             struct pkginfo *pkg, struct pkgbin *pkgbin)
+             parse_field_func *parse_field, void *parse_obj)
 {
   int c;
 
@@ -458,7 +469,7 @@ parse_stanza(struct parsedb_state *ps, struct field_state *fs,
     while (fs->valuelen && isspace(*(fs->valuestart + fs->valuelen - 1)))
       fs->valuelen--;
 
-    parse_field(ps, fs, pkg, pkgbin);
+    parse_field(ps, fs, parse_obj);
 
     if (parse_EOF(ps) || c == '\n' || c == MSDOS_EOF_CHAR)
       break;
@@ -497,6 +508,7 @@ int parsedb(const char *filename, enum parsedbflags flags,
   struct pkginfo tmp_pkg;
   struct pkginfo *new_pkg, *db_pkg;
   struct pkgbin *new_pkgbin, *db_pkgbin;
+  struct pkg_parse_object pkg_obj;
   int fieldencountered[array_count(fieldinfos)];
   int pdone;
   struct parsedb_state ps;
@@ -516,6 +528,9 @@ int parsedb(const char *filename, enum parsedbflags flags,
   ps.pkg = new_pkg;
   ps.pkgbin = new_pkgbin;
 
+  pkg_obj.pkg = new_pkg;
+  pkg_obj.pkgbin = new_pkgbin;
+
   pdone= 0;
 
   /* Loop per package. */
@@ -523,7 +538,7 @@ int parsedb(const char *filename, enum parsedbflags flags,
     memset(fieldencountered, 0, sizeof(fieldencountered));
     pkg_blank(new_pkg);
 
-    if (!parse_stanza(&ps, &fs, pkg_parse_field, new_pkg, new_pkgbin))
+    if (!parse_stanza(&ps, &fs, pkg_parse_field, &pkg_obj))
       break;
 
     if (pdone && donep)

+ 2 - 3
lib/dpkg/parsedump.h

@@ -53,11 +53,10 @@ void parse_open(struct parsedb_state *ps, const char *filename,
 void parse_close(struct parsedb_state *ps);
 
 typedef void parse_field_func(struct parsedb_state *ps, struct field_state *fs,
-                              struct pkginfo *pkg, struct pkgbin *pkgbin);
+                              void *parse_obj);
 
 bool parse_stanza(struct parsedb_state *ps, struct field_state *fs,
-                  parse_field_func *parse_field,
-                  struct pkginfo *pkg, struct pkgbin *pkgbin);
+                  parse_field_func *parse_field, void *parse_obj);
 
 #define PKGIFPOFF(f) (offsetof(struct pkgbin, f))
 #define PKGPFIELD(pifp,of,type) (*(type*)((char*)(pifp)+(of)))