aboutsummaryrefslogtreecommitdiff
path: root/src/rez/dir.cpp
blob: 62e37fb7c4169aba580ec7c42ab737929c99b2ac (plain) (blame)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <rez/dir.h>
#include <rez/io.h>
#include <iostream>

const rez::dir::entrymap &rez::dir::entries() const
{
    return m_entries;
}

const std::string &rez::dir::name() const
{
    return m_name;
}

int rez::dir::read(const struct entry::cfg &cfg, rez::io &io,
    std::string &name, direntry &de, unsigned level)
{
    rez::entry entry;

    if (entry.read(io))
        return -1;

    switch (entry.type)
    {
        case entry::type::dir:
        {
            long offset;
            dir subdir;

            if (io.read(subdir.m_name, cfg.maxdirlen)
                || (offset = io.tell()) < 0)
                return -1;

            struct entry::cfg scfg = cfg;

#if 0
            for (unsigned i = 0; i < level + 1; i++)
                std::cout << "|\t";

            std::cout << "name: " << subdir.m_name << std::endl;
#endif

            subdir.entry = entry;
            scfg.size = entry.size;
            scfg.offset = entry.pos;

            if (subdir.read(scfg, io, level + 1) || io.seek(offset))
                return -1;

            name = subdir.m_name;
            de = subdir;
        }
            break;

        case entry::type::resource:
        {
            resource resource;

            resource.entry = entry;

            if (resource.read(cfg, io))
                return -1;

#if 0
            for (unsigned i = 0; i < level + 1; i++)
                std::cout << "|\t";

            std::cout << "name: " << resource.name() << std::endl;
#endif

            name = resource.name();
            de = resource;
        }
            break;

        default:
            std::cerr << "Invalid entry type " << entry.type << std::endl;
            return -1;
    }

    return 0;
}

int rez::dir::read(const struct entry::cfg &cfg, rez::io &io, unsigned level)
{
    unsigned long size = cfg.size;
    long before = cfg.offset;

    if (io.seek(cfg.offset))
        return -1;

    while (size)
    {
        std::string name;
        direntry de;
        long after;

        if (read(cfg, io, name, de, level)
            || (after = io.tell()) < 0)
            return -1;

        unsigned long r = after - before;

        if (r > size)
        {
            std::cerr << m_name << ": exceeded maximum direntry length "
                "(" << cfg.size << ")" << std::endl;
            return -1;
        }

        m_entries[name] = de;
        before = after;
        size -= r;
    }

    return 0;
}