File: MapResourceStream.h

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (152 lines) | stat: -rw-r--r-- 3,623 bytes parent folder | download | duplicates (4)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once

#include <memory>
#include <string>
#include <fstream>
#include "os/path.h"
#include "itextstream.h"
#include "iarchive.h"
#include "ifilesystem.h"

namespace stream
{

/**
 * RAII object representing a file stream used for map loading.
 * It may either refer to a physical file or a VFS file.
 */
class MapResourceStream
{
public:
    using Ptr = std::shared_ptr<MapResourceStream>;

    virtual ~MapResourceStream() {}

    // Returns true if the stream has been successfully opened
    virtual bool isOpen() const = 0;

    // Returns the (seekable) input stream
    virtual std::istream& getStream() = 0;

    // Factory method which will return a stream reference for the given path
    // Will always return a non-empty reference
    static Ptr OpenFromPath(const std::string& path);

    // Factory method which will return a stream reference of the given ArchiveTextFile
    static Ptr OpenFromArchiveFile(const ArchiveTextFilePtr& archive);
};

namespace detail
{

// Stream implementation targeting a physical file
class FileMapResourceStream :
    public MapResourceStream
{
private:
    std::ifstream _stream;

public:
    FileMapResourceStream(const std::string& path)
    {
        rMessage() << "Open file " << path << " from filesystem...";

        _stream.open(path);

        if (!_stream)
        {
            rError() << "failure" << std::endl;
            return;
        }

        rMessage() << "success." << std::endl;
    }

    bool isOpen() const override
    {
        return _stream.good();
    }

    std::istream& getStream() override
    {
        return _stream;
    }
};

/**
 * MapResourceStream implementation working with a PAK file.
 * Since deflated file streams are not seekable, the whole 
 * file contents are pre-loaded into a seekable stringstream.
 */
class ArchivedMapResourceStream :
    public MapResourceStream
{
private:
    ArchiveTextFilePtr _archiveFile;

    std::stringstream _contentStream;

public:
    ArchivedMapResourceStream(const std::string& path)
    {
        rMessage() << "Trying to open file " << path << " from VFS...";

        _archiveFile = GlobalFileSystem().openTextFile(path);

        if (!_archiveFile)
        {
            rError() << "failure" << std::endl;
            return;
        }

        rMessage() << "success." << std::endl;

        std::istream vfsStream(&(_archiveFile->getInputStream()));

        // Load everything into one large string
        _contentStream << vfsStream.rdbuf();
    }

    ArchivedMapResourceStream(const ArchiveTextFilePtr& archive) :
        _archiveFile(archive)
    {
        rMessage() << "Opened text file in PAK: " << archive->getName() << std::endl;

        std::istream vfsStream(&(_archiveFile->getInputStream()));

        // Load everything into one large string
        _contentStream << vfsStream.rdbuf();
    }

    bool isOpen() const override
    {
        return _archiveFile != nullptr;
    }

    std::istream& getStream() override
    {
        return _contentStream;
    }
};

}

inline MapResourceStream::Ptr MapResourceStream::OpenFromPath(const std::string& path)
{
    if (path_is_absolute(path.c_str()))
    {
        return std::make_shared<detail::FileMapResourceStream>(path);
    }
    else
    {
        // Not an absolute path, might as well be a VFS path, so try to load it from the PAKs
        return std::make_shared<detail::ArchivedMapResourceStream>(path);
    }
}

inline MapResourceStream::Ptr MapResourceStream::OpenFromArchiveFile(const ArchiveTextFilePtr& archive)
{
    return std::make_shared<detail::ArchivedMapResourceStream>(archive);
}

}