Paying the taxes on invisible methods and a bunch of other idiotic changes in 2.3...
[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 := 'DEFAULT';
23         try {
24             my $tmp := %*VM<osname>;
25             $osname := $tmp if %map.contains: $tmp;
26
27             # if not, whatever. Keep it at DEFAULT
28             CATCH { }
29         }
30
31         my $class := %map{$osname};
32         my $obj := $class.new( |@pos, |%named );        # NB: Returns a different type than Path.
33         $obj;
34 }
35
36 our method instance($value?) {
37         if $value.defined {
38                 our $_Instance := $value;
39         }
40         elsif ! our $_Instance.defined {
41                 self.instance: self.new;
42         }
43
44         $_Instance;
45 }
46
47 class FileSystem::Unix
48         is FileSystem;
49
50 has     $!file;
51 has     $!os;
52
53 INIT {
54         pir::loadlib__ps('file');
55         pir::loadlib__ps('os');
56         
57         use(    Parrot::Unix::Stat );
58
59         my @multisubs := [ <exists> ];
60
61         for @multisubs -> $name {
62                 Parrot::define_multisub($name, :method, :starting_with($name));
63
64                 my $string_sub := Parrot::get_hll_global( "FileSystem::Unix::{$name}__String" );
65                 unless is_null( $string_sub ) {
66                         Parrot::define_multisub($name, [ $string_sub ], signatures => [ <_ string> ] );
67                 }
68         }
69 }
70
71 our method chdir($path = '') {
72         $!os.chdir( ~ $path);
73 }
74
75 our method cwd() {
76         $!os.cwd;
77 }
78
79 our method directory_separator() { '/' }
80
81 my method exists__Path($path) {
82         $!file.exists( ~ $path );
83 }
84
85 my method exists__String($path) {
86         $!file.exists($path);
87 }
88
89 my method exists__ANY($ignored) {
90         die( "Don't know how to check if ", pir::typeof__SP($ignored), " exists. Use a String or Path");
91 }
92
93 our method get_contents($path, *%named) {
94         my $contents;
95
96         if self.is_file: $path {
97                 %named<mode> := 'r';
98                 my $fh := self.open($path, |%named);
99                 $contents := $fh.readall;
100                 $fh.close;
101         }
102         elsif self.is_directory: $path {
103                 $contents := $!os.readdir: ~$path;
104         }
105         else {
106                 # What to do?
107                 die("Don't know how to get contents of non-file, non-directory: $path");
108         }
109
110         $contents;
111 }
112
113 my method _init_obj(*@pos, *%named) {
114         $!file := pir::new__PS( 'File' );
115         $!os := pir::new__PS( 'OS' );
116
117         self._init_args(|@pos, |%named);
118 }
119
120 our method is_device($path) {
121         my @stat := $!os.stat( ~$path );
122         my $mode := @stat[2];
123         S_ISBLK($mode) || S_ISCHR($mode) || S_ISFIFO($mode) || S_ISSOCK($mode);
124 }
125
126 our method is_directory($path) {
127         my @stat := $!os.stat( ~$path );
128         S_ISDIR(@stat[2]);
129 }
130
131 our method is_file($path) {
132         my @stat := $!os.stat( ~$path );
133         S_ISREG(@stat[2]);
134 }
135
136 our method is_link($path) {
137         my @stat := $!os.lstat( ~$path );
138         S_ISLNK(@stat[2]);
139 }
140
141 our method open($path, *%named) {
142
143         my $fh  := pir::new__PS('FileHandle');
144         my $mode        := '' ~ %named<mode> // 'r';
145
146         $fh.open(~ $path, $mode);
147
148         # Not a loop because of prefix ops (+, ~)
149         $fh.buffer_size( +%named<buffer_size> )
150                 if %named.contains( <buffer_size> );
151         $fh.buffer_type( ~%named<buffer_type> )
152                 if %named.contains( <buffer_type> );
153         $fh.encoding( ~%named<encoding> )
154                 if %named.contains( <encoding> );
155
156         $fh;
157 }
158
159 our method volume_separator() { ':' }