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
|
#include "stdafx.h"
#include "OverlayProtocol.h"
#include "Url.h"
#include "Core/Set.h"
#include "MemStream.h"
#include "Utf8Text.h"
#include "Serialization.h"
namespace storm {
OverlayProtocol::OverlayProtocol(Url *dir) : dir(dir) {
files = new (this) Map<Str *, Buffer>();
}
Bool OverlayProtocol::partEq(Str *a, Str *b) {
return dir->protocol()->partEq(a, b);
}
Nat OverlayProtocol::partHash(Str *a) {
return dir->protocol()->partHash(a);
}
Bool OverlayProtocol::isEqualTo(const Protocol *other) const {
if (const OverlayProtocol *overlay = as<const OverlayProtocol>(other))
other = overlay->dir->protocol();
return *dir->protocol() == *other;
}
MAYBE(Str *) OverlayProtocol::isBelow(Url *url) const {
if (url->isBelow(dir) && url->count() == dir->count() + 1)
return url->name();
else
return null;
}
Array<Url *> *OverlayProtocol::children(Url *url) {
Array<Url *> *result = dir->protocol()->children(url);
// Update the protocol of all elements:
for (Nat i = 0; i < result->count(); i++) {
if (result->at(i)->protocol() != this)
result->at(i) = result->at(i)->withProtocol(this);
}
// Is it our directory? If so, merge files!
if (url->isBelow(dir) && url->count() == dir->count()) {
// See which ones exist:
Set<Str *> *existing = new (this) Set<Str *>();
for (Nat i = 0; i < result->count(); i++)
existing->put(result->at(i)->name());
// And add remaining ones:
for (FileMap::Iter i = files->begin(); i != files->end(); ++i) {
if (!existing->has(i.k()))
result->push(url->push(i.k()));
}
}
return result;
}
IStream *OverlayProtocol::read(Url *url) {
if (Str *here = isBelow(url)) {
if (files->has(here)) {
return new (this) MemIStream(files->get(here));
}
}
return dir->protocol()->read(url);
}
OStream *OverlayProtocol::write(Url *url) {
// We could support it, but then we need a more custom OStream implementation.
throw new (this) ProtocolNotSupported(S("write"), toS());
}
StatType OverlayProtocol::stat(Url *url) {
if (Str *here = isBelow(url)) {
if (files->has(here)) {
return sFile;
}
}
return dir->protocol()->stat(url);
}
void OverlayProtocol::toS(StrBuf *to) const {
// *to << S("<overlay>:");
dir->protocol()->toS(to);
}
Url *OverlayProtocol::put(Str *name, Buffer content) {
files->put(name, content);
Array<Str *> *parts = dir->getParts();
parts->push(name);
return new (this) Url(this, parts);
}
Url *OverlayProtocol::put(Str *name, Str *content) {
MemOStream *out = new (this) MemOStream();
Utf8Output *utf = new (this) Utf8Output(out);
utf->write(content);
utf->flush();
return put(name, out->buffer());
}
SerializedType *OverlayProtocol::serializedType(EnginePtr e) {
SerializedStdType *type = serializedStdType<OverlayProtocol, Protocol>(e.v);
type->add(S("dir"), StormInfo<Url>::type(e.v));
return type;
}
OverlayProtocol *OverlayProtocol::read(ObjIStream *from) {
return (OverlayProtocol *)from->readClass(StormInfo<OverlayProtocol>::type(from->engine()));
}
void OverlayProtocol::write(ObjOStream *to) {
if (to->startClass(StormInfo<OverlayProtocol>::type(engine()), this)) {
Protocol::write(to);
dir->write(to);
to->end();
}
}
OverlayProtocol::OverlayProtocol(ObjIStream *from) {
dir = new (this) Url(from);
// Note: Serialization does not save files in the memory protocol, just like paths are not
// transferred between different systems.
files = new (this) Map<Str *, Buffer>();
from->end();
}
}
|