Got MockFS, FileSystem at least partially working.
[kakapo:kakapo.git] / src / FileSystem.nqp
1 # Copyright (C) 2010, Austin Hastings. See accompanying LICENSE file, or 
2 # http://www.opensource.org/licenses/artistic-license-2.0.php for license.
3
4 # Provides a conventional framework for program execution. 
5 class FileSystem;
6
7 INIT {
8         our %_Osname_class_map := Hash.new(
9                 :DEFAULT(       FileSystem::Unix),
10                 :linux( FileSystem::Unix),
11         );
12         
13         Kakapo::initload_done();
14 }
15
16 method get_osname_map() {
17         our %_Osname_class_map;
18 }
19
20 method _init_obj(*@pos, *%named) {
21         my %map := self.get_osname_map();
22         my $osname := %*VM<osname>;
23         
24         $osname := 'DEFAULT' 
25                 unless %map.contains: $osname;
26
27         my $class := %map{$osname};
28         my $obj := $class.new( |@pos, |%named );        # NB: Returns a different type than Path.
29         $obj;
30 }
31
32 our method instance($value?) {
33         if $value.defined {
34                 our $_Instance := $value;
35         }
36         elsif ! our $_Instance.defined {
37                 self.instance: self.new;
38         }
39         
40         $_Instance;
41 }
42
43 class FileSystem::Unix
44         is FileSystem;
45
46 has     $!file;
47 has     $!os;
48
49 INIT {
50         use(    Parrot::Unix::Stat );
51         
52         my @multisubs := [ <exists> ];
53         
54         for @multisubs -> $name {
55                 Parrot::define_multisub($name, :method, :starting_with($name));
56                 
57                 my $string_sub := Parrot::get_hll_global( "FileSystem::Unix::{$name}__String" );
58                 unless is_null( $string_sub ) {
59                         Parrot::define_multisub($name, [ $string_sub ], signatures => [ <_ string> ] );
60                 }
61         }
62 }
63
64 our method chdir($path = '') {
65         $!os.chdir( ~ $path);
66 }
67
68 our method cwd() {
69         $!os.cwd;
70 }
71
72 our method directory_separator() { '/' }
73
74 my method exists__Path($path) {
75         $!file.exists( ~ $path );
76 }
77
78 my method exists__String($path) {
79         $!file.exists($path);
80 }
81
82 my method exists__ANY($ignored) {
83         die( "Don't know how to check if ", pir::typeof__SP($ignored), " exists. Use a String or Path");
84 }
85
86 our method get_contents($path, *%named) {
87         my $contents;
88         
89         if self.is_file: $path {
90                 %named<mode> := 'r';
91                 my $fh := self.open($path, |%named);
92                 $contents := $fh.readall;
93                 $fh.close;
94         }
95         elsif self.is_directory: $path {
96                 $contents := $!os.readdir: ~$path;
97         }
98         else {
99                 # What to do?
100                 die("Don't know how to get contents of non-file, non-directory: $path");
101         }
102         
103         $contents;
104 }
105
106 my method _init_obj(*@pos, *%named) {
107         $!file := pir::new__PS( 'File' );
108         $!os := pir::new__PS( 'OS' );
109         
110         self._init_args(|@pos, |%named);
111 }
112
113 our method is_device($path) {
114         my @stat := $!os.stat( ~$path );
115         my $mode := @stat[2];
116         S_ISBLK($mode) || S_ISCHR($mode) || S_ISFIFO($mode) || S_ISSOCK($mode);
117 }
118
119 our method is_directory($path) {
120         my @stat := $!os.stat( ~$path );
121         S_ISDIR(@stat[2]);
122 }
123
124 our method is_file($path) {
125         my @stat := $!os.stat( ~$path );        
126         S_ISREG(@stat[2]);
127 }
128
129 our method is_link($path) {
130         my @stat := $!os.lstat( ~$path );       
131         S_ISLNK(@stat[2]);
132 }
133
134 our method open($path, *%named) {
135         
136         my $fh  := pir::new__PS('FileHandle');
137         my $mode        := '' ~ %named<mode> // 'r';
138
139         $fh.open(~ $path, $mode);
140
141         # Not a loop because of prefix ops (+, ~)
142         $fh.buffer_size( +%named<buffer_size> )
143                 if %named.contains( <buffer_size> );
144         $fh.buffer_type( ~%named<buffer_type> )
145                 if %named.contains( <buffer_type> );
146         $fh.encoding( ~%named<encoding> )
147                 if %named.contains( <encoding> );
148
149         $fh;
150 }
151
152 our method volume_separator() { ':' }