get_home_directory: handle "/" in the env vars on windows
[conkeror.git] / modules / io.js
blobb2fbcd250b8a91d62c353615601d369d127b004f
1 /**
2  * (C) Copyright 2004 Shawn Betts
3  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
4  *
5  * Portions of this file were derived from the Venkman JavaScript debugger,
6  * (C) Copyright 1998 Netscape Communications Corporation.
7  *
8  * Use, modification, and distribution are subject to the terms specified in the
9  * COPYING file.
10 **/
12 in_module(null);
14 const PERM_IWOTH = 00002;  /* write permission, others */
15 const PERM_IWGRP = 00020;  /* write permission, group */
17 const MODE_RDONLY   = 0x01;
18 const MODE_WRONLY   = 0x02;
19 const MODE_RDWR     = 0x04;
20 const MODE_CREATE   = 0x08;
21 const MODE_APPEND   = 0x10;
22 const MODE_TRUNCATE = 0x20;
23 const MODE_SYNC     = 0x40;
24 const MODE_EXCL     = 0x80;
25 const MODE_OUTPUT = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
26 const MODE_OUTPUT_APPEND = MODE_WRONLY | MODE_CREATE | MODE_APPEND;
27 const MODE_INPUT = MODE_RDONLY;
29 define_keywords("$charset");
30 function read_text_file(file)
32     keywords(arguments, $charset = "UTF-8");
34     var ifstream = null, icstream = null;
36     try {
37         ifstream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
38         icstream = Cc["@mozilla.org/intl/converter-input-stream;1"].createInstance(Ci.nsIConverterInputStream);
40         ifstream.init(file, -1, 0, 0);
41         const replacementChar = Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
42         icstream.init(ifstream, arguments.$charset, 4096, replacementChar); // 4096 bytes buffering
44         var buffer = "";
45         var str = {};
46         while (icstream.readString(4096, str) != 0)
47             buffer += str.value;
48         return buffer;
49     } finally  {
50         if (icstream)
51             icstream.close();
52         if (ifstream)
53             ifstream.close();
54     }
57 define_keywords("$mode", "$perms", "$charset");
58 function write_text_file(file, buf)
60     keywords(arguments, $charset = "UTF-8", $perms = 0644, $mode = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE);
62     var ofstream, ocstream;
63     try {
64         ofstream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
65         ocstream = Cc["@mozilla.org/intl/converter-output-stream;1"].createInstance(Ci.nsIConverterOutputStream);
67         ofstream.init(file, arguments.$mode, arguments.$perms, 0);
68         ocstream.init(ofstream, arguments.$charset, 0, 0x0000);
69         ocstream.writeString(buf);
70     } finally {
71         if (ocstream)
72             ocstream.close();
73         if (ofstream)
74             ofstream.close();
75     }
78 define_keywords("$mode", "$perms");
79 function write_binary_file(file, buf)
81     keywords(arguments, $perms = 0644, $mode = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE);
82     var stream = null, bstream = null;
84     try {
85         stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
86         stream.init(file, arguments.$mode, arguments.$perms, 0);
88         bstream = binary_output_stream(stream);
89         bstream.writeBytes(buf, buf.length);
90     } finally {
91         if (bstream)
92             bstream.close();
93         if (stream)
94             stream.close();
95     }
98 var thread_manager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
100 function input_stream_async_wait(stream, callback, requested_count) {
101     stream = stream.QueryInterface(Ci.nsIAsyncInputStream);
102     var flags = (requested_count === false) ? Ci.nsIAsyncInputStream.WAIT_CLOSURE_ONLY : 0;
103     if (requested_count == null || requested_count == false)
104         requested_count = 0;
105     stream.asyncWait({onInputStreamReady: callback}, flags, requested_count, thread_manager.mainThread);
108 function output_stream_async_wait(stream, callback, requested_count) {
109     stream = stream.QueryInterface(Ci.nsIAsyncOutputStream);
110     var flags = (requested_count === false) ? Ci.nsIAsyncOutputStream.WAIT_CLOSURE_ONLY : 0;
111     if (requested_count == null || requested_count == false)
112         requested_count = 0;
113     stream.asyncWait({onOutputStreamReady: callback}, flags, requested_count, thread_manager.mainThread);
116 function binary_output_stream(stream) {
117     var s = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);
118     s.setOutputStream(stream);
119     return s;
122 function binary_input_stream(stream) {
123     var s = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
124     s.setInputStream(stream);
125     return s;
128 //  callback is called with null if the write succeeded, and an error otherwise
129 function async_binary_write(stream, data, callback) {
130     var data1 = data;
131     function attempt_write() {
132         try {
133             while (true) {
134                 if (data.length == 0) {
135                     stream.flush();
136                     if (callback != null)
137                         callback(null);
138                     return;
139                 }
140                 var len = stream.write(data, data.length);
141                 if (len == 0)
142                     break;
143                 data = data.substring(len);
144             }
145         }
146         catch (e if (e instanceof Components.Exception) && e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK) {}
147         catch (e) {
148             if (callback != null)
149                 callback(e);
150             return;
151         }
152         output_stream_async_wait(stream, attempt_write, data.length);
153     }
154     attempt_write();
158  * The `str' parameter should be a normal JavaScript string whose char codes specify Unicode code points.
159  * The return value is a byte string (all char codes are from 0 to 255) equal to the `str' encoded in the specified charset.
160  * If charset is not specified, it defaults to UTF-8.
161  */
162 function encode_string(str, charset) {
163     var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
164     converter.charset = charset || "UTF-8";
165     var output = converter.ConvertFromUnicode(str);
166     output += converter.Finish();
167     return output;
173  * The `bstr' parameter should be a byte string (all char codes are from 0 to 255).
174  * The return value is a normal JavaScript unicode sring equal to `bstr' decoded using the specified charset.
175  * If charset is not specified, it defaults to UTF-8.
176  */
177 function decode_string(bstr, charset) {
178     var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
179     converter.charset = charset  || "UTF-8";
180     return converter.ConvertToUnicode(bstr);
183 /* Calls callback when the write has completed.  If callback is null,
184    the stream is closed when the write completes. */
185 function async_binary_string_writer(bstr, callback) {
186     return function (stream) {
187         function modified_callback (e) {
188             if (callback == null) {
189                 stream.close();
190             } else {
191                 callback(stream, e);
192             }
193         }
194         async_binary_write(stream, bstr, modified_callback);
195     };
198 function async_binary_reader(callback) {
199     return function (stream) {
200         var bstream = binary_input_stream(stream);
201         function handler() {
202             try {
203                 let avail = stream.available();
204                 if (avail > 0) {
205                     callback(bstream.readBytes(avail));
206                 }
207                 input_stream_async_wait(stream, handler);
208             } catch (e) {
209                 callback(null);
210             }
211         }
212         input_stream_async_wait(stream, handler);
213     };
216 function string_input_stream(data) {
217     var string_stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(Ci.nsIStringInputStream);
218     string_stream.data = data;
219     return string_stream;
222 function mime_input_stream(stream, headers) {
223     var mime_stream = Cc["@mozilla.org/network/mime-input-stream;1"].createInstance(Ci.nsIMIMEInputStream);
224     if (headers) {
225         for each (let [name,value] in headers) {
226             mime_stream.addHeader(name,value);
227         }
228     }
229     mime_stream.addContentLength = true;
230     mime_stream.setData(stream);
231     return mime_stream;
234 provide("io");