diff options
Diffstat (limited to 'libs/IO/src')
-rw-r--r-- | libs/IO/src/ConfigReader.cc | 64 | ||||
-rw-r--r-- | libs/IO/src/File.cc | 185 | ||||
-rw-r--r-- | libs/IO/src/FileReader.cc | 63 | ||||
-rw-r--r-- | libs/IO/src/FileRepresentation.cc | 132 | ||||
-rw-r--r-- | libs/IO/src/FileSystem.cc | 141 | ||||
-rw-r--r-- | libs/IO/src/LineReader.cc | 100 |
6 files changed, 685 insertions, 0 deletions
diff --git a/libs/IO/src/ConfigReader.cc b/libs/IO/src/ConfigReader.cc new file mode 100644 index 0000000..152c908 --- /dev/null +++ b/libs/IO/src/ConfigReader.cc @@ -0,0 +1,64 @@ +/** + * ======================== legal notice ====================== + * + * File: ConfigReader.cc + * Created: 28. Juli 2012, 18:41 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libIO: classes for files, filesystem and input/output + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <ConfigReader.h> +#include <LineReader.h> +#include <stddef.h> +#include <pcrecpp.h> + +cConfigReader::cConfigReader(cLineReader *LineReader) + : reader(LineReader) +{ +} + +cConfigReader::~cConfigReader() +{ + Close(); +} + +void cConfigReader::Close(void) +{ + if (reader) { + delete reader; + reader = NULL; + } +} + +cConfigReader::ConfigEntry *cConfigReader::ReadValue() +{ + if (!reader) return NULL; + const char *line = reader->ReadLine(); + static pcrecpp::RE comment("^\\s*#.*$"); + static pcrecpp::RE emptyLine("^\\s*$"); + static pcrecpp::RE entry("^\\s*(\\S+)\\s*=\\s*(.+)$"); + std::string name, value; + ConfigEntry *rv = NULL; + + while (line && (comment.FullMatch(line) || emptyLine.FullMatch(line))) + line = reader->ReadLine(); + if (line && entry.FullMatch(line, &name, &value)) { + rv = new ConfigEntry(name, value); + } + return rv; +} diff --git a/libs/IO/src/File.cc b/libs/IO/src/File.cc new file mode 100644 index 0000000..6770ec8 --- /dev/null +++ b/libs/IO/src/File.cc @@ -0,0 +1,185 @@ +/** + * ======================== legal notice ====================== + * + * File: File.cc + * Created: 21. Juli 2012, 12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libIO: classes for files, filesystem and input/output + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <File.h> +#include <FileSystem.h> +#include <FileRepresentation.h> +#include <StringBuilder.h> +#include <sys/stat.h> +#include <sys/dir.h> + +cFileSystem *cFile::fs = NULL; +static mode_t ReadMask = S_IRUSR | S_IRGRP | S_IROTH; +static mode_t WriteMask = S_IWUSR | S_IWGRP | S_IWOTH; +static mode_t ExecMask = S_IXUSR | S_IXGRP | S_IXOTH; + + +cFile::cFile(const char *Path) + : rep(NULL) +{ + if (!fs) fs = new cFileSystem(); + if (!Path || *Path != cFileSystem::PathSeparator) { + char *wd = getcwd(NULL, 0); + rep = fs->representationOfFile(wd); + free(wd); + if (Path) rep = fs->representationOfFile(rep, Path); + } + else rep = fs->representationOfFile(Path); +} + +cFile::cFile(const cFile &other) + : rep(other.rep) +{ + if (!fs) fs = new cFileSystem(); +} + +cFile::cFile(const cFile& Parent, const char* RelativePath) + : rep(NULL) +{ + if (!fs) fs = new cFileSystem(); + rep = fs->representationOfFile(Parent, RelativePath); +} + +cFile::cFile(const cFileRepresentation *fr) + : rep(fr) +{ + if (!fs) fs = new cFileSystem(); +} + +cFile::~cFile() +{ +} + +cFile &cFile::operator =(const cFile &other) +{ + rep = other.rep; + return *this; +} + +const char *cFile::AbsolutePath(void) const +{ + if (rep) return rep->Path(); + return NULL; +} + +bool cFile::Exists(void) const +{ + if (rep) return rep->exists; + return false; +} + +bool cFile::IsDirectory(void) const +{ + if (rep) return (rep->mode & S_IFMT) == S_IFDIR; + return false; +} + +bool cFile::IsFile(void) const +{ + if (rep) return (rep->mode & S_IFMT) == S_IFREG; + return false; +} + +bool cFile::IsSymbolic(void) const +{ + if (rep) return (rep->mode & S_IFMT) == S_IFLNK; + return false; +} + +bool cFile::CanRead(void) const +{ + if (rep) return rep->mode & ReadMask; + return false; +} + +bool cFile::CanWrite(void) const +{ + if (rep) return rep->mode & WriteMask; + return false; +} + +bool cFile::CanExecute(void) const +{ + if (rep) return rep->mode & ExecMask; + return false; +} + +off64_t cFile::Size(void) const +{ + if (rep) return rep->size; + return 0; +} + +ulong cFile::LastModified(void) const +{ + if (rep) return rep->lastModified; + return 0; +} + +cFile *cFile::Parent(void) const +{ + if (rep) return new cFile(rep->getParent()); + return NULL; +} + +const char *cFile::Name(void) const +{ + if (rep) return rep->name; + return NULL; +} + +void cFile::Cleanup(void) +{ + if (fs) { + delete fs; + fs = NULL; + } +} + +void cFile::VisitFiles(int (*cb)(void *, cFile *, const char *), void *opaque) +{ + if (!Exists() || !IsDirectory()) return; + const char *path = AbsolutePath(); + + if (!path) return; + struct dirent entryBuffer, *pE = NULL; + DIR *dir = opendir(path); + + while (!readdir_r(dir, &entryBuffer, &pE) && pE) { + if (*(pE->d_name) == '.') continue; // don't bother with hidden stuff + cb(opaque, this, pE->d_name); + } + closedir(dir); +} + +char *cFile::toURI() const +{ + if (rep) return rep->toURI(); + return NULL; +} + +void cFile::SetVirtualRoot(bool isRoot) +{ + if (rep) ((cFileRepresentation *)rep)->SetVirtualRoot(isRoot); +} diff --git a/libs/IO/src/FileReader.cc b/libs/IO/src/FileReader.cc new file mode 100644 index 0000000..519c749 --- /dev/null +++ b/libs/IO/src/FileReader.cc @@ -0,0 +1,63 @@ +/** + * ======================== legal notice ====================== + * + * File: FileReader.cc + * Created: 28. Juli 2012, 15:00 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libIO: classes for files, filesystem and input/output + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <FileReader.h> +#include <File.h> +#include <Logging.h> +#include <fcntl.h> +#include <unistd.h> + +cFileReader::cFileReader(cFile *Input) + : fd(-1) + , file(Input) +{ + if (file && file->Exists() && file->CanRead()) { + fd = open(file->AbsolutePath(), O_RDONLY); + if (fd < 0) esyslog("ERROR: could not open %s", file->AbsolutePath()); + } +} + +cFileReader::~cFileReader() +{ + Close(); +} + +void cFileReader::Close() +{ + if (fd >= 0) { + close(fd); + fd = -1; + } + if (file) { + delete file; + file = NULL; + } +} + +int cFileReader::Read(char* buf, int bufSize) +{ + if (fd >= 0) return read(fd, buf, bufSize); + esyslog("ERROR: not an open file! %s", file->AbsolutePath()); + return 0; +} diff --git a/libs/IO/src/FileRepresentation.cc b/libs/IO/src/FileRepresentation.cc new file mode 100644 index 0000000..f74d2c8 --- /dev/null +++ b/libs/IO/src/FileRepresentation.cc @@ -0,0 +1,132 @@ +/** + * ======================== legal notice ====================== + * + * File: FileRepresentation.cc + * Created: 21. Juli 2012, 12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libIO: classes for files, filesystem and input/output + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <FileRepresentation.h> +#include <FileSystem.h> +#include <StringBuilder.h> +#include <Url.h> +#include <Codec.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <stdlib.h> +#include <iostream> +#include <stack> + +cFileRepresentation::cFileRepresentation(const char *Name) + : exists(false) + , isRoot(true) + , isVirtualRoot(true) + , mode(0) + , size(0) + , lastModified(0) + , name(NULL) + , path(NULL) + , parent(NULL) +{ + struct stat st; + + if (!stat(Name, &st)) { + name = strdup(Name); + exists = true; + mode = st.st_mode; + size = st.st_size; + lastModified = st.st_mtime; + } +} + +cFileRepresentation::cFileRepresentation(const cFileRepresentation *Parent, const char *Name) + : exists(false) + , isRoot(false) + , isVirtualRoot(false) + , mode(0) + , size(0) + , lastModified(0) + , name(strdup(Name)) + , path(NULL) + , parent(Parent) +{ + struct stat st; + + if (!stat(Path(), &st)) { + exists = true; + mode = st.st_mode; + size = st.st_size; + lastModified = st.st_mtime; + } +} + +cFileRepresentation::~cFileRepresentation() +{ + free(name); + free(path); +} + +const char *cFileRepresentation::Path() const +{ + if (!path) { + cStringBuilder sb; + + if (parent) sb.Append(parent->Path()); + if (strcmp(cFileSystem::RootPath, name)) sb.Append(cFileSystem::PathSeparator).Append(name); + path = sb.toString(); + } + return path; +} + +void cFileRepresentation::SetVirtualRoot(bool isRoot) +{ + isVirtualRoot = isRoot; +} + +char *cFileRepresentation::toURI() const +{ + cStringBuilder *sb = new cStringBuilder(); + const cFileRepresentation *f = this; + std::stack<const cFileRepresentation *> rev; + cURLEncoder *enc = cUrl::Encoder(); + char *tmp, *chk, *rv; + size_t stackSize; + + while (!f->isVirtualRoot) { + rev.push(f); + stackSize = rev.size(); + f = f->parent; + } + + for (;;) { + f = rev.top(); + rev.pop(); + chk = f->name + strlen(f->name) - 1; + if (*chk != cFileSystem::PathSeparator) sb->Append(cFileSystem::PathSeparator); + tmp = enc->Encode(f->name); + sb->Append(tmp); + free(tmp); + if (rev.empty()) break; + } + rv = sb->toString(); + delete sb; + + return rv; +} diff --git a/libs/IO/src/FileSystem.cc b/libs/IO/src/FileSystem.cc new file mode 100644 index 0000000..049ca07 --- /dev/null +++ b/libs/IO/src/FileSystem.cc @@ -0,0 +1,141 @@ +/** + * ======================== legal notice ====================== + * + * File: FileSystem.cc + * Created: 21. Juli 2012, 12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libIO: classes for files, filesystem and input/output + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <FileSystem.h> +#include <FileRepresentation.h> +#include <File.h> +#include <StringBuilder.h> +#include <iostream> +#include <stdlib.h> +#include <string.h> + +char cFileSystem::PathSeparator = '/'; +char cFileSystem::RootPath[4] = { PathSeparator, 0, 0, 0 }; + +cFileSystem::cFileSystem() +{ +} + +cFileSystem::~cFileSystem() +{ + std::tr1::unordered_map<std::string, cFileRepresentation *>::iterator it = fileCache.begin(); + + while (it != fileCache.end()) { + if (it->second) delete it->second; + ++it; + } +} + +cFileRepresentation *cFileSystem::cacheEntry(const char* Path) +{ + if (fileCache.empty()) return NULL; + std::tr1::unordered_map<std::string, cFileRepresentation *>::iterator it = fileCache.find(Path); + + if (it != fileCache.end()) return it->second; + return NULL; +} + +cFileRepresentation *cFileSystem::representationOfFile(const cFile &Parent, const char* Path) +{ + cFileRepresentation *parentRep = (cFileRepresentation *) Parent.rep; + + return representationOfFile(parentRep, Path); +} + +cFileRepresentation *cFileSystem::representationOfFile(const cFileRepresentation *parentRep, const char* Path) +{ + cFileRepresentation *tmp = NULL; + cStringBuilder *sb = new cStringBuilder(parentRep->Path()); + char *scratch = strdup(Path); + char *last = scratch + strlen(Path); + char *start = *scratch == PathSeparator ? scratch + 1 : scratch; + char *end = strchr(scratch, PathSeparator); + char *path; + + while (start < last) { + end = strchr(start, PathSeparator); + if (!end) end = start + strlen(start); + *end = 0; + sb->Append(PathSeparator).Append(start); + path = sb->toString(); + tmp = cacheEntry(path); + if (!tmp) { + tmp = new cFileRepresentation(parentRep, start); + fileCache[path] = tmp; + } + parentRep = tmp; + free(path); + start = end + 1; + } + free(scratch); + delete sb; + + if (tmp) return tmp; + return NULL; +} + +cFileRepresentation *cFileSystem::representationOfFile(const char* Path) +{ + cFileRepresentation *rv = cacheEntry(Path); + + if (!rv) { + cFileRepresentation *tmp = NULL; + char *scratch = strdup(Path); + char *p, *last = scratch + strlen(Path); + + for (p = strrchr(scratch, PathSeparator); !rv && p && p < last; p = strrchr(scratch, PathSeparator)) { + if (p > scratch) *p = 0; + else { + *p = 0; + if (!(rv = cacheEntry(RootPath))) { + tmp = new cFileRepresentation(RootPath); + fileCache[RootPath] = tmp; + break; + } + } + if ((tmp = cacheEntry(scratch))) break; + } + if (rv && strcmp(rv->Path(), Path)) { + tmp = rv; + rv = NULL; + } + if (tmp) { + cFileRepresentation *parent = tmp; + size_t poolSize = fileCache.size(); + const char *last = scratch + strlen(Path); + + for (p = scratch + strlen(scratch) + 1; p < last; p += strlen(p) + 1) { + if (!*(p - 1)) *(p - 1) = PathSeparator; + tmp = new cFileRepresentation(parent, p); + fileCache[scratch] = tmp; + poolSize = fileCache.size(); + parent = tmp; + } + rv = parent; + } + free(scratch); + } + return rv; +} + diff --git a/libs/IO/src/LineReader.cc b/libs/IO/src/LineReader.cc new file mode 100644 index 0000000..bf4bcc2 --- /dev/null +++ b/libs/IO/src/LineReader.cc @@ -0,0 +1,100 @@ +/** + * ======================== legal notice ====================== + * + * File: LineReader.cc + * Created: 28. Juli 2012, 06 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libIO: classes for files, filesystem and input/output + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <LineReader.h> +#include <FileReader.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <iostream> + +cLineReader::cLineReader(cFileReader *FileReader) + : reader(FileReader) + , bytesRead(0) + , off(0) + , bufSize(1024) + , buf(NULL) + , lastLine(NULL) +{ + buf = (char *) malloc(bufSize + 1); + if (buf) { + buf[bufSize] = 0; + *buf = 0; + } +} + +cLineReader::~cLineReader() +{ + Close(); +} + +void cLineReader::Close() +{ + if (reader) { + delete reader; + reader = NULL; + } + free(buf); + buf = NULL; + off = NULL; +} + +const char *cLineReader::ReadLine(void) +{ + const char *rv = NULL; + char *p; + + if (lastLine) lastLine += strlen(lastLine) + 1; + else lastLine = buf; + if (bytesRead && lastLine - buf >= bytesRead) return NULL; + p = strchr(lastLine, '\n'); + + if (!p && strlen(lastLine)) { + memmove(buf, lastLine, strlen(lastLine)); + buf[strlen(lastLine)] = 0; + lastLine = buf; + } + + if (!p && (!bytesRead || bytesRead == bufSize)) { + bytesRead = strlen(buf); + int br = reader->Read(buf + bytesRead, bufSize - bytesRead); + + if (br > 0) bytesRead += br; + if (bytesRead < bufSize) memset(buf + bytesRead, 0, bufSize - bytesRead); + } + + if (!p) p = strchr(lastLine, '\n'); + + if (p) { + if (p - buf <= bytesRead) { + *p = 0; + rv = lastLine; + } + } + else { + if (strlen(lastLine)) rv = lastLine; + } + return rv; +} |