Bug 380813, improve scriptable io, and give file objects class info, meant to check this in a while ago, r=mfinkle,bsmedberg,sr=bsmedberg

This commit is contained in:
enndeakin@sympatico.ca 2007-07-25 09:53:37 -07:00
Родитель 5c78a2d51d
Коммит ad4871e657
22 изменённых файлов: 2147 добавлений и 67 удалений

Просмотреть файл

@ -125,6 +125,7 @@ XPIDLSRCS = \
nsIChannelEventSink.idl \
nsINetUtil.idl \
nsIProxiedChannel.idl \
nsIScriptableIO.idl \
$(NULL)
EXPORTS = \

Просмотреть файл

@ -0,0 +1,244 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Scriptable IO.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Neil Deakin <enndeakin@sympatico.ca> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIVariant;
interface nsIFile;
interface nsIInputStream;
interface nsIOutputStream;
interface nsIUnicharInputStream;
interface nsIUnicharOutputStream;
interface nsIURI;
/**
* A singleton object which contains a number of methods for creating files,
* streams and uris.
*
* This interface is intended to be used only from script.
*/
[scriptable, uuid(E54798D5-7693-43F9-9BB6-F21E434DD3FC)]
interface nsIScriptableIO : nsISupports
{
/**
* Retrieves a reference to a file or directory on disk, which may or may
* not exist. If the file exists, it may be opened for reading by passing
* the file as the base to newInputStream. If it doesn't exist, it may be
* created by opening an output stream and writing to it.
*
* Files are identified by the filename argument. The file is found relative
* to a well known directory identified by the location argument. This
* location is a string key which identifies common directories typically
* found on a system. For instance, using the location key 'Desk' will
* retrieve files in the desktop folder, and the location key 'TmpD' will
* retrieve files in the system's temporary directory.
*
* A complete list of location keys may be found at
* http://developer.mozilla.org/en/docs/IO_Guide/Directory_Keys
*
* The filename is always a file within the directory identified by the
* location key and this does not include a path. To retrieve
* subdirectories, retrieve a file and then use the file's append method
* to navigate into further subdirectories. This allows platform independent
* paths to be constructed.
*
* The filename may be a null string to retrieve a reference to the
* location directory itself.
*
* @param aLocation location key of well-known directory
* @param aFileName filename to locate within this directory, may be null
* @returns a file object
* @throws NS_ERROR_INVALID_ARG when aLocation is null
*/
nsIFile getFile(in AString aLocation, in AString aFileName);
/**
* Retrieves a reference to a file given a absolute file path.
*
* Use this method only when absolutely necessary. In most cases, getFile
* should be used instead, as file paths are not portable across different
* platforms and systems so this method should be avoided if possible.
* Instead, the getFile method should be used and a path constructed from
* it.
*
* The filepath should be an absolute path or the value of the
* persistentDescriptor of a file.
*
* @param aFilePath path to the file
* @returns a file object
* @throws NS_ERROR_INVALID_ARG when aFilePath is null
*/
nsIFile getFileWithPath(in AString aFilePath);
/**
* Creates a URI object which implements nsIURI. The url argument may either
* be a string or a file.
*
* @param aUri the url to create
* @returns a new nsIURI object
* @throws NS_ERROR_INVALID_ARG when aUri is null
*/
nsIURI newURI(in nsIVariant aUri);
/**
* Retrieves a stream which may be read from.
*
* The base argument may be one of a number of different types of objects
* which may be read from:
* nsIFile - an object returned from the getFile or getFileWithPath
* methods, or any object which implements the nsIFile
* interface.
* nsITransport - a transport object such as a socket.
* nsIInputStream - a stream returned by a previous call to this method or
* any other object which implements the nsIInputStream
* interface.
* string - a string
*
* The mode may be any number of space separated strings which control
* the manner is which the stream is created. If no strings apply, use
* a null string. Possible values are:
* text - read unicode converted text. The default character set is UTF-8.
* To read text in a different character set, set the aCharSet
* argument to the desired character set.
* buffered - a stream which uses a buffer to hold a block of the next
* part of the data to read. This mode would normally be used
* as a wrapper for other streams. The size of the buffer
* defaults to 1024 bytes, however the size may be changed by
* specifying the aBufferSize argument. If the text mode is
* used, the stream is always buffered.
* block - when reading from a transport such as a socket, an attempt to
* read from the stream while there is no data available will wait
* until data is available before returning. Without this mode,
* the stream will throw an exception if there is no data
* available.
* deleteonclose - the file is automatically deleted when the stream is
* closed. This might be used for temporary files.
* closeoneof - the file is automatically closed when the end of the file
* is reached.
* reopenonrewind - used in conjuction with the seek mode, the file will
* be reopened when a seek to the beginning of the file
* is done.
* multi - a stream which is used to concatenate the input from multiple
* streams together as if it was one long continuous stream. The
* returned stream implements the nsIMultiplexInputStream
* interface. This mode may only be used if the text or buffered
* modes are not used.
*
* If the mode is a null string, then no special type of reading is
* performed. In this case, the data from the stream is not interpreted in
* any way.
*
* @param aBase the base object to read from
* @param aMode flags controlling the reading
* @param aCharSet the character set to use when parsing text streams
* @param aReplaceChar the replacement character for unknown characters
* @param aBufferSize the size of buffer to use for buffered streams
* @returns a new input stream
* @throws NS_ERROR_INVALID_ARG when aBase is null
*/
nsISupports newInputStream(in nsIVariant aBase,
in AString aMode,
[optional] in AString aCharSet,
[optional] in AString aReplaceChar,
[optional] in unsigned long aBufferSize);
/**
* Retrieves a stream which may be written to.
*
* The base argument may be one of a number of different types of objects
* which may be written to:
* nsIFile - an object returned from the getFile or getFileWithPath
* methods, or any object which implements the nsIFile
* interface.
* nsITransport - a transport object such as a socket.
* nsIOutputStream - a stream returned by a previous call to this method
* or any other object which implements the
* nsIOutputStream interface.
* string - a string
*
* The mode may be any number of space separated strings which control
* the manner is which the stream is created. If no strings apply, use
* a null string. Possible values are:
* text - write unicode converted text. The default character set is
* UTF-8. To write text in a different character set, set the
* aCharSet argument to the desired character set.
* buffered - a stream which buffers the data being written, which would
* normally be used as a wrapper for other streams. The size of
* the buffer defaults to 1024 bytes, however the size may be
* changed by specifying the aBufferSize argument. If the text
* mode is used, the stream is always buffered.
* append - when writing to files, append to the end of the file instead
* of overwriting. If used in conjuction with the create mode, an
* existing file may be opened for appending, or a new file
* created.
* nocreate - when writing to files, and the file does not yet exist,
* don't create a new file. If this mode is not used, a
* new file will be created if it doesn't exist.
* notruncate - when writing to an existing file, overwrite the existing
* content. If this mode is not used, the file will be
* truncated to 0 length.
* syncsave - if used, then writing methods do not return until the
* data is properly saved.
* block - when writing to a transport such as a socket, an attempt
* to write to the stream will not return until all of the
* data has been written. This may cause a delay if the
* socket's underlying buffer is full. If this mode is not used,
* then an exception will be thrown if the buffer is full.
*
* If the mode is a null string, then no special type of writing is
* performed. In this case, the data being written to the stream is not
* interpreted in any way.
*
* The permissions may be set if a file is created. Typically, an octal
* value is used, for example: 0775. The default value when calling
* newOutputStream is 0664.
*
* @param aBase the base object to write to
* @param aMode flags controlling the writing
* @param aCharSet the character set to use when writing text streams
* @param aReplaceChar the replacement character for unknown characters
* @param aBufferSize the size of buffer to use for buffered streams
* @param aPermissions permissions of a file if one is created.
* @returns a new output stream
* @throws NS_ERROR_INVALID_ARG when aBase is null
*/
nsISupports newOutputStream(in nsIVariant aBase,
in AString aMode,
[optional] in AString aCharSet,
[optional] in AString aReplaceChar,
[optional] in unsigned long aBufferSize,
[optional] in unsigned long aPermissions);
};

Просмотреть файл

@ -112,6 +112,7 @@ endif
EXTRA_COMPONENTS = \
$(srcdir)/nsProxyAutoConfig.js \
$(srcdir)/nsScriptableIO.js \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a

Просмотреть файл

@ -0,0 +1,377 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Scriptable IO.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Neil Deakin <enndeakin@sympatico.ca> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const SCRIPTABLEIO_CLASS_ID = Components.ID("1EDB3B94-0E2E-419A-8C2B-D9E232D41086");
const SCRIPTABLEIO_CLASS_NAME = "Scriptable IO";
const SCRIPTABLEIO_CONTRACT_ID = "@mozilla.org/io/scriptable-io;1";
const DEFAULT_BUFFER_SIZE = 1024;
const DEFAULT_PERMISSIONS = 0644;
const Cc = Components.classes;
const Ci = Components.interfaces;
var gScriptableIO = null;
// when using the directory service, map some extra keys that are
// easier to understand for common directories
var mappedDirKeys = {
Application: "resource:app",
Working: "CurWorkD",
Profile: "ProfD",
Desktop: "Desk",
Components: "ComsD",
Temp: "TmpD"
};
function ScriptableIO() {
}
ScriptableIO.prototype =
{
_wrapBaseWithInputStream : function ScriptableIO_wrapBaseWithInputStream
(base, modes, permissions)
{
var stream;
if (base instanceof Ci.nsIFile) {
var behaviour = 0;
if (modes["deleteonclose"])
behaviour |= Ci.nsIFileInputStream.DELETE_ON_CLOSE;
if (modes["closeoneof"])
behaviour |= Ci.nsIFileInputStream.CLOSE_ON_EOF;
if (modes["reopenonrewind"])
behaviour |= Ci.nsIFileInputStream.REOPEN_ON_REWIND;
stream = Cc["@mozilla.org/network/file-input-stream;1"].
createInstance(Ci.nsIFileInputStream);
stream.init(base, 1, permissions, behaviour);
}
else if (base instanceof Ci.nsITransport) {
var flags = modes["block"] ? Ci.nsITransport.OPEN_BLOCKING : 0;
stream = base.openInputStream(flags, buffersize, 0);
}
else if (base instanceof Ci.nsIInputStream) {
stream = base;
}
else if (typeof base == "string") {
stream = Cc["@mozilla.org/io/string-input-stream;1"].
createInstance(Ci.nsIStringInputStream);
stream.setData(base, base.length);
}
if (!stream)
throw "Cannot create input stream from base";
return stream;
},
_wrapBaseWithOutputStream : function ScriptableIO_wrapBaseWithOutputStream
(base, modes, permissions)
{
var stream;
if (base instanceof Ci.nsIFile) {
stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
// default for writing is 'write create truncate'
var modeFlags = 42;
if (modes["nocreate"])
modeFlags ^= 8;
if (modes["append"])
modeFlags |= 16;
if (modes["notruncate"])
modeFlags ^= 32;
if (modes["syncsave"])
modeFlags |= 64;
stream.init(base, modeFlags, permissions, 0);
}
else if (base instanceof Ci.nsITransport) {
var flags = modes["block"] ? Ci.nsITransport.OPEN_BLOCKING : 0;
stream = base.openOutputStream(flags, buffersize, 0);
}
else if (base instanceof Ci.nsIInputStream) {
stream = base;
}
if (!stream)
throw "Cannot create output stream from base";
return stream;
},
_openForReading : function ScriptableIO_openForReading
(base, modes, buffersize, charset, replchar)
{
var stream = base;
var charstream = null;
if (modes["text"]) {
if (!charset)
charset = "UTF-8";
if (!replchar)
replchar = Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
charstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
createInstance(Ci.nsIConverterInputStream);
charstream.init(base, charset, buffersize, replchar);
}
else if (modes["buffered"]) {
stream = Cc["@mozilla.org/network/buffered-input-stream;1"].
createInstance(Ci.nsIBufferedInputStream);
stream.init(base, buffersize);
}
else if (modes["multi"]) {
stream = Cc["@mozilla.org/io/multiplex-input-stream;1"].
createInstance(Ci.nsIMultiplexInputStream);
stream.appendStream(base);
}
// wrap the stream in a scriptable stream
var sstream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance();
sstream.initWithStreams(stream, charstream);
return sstream;
},
_openForWriting : function ScriptableIO_openForWriting
(base, modes, buffersize, charset, replchar)
{
var stream = base;
var charstream = null;
if (modes["text"]) {
if (!charset)
charset = "UTF-8";
if (!replchar)
replchar = Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
charstream = Cc["@mozilla.org/intl/converter-output-stream;1"].
createInstance(Ci.nsIConverterOutputStream);
charstream.init(base, charset, buffersize, replchar);
}
else if (modes["buffered"]) {
stream = Cc["@mozilla.org/network/buffered-output-stream;1"].
createInstance(Ci.nsIBufferedOutputStream);
stream.init(base, buffersize);
}
// wrap the stream in a scriptable stream
var sstream = Cc["@mozilla.org/scriptableoutputstream;1"].createInstance();
sstream.initWithStreams(stream, charstream);
return sstream;
},
getFile : function ScriptableIO_getFile(location, file)
{
if (!location)
throw Components.results.NS_ERROR_INVALID_ARG;
if (location in mappedDirKeys)
location = mappedDirKeys[location];
var ds = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var fl = ds.get(location, Ci.nsILocalFile);
if (file)
fl.append(file);
return fl;
},
getFileWithPath : function ScriptableIO_getFileWithPath(filepath)
{
if (!filepath)
throw Components.results.NS_ERROR_INVALID_ARG;
// XXXndeakin not sure if setting persistentDescriptor is best here, but
// it's more useful than initWithPath, for instance, for preferences
var fl = Cc["@mozilla.org/file/local;1"].createInstance();
fl.persistentDescriptor = filepath;
return fl;
},
newURI : function ScriptableIO_newURI(uri)
{
if (!uri)
throw Components.results.NS_ERROR_INVALID_ARG;
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
if (uri instanceof Ci.nsIFile)
return ios.newFileURI(uri);
return ios.newURI(uri, "", null);
},
newInputStream : function ScriptableIO_newInputStream
(base, mode, charset, replchar, buffersize)
{
return this._newStream(base, mode, charset, replchar, buffersize,
DEFAULT_PERMISSIONS, false);
},
newOutputStream : function ScriptableIO_newOutputStream
(base, mode, charset, replchar, buffersize, permissions)
{
return this._newStream(base, mode, charset, replchar, buffersize,
permissions, true);
},
_newStream : function ScriptableIO_newStream
(base, mode, charset, replchar, buffersize, permissions, iswrite)
{
if (!base)
throw Components.results.NS_ERROR_INVALID_ARG;
var modes = {};
var modeArr = mode.split(/\s+/);
for (var m = 0; m < modeArr.length; m++) {
modes[modeArr[m]] = true;
}
if (!buffersize)
buffersize = DEFAULT_BUFFER_SIZE;
var stream;
if (iswrite) {
base = this._wrapBaseWithOutputStream(base, modes, permissions);
stream = this._openForWriting(base, modes, buffersize, charset, replchar);
}
else {
base = this._wrapBaseWithInputStream(base, modes, permissions);
stream = this._openForReading(base, modes, buffersize, charset, replchar);
}
if (!stream)
throw "Cannot create stream from base";
return stream;
},
// nsIClassInfo
classDescription : "IO",
classID : SCRIPTABLEIO_CLASS_ID,
contractID : SCRIPTABLEIO_CONTRACT_ID,
flags : Ci.nsIClassInfo.SINGLETON,
implementationLanguage : Ci.nsIProgrammingLanguage.JAVASCRIPT,
getInterfaces : function ScriptableIO_getInterfaces(aCount) {
var interfaces = [Ci.nsIScriptableIO, Ci.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
getHelperForLanguage : function ScriptableIO_getHelperForLanguage(aCount) {
return null;
},
QueryInterface: function ScriptableIO_QueryInterface(aIID) {
if (aIID.equals(Ci.nsIScriptableIO) ||
aIID.equals(Ci.nsIClassInfo) ||
aIID.equals(Ci.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
}
var ScriptableIOFactory = {
QueryInterface: function ScriptableIOFactory_QueryInterface(iid)
{
if (iid.equals(Ci.nsIFactory) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
createInstance: function ScriptableIOFactory_createInstance(aOuter, aIID)
{
if (aOuter != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
if (gScriptableIO == null)
gScriptableIO = new ScriptableIO();
return gScriptableIO.QueryInterface(aIID);
}
};
var ScriptableIOModule = {
QueryInterface: function ScriptableIOModule_QueryInterface(iid) {
if (iid.equals(Ci.nsIModule) ||
iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
registerSelf: function ScriptableIOModule_registerSelf(aCompMgr, aFileSpec, aLocation, aType)
{
aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation(SCRIPTABLEIO_CLASS_ID,
SCRIPTABLEIO_CLASS_NAME,
SCRIPTABLEIO_CONTRACT_ID,
aFileSpec, aLocation, aType);
var categoryManager = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
categoryManager.addCategoryEntry("JavaScript global privileged property", "IO",
SCRIPTABLEIO_CONTRACT_ID, true, true);
},
unregisterSelf: function ScriptableIOModule_unregisterSelf(aCompMgr, aLocation, aType)
{
aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.unregisterFactoryLocation(SCRIPTABLEIO_CLASS_ID, aLocation);
var categoryManager = Cc["@mozilla.org/categorymanager;1"].
getService(Ci.nsICategoryManager);
categoryManager.deleteCategoryEntry("JavaScript global privileged property",
SCRIPTABLEIO_CONTRACT_ID, true);
},
getClassObject: function ScriptableIOModule_getClassObject(aCompMgr, aCID, aIID)
{
if (!aIID.equals(Ci.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
if (aCID.equals(SCRIPTABLEIO_CLASS_ID))
return ScriptableIOFactory;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
canUnload: function ScriptableIOModule_canUnload(aCompMgr)
{
gScriptableIO = null;
return true;
}
};
function NSGetModule(aCompMgr, aFileSpec) { return ScriptableIOModule; }

Просмотреть файл

@ -46,6 +46,7 @@ include $(DEPTH)/config/autoconf.mk
MODULE = test_necko
DIRS = \
chrome \
httpserver \
$(NULL)

Просмотреть файл

@ -0,0 +1,51 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = network/test/chrome
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_scriptableio.xul \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

Просмотреть файл

@ -0,0 +1,470 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
Tests for scriptable IO
-->
<window title="Scriptable IO" width="500" height="600"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<label value="Scriptable IO Tests"/>
<!-- test resuls are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
function testIO()
{
// delete files used for this test first in case it failed last time
var fl = IO.getFile("Desk", "test-sample.txt");
if (fl.exists())
fl.remove(false);
var iswin = navigator.userAgent.indexOf("Windows") >= 0;
ok(IO, "IO is avaialble");
ok(typeof IO.getFile == "function", "IO.getFile is a function");
// -------- Creating a file object --------
fl = IO.getFile("Desk", "test-sample.txt");
is(fl.leafName, "test-sample.txt", "getFile creates file");
ok(fl instanceof Components.interfaces.nsIFile, "getFile creates an nsIFile");
is(fl.exists(), false, "file returned by getFile does not exist yet");
var dir = IO.getFile("Desktop", "");
is(dir.isDirectory(), true, "directory returned when filename is null");
expectException(function() { var s = IO.newInputStream(dir, "", ""); s.readString(5); },
"open input stream on directory");
expectException(function() { IO.newOutputStream(dir, ""); },
"open output stream on directory");
expectException(function() { IO.getFile("", ""); }, "open null file");
is(IO.getFileWithPath(fl.path + "2").leafName, "test-sample.txt2",
"getFileWithPath creates file");
expectException(function() { IO.getFileWithPath(""); },
"getFileWithPath with null path");
ok(IO.getFile("Application", "").path.length > 0, "Application directory");
ok(IO.getFile("Working", "").path.length > 0, "Working directory");
ok(IO.getFile("Profile", "").path.length > 0, "Profile directory");
ok(IO.getFile("Desktop", "").path.length > 0, "Desktop directory");
ok(IO.getFile("Components", "").path.length > 0, "Components directory");
ok(IO.getFile("Temp", "").path.length > 0, "Temp directory");
// -------- Writing to a standard stream --------
// Mac is the only platform where the file size is updated after writing
var checkFileSize = (navigator.platform.indexOf("Mac") >= 0);
var stream;
var types = ["", "buffered"];
for (var t = 0; t < types.length; t++) {
var etype = types[t];
var ename = etype + " ";
stream = IO.newOutputStream(fl, etype);
ok(typeof stream.write == "function", ename + "IO.newOutputStream returned a stream");
is(fl.exists(), true, ename + "file after creating output stream does not exist yet");
is(stream.tell(), 0, ename + "file write position is 0");
stream.write("This is a string", 16);
if (etype == "buffered") {
if (checkFileSize)
is(fl.fileSize, 0, ename + "file size after writing before flush");
stream.flush();
}
if (checkFileSize)
is(fl.fileSize, 16, ename + "file size after writing");
is(stream.tell(), 16, ename + "file write position after writing is 16");
stream.flush(); // just call flush to make sure no error occurs
// disable this test for now because the default permissions is different
// on each machine
// if (!win)
// is(fl.permissions & 511, 0644, ename + "permissions after creating file");
// check stream constants
is(stream.NS_SEEK_SET, 0, ename + "NS_SEEK_SET is 0");
is(stream.NS_SEEK_CUR, 1, ename + "NS_SEEK_CUR is 1");
is(stream.NS_SEEK_END, 2, ename + "NS_SEEK_END is 2");
// check file seeking with writing
stream.seek(stream.NS_SEEK_SET, 8);
is(stream.tell(), 8, ename + "file write position after seek is correct");
stream.write("another string", 14);
if (etype == "buffered")
stream.flush();
if (checkFileSize)
is(fl.fileSize, 22, ename + "file size after writing again is correct");
is(stream.tell(), 22, ename + "file write position after writing again is correct");
stream.seek(stream.NS_SEEK_SET, 2);
stream.seek(stream.NS_SEEK_CUR, 9);
is(stream.tell(), 11, ename + "file write position after current position seek");
stream.seek(stream.NS_SEEK_CUR, -3);
is(stream.tell(), 8, ename + "file write position after reverse current position seek");
stream.seek(stream.NS_SEEK_END, 0);
is(stream.tell(), 22, ename + "file write position after end position seek");
stream.seek(stream.NS_SEEK_END, 10);
is(stream.tell(), 32, ename + "file write position after end position with value seek");
// seeking past the end of the file and writing will fill the blank area with zeros
stream.write(".", 1);
if (etype == "buffered")
stream.flush();
if (checkFileSize)
is(fl.fileSize, 33, ename + "file size after writing beyond end is correct");
is(stream.tell(), 33, ename + "file write position after writing beyond end seek");
stream.seek(stream.NS_SEEK_END, -11);
is(stream.tell(), 22, ename + "file write position after reverse end position seek");
stream.write(" ", 3);
stream.writeString("*a*");
stream.write("\u03a9", 2); // unicode isn't processed so should output a9 and 00
stream.write("\u03a9", 1); // one character, so should output a9
stream.write("\u00a8", 2); // write single character as a8 and 00
stream.write("\u00a8", 1); // write single character as a8
stream.writeString(".");
stream.write("Ends Here", 3);
is(stream.tell(), 38, ename + "file write position extra writing is 38");
stream.writeString("More Text");
if (etype = "buffered")
stream.flush();
stream.seek(stream.NS_SEEK_SET, 42);
stream.setEOF();
if (checkFileSize)
is(fl.fileSize, 42, ename + "setEOF truncates output stream");
stream.close();
// buffered streams cause an infinite loop when writing to a closed stream
if (etype != "buffered")
expectException(function() { stream.write("write after close", 17); },
ename + "writing after stream is closed");
stream.close(); // calling close on a closed stream should do nothing
// -------- Reading from a standard stream --------
stream = IO.newInputStream(fl, etype);
ok(typeof stream.available == "function", ename + "IO.newInputStream returned a stream");
ok(!stream.isNonBlocking(), ename + "file input stream is blocking");
is(stream.tell(), 0, ename + "file read position is 0");
is(stream.available(), 42, ename + "available count after input stream creation");
is(stream.read(9), "This is a", ename + "file read");
is(stream.available(), 33, ename + "available count after read");
is(stream.tell(), 9, ename + "file read position after reading is 9");
expectException(function() { stream.setEOF(); }, ename + "setEOF on input stream");
// check file seeking with reading
stream.seek(stream.NS_SEEK_SET, 5);
is(stream.tell(), 5, ename + "file write position after seek is correct");
is(stream.read(2), "is", ename + "file read after seek");
is(stream.tell(), 7, ename + "file read position after seek and read is 7");
stream.seek(stream.NS_SEEK_CUR, 3);
is(stream.read(5), "other", ename + "file read after current seek");
stream.seek(stream.NS_SEEK_CUR, -4);
is(stream.read(3), "the", ename + "file read after reverse current seek");
stream.seek(stream.NS_SEEK_END, 0);
is(stream.available(), 0, ename + "available count after end seek");
is(stream.read(5), "", ename + "file read after end seek");
stream.seek(stream.NS_SEEK_END, -26);
is(stream.read(6), "string", ename + "file read after reverse end seek");
stream.seek(stream.NS_SEEK_SET, 5);
// this will only read to the 0 added when the unicode character was written above
is(stream.read(1000), "is another string *a*\u00a9", ename + "file read after large read");
is(stream.tell(), 42, ename + "file read position after large read is 7");
stream.seek(stream.NS_SEEK_END, -9)
is(stream.read(1000), "\u00a8.EndMore", ename + "file read after another large read");
is(stream.available(), 0, ename + "available count after end of file reached");
stream.close();
// buffered input streams don't fail when reading after closing
if (etype != "buffered")
expectException(function() { stream.read(5); },
ename + "reading after stream is closed");
stream.close();
// -------- Check other modes --------
// notruncate should open file at position 0 but doesn't truncate the file
// set the sync flag just to make sure that it doesn't cause an error
stream = IO.newOutputStream(fl, ename + "notruncate syncsave");
is(stream.tell(), 0, ename + "file write position after notruncate opening");
if (checkFileSize)
is(fl.fileSize, 42, ename + "file size after notruncate opening");
stream.writeString("That");
stream.close();
checkFile(fl, "That is", ename + "writing after notruncate opening");
stream = IO.newOutputStream(fl, "");
stream.writeString("This is a string.");
stream.close();
stream = IO.newOutputStream(fl, ename + "notruncate append");
// for appending, the write position isn't updated until a write occurs so
// it will still be 0 at this point
is(stream.tell(), 0, ename + "file write position after append opening");
if (checkFileSize)
is(fl.fileSize, 17, ename + "file size after append opening");
stream.writeString("...");
stream.close();
checkFile(fl, "This is a string....",
ename + "Writing after append opening");
stream = IO.newOutputStream(fl, etype);
is(stream.tell(), 0, ename + "file write position after reopening");
if (checkFileSize)
is(fl.fileSize, 0, ename + "file size after reopening");
stream.writeString("Hello");
stream.close();
checkFile(fl, "Hello", ename + "Writing after reopening");
var stream = IO.newInputStream(fl, "closeoneof", "", "", 512);
stream.read(50);
// the closeoneof flag actually only closes the file when an attempt is made
// to read when the end of file is already reached, so another call to read
// is needed
stream.read(1);
expectException(function() { stream.read(1); },
ename + "read after end from closeoneof opened stream");
stream = IO.newInputStream(fl, "deleteonclose");
stream.readString(5);
stream.close();
is(fl.exists(), false, ename + "file is deleted with deleteonclose flag");
expectException(function() { stream = IO.newOutputStream(fl, ename + "nocreate"); },
ename + "opening with nocreate when file doesn't exist");
is(fl.exists(), false, ename + "file doesn't exist after opening output stream with nocreate flag");
if (fl.exists())
fl.remove(false);
// -------- Check string streams --------
stream = IO.newInputStream("This is a string to read from", etype);
is(stream.available(), 29, ename + "available count in string stream");
is(stream.tell(), 0, ename + "string read positon is initially 0");
is(stream.read(4), "This", ename + "read from string stream");
is(stream.tell(), 4, ename + "string read positon after read is 4");
stream.seek(stream.NS_SEEK_SET, 10);
is(stream.tell(), 10, ename + "string read positon after set seek is 10");
is(stream.read(6), "string", ename + "string read after set seek");
stream.seek(stream.NS_SEEK_CUR, -8);
is(stream.read(1), "a", ename + "string read after cur seek");
stream.seek(stream.NS_SEEK_END, -4);
is(stream.read(40), "from", ename + "string read after end seek");
stream.close();
}
expectException(function() { IO.newInputStream(null, ""); },
"newInputStream with null base");
expectException(function() { IO.newOutputStream(null, ""); },
"newOutputStream with null base");
// -------- Writing to a text stream --------
stream = IO.newOutputStream(fl, "text");
ok(!stream.isNonBlocking(), "file output stream is blocking");
stream.write("This is cool", 12);
is(fl.fileSize, 12, "file size after text write");
stream.writeString(" \u03a9\u03a9End");
if (checkFileSize)
is(fl.fileSize, 20, "file size after text writeString");
stream.close();
// -------- Reading from a text stream --------
stream = IO.newInputStream(fl, "text");
// for text streams, 1 means text can be read, 0 means no text available
is(stream.available(), 20, "available count after text input stream creation");
is(stream.readString(4), "This", "read text file");
is(stream.available(), 1, "available count after read");
is(stream.readString(13), " is cool \u03a9\u03a9En", "read string from text file");
is(stream.available(), 1, "available count at end");
is(stream.readString(1), "d", "read string at end from text file");
is(stream.available(), 1, "available count at end");
is(stream.readString(1), "", "read string after end from text file");
is(stream.available(), 0, "available count after end");
stream.close();
fl.remove(false);
// -------- Check other character sets --------
stream = IO.newOutputStream(fl, "text", "UTF-16", "*", 2048, 0755);
ok("writeString" in stream, "newOutputStream for UTF-16 returns output stream");
stream.write("This is cool", 12);
// file size is 12 characters times 2 bytes each plus two bytes for
// the byte order mark
is(fl.fileSize, 26, "file size after UTF-16 text write");
stream.writeString(" \u03a9\u03a9End\u9999");
if (checkFileSize)
is(fl.fileSize, 40, "file size after UTF-16 text writeString");
// XXXndeakin
// disable this test for now because the default permissions is different
// on each machine
//if (!iswin)
// is(fl.permissions & 511, 0755, "permissions after creating file with newOutputStream");
stream.close();
stream = IO.newInputStream(fl, "text", "UTF-16", "*", 1024);
is(stream.available(), 40, "available count after UTF-16 input stream creation");
is(stream.readString(16), "This is cool \u03a9\u03a9E", "read UTF-16 file");
stream.close();
// -------- Check linefeed handling --------
stream = IO.newOutputStream(fl, "text");
stream.writeString("Line One\rLine Two\nLine Three\r\nLine Four\n\rLine Five\n\nLine Six");
stream.close();
stream = IO.newInputStream(fl, "text");
is(stream.readLine(), "Line One", "read line with carriage return");
is(stream.readLine(), "Line Two", "read line with newline");
is(stream.readLine(), "Line Three", "read line with carriage return and newline");
is(stream.readLine(), "Line Four", "read line with newline and carriage return");
is(stream.readLine(), "Line Five", "read line with newline and newline");
is(stream.readLine(), "", "read blank line");
is(stream.readLine(), "Line Six", "read last line");
is(stream.readLine(), "", "read after end");
// -------- Check multiplex streams --------
expectException(function() { stream.count(); }, "multi functions on non-multi stream");
stream = IO.newOutputStream(fl, "");
stream.writeString("A middle string. ");
stream.close();
stream = IO.newInputStream(fl, "multi");
is(stream.count, 1, "count on multi stream");
var stream2 = IO.newInputStream("A final string.", "");
stream.appendStream(stream2);
is(stream.getStream(1), stream2, "stream appended");
is(stream.count, 2, "count on multi stream after appending");
var stream3 = IO.newInputStream("An initial string. ", "");
stream.insertStream(stream3, 0);
is(stream.getStream(0), stream3, "stream inserting");
is(stream.count, 3, "count on multi stream after inserting");
stream.insertStream(IO.newInputStream("A small string", ""), 1);
stream.removeStream(1);
is(stream.count, 3, "count on multi stream after removing");
expectException(function() { stream.removeStream(5); },
"remove out of range index in multi stream");
var expectedText = "An initial string. A middle string. A final string.";
is(stream.read(expectedText.length), expectedText, "read from multi stream");
stream.close();
// -------- Check binary methods --------
stream = IO.newOutputStream(fl, "");
stream.writeBoolean(true);
stream.writeBoolean(false);
stream.write8(10);
stream.write16(8209);
stream.write16(-8209);
stream.write16(300000);
stream.write32(200000);
is(stream.tell(), 13, "write position after binary write");
stream.writeFloat(0.25);
stream.writeDouble(56020.65);
stream.writeByteArray([100, 0, 1000, 5], 4);
stream.seek(stream.NS_SEEK_SET, 3);
stream.write16(8211);
stream.close();
if (checkFileSize)
is(fl.fileSize, 29, "file size after binary write");
stream = IO.newInputStream(fl, "");
is(stream.readBoolean(), true, "read boolean true from binary");
is(stream.readBoolean(), false, "read boolean false from binary");
is(stream.read8(), 10, "read 8-bit integer from binary");
is(stream.read16(), 8211, "read 16-bit integer from binary");
is(stream.read16(), 57327, "read negative 16-bit integer from binary");
is(stream.read16(), 37856, "read another 16-bit integer from binary");
is(stream.tell(), 9, "read position from binary");
is(stream.read32(), 200000, "read 32-bit integer from binary");
is(stream.readFloat(), 0.25, "read float from binary");
is(stream.readDouble(), 56020.65, "read double from binary");
stream.seek(stream.NS_SEEK_SET, 2);
var arr = stream.readByteArray(27);
var expectedArr = [10, 32, 19, 223, 239, 147, 224, 0, 3, 13, 64, 62, 128,
0, 0, 64, 235, 90, 148, 204, 204, 204, 205, 100, 0, 232, 5];
var isok = true;
for (var a = 0; a < expectedArr.length; a++) {
if (expectedArr[a] != arr[a]) {
isok = false;
break;
}
}
ok(isok && arr.length == expectedArr.length, "read byte array from binary");
stream.close();
// -------- Check newURI method --------
var uri = IO.newURI("http://www.mozilla.org");
is(uri.spec, "http://www.mozilla.org/", "newURI returns nsIURI");
ok(IO.newURI(fl).spec.indexOf("file:/") == 0, "newURI returns nsIURI for file");
expectException(function() { IO.newURI(""); }, "newURI with null uri");
}
function checkFile(fl, expectedText, testname)
{
var stream = IO.newInputStream(fl, "");
is(stream.read(expectedText.length), expectedText, testname);
stream.close();
}
function expectException(fn, testname)
{
var exh = false;
try {
fn();
}
catch(ex) {
exh = true;
ok(ex, testname + " failed properly");
}
if (!exh) ok(false, testname + " didn't fail");
}
testIO();
]]>
</script>
</window>

Просмотреть файл

@ -51,6 +51,7 @@
#include "nsIProperties.h"
#include "nsPersistentProperties.h"
#include "nsScriptableInputStream.h"
#include "nsScriptableOutputStream.h"
#include "nsBinaryStream.h"
#include "nsStorageStream.h"
#include "nsPipe.h"
@ -244,6 +245,9 @@ NS_DECL_CLASSINFO(nsThreadManager)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThreadPool)
NS_DECL_CLASSINFO(nsThreadPool)
NS_DECL_CLASSINFO(nsScriptableInputStream)
NS_DECL_CLASSINFO(nsScriptableOutputStream)
static NS_METHOD
nsXPTIInterfaceInfoManagerGetSingleton(nsISupports* outer,
const nsIID& aIID,
@ -351,7 +355,10 @@ static const nsModuleComponentInfo components[] = {
COMPONENT(ERRORSERVICE, nsErrorService::Create),
COMPONENT(BYTEBUFFER, ByteBufferImpl::Create),
COMPONENT(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create),
COMPONENT_CI(SCRIPTABLEINPUTSTREAM, nsScriptableInputStream::Create,
nsScriptableInputStream),
COMPONENT_CI(SCRIPTABLEOUTPUTSTREAM, nsScriptableOutputStream::Create,
nsScriptableOutputStream),
COMPONENT(BINARYINPUTSTREAM, nsBinaryInputStreamConstructor),
COMPONENT(BINARYOUTPUTSTREAM, nsBinaryOutputStreamConstructor),
COMPONENT(STORAGESTREAM, nsStorageStreamConstructor),

Просмотреть файл

@ -66,6 +66,7 @@ CPPSRCS = \
nsPipe3.cpp \
nsStreamUtils.cpp \
nsScriptableInputStream.cpp \
nsScriptableOutputStream.cpp \
nsSegmentedBuffer.cpp \
SpecialSystemDirectory.cpp \
nsStorageStream.cpp \
@ -167,6 +168,7 @@ SDK_XPIDLSRCS = \
nsIInputStream.idl \
nsIOutputStream.idl \
nsIScriptableInputStream.idl \
nsIScriptableStreams.idl \
$(NULL)
SDK_HEADERS = \

Просмотреть файл

@ -0,0 +1,212 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Scriptable IO.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Neil Deakin <enndeakin@sympatico.ca> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIVariant;
interface nsIFile;
interface nsIInputStream;
interface nsIOutputStream;
interface nsIUnicharInputStream;
interface nsIUnicharOutputStream;
/**
* Streams used with scriptable IO, which is itself located within netwerk.
*/
[scriptable, uuid(9245740D-D22E-4065-A1A0-72F0AE45E6DF)]
interface nsIScriptableIOInputStream : nsISupports
{
/**
* Called to initialize the stream.
*/
void initWithStreams(in nsIInputStream aStream,
in nsIUnicharInputStream aCharStream);
/**
* Read string of aCount characters from the stream. If the stream is
* text, then the characters are read in the expected character set.
* If the stream is non-text aCount bytes are read and returned as a
* string. If the end of the stream, or the end of the available data
* is reached, the returned string may be shorter than the desired
* length.
*
* @param aCount the number of characters to read
* @returns the string read from the stream
*/
AString readString(in unsigned long aCount);
/**
* Read from the stream until an end of line is reached and return a string
* containing all characters up until that point. An end of line is
* indicated by a 0x0A, 0x0D, a sequence of 0x0A 0x0D or a sequence of
* 0x0D 0x0A. These characters are not returned as part of the string.
*
* @returns the next line from the stream
*/
AString readLine();
/**
* Read a single byte from a stream and return false if the byte is zero and
* true if the byte is non-zero.
*
* @param a boolean value for the next byte in the stream
*/
boolean readBoolean();
/**
* Read a single byte from a stream.
*
* @returns the next byte in the stream
*/
octet read8();
/**
* Read and interpret the next two bytes in the stream as an unsigned
* big endian integer.
*
* @returns the next 16-bit integer in the stream
*/
unsigned short read16();
/**
* Read and interpret the next four bytes in the stream as an unsigned
* big endian integer.
*
* @returns the next 32-bit integer in the stream
*/
unsigned long read32();
/**
* Read and interpret the next four bytes in the stream as a floating point
* value.
*
* @returns the next float in the stream
*/
float readFloat();
/**
* Read and interpret the next eight bytes in the stream as a double
* floating point value.
*
* @returns the next double in the stream
*/
double readDouble();
/**
* Read aCount bytes from the stream and fill the aBytes array with
* the bytes.
*
* @param aCount the number of bytes to read
* @param aBytes [out] set to the array of read bytes
*/
void readByteArray(in unsigned long aCount,
[array, size_is(aCount), retval] out octet aBytes);
};
[scriptable, uuid(11FAE7E6-DF5B-4D80-B4C9-61849378364D)]
interface nsIScriptableIOOutputStream : nsISupports
{
/**
* Called to initialize the stream.
*/
void initWithStreams(in nsIOutputStream aStream,
in nsIUnicharOutputStream aCharStream);
/**
* Write the string aString to the stream. For text streams, the string is
* written in the expected character set. For other streams, the string is
* interpreted as bytes, which means that characters above 255 are only
* written using their low 8 bits.
*
* @param aString the string to write
* @returns true if the entire string was written, false otherwise
*/
boolean writeString(in AString aString);
/**
* Write a boolean to the stream. If the boolean is false, 0 is written,
* and if the boolean is true, 1 is written.
*
* @param aBoolean the value to write
*/
void writeBoolean(in boolean aBoolean);
/**
* Write a single byte to the stream.
*
* @param aByte the value to write
*/
void write8(in octet aByte);
/**
* Write a 16-bit integer to the stream as an unsigned big endian value.
*
* @param a16 the value to write
*/
void write16(in unsigned short a16);
/**
* Write a 32-bit integer to the stream as an unsigned big endian value.
*
* @param a32 the value to write
*/
void write32(in unsigned long a32);
/**
* Write a floating point value to the stream in 4 bytes.
*
* @param aFloat the value to write
*/
void writeFloat(in float aFloat);
/**
* Write a double floating point value to the stream in 8 bytes.
*
* @param aDouble the value to write
*/
void writeDouble(in double aDouble);
/**
* Write aCount values from the array aBytes to the stream.
*
* @param aBytes the array of write
* @param aCount the number of bytes to write
*/
void writeByteArray([array, size_is(aCount)] in octet aBytes,
in unsigned long aCount);
};

Просмотреть файл

@ -51,6 +51,7 @@
#include "nsISimpleEnumerator.h"
#include "nsIDirectoryEnumerator.h"
#include "nsIComponentManager.h"
#include "nsIProgrammingLanguage.h"
#include "prtypes.h"
#include "prio.h"
@ -615,11 +616,22 @@ nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void*
// nsLocalFile::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
nsILocalFile,
nsIFile,
nsILocalFileOS2,
nsIHashable)
NS_IMPL_THREADSAFE_ADDREF(nsLocalFile)
NS_IMPL_THREADSAFE_RELEASE(nsLocalFile)
NS_IMPL_QUERY_INTERFACE5_CI(nsLocalFile,
nsILocalFile,
nsIFile,
nsILocalFileOS2,
nsIHashable,
nsIClassInfo)
NS_IMPL_CI_INTERFACE_GETTER4(nsLocalFile,
nsILocalFile,
nsIFile,
nsILocalFileOS2,
nsIHashable)
NS_DECL_CLASSINFO(nsLocalFile)
NS_IMPL_THREADSAFE_CI(nsLocalFile)
//-----------------------------------------------------------------------------

Просмотреть файл

@ -56,6 +56,7 @@
#include "nsIFactory.h"
#include "nsILocalFileOS2.h"
#include "nsIHashable.h"
#include "nsIClassInfoImpl.h"
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
@ -72,7 +73,9 @@
class TypeEaEnumerator;
class NS_COM nsLocalFile : public nsILocalFileOS2,
public nsIHashable
public nsIHashable,
public nsIClassInfo
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
@ -96,6 +99,9 @@ public:
// nsIHashable interface
NS_DECL_NSIHASHABLE
// nsIClassInfo interface
NS_DECL_NSICLASSINFO
public:
static void GlobalInit();
static void GlobalShutdown();

Просмотреть файл

@ -48,6 +48,8 @@
#include "nsISimpleEnumerator.h"
#include "nsITimelineService.h"
#include "nsVoidArray.h"
#include "nsIClassInfoImpl.h"
#include "nsIProgrammingLanguage.h"
#include "plbase64.h"
#include "prmem.h"
@ -345,12 +347,23 @@ nsLocalFile::~nsLocalFile()
#pragma mark -
#pragma mark [nsISupports]
NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
nsILocalFileMac,
nsILocalFile,
nsIFile,
nsIHashable)
NS_IMPL_THREADSAFE_ADDREF(nsLocalFile)
NS_IMPL_THREADSAFE_RELEASE(nsLocalFile)
NS_IMPL_QUERY_INTERFACE5_CI(nsLocalFile,
nsILocalFileMac,
nsILocalFile,
nsIFile,
nsIHashable,
nsIClassInfo)
NS_IMPL_CI_INTERFACE_GETTER4(nsLocalFile,
nsILocalFileMac,
nsILocalFile,
nsIFile,
nsIHashable)
NS_DECL_CLASSINFO(nsLocalFile)
NS_IMPL_THREADSAFE_CI(nsLocalFile)
NS_METHOD nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
NS_ENSURE_ARG_POINTER(aInstancePtr);

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsILocalFileMac.h"
#include "nsString.h"
#include "nsIHashable.h"
#include "nsIClassInfoImpl.h"
class nsDirEnumerator;
@ -57,7 +58,8 @@ class nsDirEnumerator;
//*****************************************************************************
class NS_COM nsLocalFile : public nsILocalFileMac,
public nsIHashable
public nsIHashable,
public nsIClassInfo
{
friend class nsDirEnumerator;
@ -73,6 +75,7 @@ public:
NS_DECL_NSILOCALFILE
NS_DECL_NSILOCALFILEMAC
NS_DECL_NSIHASHABLE
NS_DECL_NSICLASSINFO
public:

Просмотреть файл

@ -81,6 +81,7 @@
#include "nsIDirectoryEnumerator.h"
#include "nsISimpleEnumerator.h"
#include "nsITimelineService.h"
#include "nsIProgrammingLanguage.h"
#include "nsNativeCharsetUtils.h"
#include "nsTraceRefcntImpl.h"
@ -253,10 +254,20 @@ nsLocalFile::nsLocalFile(const nsLocalFile& other)
{
}
NS_IMPL_THREADSAFE_ISUPPORTS3(nsLocalFile,
nsIFile,
nsILocalFile,
nsIHashable)
NS_IMPL_THREADSAFE_ADDREF(nsLocalFile)
NS_IMPL_THREADSAFE_RELEASE(nsLocalFile)
NS_IMPL_QUERY_INTERFACE4_CI(nsLocalFile,
nsILocalFile,
nsIFile,
nsIHashable,
nsIClassInfo)
NS_IMPL_CI_INTERFACE_GETTER3(nsLocalFile,
nsILocalFile,
nsIFile,
nsIHashable)
NS_DECL_CLASSINFO(nsLocalFile)
NS_IMPL_THREADSAFE_CI(nsLocalFile)
nsresult
nsLocalFile::nsLocalFileConstructor(nsISupports *outer,

Просмотреть файл

@ -52,6 +52,7 @@
#include "nsString.h"
#include "nsReadableUtils.h"
#include "nsIHashable.h"
#include "nsIClassInfoImpl.h"
/**
* we need these for statfs()
@ -82,7 +83,8 @@
#endif
class NS_COM nsLocalFile : public nsILocalFile,
public nsIHashable
public nsIHashable,
public nsIClassInfo
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
@ -103,6 +105,9 @@ public:
// nsIHashable
NS_DECL_NSIHASHABLE
// nsIClassInfo
NS_DECL_NSICLASSINFO
public:
static void GlobalInit();
static void GlobalShutdown();

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsLocalFile.h"
#include "nsIDirectoryEnumerator.h"
#include "nsNativeCharsetUtils.h"
#include "nsIProgrammingLanguage.h"
#include "nsISimpleEnumerator.h"
#include "nsIComponentManager.h"
@ -746,11 +747,22 @@ nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void*
// nsLocalFile::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
nsILocalFile,
nsIFile,
nsILocalFileWin,
nsIHashable)
NS_IMPL_THREADSAFE_ADDREF(nsLocalFile)
NS_IMPL_THREADSAFE_RELEASE(nsLocalFile)
NS_IMPL_QUERY_INTERFACE5_CI(nsLocalFile,
nsILocalFile,
nsIFile,
nsILocalFileWin,
nsIHashable,
nsIClassInfo)
NS_IMPL_CI_INTERFACE_GETTER4(nsLocalFile,
nsILocalFile,
nsIFile,
nsILocalFileWin,
nsIHashable)
NS_DECL_CLASSINFO(nsLocalFile)
NS_IMPL_THREADSAFE_CI(nsLocalFile)
//-----------------------------------------------------------------------------

Просмотреть файл

@ -49,6 +49,7 @@
#include "nsIFactory.h"
#include "nsILocalFileWin.h"
#include "nsIHashable.h"
#include "nsIClassInfoImpl.h"
#include "windows.h"
@ -63,7 +64,8 @@ DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
#include <sys/stat.h>
class nsLocalFile : public nsILocalFileWin,
public nsIHashable
public nsIHashable,
public nsIClassInfo
{
public:
NS_DEFINE_STATIC_CID_ACCESSOR(NS_LOCAL_FILE_CID)
@ -87,6 +89,9 @@ public:
// nsIHashable interface
NS_DECL_NSIHASHABLE
// nsIClassInfo interface
NS_DECL_NSICLASSINFO
public:
static void GlobalInit();
static void GlobalShutdown();

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -36,67 +36,335 @@
* ***** END LICENSE BLOCK ***** */
#include "nsScriptableInputStream.h"
#include "nsIProgrammingLanguage.h"
#include "nsAutoPtr.h"
#include "nsMemory.h"
#include "nsString.h"
#include "nsIUnicharLineInputStream.h"
#include "nsIClassInfoImpl.h"
NS_IMPL_ISUPPORTS1(nsScriptableInputStream, nsIScriptableInputStream)
// needed for NS_SWAP macros
#include "nsIStreamBufferAccess.h"
NS_IMPL_THREADSAFE_ADDREF(nsScriptableInputStream)
NS_IMPL_THREADSAFE_RELEASE(nsScriptableInputStream)
NS_IMPL_QUERY_INTERFACE5_CI(nsScriptableInputStream,
nsIInputStream,
nsIScriptableInputStream,
nsIScriptableIOInputStream,
nsISeekableStream,
nsIMultiplexInputStream)
NS_IMPL_CI_INTERFACE_GETTER5(nsScriptableInputStream,
nsIInputStream,
nsIScriptableInputStream,
nsIScriptableIOInputStream,
nsISeekableStream,
nsIMultiplexInputStream)
// nsIBaseStream methods
NS_IMETHODIMP
nsScriptableInputStream::Close(void) {
if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
nsScriptableInputStream::Close(void)
{
if (mUnicharInputStream)
return mUnicharInputStream->Close();
if (mInputStream)
return mInputStream->Close();
return NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsScriptableInputStream::InitWithStreams(nsIInputStream *aInputStream,
nsIUnicharInputStream *aCharStream)
{
NS_ENSURE_ARG(aInputStream);
mInputStream = aInputStream;
mUnicharInputStream = aCharStream;
return NS_OK;
}
// nsIScriptableInputStream methods
NS_IMETHODIMP
nsScriptableInputStream::Init(nsIInputStream *aInputStream) {
if (!aInputStream) return NS_ERROR_NULL_POINTER;
mInputStream = aInputStream;
return NS_OK;
nsScriptableInputStream::Init(nsIInputStream *aInputStream)
{
NS_ENSURE_ARG(aInputStream);
mInputStream = aInputStream;
mUnicharInputStream = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsScriptableInputStream::Available(PRUint32 *_retval) {
if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
return mInputStream->Available(_retval);
nsScriptableInputStream::Available(PRUint32 *aIsAvailable)
{
NS_ENSURE_TRUE(mInputStream, NS_ERROR_NOT_INITIALIZED);
nsresult rv = mInputStream->Available(aIsAvailable);
NS_ENSURE_SUCCESS(rv, rv);
// if there is no data left in the stream, check if the character stream
// has more text available. This is needed because the unichar stream
// will read a buffer from the input stream, leaving it with no remaining
// data, yet there is still text to read
if (!*aIsAvailable && mUnicharInputStream)
*aIsAvailable = mUnicharInputStreamHasMore;
return NS_OK;
}
NS_IMETHODIMP
nsScriptableInputStream::Read(PRUint32 aCount, char **_retval) {
nsresult rv = NS_OK;
PRUint32 count = 0;
char *buffer = nsnull;
nsScriptableInputStream::Read(PRUint32 aCount, char **_retval)
{
nsresult rv = NS_OK;
PRUint32 count = 0;
char *buffer = nsnull;
if (!mInputStream) return NS_ERROR_NOT_INITIALIZED;
NS_ENSURE_TRUE(mInputStream, NS_ERROR_NOT_INITIALIZED);
rv = mInputStream->Available(&count);
if (NS_FAILED(rv)) return rv;
rv = mInputStream->Available(&count);
if (NS_FAILED(rv))
return rv;
count = PR_MIN(count, aCount);
buffer = (char*)nsMemory::Alloc(count+1); // make room for '\0'
if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
count = PR_MIN(count, aCount);
buffer = (char*)NS_Alloc(count+1); // make room for '\0'
NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
PRUint32 amtRead = 0;
rv = mInputStream->Read(buffer, count, &amtRead);
if (NS_FAILED(rv)) {
nsMemory::Free(buffer);
return rv;
}
PRUint32 amtRead = 0;
rv = mInputStream->Read(buffer, count, &amtRead);
if (NS_FAILED(rv)) {
NS_Free(buffer);
return rv;
}
buffer[amtRead] = '\0';
*_retval = buffer;
buffer[amtRead] = '\0';
*_retval = buffer;
return NS_OK;
}
// nsIInputStream methods
NS_IMETHODIMP
nsScriptableInputStream::IsNonBlocking(PRBool *aIsNonBlocking)
{
NS_ENSURE_TRUE(mInputStream, NS_ERROR_NOT_INITIALIZED);
return mInputStream->IsNonBlocking(aIsNonBlocking);
}
NS_IMETHODIMP
nsScriptableInputStream::Read(char* aData,
PRUint32 aCount,
PRUint32 *aReadCount)
{
if (mUnicharInputStream) {
// XXXndeakin implement this
return NS_OK;
}
if (mInputStream)
return mInputStream->Read(aData, aCount, aReadCount);
return NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsScriptableInputStream::ReadSegments(nsWriteSegmentFun aFn,
void* aClosure,
PRUint32 aCount,
PRUint32 *aReadCount)
{
NS_ENSURE_TRUE(mInputStream, NS_ERROR_NOT_INITIALIZED);
return mInputStream->ReadSegments(aFn, aClosure, aCount, aReadCount);
}
NS_IMETHODIMP
nsScriptableInputStream::ReadString(PRUint32 aCount, nsAString& aString)
{
if (mUnicharInputStream) {
PRUint32 readCount;
nsresult rv = mUnicharInputStream->ReadString(aCount, aString, &readCount);
NS_ENSURE_SUCCESS(rv, rv);
// If less characters are read than requested, then assume that the end
// of the file has been reached.
// XXXndeakin or it could be because the buffer is full
mUnicharInputStreamHasMore = (aCount == readCount);
return NS_OK;
}
// just call Read and convert to UTF-16
nsXPIDLCString cstr;
nsresult rv = Read(aCount, getter_Copies(cstr));
NS_ENSURE_SUCCESS(rv, rv);
aString.Assign(NS_ConvertASCIItoUTF16(cstr));
return NS_OK;
}
NS_IMETHODIMP
nsScriptableInputStream::ReadLine(nsAString& aLine)
{
nsCOMPtr<nsIUnicharLineInputStream> cstream = do_QueryInterface(mUnicharInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->ReadLine(aLine, &mUnicharInputStreamHasMore);
}
NS_IMETHODIMP
nsScriptableInputStream::ReadBoolean(PRBool* aBoolean)
{
PRUint8 byteResult;
nsresult rv = Read8(&byteResult);
*aBoolean = byteResult;
return rv;
}
NS_IMETHODIMP
nsScriptableInputStream::Read8(PRUint8* aVal)
{
return ReadFully(sizeof *aVal, NS_REINTERPRET_CAST(char*, aVal));
}
NS_IMETHODIMP
nsScriptableInputStream::Read16(PRUint16* aVal)
{
nsresult rv = ReadFully(sizeof *aVal, NS_REINTERPRET_CAST(char*, aVal));
NS_ENSURE_SUCCESS(rv, rv);
*aVal = NS_SWAP16(*aVal);
return NS_OK;
}
NS_IMETHODIMP
nsScriptableInputStream::Read32(PRUint32* aVal)
{
nsresult rv = ReadFully(sizeof *aVal, NS_REINTERPRET_CAST(char*, aVal));
NS_ENSURE_SUCCESS(rv, rv);
*aVal = NS_SWAP32(*aVal);
return NS_OK;
}
NS_IMETHODIMP
nsScriptableInputStream::ReadFloat(float* aFloat)
{
NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
"False assumption about sizeof(float)");
return Read32(NS_REINTERPRET_CAST(PRUint32*, aFloat));
}
NS_IMETHODIMP
nsScriptableInputStream::ReadDouble(double* aDouble)
{
NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
"False assumption about sizeof(double)");
nsresult rv = ReadFully(sizeof(double), NS_REINTERPRET_CAST(char*, aDouble));
NS_ENSURE_SUCCESS(rv, rv);
PRUint64 i = NS_SWAP64(*NS_REINTERPRET_CAST(PRUint64*, aDouble));
*aDouble = *NS_REINTERPRET_CAST(double*, &i);
return NS_OK;
}
NS_IMETHODIMP
nsScriptableInputStream::ReadByteArray(PRUint32 aCount, PRUint8 **aBytes)
{
char* s = NS_REINTERPRET_CAST(char*, NS_Alloc(aCount));
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
PRUint32 bytesRead;
nsresult rv = mInputStream->Read(s, aCount, &bytesRead);
if (NS_FAILED(rv)) {
NS_Free(s);
return rv;
}
if (bytesRead != aCount) {
NS_Free(s);
return NS_ERROR_FAILURE;
}
*aBytes = (PRUint8 *)s;
return NS_OK;
}
nsresult
nsScriptableInputStream::ReadFully(PRUint32 aCount, char* aBuf)
{
PRUint32 bytesRead;
nsresult rv = Read(aBuf, aCount, &bytesRead);
NS_ENSURE_SUCCESS(rv, rv);
return (bytesRead != aCount) ? NS_ERROR_FAILURE : NS_OK;
}
// nsISeekableStream
NS_IMETHODIMP
nsScriptableInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
nsCOMPtr<nsISeekableStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
nsScriptableInputStream::Tell(PRInt64* aOffset)
{
nsCOMPtr<nsISeekableStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->Tell(aOffset);
}
NS_IMETHODIMP
nsScriptableInputStream::SetEOF()
{
nsCOMPtr<nsISeekableStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->SetEOF();
}
// nsIMultiplexInputStream
NS_IMETHODIMP
nsScriptableInputStream::GetCount(PRUint32* aCount)
{
nsCOMPtr<nsIMultiplexInputStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->GetCount(aCount);
}
NS_IMETHODIMP
nsScriptableInputStream::GetStream(PRUint32 aIndex, nsIInputStream** aStream)
{
nsCOMPtr<nsIMultiplexInputStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->GetStream(aIndex, aStream);
}
NS_IMETHODIMP
nsScriptableInputStream::AppendStream(nsIInputStream* aStream)
{
nsCOMPtr<nsIMultiplexInputStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->AppendStream(aStream);
}
NS_IMETHODIMP
nsScriptableInputStream::InsertStream(nsIInputStream* aStream, PRUint32 aIndex)
{
nsCOMPtr<nsIMultiplexInputStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->InsertStream(aStream, aIndex);
}
NS_IMETHODIMP
nsScriptableInputStream::RemoveStream(PRUint32 aIndex)
{
nsCOMPtr<nsIMultiplexInputStream> cstream = do_QueryInterface(mInputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->RemoveStream(aIndex);
}
NS_METHOD
nsScriptableInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
if (aOuter) return NS_ERROR_NO_AGGREGATION;
nsScriptableInputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
if (aOuter) return NS_ERROR_NO_AGGREGATION;
nsScriptableInputStream *sis = new nsScriptableInputStream();
if (!sis) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(sis);
nsresult rv = sis->QueryInterface(aIID, aResult);
NS_RELEASE(sis);
return rv;
nsRefPtr<nsScriptableInputStream> sis = new nsScriptableInputStream();
NS_ENSURE_TRUE(sis, NS_ERROR_OUT_OF_MEMORY);
return sis->QueryInterface(aIID, aResult);
}

Просмотреть файл

@ -39,7 +39,11 @@
#define ___nsscriptableinputstream___h_
#include "nsIScriptableInputStream.h"
#include "nsIScriptableStreams.h"
#include "nsIInputStream.h"
#include "nsISeekableStream.h"
#include "nsIMultiplexInputStream.h"
#include "nsIUnicharInputStream.h"
#include "nsCOMPtr.h"
#define NS_SCRIPTABLEINPUTSTREAM_CID \
@ -48,16 +52,41 @@
#define NS_SCRIPTABLEINPUTSTREAM_CONTRACTID "@mozilla.org/scriptableinputstream;1"
#define NS_SCRIPTABLEINPUTSTREAM_CLASSNAME "Scriptable Input Stream"
class nsScriptableInputStream : public nsIScriptableInputStream {
class nsScriptableInputStream : public nsIScriptableInputStream,
public nsIScriptableIOInputStream,
public nsISeekableStream,
public nsIMultiplexInputStream
{
public:
// nsISupports methods
NS_DECL_ISUPPORTS
// nsIScriptableInputStream methods
NS_DECL_NSISCRIPTABLEINPUTSTREAM
// nsIScriptableIOInputStream methods
NS_DECL_NSISCRIPTABLEIOINPUTSTREAM
// nsISeekableStream methods
NS_DECL_NSISEEKABLESTREAM
// nsIMultiplexInputStream methods
NS_DECL_NSIMULTIPLEXINPUTSTREAM
// nsIInputStream and nsIScriptableInputStream methods
NS_IMETHOD Available(PRUint32 *aAvailable);
NS_IMETHOD Close();
NS_IMETHOD IsNonBlocking(PRBool *aIsNonBlocking);
NS_IMETHOD Read(char* aData,
PRUint32 aCount,
PRUint32 *aReadCount);
NS_IMETHOD ReadSegments(nsWriteSegmentFun aFn,
void* aClosure,
PRUint32 aCount,
PRUint32 *aReadCount);
NS_IMETHOD Init(nsIInputStream* aInputStream);
NS_IMETHOD Read(PRUint32 aCount, char** aData);
// nsScriptableInputStream methods
nsScriptableInputStream() {}
nsScriptableInputStream() :
mUnicharInputStreamHasMore(PR_TRUE) {}
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
@ -65,7 +94,11 @@ public:
private:
~nsScriptableInputStream() {}
nsresult ReadFully(PRUint32 aCount, char* aBuf);
PRBool mUnicharInputStreamHasMore;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsIUnicharInputStream> mUnicharInputStream;
};
#endif // ___nsscriptableinputstream___h_

Просмотреть файл

@ -0,0 +1,261 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsScriptableOutputStream.h"
#include "nsIProgrammingLanguage.h"
#include "nsAutoPtr.h"
#include "nsMemory.h"
#include "nsString.h"
#include "nsIClassInfoImpl.h"
// needed for NS_SWAP macros
#include "nsIStreamBufferAccess.h"
NS_IMPL_THREADSAFE_ADDREF(nsScriptableOutputStream)
NS_IMPL_THREADSAFE_RELEASE(nsScriptableOutputStream)
NS_IMPL_QUERY_INTERFACE3_CI(nsScriptableOutputStream,
nsIOutputStream,
nsIScriptableIOOutputStream,
nsISeekableStream)
NS_IMPL_CI_INTERFACE_GETTER3(nsScriptableOutputStream,
nsIOutputStream,
nsIScriptableIOOutputStream,
nsISeekableStream)
// nsIBaseStream methods
NS_IMETHODIMP
nsScriptableOutputStream::Close(void)
{
if (mUnicharOutputStream)
return mUnicharOutputStream->Close();
if (mOutputStream)
return mOutputStream->Close();
return NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsScriptableOutputStream::Flush(void)
{
if (mUnicharOutputStream)
return mUnicharOutputStream->Flush();
if (mOutputStream)
return mOutputStream->Flush();
return NS_ERROR_NOT_INITIALIZED;
}
// nsIScriptableIOOutputStream methods
NS_IMETHODIMP
nsScriptableOutputStream::InitWithStreams(nsIOutputStream* aOutputStream,
nsIUnicharOutputStream *aCharStream)
{
NS_ENSURE_ARG(aOutputStream);
mOutputStream = aOutputStream;
mUnicharOutputStream = aCharStream;
return NS_OK;
}
// nsIOutputStream methods
NS_IMETHODIMP
nsScriptableOutputStream::IsNonBlocking(PRBool *aIsNonBlocking)
{
if (mOutputStream)
return mOutputStream->IsNonBlocking(aIsNonBlocking);
if (mUnicharOutputStream) {
*aIsNonBlocking = PR_FALSE;
return NS_OK;
}
return NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsScriptableOutputStream::Write(const char* aBuffer, PRUint32 aCount, PRUint32 *aWriteCount)
{
if (mUnicharOutputStream) {
nsAutoString str(NS_ConvertASCIItoUTF16(aBuffer, aCount));
PRBool ok;
mUnicharOutputStream->WriteString(str, &ok);
*aWriteCount = ok ? aCount : 0;
return NS_OK;
}
if (mOutputStream)
return mOutputStream->Write(aBuffer, aCount, aWriteCount);
return NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteFrom(nsIInputStream *aStream, PRUint32 aCount, PRUint32 *aWriteCount)
{
if (mOutputStream)
return mOutputStream->WriteFrom(aStream, aCount, aWriteCount);
return NS_ERROR_NOT_INITIALIZED;
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteSegments(nsReadSegmentFun aFn,
void* aClosure,
PRUint32 aCount,
PRUint32 *aReadCount)
{
NS_ENSURE_TRUE(mOutputStream, NS_ERROR_NOT_INITIALIZED);
return mOutputStream->WriteSegments(aFn, aClosure, aCount, aReadCount);
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteString(const nsAString& aString, PRBool *aOK)
{
if (mUnicharOutputStream)
return mUnicharOutputStream->WriteString(aString, aOK);
if (!mOutputStream)
return NS_ERROR_NOT_INITIALIZED;
// just convert to ASCII and call Write
nsCAutoString cstr = NS_LossyConvertUTF16toASCII(aString);
PRUint32 count;
nsresult rv = mOutputStream->Write(cstr.get(), (PRUint32)cstr.Length(), &count);
NS_ENSURE_SUCCESS(rv, rv);
*aOK = (count == cstr.Length());
return NS_OK;
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteBoolean(PRBool aBoolean)
{
return Write8(aBoolean);
}
NS_IMETHODIMP
nsScriptableOutputStream::Write8(PRUint8 aByte)
{
return WriteFully((const char *)&aByte, sizeof aByte);
}
NS_IMETHODIMP
nsScriptableOutputStream::Write16(PRUint16 a16)
{
a16 = NS_SWAP16(a16);
return WriteFully((const char *)&a16, sizeof a16);
}
NS_IMETHODIMP
nsScriptableOutputStream::Write32(PRUint32 a32)
{
a32 = NS_SWAP32(a32);
return WriteFully((const char *)&a32, sizeof a32);
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteFloat(float aFloat)
{
NS_ASSERTION(sizeof(float) == sizeof (PRUint32),
"False assumption about sizeof(float)");
return Write32(*NS_REINTERPRET_CAST(PRUint32*, &aFloat));
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteDouble(double aDouble)
{
NS_ASSERTION(sizeof(double) == sizeof(PRUint64),
"False assumption about sizeof(double)");
PRUint64 val = NS_SWAP64(*NS_REINTERPRET_CAST(PRUint64*, &aDouble));
return WriteFully(NS_REINTERPRET_CAST(char*, &val), sizeof val);
}
NS_IMETHODIMP
nsScriptableOutputStream::WriteByteArray(PRUint8 *aBytes, PRUint32 aCount)
{
return WriteFully((char *)aBytes, aCount);
}
nsresult
nsScriptableOutputStream::WriteFully(const char *aBuf, PRUint32 aCount)
{
NS_ENSURE_TRUE(mOutputStream, NS_ERROR_NOT_INITIALIZED);
PRUint32 bytesWritten;
nsresult rv = mOutputStream->Write(aBuf, aCount, &bytesWritten);
NS_ENSURE_SUCCESS(rv, rv);
return (bytesWritten != aCount) ? NS_ERROR_FAILURE : NS_OK;
}
// nsISeekableStream
NS_IMETHODIMP
nsScriptableOutputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
nsCOMPtr<nsISeekableStream> cstream = do_QueryInterface(mOutputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->Seek(aWhence, aOffset);
}
NS_IMETHODIMP
nsScriptableOutputStream::Tell(PRInt64* aOffset)
{
nsCOMPtr<nsISeekableStream> cstream = do_QueryInterface(mOutputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->Tell(aOffset);
}
NS_IMETHODIMP
nsScriptableOutputStream::SetEOF()
{
nsCOMPtr<nsISeekableStream> cstream = do_QueryInterface(mOutputStream);
NS_ENSURE_TRUE(cstream, NS_ERROR_NOT_AVAILABLE);
return cstream->SetEOF();
}
NS_METHOD
nsScriptableOutputStream::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
if (aOuter) return NS_ERROR_NO_AGGREGATION;
nsRefPtr<nsScriptableOutputStream> sos = new nsScriptableOutputStream();
NS_ENSURE_TRUE(sos, NS_ERROR_OUT_OF_MEMORY);
return sos->QueryInterface(aIID, aResult);
}

Просмотреть файл

@ -0,0 +1,85 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef ___nsscriptableoutputstream___h_
#define ___nsscriptableoutputstream___h_
#include "nsIScriptableStreams.h"
#include "nsIOutputStream.h"
#include "nsISeekableStream.h"
#include "nsIUnicharOutputStream.h"
#include "nsCOMPtr.h"
#define NS_SCRIPTABLEOUTPUTSTREAM_CID \
{ 0xaea1cfe2, 0xf727, 0x4b94, { 0x93, 0xff, 0x41, 0x8d, 0x96, 0x87, 0x94, 0xd1 } }
#define NS_SCRIPTABLEOUTPUTSTREAM_CONTRACTID "@mozilla.org/scriptableoutputstream;1"
#define NS_SCRIPTABLEOUTPUTSTREAM_CLASSNAME "Scriptable Output Stream"
class nsScriptableOutputStream : public nsIScriptableIOOutputStream,
public nsISeekableStream,
public nsIOutputStream
{
public:
// nsISupports methods
NS_DECL_ISUPPORTS
// nsIOutputStream methods
NS_DECL_NSIOUTPUTSTREAM
// nsIScriptableIOOutputStream methods
NS_DECL_NSISCRIPTABLEIOOUTPUTSTREAM
// nsISeekableStream methods
NS_DECL_NSISEEKABLESTREAM
// nsScriptableOutputStream methods
nsScriptableOutputStream() {}
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
private:
~nsScriptableOutputStream() {}
nsresult WriteFully(const char *aBuf, PRUint32 aCount);
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsIUnicharOutputStream> mUnicharOutputStream;
};
#endif // ___nsscriptableoutputstream___h_