namespace std
. Include cheader
files only when C++-style files are unavailable. Include header.h
files from C only when an appropriate cheader
file is unavailable. Use the script cpplint.py.perl
(a wrapper for cpplint.py
) to check style.// $Id: file_sys.h,v 1.5 2016-04-07 13:36:11-07 - - $
#ifndef __INODE_H__
#define __INODE_H__
#include <map>
#include <memory>
#include <vector>
#include <iostream>
#include <exception>
using namespace std;
#include "util.h"
// inode_t -
// An inode is either a directory or a plain file.
enum file_type{
PLAIN_TYPE,
DIRECTORY_TYPE
};
class inode;
class base_file;
class plain_file;
class directory;
using inode_ptr = shared_ptr<inode>;
using base_file_ptr = shared_ptr<base_file>;
using plain_file_ptr = shared_ptr<plain_file>;
using directory_ptr = shared_ptr<directory>;
ostream& operator<< (ostream&, file_type);
</code></pre>
</div>
<div class="col">
<div class="lead">
An inode can either be a plain file or a directory, so we distinguish via <code>enum file_type</code>:
</div>
<pre><code class="language-cpp">enum file_type{
PLAIN_TYPE,
DIRECTORY_TYPE
};
if (nameOfInode::file_type == PLAIN_TYPE) {
// plain file
} else {
// directory
}
using inode_ptr = shared_ptr<inode>;
using base_file_ptr = shared_ptr<base_file>;
using plain_file_ptr = shared_ptr<plain_file>;
using directory_ptr = shared_ptr<directory>;`}
inode
class, a private member contents
of type base_file_ptr
allows retrieving resources from plain_file
and directory
children without copying whole objects./
), current directory (.
), and the prompt.
class inode_state {
friend class inode;
friend ostream& operator<< (ostream& out, const inode_state&);
private:
string prompt_ {"==>$ "};
inode_ptr cwd {nullptr};
inode_ptr root {nullptr};
public:
inode_state();
inode_state(const inode_state&) = delete;
inode_state& operator=(const inode_state&) = delete;
const string prompt();
void cat(const wordvec& words);
void cd(const wordvec& words);
void echo(const wordvec& words);
void ls(const wordvec& words);
void lsr(const wordvec& words);
void lsr_pathname(const wordvec& words);
void make(const wordvec& words);
void mkdir(const wordvec& words);
void prompt(const wordvec& words);
void pwd(const wordvec& words);
void pwd(const wordvec& words, const inode_ptr pwdLocation);
void rm(const wordvec& words);
void rmr(const wordvec& words);
bool does_dir_file_exist(const wordvec& path, const inode_ptr potentialFile);
string pwd_str(const wordvec& words, const inode_ptr pwdLocation);
inode_ptr naviPath(const wordvec& words, int path_index);
}
inode_state
in the command loop to track root
, cwd
, and prompt. The navigation helper naviPath
returns an inode_ptr
for a user-supplied pathname or nullptr
if not found.inode
tracks an inode number, name, type, and its contents
(polymorphic base).class inode {
friend class inode_state;
private:
static int next_inode_nr;
string name;
int inode_nr;
file_type type;
base_file_ptr contents;
public:
inode (file_type type);
size_t size() const;
int get_inode_nr() const;
void set_name(const string& newName);
string get_name() const;
file_type get_type() const;
base_file_ptr get_contents() const;
};
contents
, a base_file_ptr
that can point to a plain_file
or directory
.class file_error: public runtime_error {
public:
explicit file_error (const string& what);
};
class base_file {
protected:
base_file() = default;
public:
virtual ~base_file() = default;
base_file (const base_file&) = delete;
base_file& operator= (const base_file&) = delete;
virtual size_t size() const = 0;
void mkfile (const string& filename);
friend plain_file_ptr plain_file_ptr_of (base_file_ptr);
friend directory_ptr directory_ptr_of (base_file_ptr);
};
dynamic_pointer_cast
to obtain concrete pointers:auto pf = dynamic_pointer_cast<plain_file>(ptr);
auto dir = dynamic_pointer_cast<directory>(ptr);
class plain_file: public base_file {
private:
wordvec data;
public:
size_t size() const override;
const wordvec& readfile() const;
void writefile (const wordvec& newdata);
void remove (const string& filename);
void mkfile (const string& filename);
};
PLAIN_TYPE
, cast contents
to plain_file
and call writefile
with the parsed words.class directory: public base_file {
private:
// Must be ordered so printing is lexicographic
map<string, inode_ptr> dirents;
public:
size_t size() const override;
const wordvec& readfile() const;
void iterate_ls();
vector<inode_ptr> subDirectory();
void mkdir (const string& dirname);
void new_directory(inode_ptr root);
void remove (const string& filename);
void set_parent_child(inode_ptr parent, inode_ptr child);
inode_ptr lookup (const string& lookup);
inode_ptr mkfile (const string& filename);
inode_ptr get_child(const string& filename);
};
dirents
holds "."
, ".."
, and children. Helpers like mkdir
, lookup
, and get_child
encapsulate updates and queries on this map.