Skip to content

Commit

Permalink
Merge pull request #996 from TheJJ/fslike-append
Browse files Browse the repository at this point in the history
fslike: add readwrite and append modes for opening files
  • Loading branch information
mic-e committed Apr 22, 2018
2 parents 61d8c08 + 9810f6f commit c385508
Show file tree
Hide file tree
Showing 14 changed files with 241 additions and 26 deletions.
7 changes: 5 additions & 2 deletions libopenage/util/filelike/filelike.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -56,11 +56,14 @@ class OAAPI FileLike {
*
* Sync the numbers with the fslike/cpp.pyx
* because Cython can't enum class yet.
* TODO: once cython can handle enum class, add pxd annotation.
*/
enum class mode_t : int {
R = 0,
W = 1,
RW = 2
RW = 2,
A = 3,
AR = 4,
};

FileLike();
Expand Down
8 changes: 7 additions & 1 deletion libopenage/util/filelike/native.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#include "native.h"

Expand Down Expand Up @@ -28,6 +28,12 @@ Native::Native(const std::string &path, mode_t mode)
case mode_t::RW:
open_mode = std::ios_base::in | std::ios_base::out;
break;
case mode_t::A:
open_mode = std::ios_base::out | std::ios_base::ate;
break;
case mode_t::AR:
open_mode = std::ios_base::in | std::ios_base::out | std::ios_base::ate;
break;
default:
throw Error{ERR << "unknown open mode"};
}
Expand Down
30 changes: 29 additions & 1 deletion libopenage/util/fslike/directory.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#include "directory.h"

Expand Down Expand Up @@ -52,6 +52,10 @@ Directory::Directory(const std::string &basepath, bool create_if_missing)
}


// We don't need a resolve_r and resolve_w here!
// If the underlying fslike system is a Directory (i.e. this.)
// then we don't have any overlay possibility!
// -> Always resolve just the real system filename.
std::string Directory::resolve(const Path::parts_t &parts) const {
std::string ret = this->basepath;
for (auto &part : parts) {
Expand Down Expand Up @@ -192,6 +196,30 @@ File Directory::open_w(const Path::parts_t &parts) {
}


File Directory::open_rw(const Path::parts_t &parts) {
return File{
std::make_shared<filelike::Native>(this->resolve(parts),
filelike::Native::mode_t::RW)
};
}


File Directory::open_a(const Path::parts_t &parts) {
return File{
std::make_shared<filelike::Native>(this->resolve(parts),
filelike::Native::mode_t::A)
};
}


File Directory::open_ar(const Path::parts_t &parts) {
return File{
std::make_shared<filelike::Native>(this->resolve(parts),
filelike::Native::mode_t::AR)
};
}


std::string Directory::get_native_path(const Path::parts_t &parts) {
return this->resolve(parts);
}
Expand Down
6 changes: 5 additions & 1 deletion libopenage/util/fslike/directory.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -32,6 +32,10 @@ class Directory : public FSLike {
bool mkdirs(const Path::parts_t &parts) override;
File open_r(const Path::parts_t &parts) override;
File open_w(const Path::parts_t &parts) override;
File open_rw(const Path::parts_t &parts) override;
File open_a(const Path::parts_t &parts) override;
File open_ar(const Path::parts_t &parts) override;
// inherit the resolve_r/resolve_w functions
std::string get_native_path(const Path::parts_t &parts) override;
bool rename(const Path::parts_t &parts,
const Path::parts_t &target_parts) override;
Expand Down
11 changes: 10 additions & 1 deletion libopenage/util/fslike/fslike.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -47,6 +47,9 @@ namespace fslike {
*
* File open_r(const parts_t &parts) except +
* File open_w(const parts_t &parts) except +
* File open_rw(const parts_t &parts) except +
* File open_a(const parts_t &parts) except +
* File open_ar(const parts_t &parts) except +
* pair[bool, Path] resolve_r(const parts_t &parts) except +
* pair[bool, Path] resolve_w(const parts_t &parts) except +
* string get_native_path(const parts_t &parts) except +
Expand Down Expand Up @@ -78,6 +81,12 @@ class OAAPI FSLike : public std::enable_shared_from_this<FSLike> {
virtual bool mkdirs(const Path::parts_t &parts) = 0;
virtual File open_r(const Path::parts_t &parts) = 0;
virtual File open_w(const Path::parts_t &parts) = 0;
virtual File open_rw(const Path::parts_t &parts) = 0;
virtual File open_a(const Path::parts_t &parts) = 0;
virtual File open_ar(const Path::parts_t &parts) = 0;

// provide a default implementation that resolves the path
// by checking if it is readable/writable:
virtual std::pair<bool, Path> resolve_r(const Path::parts_t &parts);
virtual std::pair<bool, Path> resolve_w(const Path::parts_t &parts);
virtual std::string get_native_path(const Path::parts_t &parts) = 0;
Expand Down
17 changes: 16 additions & 1 deletion libopenage/util/fslike/python.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#include "python.h"

Expand Down Expand Up @@ -42,6 +42,18 @@ File Python::open_w(const Path::parts_t &parts) {
return pyx_fs_open_w.call(this->fsobj->get_ref(), parts);
}

File Python::open_rw(const Path::parts_t &parts) {
return pyx_fs_open_rw.call(this->fsobj->get_ref(), parts);
}

File Python::open_a(const Path::parts_t &parts) {
return pyx_fs_open_a.call(this->fsobj->get_ref(), parts);
}

File Python::open_ar(const Path::parts_t &parts) {
return pyx_fs_open_ar.call(this->fsobj->get_ref(), parts);
}

std::pair<bool, Path> Python::resolve_r(const Path::parts_t &parts) {
auto path = pyx_fs_resolve_r.call(this->fsobj->get_ref(), parts);
return std::make_pair(path.get_fsobj() != nullptr, path);
Expand Down Expand Up @@ -113,6 +125,9 @@ pyinterface::PyIfFunc<std::vector<std::string>, PyObject *, const std::vector<st
pyinterface::PyIfFunc<bool, PyObject *, const std::vector<std::string>&> pyx_fs_mkdirs;
pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_r;
pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_w;
pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_rw;
pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_a;
pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_ar;
pyinterface::PyIfFunc<Path, PyObject *, const std::vector<std::string>&> pyx_fs_resolve_r;
pyinterface::PyIfFunc<Path, PyObject *, const std::vector<std::string>&> pyx_fs_resolve_w;

Expand Down
15 changes: 14 additions & 1 deletion libopenage/util/fslike/python.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2017 the openage authors. See copying.md for legal info.
// Copyright 2017-2018 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -49,6 +49,10 @@ class Python : public FSLike {
bool mkdirs(const Path::parts_t &parts) override;
File open_r(const Path::parts_t &parts) override;
File open_w(const Path::parts_t &parts) override;
File open_rw(const Path::parts_t &parts) override;
File open_a(const Path::parts_t &parts) override;
File open_ar(const Path::parts_t &parts) override;
// specialize the resolve functions to relay them to python.
std::pair<bool, Path> resolve_r(const Path::parts_t &parts) override;
std::pair<bool, Path> resolve_w(const Path::parts_t &parts) override;
std::string get_native_path(const Path::parts_t &parts) override;
Expand Down Expand Up @@ -92,6 +96,15 @@ extern OAAPI pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::stri
// pxd: PyIfFunc2[File, PyObjectPtr, const vector[string]] pyx_fs_open_w
extern OAAPI pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_w;

// pxd: PyIfFunc2[File, PyObjectPtr, const vector[string]] pyx_fs_open_rw
extern OAAPI pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_rw;

// pxd: PyIfFunc2[File, PyObjectPtr, const vector[string]] pyx_fs_open_a
extern OAAPI pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_a;

// pxd: PyIfFunc2[File, PyObjectPtr, const vector[string]] pyx_fs_open_ar
extern OAAPI pyinterface::PyIfFunc<File, PyObject *, const std::vector<std::string>&> pyx_fs_open_ar;

// pxd: PyIfFunc2[Path, PyObjectPtr, const vector[string]] pyx_fs_resolve_r
extern OAAPI pyinterface::PyIfFunc<Path, PyObject *, const std::vector<std::string>&> pyx_fs_resolve_r;

Expand Down
26 changes: 25 additions & 1 deletion libopenage/util/path.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2017 the openage authors. See copying.md for legal info.
// Copyright 2015-2018 the openage authors. See copying.md for legal info.

#include "path.h"

Expand Down Expand Up @@ -115,6 +115,15 @@ File Path::open(const std::string &mode) const {
else if (mode == "w") {
return this->open_w();
}
else if (mode == "rw" or mode == "r+") {
return this->open_w();
}
else if (mode == "a") {
return this->open_a();
}
else if (mode == "a+" or mode == "ar") {
return this->open_ar();
}
else {
throw Error{ERR << "unsupported open mode: " << mode};
}
Expand All @@ -131,6 +140,21 @@ File Path::open_w() const {
}


File Path::open_rw() const {
return this->fsobj->open_rw(this->parts);
}


File Path::open_a() const {
return this->fsobj->open_a(this->parts);
}


File Path::open_ar() const {
return this->fsobj->open_ar(this->parts);
}


std::string Path::get_native_path() const {
return this->fsobj->get_native_path(this->parts);
}
Expand Down
5 changes: 4 additions & 1 deletion libopenage/util/path.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2017 the openage authors. See copying.md for legal info.
// Copyright 2015-2018 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -94,6 +94,9 @@ class OAAPI Path {
File open(const std::string &mode="r") const;
File open_r() const;
File open_w() const;
File open_rw() const;
File open_a() const;
File open_ar() const;

/**
* Resolve the native path by flattening all underlying
Expand Down
14 changes: 13 additions & 1 deletion openage/util/fslike/abstract.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2017 the openage authors. See copying.md for legal info.
# Copyright 2015-2018 the openage authors. See copying.md for legal info.

"""
Provides filesystem-like interfaces:
Expand Down Expand Up @@ -64,6 +64,18 @@ def open_w(self, parts):
""" Shall return a BufferedWriter for the given file ("mode 'wb'"). """
pass

def open_rw(self, parts):
""" Shall return a BufferedWriter for the given file ("mode 'r+'"). """
pass

def open_a(self, parts):
""" Shall return a BufferedWriter for the given file ("mode 'a'"). """
pass

def open_ar(self, parts):
""" Shall return a BufferedWriter for the given file ("mode 'a+'"). """
pass

def exists(self, parts):
""" Test if the parts are a file or a directory """
return self.is_file(parts) or self.is_dir(parts)
Expand Down
38 changes: 36 additions & 2 deletions openage/util/fslike/cpp.pyx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2017-2017 the openage authors. See copying.md for legal info.
# Copyright 2017-2018 the openage authors. See copying.md for legal info.

"""
Functions called from C++ to perform method calls on
Expand Down Expand Up @@ -27,6 +27,9 @@ from libopenage.util.fslike.python cimport (
pyx_fs_mkdirs,
pyx_fs_open_r,
pyx_fs_open_w,
pyx_fs_open_rw,
pyx_fs_open_a,
pyx_fs_open_ar,
pyx_fs_resolve_r,
pyx_fs_resolve_w,
pyx_fs_get_native_path,
Expand Down Expand Up @@ -253,7 +256,20 @@ cdef File_cpp fs_open(object path, int mode) except *:
return File_cpp(native_path, mode)

else:
access_mode = "rb" if mode == 0 else "wb"
# sync with filelike/filelike.h enum class mode_t
# (and the calls to fs_open_* below)
if mode == 0:
access_mode = 'rb'
elif mode == 1:
access_mode = 'wb'
elif mode == 2:
access_mode = 'r+b'
elif mode == 3:
access_mode = 'ab'
elif mode == 4:
access_mode = 'a+b'
else:
raise ValueError("unknown file open mode id: %s" % mode)

# open it the python-way and wrap it
filelike = path.open(access_mode)
Expand All @@ -271,6 +287,21 @@ cdef File_cpp fs_open_w(PyObject *fslike, const vector[string]& parts) except *
return fs_open(open_path, 1)


cdef File_cpp fs_open_rw(PyObject *fslike, const vector[string]& parts) except * with gil:
open_path = (<object> fslike).resolve_w(parts)
return fs_open(open_path, 2)


cdef File_cpp fs_open_a(PyObject *fslike, const vector[string]& parts) except * with gil:
open_path = (<object> fslike).resolve_w(parts)
return fs_open(open_path, 3)


cdef File_cpp fs_open_ar(PyObject *fslike, const vector[string]& parts) except * with gil:
open_path = (<object> fslike).resolve_w(parts)
return fs_open(open_path, 4)


cdef Path_cpp fs_resolve_r(PyObject *fslike, const vector[string]& parts) except * with gil:
path = (<object> fslike).resolve_r(parts)
if path is not None:
Expand Down Expand Up @@ -333,6 +364,9 @@ def setup():
pyx_fs_mkdirs.bind0(fs_mkdirs)
pyx_fs_open_r.bind0(fs_open_r)
pyx_fs_open_w.bind0(fs_open_w)
pyx_fs_open_rw.bind0(fs_open_rw)
pyx_fs_open_a.bind0(fs_open_a)
pyx_fs_open_ar.bind0(fs_open_ar)
pyx_fs_resolve_r.bind0(fs_resolve_r)
pyx_fs_resolve_w.bind0(fs_resolve_w)
pyx_fs_get_native_path.bind0(fs_get_native_path)
Expand Down
11 changes: 10 additions & 1 deletion openage/util/fslike/directory.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2015-2017 the openage authors. See copying.md for legal info.
# Copyright 2015-2018 the openage authors. See copying.md for legal info.

"""
FSLikeObjects that represent actual file system paths:
Expand Down Expand Up @@ -51,6 +51,15 @@ def open_r(self, parts):
def open_w(self, parts):
return open(self.resolve(parts), 'wb')

def open_rw(self, parts):
return open(self.resolve(parts), 'r+b')

def open_a(self, parts):
return open(self.resolve(parts), 'ab')

def open_ar(self, parts):
return open(self.resolve(parts), 'a+b')

def get_native_path(self, parts):
return self.resolve(parts)

Expand Down
Loading

0 comments on commit c385508

Please sign in to comment.