Design Pattern Examples
Overview of object-oriented design patterns
Composite_FileAccess.cpp
Go to the documentation of this file.
1
5
6#include <filesystem>
7#include <system_error>
8
9#include "helpers/DateTime.h"
10#include "helpers/formatstring.h"
11#include "helpers/replace.h"
12#include "helpers/split.h"
13
15
17
19{
20
21 // The hardcoded hierarchy representing a file/directory structure.
22 // Note: This is the Composite pattern in action.
23 std::shared_ptr<FileDirEntry> Composite_FileAccess::rootEntry =
24 std::make_shared<DirEntry>("root", DateTime::Now(), FileDirEntryList{
25 std::make_shared<FileEntry>("FileA.txt", 101, DateTime::Now()),
26 std::make_shared<FileEntry>("FileB.txt", 102, DateTime::Now()),
27 std::make_shared<FileEntry>("FileC.txt", 103, DateTime::Now()),
28 std::make_shared<DirEntry>("subdir1", DateTime::Now(), FileDirEntryList{
29 std::make_shared<FileEntry>("FileD.txt", 104, DateTime::Now()),
30 std::make_shared<FileEntry>("FileE.txt", 105, DateTime::Now()),
31 std::make_shared<DirEntry>("subdir2", DateTime::Now(), FileDirEntryList{
32 std::make_shared<FileEntry>("FileF.txt", 106, DateTime::Now()),
33 std::make_shared<FileEntry>("FileG.txt", 107, DateTime::Now())
34 }),
35 }),
36 });
37
38
40 {
41 FileDirEntry* root = rootEntry.get();
42
43 std::vector<std::string> pathComponents = Helpers::split(filepath, "/");
44 size_t numComponents = pathComponents.size();
45 for (size_t index = 0; index < numComponents; ++index)
46 {
47 if (root->Name() != pathComponents[index])
48 {
49 // Mismatch in path to this entry, bad path
50 root = nullptr;
51 break;
52 }
53 if (index + 1 >= numComponents)
54 {
55 // Reached end of path so we found what was asked for.
56 break;
57 }
58
59 // Still haven't reached end of specified path, look at
60 // the current root for children.
61
62 FileDirEntryList children = root->Children();
63 if (children.empty())
64 {
65 // Path included leaf in the middle, bad path
66 break;
67 }
68
69 root = nullptr; // assume we won't find anything
70 // Look ahead in the path for a matching child.
71 std::string childComponent = pathComponents[index + 1];
72 for (FileDirEntryList::iterator childIter = std::begin(children);
73 childIter != std::end(children);
74 childIter++)
75 {
76 if (childComponent == (*childIter)->Name())
77 {
78 root = (*childIter).get();
79 break;
80 }
81 }
82 if (root == nullptr)
83 {
84 // Couldn't find matching child, bad path
85 break;
86 }
87 }
88
89 return root;
90 }
91
92
94 {
95 filepath = Helpers::Replace(filepath, '\\', '/');
96 FileDirEntry* fileDirEntry = _FindEntry(filepath);
97
98 if (fileDirEntry == nullptr)
99 {
100 std::string msg = Helpers::formatstring("Unable to find '%s'", filepath.c_str());
101 std::error_code errorcode(2, std::generic_category());
102 throw std::filesystem::filesystem_error(msg, errorcode);
103 }
104
105 return fileDirEntry;
106 }
107
108} // end namespace
static FileDirEntry * _FindEntry(std::string filepath)
Helper method to search the static data list for the specified file/dir entry.
static std::shared_ptr< FileDirEntry > rootEntry
List of all "files" and "directories" used in the Command Pattern example.
static FileDirEntry * GetEntry(std::string filepath)
Return a FileDirEntry object representing the specified file "path" in an internal list of data entri...
Base class representing a File or Directory entry.
virtual std::string Name()
The name of this entry.
virtual FileDirEntryList Children()
The children of this entry. Is empty if the entry can never have any children (that is,...
Represents a timestamp composed of a date and a time encoded in a time_t value. Provides ways of gett...
Declaration of the Composite_FileAccess class used in the Composite Pattern.
The namespace containing all Design Pattern Examples implemented in C++.
std::vector< std::shared_ptr< FileDirEntry > > FileDirEntryList
Makes it easier to refer to a list of child nodes.
std::string formatstring(const char *fmt,...)
Use the given string and arguments to return a buffer containing the formatted string....
std::vector< std::string > split(const char *pszString, const char *splitChars)
Split the given string into a list of strings given the character on which to split....
Definition: split.cpp:13
std::string Replace(const std::string &s, const char *str1, const char *str2, bool bCaseInsensitive)
Replace all occurrences of narrow string str1 with narrow string str2 in s. If str2 is empty then all...
Definition: replace.cpp:47