File: dpkgparser.cpp

package info (click to toggle)
packagesearch 2.10.1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,704 kB
  • sloc: cpp: 9,176; perl: 248; makefile: 15; sh: 11
file content (88 lines) | stat: -rw-r--r-- 2,428 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "dpkgparser.h"

#include <sstream>

#include "packagename.h"
#include "runcommandforparsing.h"

namespace NApt {



/** parse a line of dpkg -l and return a pair(packageName, version)
 */
const DpkgParser::PackageInformation parseDpkgLine(const string& line) {

    std::istringstream stream(line);
    std::string word;

    std::string package;
    std::string version;
    std::string architecture;
    std::string description;

    for (int i = 0; i < 5 && stream; ++i) {
        // should not happen, but to improve robustness provide some fallback
        if (!(stream >> word))
            break;
        switch (i) {
        case 0:
            // ignore, should be "ii"
            break;
        case 1: {
            string packageName = PackageName::extractArchitecture(word).name;
            package = packageName;
            break;
        }
        case 2:
            version = word;
            break;
        case 3:
            architecture = word;
            // skip whitespace and put the rest into description
            std::getline(stream >> std::ws, description);
            break;
        }
    }
    return DpkgParser::PackageInformation {
        .name = package,
        .version = version,
        .architecture = architecture,
        .description = description
    };
}

void mergeIntoPackages(
    const DpkgParser::PackageInformation& package,
    map<string, const DpkgParser::PackageInformation>& target
) {
    auto packageIterator = target.find(package.name);
    if (packageIterator == target.end()) {
        target.insert({package.name, package});
    } else if (package.architecture == PackageName::defaultArchitecture()) {
        // replace only, if we have the target architecture

        // c++ speciality: we have to first remove the old, then add the
        // new entry, if the value type is const
        target.erase(packageIterator);
        target.insert({package.name, package});
    }
}

map<string, const DpkgParser::PackageInformation> DpkgParser::getInstalledPackages() {
    map<string, const PackageInformation> packages;

    auto lineProcessor = [&packages](const string& line) {
        auto package = parseDpkgLine(line);
        if (!package.name.empty()) {
            mergeIntoPackages(package, packages);
        }
    };

    NApplication::runCommandForParsing("dpkg -l |grep -E \"^ii\"", lineProcessor);

    return packages;
}

}   // NApt