zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #24806
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
Paul J. Lucas has proposed merging lp:~zorba-coders/zorba/bug-942171 into lp:zorba.
Commit message:
Added arbitrary encoding support.
Added missing functions from spec.
Requested reviews:
Paul J. Lucas (paul-lucas)
Related bugs:
Bug #942171 in Zorba: "file module to allow for arbitrary encodings"
https://bugs.launchpad.net/zorba/+bug/942171
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-942171/+merge/178637
Added arbitrary encoding support.
Added missing functions from spec.
--
https://code.launchpad.net/~zorba-coders/zorba/bug-942171/+merge/178637
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog 2013-08-02 14:56:12 +0000
+++ ChangeLog 2013-08-05 22:16:26 +0000
@@ -28,6 +28,7 @@
* Fixed bug #1189636 (transcoding hexBinary streambuf)
* Fixed bug in hoisting through try-catch expr
* Fixed bug #1162631 (format-integer 'w' format of negative numbers)
+ * Fixed bug #942171 (file module to allow for arbitrary encodings)
* Fixed bug #1192285 (Have JSON token know number subtype)
* Fixed bug #1190261 (relative paths bug in file module)
* Fixed bug #1189798 (Update core module "errors")
=== modified file 'include/zorba/util/base64_stream.h'
--- include/zorba/util/base64_stream.h 2013-06-19 23:15:33 +0000
+++ include/zorba/util/base64_stream.h 2013-08-05 22:16:26 +0000
@@ -29,8 +29,8 @@
///////////////////////////////////////////////////////////////////////////////
/**
- * A %base64::streambuf is-a std::streambuf for encoding to and decoding from
- * Base64 on-the-fly.
+ * A %base64::streambuf is-a std::streambuf for decoding from and encoding to
+ * Base64 on-the-fly while reading or writing, respectively.
*
* To use it, replace a stream's streambuf:
* \code
@@ -149,9 +149,10 @@
* @param ios The stream to attach the base64::streambuf to. If the stream
* already has a base64::streambuf attached to it, this function does
* nothing.
+ * @return \c true only if a base64::streambuf was attached.
*/
template<typename charT,class Traits> inline
-void attach( std::basic_ios<charT,Traits> &ios ) {
+bool attach( std::basic_ios<charT,Traits> &ios ) {
int const index = internal::base64::get_streambuf_index();
void *&pword = ios.pword( index );
if ( !pword ) {
@@ -160,7 +161,9 @@
ios.rdbuf( buf );
pword = buf;
ios.register_callback( internal::stream_callback, index );
+ return true;
}
+ return false;
}
/**
@@ -170,15 +173,18 @@
* @param ios The stream to detach the base64::streambuf from. If the
* stream doesn't have a base64::streambuf attached to it, this function
* does nothing.
+ * @return \c true only if a base64::streambuf was detached.
*/
template<typename charT,class Traits> inline
-void detach( std::basic_ios<charT,Traits> &ios ) {
+bool detach( std::basic_ios<charT,Traits> &ios ) {
int const index = internal::base64::get_streambuf_index();
if ( streambuf *const buf = static_cast<streambuf*>( ios.pword( index ) ) ) {
ios.pword( index ) = nullptr;
ios.rdbuf( buf->orig_streambuf() );
internal::dealloc_streambuf( buf );
+ return true;
}
+ return false;
}
/**
@@ -210,26 +216,82 @@
class auto_attach {
public:
/**
+ * Default constructor; does nothing.
+ */
+ auto_attach() : stream_( 0 ) {
+ }
+
+ /**
* Constructs an %auto_attach object calling attach() on the given stream.
*
* @param stream The stream to attach the base64::streambuf to. If the
* stream already has a base64::streambuf attached to it, this contructor
* does nothing.
*/
- auto_attach( StreamType &stream ) : stream_( stream ) {
- attach( stream );
+ auto_attach( StreamType &stream ) : stream_( &stream ) {
+ base64::attach( stream );
+ }
+
+ /**
+ * Copy constructor that takes ownership of the stream.
+ *
+ * @param from The %auto_attach to take ownership from.
+ */
+ auto_attach( auto_attach &from ) : stream_( from.stream_ ) {
+ from.stream_ = 0;
}
/**
* Destroys this %auto_attach object calling detach() on the previously
- * attached stream.
+ * attached stream, if any.
*/
~auto_attach() {
- detach( stream_ );
+ detach();
+ }
+
+ /**
+ * Assignment operator that takes ownership of the stream.
+ *
+ * @param from The %auto_attach to take ownership from.
+ * @return \c *this.
+ */
+ auto_attach& operator=( auto_attach &from ) {
+ if ( &from != this ) {
+ stream_ = from.stream_;
+ from.stream_ = 0;
+ }
+ return *this;
+ }
+
+ /**
+ * Calls base64::attach() on the given stream.
+ *
+ * @param stream The stream to attach the base64::streambuf to. If the
+ * stream already has a base64::streambuf attached to it, this contructor
+ * does nothing.
+ * @param charset The name of the character encoding to convert from/to.
+ * @return \c true only if a base64::streambuf was attached.
+ */
+ bool attach( StreamType &stream, char const *charset ) {
+ if ( base64::attach( stream, charset ) ) {
+ stream_ = &stream;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Calls base64::detach().
+ */
+ void detach() {
+ if ( stream_ ) {
+ base64::detach( *stream_ );
+ stream_ = 0;
+ }
}
private:
- StreamType &stream_;
+ StreamType *stream_;
};
///////////////////////////////////////////////////////////////////////////////
=== modified file 'include/zorba/util/fs_util.h'
--- include/zorba/util/fs_util.h 2013-08-02 14:55:29 +0000
+++ include/zorba/util/fs_util.h 2013-08-05 22:16:26 +0000
@@ -47,9 +47,11 @@
#ifdef WIN32
char const dir_separator = '\\';
char const path_separator = ';';
+char const newline[] = "\r\n";
#else
char const dir_separator = '/';
char const path_separator = ':';
+char const newline[] = "\n";
#endif /* WIN32 */
////////// types //////////////////////////////////////////////////////////////
@@ -74,7 +76,6 @@
volume,
other // named pipe, character/block special, socket, etc.
};
-extern char const *const type_string[];
/**
* Emits the string representation of a file type to the given ostream.
@@ -83,9 +84,8 @@
* @param t The file type to emit.
* @return Returns \a o.
*/
-inline std::ostream& operator<<( std::ostream &o, type t ) {
- return o << type_string[ t ];
-}
+ZORBA_DLL_PUBLIC
+std::ostream& operator<<( std::ostream &o, type t );
////////// Directory //////////////////////////////////////////////////////////
=== modified file 'include/zorba/util/hexbinary_stream.h'
--- include/zorba/util/hexbinary_stream.h 2013-06-20 00:53:29 +0000
+++ include/zorba/util/hexbinary_stream.h 2013-08-05 22:16:26 +0000
@@ -133,9 +133,10 @@
* @param ios The stream to attach the hexbinary::streambuf to. If the stream
* already has a hexbinary::streambuf attached to it, this function does
* nothing.
+ * @return \c true only if a hexbinary::streambuf was attached.
*/
template<typename charT,class Traits> inline
-void attach( std::basic_ios<charT,Traits> &ios ) {
+bool attach( std::basic_ios<charT,Traits> &ios ) {
int const index = internal::hexbinary::get_streambuf_index();
void *&pword = ios.pword( index );
if ( !pword ) {
@@ -144,7 +145,9 @@
ios.rdbuf( buf );
pword = buf;
ios.register_callback( internal::stream_callback, index );
+ return true;
}
+ return false;
}
/**
@@ -154,15 +157,18 @@
* @param ios The stream to detach the hexbinary::streambuf from. If the
* stream doesn't have a hexbinary::streambuf attached to it, this function
* does nothing.
+ * @return \c true only if a hexbinary::streambuf was detached.
*/
template<typename charT,class Traits> inline
-void detach( std::basic_ios<charT,Traits> &ios ) {
+bool detach( std::basic_ios<charT,Traits> &ios ) {
int const index = internal::hexbinary::get_streambuf_index();
if ( streambuf *const buf = static_cast<streambuf*>( ios.pword( index ) ) ) {
ios.pword( index ) = nullptr;
ios.rdbuf( buf->orig_streambuf() );
internal::dealloc_streambuf( buf );
+ return true;
}
+ return false;
}
/**
@@ -194,26 +200,81 @@
class auto_attach {
public:
/**
+ * Default constructor; does nothing.
+ */
+ auto_attach() : stream_( 0 ) {
+ }
+
+ /**
* Constructs an %auto_attach object calling attach() on the given stream.
*
* @param stream The stream to attach the hexbinary::streambuf to. If the
* stream already has a hexbinary::streambuf attached to it, this contructor
* does nothing.
*/
- auto_attach( StreamType &stream ) : stream_( stream ) {
+ auto_attach( StreamType &stream ) : stream_( &stream ) {
attach( stream );
}
/**
+ * Copy constructor that takes ownership of the stream.
+ *
+ * @param from The %auto_attach to take ownership from.
+ */
+ auto_attach( auto_attach &from ) : stream_( from.stream_ ) {
+ from.stream_ = 0;
+ }
+
+ /**
* Destroys this %auto_attach object calling detach() on the previously
* attached stream.
*/
~auto_attach() {
- detach( stream_ );
+ detach();
+ }
+
+ /**
+ * Assignment operator that takes ownership of the stream.
+ *
+ * @param from The %auto_attach to take ownership from.
+ * @return \c *this.
+ */
+ auto_attach& operator=( auto_attach &from ) {
+ if ( &from != this ) {
+ stream_ = from.stream_;
+ from.stream_ = 0;
+ }
+ return *this;
+ }
+
+ /**
+ * Calls hexbinary::attach() on the given stream.
+ *
+ * @param stream The stream to attach the hexbinary::streambuf to. If the
+ * stream already has a hexbinary::streambuf attached to it, this contructor
+ * does nothing.
+ * @return \c true only if a hexbinary::streambuf was attached.
+ */
+ bool attach( StreamType &stream ) {
+ if ( hexbinary::attach( stream ) ) {
+ stream_ = &stream;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Calls hexbinary::detach().
+ */
+ void detach() {
+ if ( stream_ ) {
+ hexbinary::detach( *stream_ );
+ stream_ = 0;
+ }
}
private:
- StreamType &stream_;
+ StreamType *stream_;
};
///////////////////////////////////////////////////////////////////////////////
=== modified file 'include/zorba/util/transcode_stream.h'
--- include/zorba/util/transcode_stream.h 2013-06-12 00:21:05 +0000
+++ include/zorba/util/transcode_stream.h 2013-08-05 22:16:26 +0000
@@ -139,9 +139,10 @@
* already has a transcode::streambuf attached to it, this function does
* nothing.
* @param charset The name of the character encoding to convert from/to.
+ * @return \c true only if a transcode::streambuf was attached.
*/
template<typename charT,class Traits> inline
-void attach( std::basic_ios<charT,Traits> &ios, char const *charset ) {
+bool attach( std::basic_ios<charT,Traits> &ios, char const *charset ) {
int const index = internal::transcode::get_streambuf_index();
void *&pword = ios.pword( index );
if ( !pword ) {
@@ -150,7 +151,9 @@
ios.rdbuf( buf );
pword = buf;
ios.register_callback( internal::stream_callback, index );
+ return true;
}
+ return false;
}
/**
@@ -160,15 +163,18 @@
* @param ios The stream to detach the transcode::streambuf from. If the
* stream doesn't have a transcode::streambuf attached to it, this function
* does nothing.
+ * @return \c true only if a transcode::streambuf was detached.
*/
template<typename charT,class Traits> inline
-void detach( std::basic_ios<charT,Traits> &ios ) {
+bool detach( std::basic_ios<charT,Traits> &ios ) {
int const index = internal::transcode::get_streambuf_index();
if ( streambuf *const buf = static_cast<streambuf*>( ios.pword( index ) ) ) {
ios.pword( index ) = nullptr;
ios.rdbuf( buf->orig_streambuf() );
internal::dealloc_streambuf( buf );
+ return true;
}
+ return false;
}
/**
@@ -214,6 +220,12 @@
class auto_attach {
public:
/**
+ * Default constructor; does nothing.
+ */
+ auto_attach() : stream_( 0 ) {
+ }
+
+ /**
* Constructs an %auto_attach object calling attach() on the given stream.
*
* @param stream The stream to attach the transcode::streambuf to. If the
@@ -221,20 +233,70 @@
* does nothing.
* @param charset The name of the character encoding to convert from/to.
*/
- auto_attach( StreamType &stream, char const *charset ) : stream_( stream ) {
- attach( stream, charset );
+ auto_attach( StreamType &stream, char const *charset ) : stream_( &stream ) {
+ transcode::attach( stream, charset );
+ }
+
+ /**
+ * Copy constructor that takes ownership of the stream.
+ *
+ * @param from The %auto_attach to take ownership from.
+ */
+ auto_attach( auto_attach &from ) : stream_( from.stream_ ) {
+ from.stream_ = 0;
}
/**
* Destroys this %auto_attach object calling detach() on the previously
- * attached stream.
+ * attached stream, if any.
*/
~auto_attach() {
- detach( stream_ );
+ detach();
+ }
+
+ /**
+ * Assignment operator that takes ownership of the stream.
+ *
+ * @param from The %auto_attach to take ownership from.
+ * @return \c *this.
+ */
+ auto_attach& operator=( auto_attach &from ) {
+ if ( &from != this ) {
+ stream_ = from.stream_;
+ from.stream_ = 0;
+ }
+ return *this;
+ }
+
+ /**
+ * Calls transcode::attach() on the given stream.
+ *
+ * @param stream The stream to attach the transcode::streambuf to. If the
+ * stream already has a transcode::streambuf attached to it, this contructor
+ * does nothing.
+ * @param charset The name of the character encoding to convert from/to.
+ * @return \c true only if a transcode::streambuf was attached.
+ */
+ bool attach( StreamType &stream, char const *charset ) {
+ if ( transcode::attach( stream, charset ) ) {
+ stream_ = &stream;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Calls transcode::detach().
+ */
+ void detach() {
+ if ( stream_ ) {
+ transcode::detach( *stream_ );
+ stream_ = 0;
+ }
}
private:
- StreamType &stream_;
+ StreamType *stream_;
};
///////////////////////////////////////////////////////////////////////////////
=== modified file 'modules/org/expath/ns/file.xq'
--- modules/org/expath/ns/file.xq 2013-06-15 20:57:44 +0000
+++ modules/org/expath/ns/file.xq 2013-08-05 22:16:26 +0000
@@ -1,7 +1,7 @@
xquery version "3.0";
(:
- : Copyright 2006-2009 The FLWOR Foundation.
+ : Copyright 2006-2013 The FLWOR Foundation.
:
: Licensed under the Apache License, Version 2.0 (the "License");
: you may not use this file except in compliance with the License.
@@ -24,68 +24,128 @@
:)
module namespace file = "http://expath.org/ns/file";
-import schema namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace an = "http://www.zorba-xquery.com/annotations";
declare namespace ver = "http://www.zorba-xquery.com/options/versioning";
declare option ver:module-version "2.0";
(:~
- : Appends a sequence of items to a file. If the file pointed by <pre>$file</pre>
- : does not exist, a new file will be created. Before writing to the file, the items
- : are serialized according to the <pre>$serializer-params</pre>.
- :
- : The semantics of <pre>$serializer-params</pre> is the same as for the
- : <pre>$params</pre> parameter of the <a target="_blank"
- : href="http://www.w3.org/TR/xpath-functions-11/#func-serialize">fn:serialize</a>
- : function.
- :
- : @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @param $serializer-params Parameter to control the serialization of the
- : content.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:sequential function file:append(
- $file as xs:string,
- $content as item()*,
- $serializer-params as element(output:serialization-parameters)?
-) as empty-sequence()
-{
- file:append-text(
- $file,
- fn:serialize($content, $serializer-params))
-};
-
-(:~
: Appends a sequence of Base64 items as binary to a file. If the file pointed
: by <pre>$file</pre> does not exist, a new file will be created.
:
: @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:sequential function file:append-binary(
- $file as xs:string,
- $content as xs:base64Binary*
-) as empty-sequence() external;
-
-(:~
- : Appends a sequence of string items to a file.
- :
- : @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %private %an:sequential function file:append-text(
- $file as xs:string,
- $content as xs:string*
-) as empty-sequence() external;
+ : @param $content The content to be written to the file.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:append-binary( $file as xs:string, $content as xs:base64Binary )
+ as empty-sequence() external;
+
+(:~
+ : Appends a sequence of string items to a file.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @param $encoding The character encoding to append <code>$content</code> as.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:append-text( $file as xs:string, $content as xs:string*,
+ $encoding as xs:string )
+ as empty-sequence() external;
+
+(:~
+ : Appends a sequence of string items to a file.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:append-text( $file as xs:string, $content as xs:string* )
+ as empty-sequence()
+{
+ file:append-text( $file, $content, "UTF-8" )
+};
+
+(:~
+ : Appends a sequence of string items to a file, each followed by a
+ : platform-dependent newline character(s).
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @param $encoding The character encoding to append <code>$content</code> as.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:append-text-lines( $file as xs:string, $content as xs:string*,
+ $encoding as xs:string )
+ as empty-sequence() external;
+
+(:~
+ : Appends a sequence of string to a file, each followed by a
+ : platform-dependent newline character(s), using the UTF-8 character encoding.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:append-text-lines( $file as xs:string, $content as xs:string* )
+ as empty-sequence()
+{
+ file:append-text-lines( $file, $content, "UTF-8" )
+};
+
+(:~
+ : Returns the last component from the <pre>$path</pre>, deleting any
+ : trailing directory-separator characters. If <pre>$path</pre> consists
+ : entirely directory-separator characters, the empty string is returned. If
+ : <pre>$path</pre> is the empty string, the string <pre>"."</pre> is returned,
+ : signifying the current directory.
+ :
+ : No path existence check is made.
+ :
+ : @param $path A file path/URI.
+ : @return The base name of this file.
+ :)
+declare function file:base-name( $path as xs:string )
+ as xs:string external;
+
+(:~
+ : Returns the last component from the <pre>$path</pre>, deleting any
+ : trailing directory-separator characters and the <pre>$suffix</pre>. If path
+ : consists entirely directory-separator characters, the empty string is
+ : returned. If path is the empty string, the string <pre>"."</pre> is
+ : returned, signifying the current directory.
+ :
+ : No path existence check is made.
+ :
+ : The <pre>$suffix</pre> can be used for example to eliminate file extensions.
+ :
+ : @param $path A file path/URI.
+ : @param $suffix A suffix which should get deleted from the result.
+ : @return The base-name of $path with a deleted $suffix.
+ :)
+declare function file:base-name( $path as xs:string, $suffix as xs:string )
+ as xs:string
+{
+ let $res := file:base-name($path)
+ return
+ if (fn:ends-with($res, $suffix) and $res ne ".") then
+ fn:substring($res, 1, fn:string-length($res) - fn:string-length($suffix))
+ else
+ $res
+};
(:~
: Copies a file or a directory given a source and a destination path/URI.
@@ -100,10 +160,9 @@
: parent directory does not exist either.
: @error file:FOFL9999 If any other error occurs.
:)
-declare %an:nondeterministic %an:sequential function file:copy(
- $source as xs:string,
- $destination as xs:string
-) as empty-sequence()
+declare %an:nondeterministic %an:sequential
+function file:copy( $source as xs:string, $destination as xs:string )
+ as empty-sequence()
{
if (file:exists($source)) then
if (file:is-directory($source)) then
@@ -115,89 +174,6 @@
};
(:~
- : Copies a file given a source and a destination path/URI.
- :
- : @param $sourceFile The path/URI of the file to copy.
- : @param $destination The destination path/URI.
- : @return The empty sequence.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0002 If the computed destination points to directory.
- : @error file:FOFL0003 If <pre>$destination</pre> does not exist and it's
- : parent directory does not exist either.
- : @error file:FOFL0004 If <pre>$sourceFile</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %private %an:sequential function file:copy-file-impl(
- $sourceFile as xs:string,
- $destination as xs:string
-) as empty-sequence() external;
-
-(:~
- : Copies a source directory recursively to a destination path/URI.
- :
- : @param $sourceDir The path/URI of the directory to copy.
- : @param $destination The destination path/URI.
- : @return The empty sequence.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0002 If <pre>$destination</pre> points to an existing file.
- : @error file:FOFL0003 If <pre>$destination</pre> does not exist and it's
- : parent directory does not exist either.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %private %an:nondeterministic %an:sequential function file:copy-directory-impl(
- $sourceDir as xs:string,
- $destination as xs:string
-) as empty-sequence()
-{
- if (file:is-file($destination)) then
- fn:error(xs:QName("file:FOFL0002"), fn:concat("The specified destination path already exists: ", $destination))
- else if (fn:not(file:exists($destination))) then
- let $dirname := file:dir-name($destination)
- return
- if (fn:not(file:exists($dirname))) then
- fn:error(xs:QName("file:FOFL0003"), fn:concat("The destination directory does not exist: ", $dirname))
- else
- {
- file:create-directory($destination);
- file:copy-directory-content($sourceDir, $destination)
- }
-
- else
- let $basename := file:base-name($sourceDir)
- let $newdir := fn:concat($destination, file:directory-separator(), $basename)
- return
- {
- file:create-directory($newdir);
- file:copy-directory-content($sourceDir, $newdir)
- }
-};
-
-(:~
- : Copies the content of a given directory to an existing destination
- : directory.
- :
- : @param $sourceDir The path/URI of the directory to copy the content from.
- : @param $destination The destination directory path/URI.
- : @return The empty sequence.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0003 If <pre>$destination</pre> directory does not exist.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %private %an:nondeterministic %an:sequential function file:copy-directory-content(
- $sourceDir as xs:string,
- $destination as xs:string
-) as empty-sequence()
-{
- if (file:is-directory($destination)) then
- for $item in file:list($sourceDir)
- let $fullPath := fn:concat($sourceDir, file:directory-separator(), $item)
- return
- file:copy($fullPath, $destination)
- else
- fn:error(xs:QName("file:FOFL0003"), fn:concat("The specified destination directory does not exist: ", $destination))
-};
-
-(:~
: Creates a directory.
:
: The operation is will create all the missing parent directories from the
@@ -209,9 +185,9 @@
: existing file.
: @error file:FOFL9999 If any other error occurs.
:)
-declare %an:sequential function file:create-directory(
- $dir as xs:string
-) as empty-sequence() external;
+declare %an:sequential function
+file:create-directory( $dir as xs:string )
+ as empty-sequence() external;
(:~
: Deletes a file or a directory from the file system.
@@ -224,9 +200,9 @@
: @error file:FOFL0001 If the <pre>$path</pre> path does not exist.
: @error file:FOFL9999 If any other error occurs.
:)
-declare %an:nondeterministic %an:sequential function file:delete(
- $path as xs:string
-) as empty-sequence()
+declare %an:nondeterministic %an:sequential
+function file:delete( $path as xs:string )
+ as empty-sequence()
{
if (file:exists($path,false())) then
if (not(file:is-symlink($path)) and file:is-directory($path)) then
@@ -238,40 +214,29 @@
};
(:~
- : Deletes a file from the file system.
+ : This function returns the value of the operating system specific directory
+ : separator. For example, <pre>/</pre> on Unix-based systems and <pre>\</pre>
+ : on Windows systems.
:
- : @param $file The path/URI of the file to delete.
- : @return The empty sequence.
- : @error file:FOFL0001 If the <pre>$file</pre> path does not exist.
- : @error file:FOFL9999 If any other error occurs.
+ : @return The operating system specific directory separator.
:)
-declare %private %an:sequential function file:delete-file-impl(
- $file as xs:string
-) as empty-sequence() external;
+declare function file:directory-separator()
+ as xs:string external;
(:~
- : Deletes a directory from the file system.
- :
- : @param $dir The path/URI of the directory to delete.
- : @return The empty sequence.
- : @error file:FOFL0001 If the <pre>$dir</pre> path does not exist.
- : @error file:FOFL0003 If <pre>$dir</pre> does not point to a directory.
- : @error file:FOFL9999 If any other error occurs.
+ : This function is the converse of <pre>file:base-name</pre>. It returns a
+ : string denoting the parent directory of the <pre>$path</pre>. Any trailing
+ : directory-separator characters are not counted as part of the directory
+ : name. If path is the empty string or contains no directory-separator string,
+ : <pre>"."</pre> is returned, signifying the current directory.
+ :
+ : No path existence check is made.
+ :
+ : @param $path The filename, of which the dirname should be get.
+ : @return The name of the directory the file is in.
:)
-declare %private %an:nondeterministic %an:sequential function file:delete-directory-impl(
- $dir as xs:string
-) as empty-sequence()
-{
- for $item in file:list($dir)
- let $fullPath := fn:concat($dir, file:directory-separator(), $item)
- return
- if (file:is-directory($fullPath)) then
- file:delete-directory-impl($fullPath);
- else
- file:delete-file-impl($fullPath);
-
- file:delete-file-impl($dir)
-};
+declare function file:dir-name( $path as xs:string )
+ as xs:string external;
(:~
: Tests if a path/URI is already used in the file system.
@@ -280,9 +245,9 @@
: @param $follow-symlinks if <code>true</code>, follows symbolic links.
: @return true if <code>$path</code> points to an existing file system item.
:)
-declare %an:nondeterministic function file:exists(
- $path as xs:string, $follow-symlinks as xs:boolean
-) as xs:boolean external;
+declare %an:nondeterministic
+function file:exists( $path as xs:string, $follow-symlinks as xs:boolean )
+ as xs:boolean external;
(:~
: Tests if a path/URI is already used in the file system.
@@ -291,11 +256,27 @@
: @return true if <code>$path</code> points to an existing file system item;
: for symbolic links, retuns true if the linked-to item exists.
:)
-declare %an:nondeterministic function file:exists(
- $path as xs:string
-) as xs:boolean
-{
- file:exists($path,true())
+declare %an:nondeterministic
+function file:exists( $path as xs:string )
+ as xs:boolean
+{
+ file:exists( $path, true() )
+};
+
+(:~
+ : A helper function that performs a trivial (not complete) glob to regex
+ : pattern translation.
+ :
+ : @param $pattern The glob pattern.
+ : @return A regex pattern corresponding to the glob pattern provided.
+ :)
+declare function file:glob-to-regex( $pattern as xs:string )
+ as xs:string
+{
+ let $pattern := fn:replace($pattern, '(\.|\[|\]|\\|/|\||\-|\^|\$|\?|\*|\+|\{|\}|\(|\))','\\$1')
+ let $pattern := fn:replace($pattern, '\\\?', '.')
+ let $pattern := fn:replace($pattern, '\\\*', '.*')
+ return fn:concat( "^", $pattern, "$" )
};
(:~
@@ -306,9 +287,9 @@
: @return true if <code>$path</code> points to a directory; for symbolic
: links, returns true if the linked-to item is a directory.
:)
-declare %an:nondeterministic function file:is-directory(
- $path as xs:string
-) as xs:boolean external;
+declare %an:nondeterministic
+function file:is-directory( $path as xs:string )
+ as xs:boolean external;
(:~
: Tests if a path/URI points to a file.
@@ -317,9 +298,9 @@
: @return true if <code>$path</code> points to a file; for symbolic links,
: returns true if the linked-to item is a file.
:)
-declare %an:nondeterministic function file:is-file(
- $path as xs:string
-) as xs:boolean external;
+declare %an:nondeterministic
+function file:is-file( $path as xs:string )
+ as xs:boolean external;
(:~
: Tests if a path/URI points to symbolic link. This works on all Unix-based
@@ -328,235 +309,22 @@
: @param $path The path/URI to test.
: @return true if <code>$path</code> points to a symbolic link.
:)
-declare %an:nondeterministic function file:is-symlink(
- $path as xs:string
-) as xs:boolean external;
-
-(:~
- : Moves a file or directory given a source and a destination paths/URIs.
- :
- : @param $source The path/URI of the file to move.
- : @param $destination The destination path/URI.
- : @return The empty sequence.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0002 If <pre>$source</pre> points to a directory and
- : <pre>$destination</pre> points to an existing file.
- : @error file:FOFL0003 If <pre>$destination</pre> does not exist and it's parent
- : directory does not exist either.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:sequential function file:move(
- $source as xs:string,
- $destination as xs:string
-) as empty-sequence()
-{
- file:copy($source, $destination);
- file:delete($source);
-};
-
-(:~
- : Reads the content of a file and returns a Base64 representation of the
- : content.
- :
- : @param $file The file to read.
- : @return The content of the file as Base64.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:read-binary(
- $file as xs:string
-) as xs:base64Binary external;
-
-(:~
- : Reads the content of a file and returns a string representation of the
- : content.
- :
- : The operation is equivalent to calling:
- : <pre>file:read-text($file, "UTF-8")</pre>.
- :
- : @param $file The file to read.
- : @return The content of the file as string.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:read-text(
- $file as xs:string
-) as xs:string
-{
- file:read-text($file, "UTF-8")
-};
-
-(:~
- : Reads the content of a file using the specified encoding and returns a
- : string representation of the content.
- :
- : @param $file The file to read.
- : @param $encoding The encoding used when reading the file.
- : If compiled with ICU, then Zorba supports any encoding that ICU supports;
- : otherwise Zorba only supports ASCII and UTF-8.
- : The encoding parameter is case insensitive.
- : @return The content of the file as string.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
- : @error file:FOFL0006 If <pre>$encoding</pre> is not supported.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:read-text(
- $file as xs:string,
- $encoding as xs:string
-) as xs:string external;
-
-(:~
- : Reads the content of a file and returns a sequence of strings representing
- : the lines in the content of the file.
- :
- : The operation is equivalent to calling:
- : <pre>file:read-text-lines($file, "UTF-8")</pre>.
- :
- : @param $file The file to read.
- : @return The content of the file as a sequence of strings.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:read-text-lines(
- $file as xs:string
-) as xs:string*
-{
- file:read-text-lines($file, "UTF-8")
-};
-
-(:~
- : Reads the content of a file using the specified encoding and returns a
- : sequence of strings representing the lines in the content of the file.
- :
- : This implementation considers the LF (
) character as the line
- : separator. If a resulting line ends with the CR (
) character, this is
- : trimmed as well. This implementation will uniformly treat LF and CRLF as
- : line separators.
- :
- : @param $file The file to read.
- : @param $encoding The encoding used when reading the file.
- : If compiled with ICU, then Zorba supports any encoding that ICU supports;
- : otherwise Zorba only supports ASCII and UTF-8.
- : The encoding parameter is case insensitive.
- : @return The content of the file as a sequence of strings.
- : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
- : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
- : @error file:FOFL0006 If <pre>$encoding</pre> is not supported.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:read-text-lines(
- $file as xs:string,
- $encoding as xs:string
-) as xs:string* external;
-
-(:~
- : This is an internal function that copies an entire source directory to an
- : destination directory. The caller to this function must make sure that both
- : the source and destination point to existing directories.
- :
- : @param $sourceDir The existing source directory.
- : @param $destinationDir The existing destination directory.
- : @return The empty sequence.
- :)
-declare %private %an:nondeterministic %an:sequential function file:copy-directory(
- $sourceDir as xs:string,
- $destinationDir as xs:string
-) as empty-sequence()
-{
- let $name := file:base-name($sourceDir)
- let $destDir := fn:concat($destinationDir, file:directory-separator(), $name)
- return
- {
- file:create-directory($destDir);
-
- for $item in file:list($sourceDir)
- let $fullSrcPath := fn:concat($sourceDir, file:directory-separator(), $item)
- let $fullDestPath := fn:concat($destDir, file:directory-separator(), $item)
- return
- if (file:is-directory($fullSrcPath)) then
- file:copy-directory($fullSrcPath, $fullDestPath)
- else
- file:copy($fullSrcPath, $fullDestPath)
- }
-};
-
-(:~
- : Writes a sequence of items to a file. Before writing to the file, the items
- : are serialized according to the <pre>$serializer-params</pre>.
- :
- : The semantics of <pre>$serializer-params</pre> is the same as for the
- : <pre>$params</pre> parameter of the <a target="_blank"
- : href="http://www.w3.org/TR/xpath-functions-11/#func-serialize">fn:serialize</a>
- : function.
- :
- : @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @param $serializer-params Parameter to control the serialization of the
- : content.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:sequential function file:write(
- $file as xs:string,
- $content as item()*,
- $serializer-params as element(output:serialization-parameters)?
-) as empty-sequence()
-{
- file:write-text($file, fn:serialize($content, $serializer-params))
-};
-
-(:~
- : Writes a sequence of Base64 items as binary to a file.
- :
- : The operation is equivalent to calling:
- : <pre>file:write-binary($file, $content, fn:true())</pre>.
- :
- : @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:sequential function file:write-binary(
- $file as xs:string,
- $content as xs:base64Binary*
-) as empty-sequence() external;
-
-(:~
- : Writes a sequence of Base64 items as binary to a file.
- :
- : @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:sequential function file:write-binary(
- $file as xs:string,
- $content as xs:base64Binary*
-) as empty-sequence() external;
-
-(:~
- : Writes a sequence of string items to a file.
- :
- : The operation is equivalent to calling:
- : <pre>file:write-text($file, $content, fn:true())</pre>.
- :
- : @param $file The path/URI of the file to write the content to.
- : @param $content The content to be serialized to the file.
- : @return The empty sequence.
- : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %private %an:sequential function file:write-text(
- $file as xs:string,
- $content as xs:string*
-) as empty-sequence() external;
+declare %an:nondeterministic
+function file:is-symlink( $path as xs:string )
+ as xs:boolean external;
+
+(:~
+ : Retrieves the timestamp of the last modification of the file system item
+ : pointed by the path/URI.
+ :
+ : @param $path The file system item to read the last modification
+ : timestamp from.
+ : @return The date and time of the last modification of the item.
+ : @error file:FOFL0001 If the <pre>$path</pre> does not exist.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic function file:last-modified( $path as xs:string )
+ as xs:dateTime external;
(:~
: Lists the file system items in a certain directory.
@@ -569,9 +337,9 @@
: @error file:FOFL0003 If <pre>$dir</pre> does not point to an existing directory.
: @error file:FOFL9999 If any other error occurs.
:)
-declare %an:nondeterministic function file:list(
- $dir as xs:string
-) as xs:string* external;
+declare %an:nondeterministic
+function file:list( $dir as xs:string )
+ as xs:string* external;
(:~
: Lists the file system items in a certain directory. The order of the items
@@ -588,10 +356,9 @@
: @error file:FOFL0003 If <pre>$dir</pre> does not point to an existing directory.
: @error file:FOFL9999 If any other error occurs.
:)
-declare %an:nondeterministic function file:list(
- $path as xs:string,
- $recursive as xs:boolean
-) as xs:string*
+declare %an:nondeterministic
+function file:list( $path as xs:string, $recursive as xs:boolean )
+ as xs:string*
{
for $f in file:list($path)
let $full := fn:concat($path, file:directory-separator(), $f)
@@ -625,81 +392,174 @@
: @error file:FOFL0003 If <pre>$dir</pre> does not point to an existing directory.
: @error file:FOFL9999 If any other error occurs.
:)
-declare %an:nondeterministic function file:list(
- $path as xs:string,
- $recursive as xs:boolean,
- $pattern as xs:string
-) as xs:string* {
- for $file in file:list($path, $recursive)
- let $name := file:base-name($file)
+declare %an:nondeterministic
+function file:list( $path as xs:string, $recursive as xs:boolean,
+ $pattern as xs:string )
+ as xs:string*
+{
+ for $file in file:list( $path, $recursive )
+ let $name := file:base-name( $file )
return
- if (fn:matches($name, file:glob-to-regex($pattern))) then
+ if ( fn:matches( $name, file:glob-to-regex( $pattern ) ) ) then
$file
else
()
};
(:~
- : A helper function that performs a trivial (not complete) glob to regex
- : pattern translation.
- :
- : @param $pattern The glob pattern.
- : @return A regex pattern corresponding to the glob pattern provided.
+ : Moves a file or directory given a source and a destination paths/URIs.
+ :
+ : @param $source The path/URI of the file to move.
+ : @param $destination The destination path/URI.
+ : @return The empty sequence.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0002 If <pre>$source</pre> points to a directory and
+ : <pre>$destination</pre> points to an existing file.
+ : @error file:FOFL0003 If <pre>$destination</pre> does not exist and its
+ : parent directory does not exist either.
+ : @error file:FOFL9999 If any other error occurs.
:)
-declare function file:glob-to-regex(
- $pattern as xs:string
-) as xs:string {
- let $pattern := fn:replace($pattern, '(\.|\[|\]|\\|/|\||\-|\^|\$|\?|\*|\+|\{|\}|\(|\))','\\$1')
- let $pattern := fn:replace($pattern, '\\\?', '.')
- let $pattern := fn:replace($pattern, '\\\*', '.*')
- return
- fn:concat("^", $pattern, "$")
+declare %an:sequential
+function file:move( $source as xs:string, $destination as xs:string )
+ as empty-sequence()
+{
+ file:copy( $source, $destination );
+ file:delete( $source );
};
(:~
- : Retrieves the timestamp of the last modification of the file system item
- : pointed by the path/URI.
- :
- : @param $path The file system item to read the last modification
- : timestamp from.
- : @return The date and time of the last modification of the item.
- : @error file:FOFL0001 If the <pre>$path</pre> does not exist.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:last-modified(
- $path as xs:string
-) as xs:dateTime external;
-
-(:~
- : Retrieves the size of a file.
- :
- : @param $file The file get the size.
- : @return An integer representing the size in bytes of the file.
- : @error file:FOFL0001 If the <pre>$file</pre> does not exist.
- : @error file:FOFL0004 If the <pre>$file</pre> points to a directory.
- : @error file:FOFL9999 If any other error occurs.
- :)
-declare %an:nondeterministic function file:size(
- $file as xs:string
-) as xs:integer external;
-
-(:~
- : This function returns the value of the operating system specific directory
- : separator. For example, <pre>/</pre> on Unix-based systems and <pre>\</pre>
- : on Windows systems.
- :
- : @return The operating system specific directory separator.
- :)
-declare function file:directory-separator() as xs:string external;
-
-(:~
: This function returns the value of the operating system specific path
: separator. For example, <pre>:</pre> on Unix-based systems and <pre>;</pre>
: on Windows systems.
:
: @return The operating system specific path separator.
:)
-declare function file:path-separator() as xs:string external;
+declare function file:path-separator()
+ as xs:string external;
+
+(:~
+ : Transforms a URI, an absolute path, or relative path to a native path on the
+ : running platform.
+ :
+ : No path existence check is made.
+ :
+ : @param $path The uri or path to normalize.
+ : @return The native path corresponding to <pre>$path</pre>.
+ : @error file:FOFL9999 If an error occurs while trying to obtain the native
+ : path.
+ :)
+declare function file:path-to-native( $path as xs:string )
+ as xs:string external;
+
+(:~
+ : Transforms a file system path into a URI with the file:// scheme. If the
+ : path is relative, it is first resolved against the current working
+ : directory.
+ :
+ : No path existence check is made.
+ :
+ : @param $path The path to transform.
+ : @return The file URI corresponding to <pre>path</pre>.
+ :)
+declare function file:path-to-uri( $path as xs:string )
+ as xs:anyURI external;
+
+(:~
+ : Reads the content of a file and returns a Base64 representation of the
+ : content.
+ :
+ : @param $file The file to read.
+ : @return The content of the file as Base64.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic
+function file:read-binary( $file as xs:string )
+ as xs:base64Binary external;
+
+(:~
+ : Reads the content of a file using the specified encoding and returns a
+ : string representation of the content.
+ :
+ : @param $file The file to read.
+ : @param $encoding The encoding used when reading the file.
+ : If compiled with ICU, then Zorba supports any encoding that ICU supports;
+ : otherwise Zorba only supports ASCII and UTF-8.
+ : The encoding parameter is case insensitive.
+ : @return The content of the file as string.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
+ : @error file:FOFL0006 If <pre>$encoding</pre> is not supported.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic
+function file:read-text( $file as xs:string, $encoding as xs:string )
+ as xs:string external;
+
+(:~
+ : Reads the content of a file and returns a string representation of the
+ : content.
+ :
+ : The operation is equivalent to calling:
+ : <pre>file:read-text($file, "UTF-8")</pre>.
+ :
+ : @param $file The file to read.
+ : @return The content of the file as string.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic
+function file:read-text( $file as xs:string )
+ as xs:string
+{
+ file:read-text( $file, "UTF-8" )
+};
+
+(:~
+ : Reads the content of a file and returns a sequence of strings representing
+ : the lines in the content of the file.
+ :
+ : The operation is equivalent to calling:
+ : <pre>file:read-text-lines($file, "UTF-8")</pre>.
+ :
+ : @param $file The file to read.
+ : @return The content of the file as a sequence of strings.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic
+function file:read-text-lines( $file as xs:string )
+ as xs:string*
+{
+ file:read-text-lines( $file, "UTF-8" )
+};
+
+(:~
+ : Reads the content of a file using the specified encoding and returns a
+ : sequence of strings representing the lines in the content of the file.
+ :
+ : This implementation considers the LF (
) character as the line
+ : separator. If a resulting line ends with the CR (
) character, this is
+ : trimmed as well. This implementation will uniformly treat LF and CRLF as
+ : line separators.
+ :
+ : @param $file The file to read.
+ : @param $encoding The encoding used when reading the file.
+ : If compiled with ICU, then Zorba supports any encoding that ICU supports;
+ : otherwise Zorba only supports ASCII and UTF-8.
+ : The encoding parameter is case insensitive.
+ : @return The content of the file as a sequence of strings.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0004 If <pre>$source</pre> points to a directory.
+ : @error file:FOFL0006 If <pre>$encoding</pre> is not supported.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic
+function file:read-text-lines( $file as xs:string, $encoding as xs:string )
+ as xs:string* external;
(:~
: Transforms a relative path/URI into an absolute operating system path by
@@ -710,88 +570,247 @@
: @param $path The path/URI to transform.
: @return The operating system file path.
:)
-declare function file:resolve-path(
- $path as xs:string
-) as xs:string external;
-
-(:~
- : Transforms a file system path into a URI with the file:// scheme. If the
- : path is relative, it is first resolved against the current working
+declare function file:resolve-path( $path as xs:string )
+ as xs:string external;
+
+(:~
+ : Retrieves the size of a file.
+ :
+ : @param $file The file get the size.
+ : @return An integer representing the size in bytes of the file.
+ : @error file:FOFL0001 If the <pre>$file</pre> does not exist.
+ : @error file:FOFL0004 If the <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:nondeterministic function file:size( $file as xs:string )
+ as xs:integer external;
+
+(:~
+ : Writes a sequence of Base64 items as binary to a file.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:write-binary( $file as xs:string, $content as xs:base64Binary )
+ as empty-sequence() external;
+
+(:~
+ : Writes a sequence of strings to a file.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @param $encoding The character encoding to write <code>$content</code> as.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:write-text( $file as xs:string, $content as xs:string*,
+ $encoding as xs:string )
+ as empty-sequence() external;
+
+(:~
+ : Writes a sequence of strings to a file using the UTF-8 character encoding.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:write-text( $file as xs:string, $content as xs:string* )
+ as empty-sequence()
+{
+ file:write-text( $file, $content, "UTF-8" )
+};
+
+(:~
+ : Writes a sequence of strings to a file, each followed by a
+ : platform-dependent newline character(s).
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @param $encoding The character encoding to write <code>$content</code> as.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:write-text-lines( $file as xs:string, $content as xs:string*,
+ $encoding as xs:string )
+ as empty-sequence() external;
+
+(:~
+ : Writes a sequence of strings to a file, each followed by a
+ : platform-dependent newline character(s), using the UTF-8 character encoding.
+ :
+ : @param $file The path/URI of the file to write the content to.
+ : @param $content The content to be written to the file.
+ : @return The empty sequence.
+ : @error file:FOFL0004 If <pre>$file</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %an:sequential
+function file:write-text-lines( $file as xs:string, $content as xs:string* )
+ as empty-sequence()
+{
+ file:write-text-lines( $file, $content, "UTF-8" )
+};
+
+(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
+
+(:~
+ : Copies a file given a source and a destination path/URI.
+ :
+ : @param $sourceFile The path/URI of the file to copy.
+ : @param $destination The destination path/URI.
+ : @return The empty sequence.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0002 If the computed destination points to directory.
+ : @error file:FOFL0003 If <pre>$destination</pre> does not exist and it's
+ : parent directory does not exist either.
+ : @error file:FOFL0004 If <pre>$sourceFile</pre> points to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %private %an:sequential
+function file:copy-file-impl( $sourceFile as xs:string,
+ $destination as xs:string )
+ as empty-sequence() external;
+
+(:~
+ : Copies a source directory recursively to a destination path/URI.
+ :
+ : @param $sourceDir The path/URI of the directory to copy.
+ : @param $destination The destination path/URI.
+ : @return The empty sequence.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0002 If <pre>$destination</pre> points to an existing file.
+ : @error file:FOFL0003 If <pre>$destination</pre> does not exist and it's
+ : parent directory does not exist either.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %private %an:nondeterministic %an:sequential
+function file:copy-directory-impl( $sourceDir as xs:string,
+ $destination as xs:string )
+ as empty-sequence()
+{
+ if (file:is-file($destination)) then
+ fn:error(xs:QName("file:FOFL0002"), fn:concat("The specified destination path already exists: ", $destination))
+ else if (fn:not(file:exists($destination))) then
+ let $dirname := file:dir-name($destination)
+ return
+ if (fn:not(file:exists($dirname))) then
+ fn:error(xs:QName("file:FOFL0003"), fn:concat("The destination directory does not exist: ", $dirname))
+ else
+ {
+ file:create-directory($destination);
+ file:copy-directory-content($sourceDir, $destination)
+ }
+ else
+ let $basename := file:base-name($sourceDir)
+ let $newdir := fn:concat($destination, file:directory-separator(), $basename)
+ return
+ {
+ file:create-directory($newdir);
+ file:copy-directory-content($sourceDir, $newdir)
+ }
+};
+
+(:~
+ : This is an internal function that copies an entire source directory to an
+ : destination directory. The caller to this function must make sure that both
+ : the source and destination point to existing directories.
+ :
+ : @param $sourceDir The existing source directory.
+ : @param $destinationDir The existing destination directory.
+ : @return The empty sequence.
+ :)
+declare %private %an:nondeterministic %an:sequential
+function file:copy-directory( $sourceDir as xs:string,
+ $destinationDir as xs:string )
+ as empty-sequence()
+{
+ let $name := file:base-name($sourceDir)
+ let $destDir := fn:concat($destinationDir, file:directory-separator(), $name)
+ return
+ {
+ file:create-directory($destDir);
+
+ for $item in file:list($sourceDir)
+ let $fullSrcPath := fn:concat($sourceDir, file:directory-separator(), $item)
+ let $fullDestPath := fn:concat($destDir, file:directory-separator(), $item)
+ return
+ if (file:is-directory($fullSrcPath)) then
+ file:copy-directory($fullSrcPath, $fullDestPath)
+ else
+ file:copy($fullSrcPath, $fullDestPath)
+ }
+};
+
+(:~
+ : Copies the content of a given directory to an existing destination
: directory.
:
- : No path existence check is made.
- :
- : @param $path The path to transform.
- : @return The file URI corresponding to <pre>path</pre>.
- :)
-declare function file:path-to-uri(
- $path as xs:string
-) as xs:anyURI external;
-
-(:~
- : Transforms a URI, an absolute path, or relative path to a native path on the
- : running platform.
- :
- : No path existence check is made.
- :
- : @param $path The uri or path to normalize.
- : @return The native path corresponding to <pre>$path</pre>.
- : @error file:FOFL9999 If an error occurs while trying to obtain the native path.
- :)
-declare function file:path-to-native($path as xs:string) as xs:string external;
-
-(:~
- : Returns the last component from the <pre>$path</pre>, deleting any
- : trailing directory-separator characters. If <pre>$path</pre> consists
- : entirely directory-separator characters, the empty string is returned. If
- : <pre>$path</pre> is the empty string, the string <pre>"."</pre> is returned,
- : signifying the current directory.
- :
- : No path existence check is made.
- :
- : @param $path A file path/URI.
- : @return The base name of this file.
- :)
-declare function file:base-name($path as xs:string) as xs:string external;
-
-(:~
- : Returns the last component from the <pre>$path</pre>, deleting any
- : trailing directory-separator characters and the <pre>$suffix</pre>. If path
- : consists entirely directory-separator characters, the empty string is
- : returned. If path is the empty string, the string <pre>"."</pre> is
- : returned, signifying the current directory.
- :
- : No path existence check is made.
- :
- : The <pre>$suffix</pre> can be used for example to eliminate file extensions.
- :
- : @param $path A file path/URI.
- : @param $suffix A suffix which should get deleted from the result.
- : @return The base-name of $path with a deleted $suffix.
- :)
-declare function file:base-name($path as xs:string, $suffix as xs:string)
- as xs:string
-{
- let $res := file:base-name($path)
+ : @param $sourceDir The path/URI of the directory to copy the content from.
+ : @param $destination The destination directory path/URI.
+ : @return The empty sequence.
+ : @error file:FOFL0001 If the <pre>$source</pre> path does not exist.
+ : @error file:FOFL0003 If <pre>$destination</pre> directory does not exist.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %private %an:nondeterministic %an:sequential
+function file:copy-directory-content( $sourceDir as xs:string,
+ $destination as xs:string )
+ as empty-sequence()
+{
+ if (file:is-directory($destination)) then
+ for $item in file:list($sourceDir)
+ let $fullPath := fn:concat($sourceDir, file:directory-separator(), $item)
+ return
+ file:copy($fullPath, $destination)
+ else
+ fn:error(xs:QName("file:FOFL0003"), fn:concat("The specified destination directory does not exist: ", $destination))
+};
+
+(:~
+ : Deletes a file from the file system.
+ :
+ : @param $file The path/URI of the file to delete.
+ : @return The empty sequence.
+ : @error file:FOFL0001 If the <pre>$file</pre> path does not exist.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %private %an:sequential
+function file:delete-file-impl( $file as xs:string )
+ as empty-sequence() external;
+
+(:~
+ : Deletes a directory from the file system.
+ :
+ : @param $dir The path/URI of the directory to delete.
+ : @return The empty sequence.
+ : @error file:FOFL0001 If the <pre>$dir</pre> path does not exist.
+ : @error file:FOFL0003 If <pre>$dir</pre> does not point to a directory.
+ : @error file:FOFL9999 If any other error occurs.
+ :)
+declare %private %an:nondeterministic %an:sequential
+function file:delete-directory-impl( $dir as xs:string )
+ as empty-sequence()
+{
+ for $item in file:list($dir)
+ let $fullPath := fn:concat($dir, file:directory-separator(), $item)
return
- if (fn:ends-with($res, $suffix) and $res ne ".") then
- fn:substring($res, 1, fn:string-length($res) - fn:string-length($suffix))
+ if (file:is-directory($fullPath)) then
+ file:delete-directory-impl($fullPath);
else
- $res
+ file:delete-file-impl($fullPath);
+
+ file:delete-file-impl($dir)
};
-(:~
- : This function is the converse of <pre>file:base-name</pre>. It returns a
- : string denoting the parent directory of the <pre>$path</pre>. Any trailing
- : directory-separator characters are not counted as part of the directory
- : name. If path is the empty string or contains no directory-separator string,
- : <pre>"."</pre> is returned, signifying the current directory.
- :
- : No path existence check is made.
- :
- : @param $path The filename, of which the dirname should be get.
- : @return The name of the directory the file is in.
- :)
-declare function file:dir-name($path as xs:string) as xs:string external;
-
(: vim:set et sw=2 ts=2: :)
=== modified file 'modules/org/expath/ns/file.xq.src/file.cpp'
--- modules/org/expath/ns/file.xq.src/file.cpp 2013-08-05 11:54:06 +0000
+++ modules/org/expath/ns/file.xq.src/file.cpp 2013-08-05 22:16:26 +0000
@@ -38,10 +38,31 @@
namespace zorba {
namespace filemodule {
-//*****************************************************************************
-
-BaseNameFunction::BaseNameFunction(const FileModule* aModule)
- : FileFunction(aModule)
+///////////////////////////////////////////////////////////////////////////////
+
+AppendTextFunction::AppendTextFunction( FileModule const *m ) :
+ WriteTextFunctionImpl( m, "append-text", true, false )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AppendTextLinesFunction::AppendTextLinesFunction( FileModule const *m ) :
+ WriteTextFunctionImpl( m, "append-text-lines", true, true )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AppendBinaryFunction::AppendBinaryFunction( FileModule const *m ) :
+ WriteBinaryFunctionImpl( m, "append-binary", true )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+BaseNameFunction::BaseNameFunction( FileModule const *m ) :
+ FileFunction( m, "base-name" )
{
}
@@ -55,14 +76,63 @@
while ( path.size() > 1 && path[ path.size() - 1 ] == fs::dir_separator )
path.erase( path.size() - 1 );
String const base_name( fs::base_name( path ) );
- Item item( theModule->getItemFactory()->createString( base_name ) );
+ Item item( module_->getItemFactory()->createString( base_name ) );
return ItemSequence_t( new SingletonItemSequence( item ) );
}
-//*****************************************************************************
-
-CreateDirectoryFunction::CreateDirectoryFunction(const FileModule* aModule)
- : FileFunction(aModule)
+///////////////////////////////////////////////////////////////////////////////
+
+CopyFileImplFunction::CopyFileImplFunction( FileModule const *m ) :
+ FileFunction( m, "copy-file-impl" )
+{
+}
+
+ItemSequence_t
+CopyFileImplFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const src_path( getPathArg( args, 0 ) );
+ String dst_path( getPathArg( args, 1 ) );
+
+ fs::type const src_type = fs::get_type( src_path );
+ if ( !src_type )
+ raiseFileError( "FOFL0001", "file not found", src_path );
+ if ( src_type != fs::file )
+ raiseFileError( "FOFL0004", "not a plain file", src_path );
+
+ fs::type dst_type = fs::get_type( dst_path );
+ if ( dst_type == fs::directory ) { // we are copying into a directory
+ fs::append( dst_path, fs::base_name( src_path ) );
+ dst_type = fs::get_type( dst_path );
+ if ( dst_type == fs::directory )
+ raiseFileError( "FOFL0002", "path already exists", dst_path );
+ }
+
+ if ( src_path == dst_path )
+ raiseFileError( "FOFL9999", "source and destination paths must not be equal", src_path );
+
+ try {
+ std::ifstream fin( src_path.c_str(), std::ios_base::binary );
+ std::ofstream fout( dst_path.c_str(), std::ios_base::binary | std::ios_base::trunc );
+ char buf[ 8192 ];
+ while ( !fin.eof() ) {
+ fin.read( buf, sizeof buf );
+ fout.write( buf, fin.gcount() );
+ }
+ }
+ catch ( std::exception const &e ) {
+ throw raiseFileError( "FOFL9999", e.what(), src_path );
+ }
+
+ return ItemSequence_t( new EmptySequence() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+CreateDirectoryFunction::CreateDirectoryFunction( FileModule const *m ) :
+ FileFunction( m, "create-directory" )
{
}
@@ -75,31 +145,25 @@
String const path( getPathArg( args, 0 ) );
fs::type const fs_type = fs::get_type( path );
- if ( !fs_type )
- {
+ if ( !fs_type ) {
try {
fs::mkdir( path, true );
}
catch ( std::exception const &e ) {
throw raiseFileError( "FOFL9999", e.what(), path );
}
- }
- else if ( fs_type != fs::directory )
- {
+ } else if ( fs_type != fs::directory )
raiseFileError( "FOFL0002", "file already exists", path );
- }
else
- {
/* directory already exists: do nothing */;
- }
return ItemSequence_t( new EmptySequence() );
}
-//*****************************************************************************
+///////////////////////////////////////////////////////////////////////////////
-DeleteFileImplFunction::DeleteFileImplFunction(const FileModule* aModule) :
- FileFunction(aModule)
+DeleteFileImplFunction::DeleteFileImplFunction( FileModule const *m ) :
+ FileFunction( m, "delete-file-impl" )
{
}
@@ -124,10 +188,31 @@
return ItemSequence_t( new EmptySequence() );
}
-//*****************************************************************************
-
-DirNameFunction::DirNameFunction(const FileModule* aModule)
- : FileFunction(aModule)
+///////////////////////////////////////////////////////////////////////////////
+
+DirectorySeparator::DirectorySeparator( FileModule const *m ) :
+ FileFunction( m, "directory-separator" )
+{
+}
+
+ItemSequence_t
+DirectorySeparator::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const dir_separator( 1, fs::dir_separator );
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createString( dir_separator )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+DirNameFunction::DirNameFunction( FileModule const *m ) :
+ FileFunction( m, "dir-name" )
{
}
@@ -141,14 +226,235 @@
while ( path.size() > 1 && path[ path.size() - 1 ] == fs::dir_separator )
path.erase( path.size() - 1 );
String const dir_name( fs::dir_name( path ) );
- Item item( theModule->getItemFactory()->createString( dir_name ) );
+ Item item( module_->getItemFactory()->createString( dir_name ) );
return ItemSequence_t( new SingletonItemSequence( item ) );
}
-//*****************************************************************************
-
-ReadBinaryFunction::ReadBinaryFunction( FileModule const *aModule ) :
- FileFunction( aModule )
+///////////////////////////////////////////////////////////////////////////////
+
+ExistsFunction::ExistsFunction( FileModule const *m ) :
+ FileFunction( m, "exists" )
+{
+}
+
+ItemSequence_t
+ExistsFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path = getPathArg( args, 0 );
+ bool const follow_symlink = getItem( args, 1 ).getBooleanValue();
+ bool const exists = !!fs::get_type( path, follow_symlink );
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createBoolean( exists )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+IsDirectoryFunction::IsDirectoryFunction( FileModule const *m ) :
+ FileFunction( m, "is-directory" )
+{
+}
+
+ItemSequence_t
+IsDirectoryFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+ bool const is_directory = fs::get_type( path ) == fs::directory;
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createBoolean( is_directory )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+IsFileFunction::IsFileFunction( FileModule const *m ) :
+ FileFunction( m, "is-file" )
+{
+}
+
+ItemSequence_t
+IsFileFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+ bool const is_file = fs::get_type( path ) == fs::file;
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createBoolean( is_file )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+IsSymlinkFunction::IsSymlinkFunction( FileModule const *m ) :
+ FileFunction( m, "is-symlink" )
+{
+}
+
+ItemSequence_t
+IsSymlinkFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+ bool const is_symlink = fs::get_type( path, false ) == fs::link;
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createBoolean( is_symlink )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+LastModifiedFunction::LastModifiedFunction( FileModule const *m ) :
+ FileFunction( m, "last-modified" )
+{
+}
+
+ItemSequence_t
+LastModifiedFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+
+ fs::info info;
+ if ( !fs::get_type( path, &info ) )
+ raiseFileError( "FOFL0001", "file not found", path );
+
+ try {
+ time_t lTime = info.mtime;
+ // result of localtime needs to be copied.
+ // Otherwise, nasty side effecs do happen
+ struct tm lT( *localtime( &lTime ) );
+ int gmtOffset = LastModifiedFunction::getGmtOffset();
+
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createDateTime(
+ 1900 + lT.tm_year,
+ lT.tm_mon,
+ lT.tm_mday,
+ lT.tm_hour,
+ lT.tm_min,
+ lT.tm_sec,
+ gmtOffset
+ )
+ )
+ );
+ }
+ catch ( std::exception const &e ) {
+ throw raiseFileError( "FOFL9999", e.what(), path );
+ }
+}
+
+int
+LastModifiedFunction::getGmtOffset()
+{
+ time_t t = ::time(0);
+ struct tm* data;
+ data = localtime(&t);
+ data->tm_isdst = 0;
+ time_t a = mktime(data);
+ data = gmtime(&t);
+ data->tm_isdst = 0;
+ time_t b = mktime(data);
+ return (int)(a - b)/3600;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ListFunction::ListFunction( FileModule const *m ) :
+ FileFunction( m, "list" )
+{
+}
+
+ItemSequence_t
+ListFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+
+ if ( fs::get_type( path ) != fs::directory )
+ raiseFileError( "FOFL0003", "path is not a directory", path );
+
+ try {
+ return ItemSequence_t(
+ new IteratorBackedItemSequence( path, module_->getItemFactory() )
+ );
+ }
+ catch ( std::exception const &e ) {
+ throw raiseFileError( "FOFL9999", e.what(), path );
+ }
+}
+
+ListFunction::IteratorBackedItemSequence::IteratorBackedItemSequence(
+ String const& path,
+ ItemFactory* aFactory
+) :
+ theIterator( path ),
+ theItemFactory( aFactory )
+{
+ is_open = false;
+ open_count = 0;
+}
+
+Iterator_t ListFunction::IteratorBackedItemSequence::getIterator()
+{
+ return this;
+}
+
+void ListFunction::IteratorBackedItemSequence::open()
+{
+ if (open_count) {
+ theIterator.reset();
+ }
+ open_count++;
+ is_open = true;
+}
+
+void ListFunction::IteratorBackedItemSequence::close()
+{
+ is_open = false;
+}
+
+bool ListFunction::IteratorBackedItemSequence::isOpen() const
+{
+ return is_open;
+}
+
+bool
+ListFunction::IteratorBackedItemSequence::next(Item& lItem)
+{
+ if ( !theIterator.next() )
+ return false;
+ String const lUriStr( theIterator->name );
+ lItem = theItemFactory->createString( lUriStr );
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ReadBinaryFunction::ReadBinaryFunction( FileModule const *m ) :
+ FileFunction( m, "read-binary" )
{
}
@@ -170,7 +476,7 @@
std::unique_ptr<std::ifstream> pin(
new std::ifstream( path.c_str(), std::ios_base::binary )
);
- Item item = theModule->getItemFactory()->createStreamableBase64Binary(
+ Item item = module_->getItemFactory()->createStreamableBase64Binary(
*pin, &FileModule::streamReleaser, true
);
pin.release();
@@ -181,10 +487,10 @@
}
}
-//*****************************************************************************
+///////////////////////////////////////////////////////////////////////////////
-ReadTextFunction::ReadTextFunction(const FileModule* aModule)
- : StreamableFileFunction(aModule)
+ReadTextFunction::ReadTextFunction( FileModule const *m ) :
+ FileFunction( m, "read-text" )
{
}
@@ -221,7 +527,7 @@
pin->open( path.c_str() );
skip_utf8_bom( *pin );
- lResult = theModule->getItemFactory()->createStreamableString(
+ lResult = module_->getItemFactory()->createStreamableString(
*pin, &FileModule::streamReleaser, path.c_str(), true
);
pin.release();
@@ -229,10 +535,10 @@
return ItemSequence_t( new SingletonItemSequence( lResult ) );
}
-//*****************************************************************************
+///////////////////////////////////////////////////////////////////////////////
-ReadTextLinesFunction::ReadTextLinesFunction(const FileModule* aModule)
- : FileFunction(aModule)
+ReadTextLinesFunction::ReadTextLinesFunction( FileModule const *m ) :
+ FileFunction( m, "read-text-lines" )
{
}
@@ -285,14 +591,11 @@
{
}
-ReadTextLinesFunction::LinesItemSequence::LinesIterator::~LinesIterator()
-{
+ReadTextLinesFunction::LinesItemSequence::LinesIterator::~LinesIterator() {
delete theStream;
}
-void
-ReadTextLinesFunction::LinesItemSequence::LinesIterator::open()
-{
+void ReadTextLinesFunction::LinesItemSequence::LinesIterator::open() {
if ( transcode::is_necessary( theEncoding.c_str() ) ) {
try {
theStream = new transcode::stream<std::ifstream>( theEncoding.c_str() );
@@ -307,8 +610,7 @@
}
bool
-ReadTextLinesFunction::LinesItemSequence::LinesIterator::next(Item& aRes)
-{
+ReadTextLinesFunction::LinesItemSequence::LinesIterator::next(Item& aRes) {
if ( !theStream || !theStream->good() )
return false;
@@ -317,7 +619,7 @@
if ( theStream->bad() )
return false;
- aRes = theFunc->theModule->getItemFactory()->createString( s );
+ aRes = theFunc->module_->getItemFactory()->createString( s );
return true;
}
@@ -331,312 +633,13 @@
bool
ReadTextLinesFunction::LinesItemSequence::LinesIterator::isOpen() const
{
- return theStream != 0;
-}
-
-//*****************************************************************************
-
-ExistsFunction::ExistsFunction(const FileModule* aModule) :
- FileFunction( aModule )
-{
-}
-
-ItemSequence_t
-ExistsFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path = getPathArg( args, 0 );
- bool const follow_symlink = getItem( args, 1 ).getBooleanValue();
- bool const exists = !!fs::get_type( path, follow_symlink );
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createBoolean( exists )
- )
- );
-}
-
-//*****************************************************************************
-
-IsDirectoryFunction::IsDirectoryFunction( FileModule const *aModule ) :
- FileFunction( aModule )
-{
-}
-
-ItemSequence_t
-IsDirectoryFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
- bool const is_directory = fs::get_type( path ) == fs::directory;
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createBoolean( is_directory )
- )
- );
-}
-
-//*****************************************************************************
-
-IsFileFunction::IsFileFunction( FileModule const *aModule ) :
- FileFunction( aModule )
-{
-}
-
-ItemSequence_t
-IsFileFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
- bool const is_file = fs::get_type( path ) == fs::file;
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createBoolean( is_file )
- )
- );
-}
-
-//*****************************************************************************
-
-IsSymlinkFunction::IsSymlinkFunction( FileModule const *aModule ) :
- FileFunction( aModule )
-{
-}
-
-ItemSequence_t
-IsSymlinkFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
- bool const is_symlink = fs::get_type( path, false ) == fs::link;
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createBoolean( is_symlink )
- )
- );
-}
-
-//*****************************************************************************
-
-CopyFileImplFunction::CopyFileImplFunction( FileModule const *aModule ) :
- FileFunction( aModule )
-{
-}
-
-ItemSequence_t
-CopyFileImplFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const src_path( getPathArg( args, 0 ) );
- String dst_path( getPathArg( args, 1 ) );
-
- fs::type const src_type = fs::get_type( src_path );
- if ( !src_type )
- raiseFileError( "FOFL0001", "file not found", src_path );
- if ( src_type != fs::file )
- raiseFileError( "FOFL0004", "not a plain file", src_path );
-
- fs::type dst_type = fs::get_type( dst_path );
- if ( dst_type == fs::directory ) { // we are copying into a directory
- fs::append( dst_path, fs::base_name( src_path ) );
- dst_type = fs::get_type( dst_path );
- if ( dst_type == fs::directory )
- raiseFileError( "FOFL0002", "path already exists", dst_path );
- }
-
- if ( src_path == dst_path )
- raiseFileError( "FOFL9999", "source and destination paths must not be equal", src_path );
-
- try {
- std::ifstream fin( src_path.c_str(), std::ios_base::binary );
- std::ofstream fout( dst_path.c_str(), std::ios_base::binary | std::ios_base::trunc );
- char buf[ 8192 ];
- while ( !fin.eof() ) {
- fin.read( buf, sizeof buf );
- fout.write( buf, fin.gcount() );
- }
- }
- catch ( std::exception const &e ) {
- throw raiseFileError( "FOFL9999", e.what(), src_path );
- }
-
- return ItemSequence_t( new EmptySequence() );
-}
-
-//*****************************************************************************
-
-ListFunction::ListFunction( FileModule const *aModule ) :
- FileFunction( aModule )
-{
-}
-
-ItemSequence_t
-ListFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
-
- if ( fs::get_type( path ) != fs::directory )
- raiseFileError( "FOFL0003", "path is not a directory", path );
-
- try {
- return ItemSequence_t(
- new IteratorBackedItemSequence( path, theModule->getItemFactory() )
- );
- }
- catch ( std::exception const &e ) {
- throw raiseFileError( "FOFL9999", e.what(), path );
- }
-}
-
-ListFunction::IteratorBackedItemSequence::IteratorBackedItemSequence(
- String const& path,
- ItemFactory* aFactory
-) :
- theIterator( path ),
- theItemFactory( aFactory )
-{
- is_open = false;
- open_count = 0;
-}
-
-ListFunction::IteratorBackedItemSequence::~IteratorBackedItemSequence()
-{
-}
-
-Iterator_t ListFunction::IteratorBackedItemSequence::getIterator()
-{
- return this;
-}
-
-void ListFunction::IteratorBackedItemSequence::open()
-{
- if (open_count) {
- theIterator.reset();
- }
- open_count++;
- is_open = true;
-}
-
-void ListFunction::IteratorBackedItemSequence::close()
-{
- is_open = false;
-}
-
-bool ListFunction::IteratorBackedItemSequence::isOpen() const
-{
- return is_open;
-}
-
-bool
-ListFunction::IteratorBackedItemSequence::next(Item& lItem)
-{
- if ( !theIterator.next() )
- return false;
- String const lUriStr( theIterator->name );
- lItem = theItemFactory->createString( lUriStr );
- return true;
-}
-
-//*****************************************************************************
-
-LastModifiedFunction::LastModifiedFunction(const FileModule* aModule) :
- FileFunction(aModule)
-{
-}
-
-ItemSequence_t
-LastModifiedFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
-
- fs::info info;
- if ( !fs::get_type( path, &info ) )
- raiseFileError( "FOFL0001", "file not found", path );
-
- try {
- time_t lTime = info.mtime;
- // result of localtime needs to be copied.
- // Otherwise, nasty side effecs do happen
- struct tm lT(*localtime(&lTime));
- int gmtOffset = LastModifiedFunction::getGmtOffset();
-
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createDateTime(
- 1900 + lT.tm_year,
- lT.tm_mon,
- lT.tm_mday,
- lT.tm_hour,
- lT.tm_min,
- lT.tm_sec,
- gmtOffset
- )
- )
- );
- }
- catch ( std::exception const &e ) {
- throw raiseFileError( "FOFL9999", e.what(), path );
- }
-}
-
-int
-LastModifiedFunction::getGmtOffset()
-{
- time_t t = ::time(0);
- struct tm* data;
- data = localtime(&t);
- data->tm_isdst = 0;
- time_t a = mktime(data);
- data = gmtime(&t);
- data->tm_isdst = 0;
- time_t b = mktime(data);
- return (int)(a - b)/3600;
-}
-
-//*****************************************************************************
-
-SizeFunction::SizeFunction(const FileModule* aModule)
- : FileFunction(aModule)
-{
-}
-
-ItemSequence_t
-SizeFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
-
- fs::info info;
- if ( !fs::get_type( path, &info ) )
- raiseFileError( "FOFL0001", "file not found", path );
- if ( info.type != fs::file )
- raiseFileError( "FOFL0004", "not plain file", path );
-
- return ItemSequence_t(new SingletonItemSequence(
- theModule->getItemFactory()->createInteger(info.size)));
-}
-
-//*****************************************************************************
-
-PathSeparator::PathSeparator(const FileModule* aModule)
- : FileFunction(aModule)
+ return !!theStream;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PathSeparator::PathSeparator( FileModule const *m ) :
+ FileFunction( m, "path-separator" )
{
}
@@ -649,58 +652,15 @@
String const path_separator( 1, fs::path_separator );
return ItemSequence_t(
new SingletonItemSequence(
- theModule->getItemFactory()->createString( path_separator )
- )
- );
-}
-
-//*****************************************************************************
-
-DirectorySeparator::DirectorySeparator(const FileModule* aModule)
- : FileFunction(aModule)
-{
-}
-
-ItemSequence_t
-DirectorySeparator::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const dir_separator( 1, fs::dir_separator );
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createString( dir_separator )
- )
- );
-}
-
-//*****************************************************************************
-
-ResolvePathFunction::ResolvePathFunction(const FileModule* aModule)
- : FileFunction(aModule)
-{
-}
-
-ItemSequence_t
-ResolvePathFunction::evaluate(
- ExternalFunction::Arguments_t const &args,
- StaticContext const*,
- DynamicContext const* ) const
-{
- String const path( getPathArg( args, 0 ) );
- String const result( pathToOSPath( path ) );
- return ItemSequence_t(
- new SingletonItemSequence(
- theModule->getItemFactory()->createString( result )
- )
- );
-}
-
-//*****************************************************************************
-
-PathToNativeFunction::PathToNativeFunction(const FileModule* aModule)
- : FileFunction(aModule)
+ module_->getItemFactory()->createString( path_separator )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PathToNativeFunction::PathToNativeFunction( FileModule const *m ) :
+ FileFunction( m, "path-to-native" )
{
}
@@ -715,7 +675,7 @@
String const native_path( fs::normalize_path( path ) );
return ItemSequence_t(
new SingletonItemSequence(
- theModule->getItemFactory()->createString( native_path )
+ module_->getItemFactory()->createString( native_path )
)
);
}
@@ -724,10 +684,10 @@
}
}
-//*****************************************************************************
+///////////////////////////////////////////////////////////////////////////////
-PathToUriFunction::PathToUriFunction(const FileModule* aModule)
- : FileFunction(aModule)
+PathToUriFunction::PathToUriFunction( FileModule const *m ) :
+ FileFunction( m, "path-to-uri" )
{
}
@@ -741,80 +701,87 @@
String const result = pathToUriString( path );
return ItemSequence_t(
new SingletonItemSequence(
- theModule->getItemFactory()->createAnyURI( result ) )
- );
-}
-
-//*****************************************************************************
-
-WriteTextFunction::WriteTextFunction(const FileModule* aModule)
- : WriterFileFunction(aModule)
-{
-}
-
-bool
-WriteTextFunction::isAppend() const {
- return false;
-}
-
-bool
-WriteTextFunction::isBinary() const {
- return false;
-}
-
-//*****************************************************************************
-
-WriteBinaryFunction::WriteBinaryFunction(const FileModule* aModule)
- : WriterFileFunction(aModule)
-{
-}
-
-bool
-WriteBinaryFunction::isAppend() const {
- return false;
-}
-
-bool
-WriteBinaryFunction::isBinary() const {
- return true;
-}
-
-//*****************************************************************************
-
-AppendTextFunction::AppendTextFunction(const FileModule* aModule)
- : WriterFileFunction(aModule)
-{
-}
-
-bool
-AppendTextFunction::isAppend() const {
- return true;
-}
-
-bool
-AppendTextFunction::isBinary() const {
- return false;
-}
-
-//*****************************************************************************
-
-AppendBinaryFunction::AppendBinaryFunction(const FileModule* aModule)
- : WriterFileFunction(aModule)
-{
-}
-
-bool
-AppendBinaryFunction::isAppend() const {
- return true;
-}
-
-bool
-AppendBinaryFunction::isBinary() const {
- return true;
-}
-
-//*****************************************************************************
-
+ module_->getItemFactory()->createAnyURI( result )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+ResolvePathFunction::ResolvePathFunction( FileModule const *m ) :
+ FileFunction( m, "resolve-path" )
+{
+}
+
+ItemSequence_t
+ResolvePathFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+ try {
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createString( fs::normalize_path( path ) )
+ )
+ );
+ }
+ catch ( std::invalid_argument const &e ) {
+ throw raiseFileError( "FOFL9999", e.what(), path );
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+SizeFunction::SizeFunction( FileModule const *m ) :
+ FileFunction( m, "size" )
+{
+}
+
+ItemSequence_t
+SizeFunction::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+
+ fs::info info;
+ if ( !fs::get_type( path, &info ) )
+ raiseFileError( "FOFL0001", "file not found", path );
+ if ( info.type != fs::file )
+ raiseFileError( "FOFL0004", "not plain file", path );
+
+ return ItemSequence_t(
+ new SingletonItemSequence(
+ module_->getItemFactory()->createInteger( info.size )
+ )
+ );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+WriteBinaryFunction::WriteBinaryFunction( FileModule const *m ) :
+ WriteBinaryFunctionImpl( m, "write-binary", false )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+WriteTextFunction::WriteTextFunction( FileModule const *m ) :
+ WriteTextFunctionImpl( m, "write-text", false, false )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+WriteTextLinesFunction::WriteTextLinesFunction( FileModule const *m ) :
+ WriteTextFunctionImpl( m, "write-text-lines", false, true )
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
} // namespace filemodule
} // namespace zorba
=== modified file 'modules/org/expath/ns/file.xq.src/file.h'
--- modules/org/expath/ns/file.xq.src/file.h 2013-06-12 15:35:27 +0000
+++ modules/org/expath/ns/file.xq.src/file.h 2013-08-05 22:16:26 +0000
@@ -1,12 +1,12 @@
/*
* Copyright 2006-2008 The FLWOR Foundation.
- *
+ *
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,488 +20,361 @@
#include "file_function.h"
-namespace zorba {
-
- class ItemFactory;
-
- namespace filemodule {
-
-//*****************************************************************************
-
- class BaseNameFunction : public FileFunction
- {
- public:
- BaseNameFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "base-name"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class CreateDirectoryFunction : public FileFunction
- {
- public:
- CreateDirectoryFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "create-directory"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class DeleteFileImplFunction : public FileFunction
- {
- public:
- DeleteFileImplFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "delete-file-impl"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class DirNameFunction : public FileFunction
- {
- public:
- DirNameFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "dir-name"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class CopyFileImplFunction : public FileFunction
- {
- public:
- CopyFileImplFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "copy-file-impl"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class ExistsFunction : public FileFunction
- {
- public:
- ExistsFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "exists"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class ListFunction : public FileFunction
- {
- public:
- ListFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "list"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- private:
- class IteratorBackedItemSequence : public ItemSequence , public Iterator{
-
- public:
- IteratorBackedItemSequence(
- String const& path,
- zorba::ItemFactory* aFactory);
-
- virtual ~IteratorBackedItemSequence();
-
- //ItemSequence interface
- Iterator_t getIterator();
-
- //Iterator interface
- virtual void open();
- virtual bool next(Item& aItem);
- virtual void close();
- virtual bool isOpen() const;
- private:
- bool is_open;
- int open_count;
- fs::iterator theIterator;
- ItemFactory* theItemFactory;
+namespace zorba {
+
+class ItemFactory;
+
+namespace filemodule {
+
+//*****************************************************************************
+
+class AppendTextFunction : public WriteTextFunctionImpl {
+public:
+ AppendTextFunction( FileModule const* );
+};
+
+//*****************************************************************************
+
+class AppendTextLinesFunction : public WriteTextFunctionImpl {
+public:
+ AppendTextLinesFunction( FileModule const* );
+};
+
+//*****************************************************************************
+
+class AppendBinaryFunction : public WriteBinaryFunctionImpl {
+public:
+ AppendBinaryFunction( FileModule const* );
+};
+
+//*****************************************************************************
+
+class BaseNameFunction : public FileFunction {
+public:
+ BaseNameFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class CopyFileImplFunction : public FileFunction {
+public:
+ CopyFileImplFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class CreateDirectoryFunction : public FileFunction {
+public:
+ CreateDirectoryFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class DeleteFileImplFunction : public FileFunction {
+public:
+ DeleteFileImplFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class DirectorySeparator : public FileFunction {
+public:
+ DirectorySeparator( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class DirNameFunction : public FileFunction {
+public:
+ DirNameFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class ExistsFunction : public FileFunction {
+public:
+ ExistsFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class ListFunction : public FileFunction {
+public:
+ ListFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+private:
+ class IteratorBackedItemSequence : public ItemSequence, public Iterator {
+ public:
+ IteratorBackedItemSequence( String const &path, zorba::ItemFactory* );
+
+ //ItemSequence interface
+ Iterator_t getIterator();
+
+ //Iterator interface
+ virtual void open();
+ virtual bool next(Item& aItem);
+ virtual void close();
+ virtual bool isOpen() const;
+
+ private:
+ bool is_open;
+ int open_count;
+ fs::iterator theIterator;
+ ItemFactory *theItemFactory;
+ };
+};
+
+//*****************************************************************************
+
+class IsDirectoryFunction : public FileFunction {
+public:
+ IsDirectoryFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class IsFileFunction : public FileFunction {
+public:
+ IsFileFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class IsSymlinkFunction : public FileFunction {
+public:
+ IsSymlinkFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class LastModifiedFunction : public FileFunction {
+public:
+ LastModifiedFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+
+private:
+ static int getGmtOffset();
+};
+
+//*****************************************************************************
+
+class ResolvePathFunction : public FileFunction {
+public:
+ ResolvePathFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class PathSeparator : public FileFunction {
+public:
+ PathSeparator( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class PathToNativeFunction : public FileFunction {
+public:
+ PathToNativeFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class PathToUriFunction : public FileFunction {
+public:
+ PathToUriFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class ReadBinaryFunction : public FileFunction {
+public:
+ ReadBinaryFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class ReadTextFunction : public FileFunction {
+public:
+ ReadTextFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+};
+
+//*****************************************************************************
+
+class ReadTextLinesFunction : public FileFunction {
+public:
+ ReadTextLinesFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+
+protected:
+ class LinesItemSequence : public ItemSequence {
+ protected:
+ String theFile;
+ String theEncoding;
+ const ReadTextLinesFunction* theFunc;
+
+ class LinesIterator : public Iterator {
+ protected:
+ const String& theFile;
+ const String& theEncoding;
+ const ReadTextLinesFunction* theFunc;
+
+ std::ifstream* theStream;
+
+ public:
+ LinesIterator(
+ const String&,
+ const String&,
+ const ReadTextLinesFunction*);
+
+ virtual ~LinesIterator();
+
+ virtual void open();
+ virtual bool next(Item&);
+ virtual void close();
+ virtual bool isOpen() const;
};
- };
-
-//*****************************************************************************
-
- class IsDirectoryFunction : public FileFunction
- {
- public:
- IsDirectoryFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "is-directory"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class IsFileFunction : public FileFunction
- {
- public:
- IsFileFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "is-file"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class IsSymlinkFunction : public FileFunction
- {
- public:
- IsSymlinkFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "is-symlink"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class LastModifiedFunction : public FileFunction
- {
- public:
- LastModifiedFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "last-modified"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
-
- private:
- static int
- getGmtOffset();
-
- };
-
-//*****************************************************************************
-
- class SizeFunction : public FileFunction
- {
- public:
- SizeFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "size"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
-
- private:
- static int
- getGmtOffset();
-
- };
-
-//*****************************************************************************
-
- class PathSeparator : public FileFunction
- {
- public:
- PathSeparator(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "path-separator"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class DirectorySeparator : public FileFunction
- {
- public:
- DirectorySeparator(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "directory-separator"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class ResolvePathFunction : public FileFunction
- {
- public:
- ResolvePathFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "resolve-path"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class PathToUriFunction : public FileFunction
- {
- public:
- PathToUriFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "path-to-uri"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class PathToNativeFunction : public FileFunction
- {
- public:
- PathToNativeFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "path-to-native"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aStctxCtx,
- const DynamicContext* aDznCtx) const;
- };
-
-//*****************************************************************************
-
- class ReadBinaryFunction : public FileFunction
- {
- public:
- ReadBinaryFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "read-binary"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class ReadTextFunction : public StreamableFileFunction
- {
- public:
- ReadTextFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "read-text"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
- };
-
-//*****************************************************************************
-
- class ReadTextLinesFunction : public FileFunction
- {
- public:
- ReadTextLinesFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "read-text-lines"; }
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
-
- protected:
- class LinesItemSequence : public ItemSequence
- {
- protected:
- String theFile;
- String theEncoding;
- const ReadTextLinesFunction* theFunc;
-
- class LinesIterator : public Iterator
- {
- protected:
- const String& theFile;
- const String& theEncoding;
- const ReadTextLinesFunction* theFunc;
-
- std::ifstream* theStream;
-
- public:
- LinesIterator(
- const String&,
- const String&,
- const ReadTextLinesFunction*);
-
- virtual ~LinesIterator();
-
- virtual void
- open();
-
- virtual bool
- next(Item&);
-
- virtual void
- close();
-
- virtual bool
- isOpen() const;
- };
-
- public:
- LinesItemSequence(
- const String& aFile,
- const String& aEncoding,
- const ReadTextLinesFunction*);
-
- Iterator_t
- getIterator();
- };
- };
-
-//*****************************************************************************
-
- class WriteTextFunction : public WriterFileFunction
- {
- public:
- WriteTextFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "write-text"; }
-
- protected:
- virtual bool
- isAppend() const;
-
- virtual bool
- isBinary() const;
- };
-
-//*****************************************************************************
-
- class WriteBinaryFunction : public WriterFileFunction
- {
- public:
- WriteBinaryFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "write-binary"; }
-
- protected:
- virtual bool
- isAppend() const;
-
- virtual bool
- isBinary() const;
- };
-
-//*****************************************************************************
-
- class AppendTextFunction : public WriterFileFunction
- {
- public:
- AppendTextFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "append-text"; }
-
- protected:
- virtual bool
- isAppend() const;
-
- virtual bool
- isBinary() const;
- };
-
-//*****************************************************************************
-
- class AppendBinaryFunction : public WriterFileFunction
- {
- public:
- AppendBinaryFunction(const FileModule* aModule);
-
- virtual String
- getLocalName() const { return "append-binary"; }
-
- protected:
- virtual bool
- isAppend() const;
-
- virtual bool
- isBinary() const;
- };
-
-//*****************************************************************************
-
-} /* namespace filemodule */ } /* namespace zorba */
-
+
+ public:
+ LinesItemSequence(
+ const String& aFile,
+ const String& aEncoding,
+ const ReadTextLinesFunction*);
+
+ Iterator_t getIterator();
+ };
+};
+
+//*****************************************************************************
+
+class SizeFunction : public FileFunction {
+public:
+ SizeFunction( FileModule const* );
+
+ virtual ItemSequence_t
+ evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+
+private:
+ static int getGmtOffset();
+};
+
+//*****************************************************************************
+
+class WriteTextFunction : public WriteTextFunctionImpl {
+public:
+ WriteTextFunction( FileModule const* );
+};
+
+//*****************************************************************************
+
+class WriteTextLinesFunction : public WriteTextFunctionImpl {
+public:
+ WriteTextLinesFunction( FileModule const* );
+};
+
+//*****************************************************************************
+
+class WriteBinaryFunction : public WriteBinaryFunctionImpl {
+public:
+ WriteBinaryFunction( FileModule const* );
+};
+
+//*****************************************************************************
+
+} // namespace filemodule
+} // namespace zorba
#endif /* ZORBA_FILEMODULE_FILE_H */
+/* vim:set et sw=2 ts=2: */
=== modified file 'modules/org/expath/ns/file.xq.src/file_function.cpp'
--- modules/org/expath/ns/file.xq.src/file_function.cpp 2013-06-12 23:54:27 +0000
+++ modules/org/expath/ns/file.xq.src/file_function.cpp 2013-08-05 22:16:26 +0000
@@ -14,280 +14,228 @@
* limitations under the License.
*/
-#include "file_function.h"
-
+// standard
+#include <cstdio>
+#include <cstdlib>
#include <sstream>
+#ifdef WIN32
+#include <windows.h>
+#include <direct.h>
+#else
+#include <unistd.h>
+#endif /* WIN32 */
+// Zorba
+#include <zorba/diagnostic_list.h>
#include <zorba/empty_sequence.h>
-#include <zorba/diagnostic_list.h>
#include <zorba/serializer.h>
+#include <zorba/singleton_item_sequence.h>
#include <zorba/store_consts.h>
#include <zorba/user_exception.h>
+#include <zorba/util/base64_util.h>
#include <zorba/util/fs_util.h>
+#include <zorba/util/transcode_stream.h>
#include <zorba/xquery_functions.h>
-#include <zorba/singleton_item_sequence.h>
#include <zorba/zorba.h>
+// local
+#include "file_function.h"
#include "file_module.h"
-#include <cassert>
-
-#include <stdlib.h>
-#include <stdio.h>
-#ifdef WIN32
-#include <Windows.h>
-#include <direct.h>
-#else
-#include <unistd.h>
-#endif
-
-namespace zorba { namespace filemodule {
-
-FileFunction::FileFunction(const FileModule* aModule)
- : theModule(aModule)
-{
-}
-
-FileFunction::~FileFunction()
-{
-}
-
-int
-FileFunction::raiseFileError(
- char const *aQName,
- char const *aMessage,
- String const &aPath ) const
-{
+using namespace std;
+
+namespace zorba {
+namespace filemodule {
+
+///////////////////////////////////////////////////////////////////////////////
+
+FileFunction::FileFunction( FileModule const *m, char const *local_name ) :
+ module_( m ),
+ local_name_( local_name )
+{
+}
+
+String FileFunction::getLocalName() const {
+ return local_name_;
+}
+
+int FileFunction::raiseFileError( char const *aQName, char const *aMessage,
+ String const &aPath ) const {
Item const lQName(
- theModule->getItemFactory()->createQName( getURI(), "file", aQName )
+ module_->getItemFactory()->createQName( getURI(), "file", aQName )
);
- std::ostringstream lErrorMessage;
+ ostringstream lErrorMessage;
lErrorMessage << '"' << aPath << "\": " << aMessage;
throw USER_EXCEPTION( lQName, lErrorMessage.str() );
}
-String
-FileFunction::getURI() const
-{
- return theModule->getURI();
+String FileFunction::getURI() const {
+ return module_->getURI();
}
-String
-FileFunction::getEncodingArg(
- const ExternalFunction::Arguments_t& aArgs,
- unsigned int aPos) const
-{
- String encoding( getStringArg( aArgs, aPos ) );
+String FileFunction::getEncodingArg( ExternalFunction::Arguments_t const &args,
+ unsigned pos ) const {
+ String encoding( getStringArg( args, pos ) );
if ( encoding.empty() )
encoding = "UTF-8"; // the default file encoding
return encoding;
}
-String
-FileFunction::getPathArg(
- const ExternalFunction::Arguments_t& aArgs,
- unsigned int aPos) const
-{
- String const path( getStringArg( aArgs, aPos ) );
+String FileFunction::getPathArg( ExternalFunction::Arguments_t const &args,
+ unsigned pos ) const {
+ String const path( getStringArg( args, pos ) );
if ( path.empty() )
return path;
try {
return fs::normalize_path( path, fs::curdir() );
}
- catch ( std::invalid_argument const &e ) {
+ catch ( invalid_argument const &e ) {
throw raiseFileError( "FOFL9999", e.what(), path );
}
}
-String
-FileFunction::getStringArg(
- const ExternalFunction::Arguments_t& aArgs,
- unsigned int aPos) const
-{
- String str;
- if ( aPos < aArgs.size() ) {
- Iterator_t i( aArgs[ aPos ]->getIterator() );
- i->open();
+String FileFunction::getStringArg( ExternalFunction::Arguments_t const &args,
+ unsigned pos ) const {
+ String s;
+ if ( pos < args.size() ) {
+ Iterator_t it( args[ pos ]->getIterator() );
+ it->open();
Item item;
- if ( i->next( item ) )
- str = item.getStringValue();
- i->close();
- }
- return str;
-}
-
-String
-FileFunction::pathToFullOSPath(const String& aPath) const {
- try {
- return fs::normalize_path( aPath );
- }
- catch ( std::invalid_argument const &e ) {
- throw raiseFileError( "FOFL9999", e.what(), aPath );
- }
-}
-
-String
-FileFunction::pathToOSPath(const String& aPath) const {
- try {
- return fs::normalize_path( aPath );
- }
- catch ( std::invalid_argument const &e ) {
- throw raiseFileError( "FOFL9999", e.what(), aPath );
- }
-}
-
-String
-FileFunction::pathToUriString(const String& aPath) const {
-
+ if ( it->next( item ) )
+ s = item.getStringValue();
+ it->close();
+ }
+ return s;
+}
+
+String FileFunction::pathToUriString(const String& aPath) const {
if ( fn::starts_with( aPath,"file://" ) ) {
- std::stringstream lErrorMessage;
- lErrorMessage << "Please provide a path, not a URI";
- Item lQName = theModule->getItemFactory()->createQName(
- "http://www.w3.org/2005/xqt-errors",
- "err",
- "XPTY0004");
- throw USER_EXCEPTION( lQName, lErrorMessage.str() );
+ stringstream msg;
+ msg << '"' << aPath << "\": path must not be a URI";
+ Item const lQName(
+ module_->getItemFactory()->createQName(
+ "http://www.w3.org/2005/xqt-errors", "err", "XPTY0004"
+ )
+ );
+ throw USER_EXCEPTION( lQName, msg.str() );
}
-
- String uri( aPath );
-
+ String const uri( aPath );
return uri;
}
-#ifdef WIN32
-bool
-FileFunction::isValidDriveSegment(
- String& aString)
-{
- aString = fn::upper_case( aString );
- // the drive segment has one of the forms: "C:", "C%3A"
- if ((aString.length() != 2 && aString.length() != 4) ||
- (aString.length() == 2 && !fn::ends_with(aString,":")) ||
- (aString.length() == 4 && !fn::ends_with(aString,"%3A"))) {
- return false;
- }
-
- char const lDrive = aString[0];
- // the string is already upper case
- return lDrive >= 'A' && lDrive <= 'Z';
-}
-#endif
-
-//*****************************************************************************
-
-StreamableFileFunction::StreamableFileFunction(const FileModule* aModule)
- : FileFunction(aModule)
-{
-}
-
-StreamableFileFunction::~StreamableFileFunction()
-{
-}
-
-bool
-StreamableFileFunction::StreamableItemSequence::InternalIterator::next(Item& aResult)
-{
- assert(theIsOpen);
-
- if (theHasNext) {
- aResult = theItemSequence->theItem;
- theHasNext = false;
- return !aResult.isNull();
- }
- return false;
-}
-
-//*****************************************************************************
-
-WriterFileFunction::WriterFileFunction(const FileModule* aModule)
- : FileFunction(aModule)
-{
-}
-
-WriterFileFunction::~WriterFileFunction()
-{
-}
-
-ItemSequence_t
-WriterFileFunction::evaluate(
- const ExternalFunction::Arguments_t& aArgs,
- const StaticContext*,
- const DynamicContext* ) const
-{
- String const lFileStr( getPathArg(aArgs, 0) );
-
- fs::type const fs_type = fs::get_type( lFileStr );
- if ( fs_type && fs_type != fs::file )
- raiseFileError( "FOFL0004", "not a plain file", lFileStr );
-
- bool const lBinary = isBinary();
-
- std::ios_base::openmode mode = std::ios_base::out
- | (isAppend() ? std::ios_base::app : std::ios_base::trunc);
- if ( lBinary )
- mode |= std::ios_base::binary;
-
- std::ofstream lOutStream( lFileStr.c_str(), mode );
- if ( !lOutStream ) {
- std::ostringstream oss;
- oss << '"' << lFileStr << "\": can not open file for writing";
- raiseFileError( "FOFL9999", oss.str().c_str(), lFileStr );
- }
-
- // if this is a binary write
- if (lBinary)
- {
- Item lBinaryItem;
- Iterator_t lContentSeq = aArgs[1]->getIterator();
- lContentSeq->open();
- while (lContentSeq->next(lBinaryItem))
- {
- if (lBinaryItem.isStreamable() && !lBinaryItem.isEncoded())
- {
- lOutStream << lBinaryItem.getStream().rdbuf();
- }
- else
- {
- Zorba_SerializerOptions lOptions;
- lOptions.ser_method = ZORBA_SERIALIZATION_METHOD_BINARY;
- Serializer_t lSerializer = Serializer::createSerializer(lOptions);
- SingletonItemSequence lSeq(lBinaryItem);
- lSerializer->serialize(&lSeq, lOutStream);
- }
-
- }
- }
- // if we only write text
- else
- {
- Item lStringItem;
- Iterator_t lContentSeq = aArgs[1]->getIterator();
- lContentSeq->open();
- // for each item (string or base64Binary) in the content sequence
- while (lContentSeq->next(lStringItem)) {
- // if the item is streamable make use of the stream
- if (lStringItem.isStreamable()) {
- std::istream& lInStream = lStringItem.getStream();
- char lBuf[1024];
- while (!lInStream.eof()) {
- lInStream.read(lBuf, 1024);
- lOutStream.write(lBuf, lInStream.gcount());
- }
- }
- // else write the string value
- else {
- zorba::String lString = lStringItem.getStringValue();
- lOutStream.write(lString.data(), lString.size());
- }
- }
- lContentSeq->close();
- }
-
- // close the file stream
- lOutStream.close();
-
- return ItemSequence_t(new EmptySequence());
-}
+///////////////////////////////////////////////////////////////////////////////
+
+WriteBinaryFunctionImpl::WriteBinaryFunctionImpl( FileModule const *m,
+ char const *local_name,
+ bool append ) :
+ FileFunction( m, local_name ),
+ append_( append )
+{
+}
+
+ItemSequence_t WriteBinaryFunctionImpl::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+
+ fs::type const fs_type = fs::get_type( path );
+ if ( fs_type && fs_type != fs::file )
+ raiseFileError( "FOFL0004", "not a plain file", path );
+
+ ios_base::openmode const mode = ios_base::out | ios_base::binary
+ | (append_ ? ios_base::app : ios_base::trunc);
+
+ ofstream ofs( path.c_str(), mode );
+ if ( !ofs ) {
+ ostringstream oss;
+ oss << '"' << path << "\": can not open file for writing";
+ raiseFileError( "FOFL9999", oss.str().c_str(), path );
+ }
+
+ Iterator_t it( args[1]->getIterator() );
+ it->open();
+ Item item;
+ while ( it->next( item ) ) {
+ if ( item.isStreamable() ) {
+ if ( item.isEncoded() )
+ base64::decode( item.getStream(), ofs );
+ else
+ ofs << item.getStream().rdbuf();
+ } else {
+ size_t b64_size;
+ char const *const b64_value = item.getBase64BinaryValue( b64_size );
+ if ( item.isEncoded() )
+ base64::decode( b64_value, b64_size, ofs );
+ else
+ ofs.write( b64_value, b64_size );
+ }
+ }
+ it->close();
+
+ return ItemSequence_t( new EmptySequence() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+WriteTextFunctionImpl::WriteTextFunctionImpl( FileModule const *m,
+ char const *local_name,
+ bool append, bool newlines ) :
+ FileFunction( m, local_name ),
+ append_( append ),
+ newlines_( newlines )
+{
+}
+
+ItemSequence_t WriteTextFunctionImpl::evaluate(
+ ExternalFunction::Arguments_t const &args,
+ StaticContext const*,
+ DynamicContext const* ) const
+{
+ String const path( getPathArg( args, 0 ) );
+ String const encoding( getStringArg( args, 2 ) );
+
+ fs::type const fs_type = fs::get_type( path );
+ if ( fs_type && fs_type != fs::file )
+ raiseFileError( "FOFL0004", "not a plain file", path );
+
+ if ( !transcode::is_supported( encoding.c_str() ) )
+ raiseFileError( "FOFL9999", "encoding not supported", encoding );
+
+ ios_base::openmode const mode = ios_base::out
+ | (append_ ? ios_base::app : ios_base::trunc);
+
+ ofstream ofs( path.c_str(), mode );
+ if ( !ofs ) {
+ ostringstream oss;
+ oss << '"' << path << "\": can not open file for writing";
+ raiseFileError( "FOFL9999", oss.str().c_str(), path );
+ }
+
+ transcode::auto_attach<ofstream> transcoder;
+ if ( transcode::is_necessary( encoding.c_str() ) )
+ transcoder.attach( ofs, encoding.c_str() );
+
+ Iterator_t it( args[1]->getIterator() );
+ it->open();
+ Item item;
+ while ( it->next( item ) ) {
+ if ( item.isStreamable() ) {
+ ofs << item.getStream().rdbuf();
+ } else {
+ zorba::String const s( item.getStringValue() );
+ ofs.write( s.data(), s.size() );
+ }
+ if ( newlines_ )
+ ofs << fs::newline;
+ }
+ it->close();
+
+ return ItemSequence_t( new EmptySequence() );
+}
+
+///////////////////////////////////////////////////////////////////////////////
} // namespace filemodule
} // namespace zorba
=== modified file 'modules/org/expath/ns/file.xq.src/file_function.h'
--- modules/org/expath/ns/file.xq.src/file_function.h 2013-06-12 23:54:27 +0000
+++ modules/org/expath/ns/file.xq.src/file_function.h 2013-08-05 22:16:26 +0000
@@ -17,162 +17,87 @@
#ifndef ZORBA_FILEMODULE_FILEFUNCTION_H
#define ZORBA_FILEMODULE_FILEFUNCTION_H
+// standard
+#include <fstream>
+
+// Zorba
#include <zorba/error.h>
#include <zorba/function.h>
#include <zorba/item.h>
#include <zorba/iterator.h>
#include <zorba/options.h>
-#include <fstream>
-
namespace zorba {
-
- namespace filemodule {
-
- class FileModule;
-
- class FileFunction : public ContextualExternalFunction
- {
- private:
-
-#ifdef WIN32
- static bool
- isValidDriveSegment(
- String& value);
-#endif
-
- protected:
- const FileModule* theModule;
-
- int
- raiseFileError(
- char const *qName,
- char const *message,
- const String& path) const;
-
- /*
- * Gets the argument on position pos as a normalised file system path.
- * pos must point to a file function argument. No checks are made.
- */
- String
- getPathArg(
- const ExternalFunction::Arguments_t& args,
- unsigned int pos) const;
-
- String
- getEncodingArg(
- const ExternalFunction::Arguments_t& args,
- unsigned int pos) const;
-
- String
- getStringArg(
- const ExternalFunction::Arguments_t& args,
- unsigned int pos) const;
-
- String
- pathToFullOSPath(const String& path) const;
-
- String
- pathToOSPath(const String& path) const;
-
- String
- pathToUriString(const String& path) const;
-
- public:
- FileFunction(const FileModule* module);
- ~FileFunction();
-
- virtual String
- getURI() const;
-
- };
-
- class StreamableFileFunction : public FileFunction
- {
- public:
-
- StreamableFileFunction(const FileModule* module);
-
- ~StreamableFileFunction();
-
- protected:
-
- class StreamableItemSequence : public ItemSequence {
-
- public:
- class InternalIterator : public Iterator
- {
- private:
- StreamableItemSequence *theItemSequence;
- bool theIsOpen;
- bool theHasNext;
-
- public:
- InternalIterator(StreamableItemSequence* aItemSequence)
- : theItemSequence(aItemSequence),
- theIsOpen(false),
- theHasNext(true)
- { }
-
- virtual void
- open()
- {
- theIsOpen = true;
- theHasNext = true;
- }
-
- virtual void
- close()
- {
- theIsOpen = false;
- }
-
- virtual bool
- isOpen() const
- {
- return theIsOpen;
- }
-
- bool
- next(Item& aResult);
- };
-
- Item theItem;
- std::ifstream* theStream;
-
- StreamableItemSequence()
- : theStream(new std::ifstream()) {}
-
- Iterator_t getIterator()
- {
- return new InternalIterator(this);
- }
- };
- };
-
- class WriterFileFunction : public FileFunction
- {
- public:
-
- WriterFileFunction(const FileModule* module);
-
- ~WriterFileFunction();
-
- virtual ItemSequence_t
- evaluate(const ExternalFunction::Arguments_t& args,
- const StaticContext* aSctxCtx,
- const DynamicContext* aDynCtx) const;
-
- protected:
-
- virtual bool
- isAppend() const = 0;
-
- virtual bool
- isBinary() const = 0;
- };
-
-} /* namespace filemodule */
-} /* namespace zorba */
+namespace filemodule {
+
+class FileModule;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class FileFunction : public ContextualExternalFunction {
+public:
+ virtual String getLocalName() const;
+ virtual String getURI() const;
+
+protected:
+ FileFunction( FileModule const *module, char const *local_name );
+
+ /**
+ * Gets the argument on position pos as a normalised file system path.
+ * pos must point to a file function argument. No checks are made.
+ */
+ String getPathArg( ExternalFunction::Arguments_t const&, unsigned pos ) const;
+
+ String getEncodingArg( ExternalFunction::Arguments_t const&,
+ unsigned pos ) const;
+
+ String getStringArg( ExternalFunction::Arguments_t const&,
+ unsigned pos ) const;
+
+ String pathToUriString(const String& path) const;
+
+ int raiseFileError( char const *qName, char const *message,
+ String const &path ) const;
+
+ FileModule const *module_;
+ char const *const local_name_; // points to string literal
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class WriteBinaryFunctionImpl : public FileFunction {
+public:
+ ItemSequence_t evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+
+protected:
+ WriteBinaryFunctionImpl( FileModule const*, char const *local_name,
+ bool append );
+
+ bool const append_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+class WriteTextFunctionImpl : public FileFunction {
+public:
+ ItemSequence_t evaluate( ExternalFunction::Arguments_t const&,
+ StaticContext const*,
+ DynamicContext const* ) const;
+
+protected:
+ WriteTextFunctionImpl( FileModule const*, char const *local_name,
+ bool append, bool newlines );
+
+ bool const append_;
+ bool const newlines_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+} // namespace filemodule
+} // namespace zorba
#endif /* ZORBA_FILEMODULE_FILEFUNCTION_H */
+/* vim:set et sw=2 ts=2: */
=== modified file 'modules/org/expath/ns/file.xq.src/file_module.cpp'
--- modules/org/expath/ns/file.xq.src/file_module.cpp 2013-06-12 15:35:27 +0000
+++ modules/org/expath/ns/file.xq.src/file_module.cpp 2013-08-05 22:16:26 +0000
@@ -1,12 +1,12 @@
/*
* Copyright 2006-2008 The FLWOR Foundation.
- *
+ *
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,87 +17,87 @@
#include "file.h"
#include "file_module.h"
#include "file_function.h"
-#include <cassert>
-
-namespace zorba { namespace filemodule {
-
- const char* FileModule::theNamespace = "http://expath.org/ns/file";
-
-
-FileModule::~FileModule()
-{
- for (FuncMap_t::const_iterator lIter = theFunctions.begin();
- lIter != theFunctions.end(); ++lIter) {
- delete lIter->second;
+
+namespace zorba {
+namespace filemodule {
+
+///////////////////////////////////////////////////////////////////////////////
+
+FileModule::~FileModule() {
+ for ( FuncMap_t::const_iterator i = theFunctions.begin();
+ i != theFunctions.end(); ++i ) {
+ delete i->second;
}
- theFunctions.clear();
}
-ExternalFunction*
-FileModule::getExternalFunction(const String& aLocalname)
-{
- ExternalFunction*& lFunc = theFunctions[aLocalname];
- if (!lFunc) {
- if (aLocalname == "base-name") {
- lFunc = new BaseNameFunction(this);
- } else if (aLocalname == "copy-file-impl") {
- lFunc = new CopyFileImplFunction(this);
- } else if (aLocalname == "create-directory") {
- lFunc = new CreateDirectoryFunction(this);
- } else if (aLocalname == "delete-file-impl") {
- lFunc = new DeleteFileImplFunction(this);
- } else if (aLocalname == "dir-name") {
- lFunc = new DirNameFunction(this);
- } else if (aLocalname == "exists") {
- lFunc = new ExistsFunction(this);
- } else if (aLocalname == "is-directory") {
- lFunc = new IsDirectoryFunction(this);
- } else if (aLocalname == "is-file") {
- lFunc = new IsFileFunction(this);
- } else if (aLocalname == "read-binary") {
- lFunc = new ReadBinaryFunction(this);
- } else if (aLocalname == "read-text") {
- lFunc = new ReadTextFunction(this);
- } else if (aLocalname == "read-text-lines") {
- lFunc = new ReadTextLinesFunction(this);
- } else if (aLocalname == "is-symlink") {
- lFunc = new IsSymlinkFunction(this);
- } else if (aLocalname == "write-text") {
- lFunc = new WriteTextFunction(this);
- } else if (aLocalname == "write-binary") {
- lFunc = new WriteBinaryFunction(this);
- } else if (aLocalname == "append-text") {
- lFunc = new AppendTextFunction(this);
- } else if (aLocalname == "append-binary") {
- lFunc = new AppendBinaryFunction(this);
- } else if (aLocalname == "list") {
- lFunc = new ListFunction(this);
- } else if (aLocalname == "last-modified") {
- lFunc = new LastModifiedFunction(this);
- } else if (aLocalname == "size") {
- lFunc = new SizeFunction(this);
- } else if (aLocalname == "directory-separator") {
- lFunc = new DirectorySeparator(this);
- } else if (aLocalname == "path-separator") {
- lFunc = new PathSeparator(this);
- } else if (aLocalname == "resolve-path") {
- lFunc = new ResolvePathFunction(this);
- } else if (aLocalname == "path-to-uri") {
- lFunc = new PathToUriFunction(this);
- } else if (aLocalname == "path-to-native") {
- lFunc = new PathToNativeFunction(this);
- }
+ExternalFunction* FileModule::getExternalFunction( String const &aLocalname ) {
+ ExternalFunction *&lFunc = theFunctions[ aLocalname ];
+ if ( !lFunc ) {
+ if ( aLocalname == "append-text" )
+ lFunc = new AppendTextFunction( this );
+ else if ( aLocalname == "append-text-lines" )
+ lFunc = new AppendTextLinesFunction( this );
+ else if ( aLocalname == "append-binary" )
+ lFunc = new AppendBinaryFunction( this );
+ else if ( aLocalname == "base-name" )
+ lFunc = new BaseNameFunction( this );
+ else if ( aLocalname == "copy-file-impl" )
+ lFunc = new CopyFileImplFunction( this );
+ else if ( aLocalname == "create-directory" )
+ lFunc = new CreateDirectoryFunction( this );
+ else if ( aLocalname == "delete-file-impl" )
+ lFunc = new DeleteFileImplFunction( this );
+ else if ( aLocalname == "dir-name" )
+ lFunc = new DirNameFunction( this );
+ else if ( aLocalname == "directory-separator" )
+ lFunc = new DirectorySeparator( this );
+ else if ( aLocalname == "exists" )
+ lFunc = new ExistsFunction( this );
+ else if ( aLocalname == "is-directory" )
+ lFunc = new IsDirectoryFunction( this );
+ else if ( aLocalname == "is-file" )
+ lFunc = new IsFileFunction( this );
+ else if ( aLocalname == "is-symlink" )
+ lFunc = new IsSymlinkFunction( this );
+ else if ( aLocalname == "last-modified" )
+ lFunc = new LastModifiedFunction( this );
+ else if ( aLocalname == "list" )
+ lFunc = new ListFunction( this );
+ else if ( aLocalname == "path-separator" )
+ lFunc = new PathSeparator( this );
+ else if ( aLocalname == "path-to-native" )
+ lFunc = new PathToNativeFunction( this );
+ else if ( aLocalname == "path-to-uri" )
+ lFunc = new PathToUriFunction( this );
+ else if ( aLocalname == "read-binary" )
+ lFunc = new ReadBinaryFunction( this );
+ else if ( aLocalname == "read-text" )
+ lFunc = new ReadTextFunction( this );
+ else if ( aLocalname == "read-text-lines" )
+ lFunc = new ReadTextLinesFunction( this );
+ else if ( aLocalname == "resolve-path" )
+ lFunc = new ResolvePathFunction( this );
+ else if ( aLocalname == "write-text" )
+ lFunc = new WriteTextFunction( this );
+ else if ( aLocalname == "write-text-lines" )
+ lFunc = new WriteTextLinesFunction( this );
+ else if ( aLocalname == "write-binary" )
+ lFunc = new WriteBinaryFunction( this );
+ else if ( aLocalname == "size" )
+ lFunc = new SizeFunction( this );
}
return lFunc;
}
-void
-FileModule::destroy()
-{
- if (dynamic_cast<FileModule*>(this)) {
- delete this;
- }
-}
+void FileModule::destroy() {
+ delete this;
+}
+
+String FileModule::getURI() const {
+ return "http://expath.org/ns/file";
+}
+
+///////////////////////////////////////////////////////////////////////////////
} // namespace filemodule
} // namespace zorba
=== modified file 'modules/org/expath/ns/file.xq.src/file_module.h'
--- modules/org/expath/ns/file.xq.src/file_module.h 2013-02-07 17:24:36 +0000
+++ modules/org/expath/ns/file.xq.src/file_module.h 2013-08-05 22:16:26 +0000
@@ -1,12 +1,12 @@
/*
* Copyright 2006-2008 The FLWOR Foundation.
- *
+ *
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,67 +22,44 @@
#include <zorba/zorba.h>
#include <zorba/external_module.h>
-namespace zorba { namespace filemodule {
-
-class FileModule : public ExternalModule
-{
-private:
- mutable ItemFactory* theFactory;
-
-public:
- static const char* theNamespace;
-
-protected:
- class ltstr
- {
- public:
- bool operator()(const String& s1, const String& s2) const
- {
- return s1.compare(s2) < 0;
- }
- };
-
- typedef std::map<String, ExternalFunction*, ltstr> FuncMap_t;
- FuncMap_t theFunctions;
-
-public:
- static void
- streamReleaser(std::istream* stream)
- {
+namespace zorba {
+namespace filemodule {
+
+///////////////////////////////////////////////////////////////////////////////
+
+class FileModule : public ExternalModule {
+public:
+ static void streamReleaser( std::istream *stream ) {
delete stream;
}
- FileModule() : theFactory(0) {}
-
+ FileModule() : theFactory(0) { }
virtual ~FileModule();
-
- virtual String
- getURI() const { return theNamespace; }
-
- virtual ExternalFunction*
- getExternalFunction(const String& aLocalname);
-
- virtual void
- destroy();
-
- ItemFactory*
- getItemFactory() const
- {
- if (!theFactory)
- {
+
+ virtual void destroy();
+ virtual ExternalFunction* getExternalFunction( String const &aLocalname );
+ virtual String getURI() const;
+
+ ItemFactory* getItemFactory() const {
+ if ( !theFactory )
theFactory = Zorba::getInstance(0)->getItemFactory();
- }
-
return theFactory;
}
+
+protected:
+ typedef std::map<String,ExternalFunction*> FuncMap_t;
+ FuncMap_t theFunctions;
+
+private:
+ mutable ItemFactory *theFactory;
};
+///////////////////////////////////////////////////////////////////////////////
-} /* namespace filemodule */
-} /* namespace zorba */
+} // namespace filemodule
+} // namespace zorba
#endif /* ZORBA_FILEMODULE_FILEMODULE_H */
-
/*
* Local variables:
* mode: c++
=== modified file 'scripts/notice-generator.xq.in'
--- scripts/notice-generator.xq.in 2013-02-07 17:24:36 +0000
+++ scripts/notice-generator.xq.in 2013-08-05 22:16:26 +0000
@@ -171,12 +171,8 @@
()
else
let $contents := local:contents($notice)
- return file:write (
- fn:concat($relpath-from-this, "/NOTICE.txt"), $contents,
- <output:serialization-parameters
- xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
- <output:method value="text"/>
- </output:serialization-parameters>
+ return file:write-text(
+ fn:concat($relpath-from-this, "/NOTICE.txt"), $contents
)
};
=== modified file 'src/util/fs_util.cpp'
--- src/util/fs_util.cpp 2013-06-17 22:19:13 +0000
+++ src/util/fs_util.cpp 2013-08-05 22:16:26 +0000
@@ -44,14 +44,21 @@
///////////////////////////////////////////////////////////////////////////////
-char const *const type_string[] = {
- "non_existant",
- "directory",
- "file",
- "link",
- "volume",
- "other"
-};
+ostream& operator<<( ostream &o, type t ) {
+ static char const *const string_of[] = {
+ "non_existant",
+ "directory",
+ "file",
+ "link",
+ "volume",
+ "other"
+ };
+ if ( t >= 0 && t <= other )
+ o << string_of[ t ];
+ else
+ o << "<invalid fs::type " << (int)t << '>';
+ return o;
+}
////////// helper functions ///////////////////////////////////////////////////
=== modified file 'test/rbkt/Queries/zorba/file/common.xqlib'
--- test/rbkt/Queries/zorba/file/common.xqlib 2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/file/common.xqlib 2013-08-05 22:16:26 +0000
@@ -37,8 +37,8 @@
}
};
-declare %ann:sequential function commons:testWriteXml($path as xs:string, $xml as item()) as xs:string* {
- file:write($path, $xml, ());
+declare %ann:sequential function commons:testWriteXml($path as xs:string, $xml as node()) as xs:string* {
+ file:write-text($path, serialize($xml));
"SUCCESS"
};
@@ -66,13 +66,15 @@
};
declare %ann:sequential function commons:testWriteSerializeXml($path as xs:string, $xml as item()) as xs:string* {
- file:write(
+ file:write-text(
$path,
- $xml,
- <output:serialization-parameters>
- <output:method value="xml"/>
- </output:serialization-parameters>);
-
+ fn:serialize(
+ $xml,
+ <output:serialization-parameters>
+ <output:method value="xml"/>
+ </output:serialization-parameters>
+ )
+ );
"SUCCESS";
};
@@ -138,3 +140,4 @@
else
fn:false()
};
+(: vim:set syntax=xquery et sw=2 ts=2: :)
=== modified file 'test/rbkt/Queries/zorba/file/file_read_serialize.xq'
--- test/rbkt/Queries/zorba/file/file_read_serialize.xq 2013-02-07 17:24:36 +0000
+++ test/rbkt/Queries/zorba/file/file_read_serialize.xq 2013-08-05 22:16:26 +0000
@@ -11,8 +11,7 @@
return replace value of node $price with xs:double($price) * 2;
(: write the updated data to a new file :)
-file:write("new-prices.xml", $local:my-doc, ());
+file:write-text("new-prices.xml", $local:my-doc);
(: return the new data as result of the program :)
$local:my-doc
-
Follow ups
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: noreply, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Paul J. Lucas, 2013-08-06
-
Re: [Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Matthias Brantner, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Paul J. Lucas, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-06
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-05
-
[Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Zorba Build Bot, 2013-08-05
-
Re: [Merge] lp:~zorba-coders/zorba/bug-942171 into lp:zorba
From: Paul J. Lucas, 2013-08-05