aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/archive/directory_models_archive_reader.cpp
blob: 6c85cecf67560332f8d8042fc6d75fca8950797f (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
#include "directory_models_archive_reader.h" 
#include "yarchive.h"
 
#include <util/folder/dirut.h> 
#include <util/folder/filelist.h> 
#include <util/folder/path.h> 
#include <util/memory/blob.h> 
#include <util/stream/file.h> 
#include <util/stream/input.h> 
#include <util/stream/mem.h> 
 
TDirectoryModelsArchiveReader::TDirectoryModelsArchiveReader(const TString& path, bool lockMemory, bool ownBlobs)
    : Path_(path) 
{ 
    Y_ENSURE(IsDir(path), "directory not found on this path"); 
 
    LoadFilesAndSubdirs("", lockMemory, ownBlobs);
} 
 
TDirectoryModelsArchiveReader::~TDirectoryModelsArchiveReader() {} 
 
size_t TDirectoryModelsArchiveReader::Count() const noexcept { 
    return Recs_.size(); 
} 
 
TString TDirectoryModelsArchiveReader::KeyByIndex(size_t n) const { 
   Y_ENSURE(n < Count(), "incorrect index " << n); 
   return Recs_[n]; 
} 
 
bool TDirectoryModelsArchiveReader::Has(const TStringBuf key) const { 
    return BlobByKey_.contains(key) || PathByKey_.contains(key);
} 
 
namespace {
    struct TBlobOwningStream : public TMemoryInput {
        TBlob Blob;
        TBlobOwningStream(TBlob blob)
        : TMemoryInput(blob.Data(), blob.Length())
        , Blob(blob)
        {}
    };
}

TAutoPtr<IInputStream> TDirectoryModelsArchiveReader::ObjectByKey(const TStringBuf key) const { 
    return new TBlobOwningStream(BlobByKey(key));
} 
 
TBlob TDirectoryModelsArchiveReader::ObjectBlobByKey(const TStringBuf key) const { 
    return BlobByKey(key); 
} 
 
TBlob TDirectoryModelsArchiveReader::BlobByKey(const TStringBuf key) const { 
    Y_ENSURE(Has(key), "key " << key << " not found");
    if (auto ptr = BlobByKey_.FindPtr(key); ptr) {
        return *ptr;
    }
    if (auto ptr = PathByKey_.FindPtr(key); ptr) {
        return TBlob::FromFile(*ptr);
    }
    Y_UNREACHABLE();
} 
 
bool TDirectoryModelsArchiveReader::Compressed() const { 
    return false; 
} 
 
TString TDirectoryModelsArchiveReader::NormalizePath(TString path) const { 
    path = "/" + path; 
    for (size_t i = 0; i < path.size(); i++) { 
        if (path[i] == '\\') 
            path[i] = '/'; 
    } 
    return path; 
} 
 
void TDirectoryModelsArchiveReader::LoadFilesAndSubdirs(const TString& subPath, bool lockMemory, bool ownBlobs) {
    TFileList fileList; 
    fileList.Fill(JoinFsPaths(Path_, subPath)); 
    const char* file; 
    while ((file = fileList.Next()) != nullptr) { 
        TString key = JoinFsPaths(subPath, TString(file)); 
        TString fullPath = JoinFsPaths(Path_, key);
        TBlob fileBlob;
        if (lockMemory) { 
            fileBlob = TBlob::LockedFromFile(fullPath);
        } else { 
            fileBlob = TBlob::FromFile(fullPath);
        } 
        if (key.EndsWith(".archive")) {
            TArchiveReader reader(fileBlob);
            for (size_t i = 0, iEnd = reader.Count(); i < iEnd; ++i) {
                const TString archiveKey = reader.KeyByIndex(i);
                const TString normalizedPath = NormalizePath(JoinFsPaths(subPath, archiveKey.substr(1)));
                BlobByKey_.emplace(normalizedPath, reader.ObjectBlobByKey(archiveKey));
                Recs_.push_back(normalizedPath);
            }
        } else {
            const TString normalizedPath = NormalizePath(key);
            if (lockMemory || ownBlobs) {
                BlobByKey_.emplace(normalizedPath, fileBlob);
            } else {
                PathByKey_.emplace(normalizedPath, RealPath(fullPath));
            }
            Recs_.push_back(normalizedPath);
        }
    } 
 
    TDirsList dirsList; 
    dirsList.Fill(JoinFsPaths(Path_, subPath)); 
    const char* dir; 
    while ((dir = dirsList.Next()) != nullptr) { 
        LoadFilesAndSubdirs(JoinFsPaths(subPath, TString(dir)), lockMemory, ownBlobs);
    } 
}