Changes

Jump to navigation Jump to search
6,402 bytes added ,  18:46, 16 November 2016
Update {{func link}} form
Line 1: Line 1: −
{{WIP}}
+
{{Nasal Navigation|nocat=1}}
{{Nasal Navigation}}
   
This page contains documentation for the '''<code>io</code> namespace''' in [[Nasal]]. This namespace provides APIs for input/output (IO) operations on files. The <code>io</code> namespace is sourced from {{fgdata file|Nasal/io.nas}} and {{simgear file|simgear/nasal/iolib.c}}.
 
This page contains documentation for the '''<code>io</code> namespace''' in [[Nasal]]. This namespace provides APIs for input/output (IO) operations on files. The <code>io</code> namespace is sourced from {{fgdata file|Nasal/io.nas}} and {{simgear file|simgear/nasal/iolib.c}}.
   Line 23: Line 22:  
|text = Flushes and closes the specified file. Returns <code>'''nil'''</code>.
 
|text = Flushes and closes the specified file. Returns <code>'''nil'''</code>.
 
|param1 = file
 
|param1 = file
|param1text = File object as returned by {{func link|open()}}.
+
|param1text = File object as returned by {{func link|open()|page=this}}.
 
|example1 = var path = getprop("/sim/fg-root") ~ '/keyboard.xml';
 
|example1 = var path = getprop("/sim/fg-root") ~ '/keyboard.xml';
 
var file = io.open(path);
 
var file = io.open(path);
Line 47: Line 46:  
{{Nasal doc
 
{{Nasal doc
 
|syntax = io.flush(file);
 
|syntax = io.flush(file);
|text = Flushes the file's buffer. This means that the contents of the buffer (a kind of temporary storage) are written to the actual file on the hard disk. Note that the buffer is also flushed when {{func link|close()}} is called.
+
|text = Flushes the file's buffer. This means that the contents of the buffer (a kind of temporary storage) are written to the actual file on the hard disk. Note that the buffer is also flushed when {{func link|close()|page=this}} is called.
 
|param1 = file
 
|param1 = file
|param1text = File object as returned by {{func link|open()}}.
+
|param1text = File object as returned by {{func link|open()|page=this}}.
 
|example1 = var path = getprop("/sim/fg-home") ~ '/Export/demo.txt';
 
|example1 = var path = getprop("/sim/fg-home") ~ '/Export/demo.txt';
 
var file = io.open(path, "w"); # create and open file
 
var file = io.open(path, "w"); # create and open file
Line 126: Line 125:  
{{!-}}
 
{{!-}}
 
{{!}} <code>a+</code>
 
{{!}} <code>a+</code>
{{!}} Opens a file for input and output operations. Output operations will append data to the end of the file. Input operations are affected by {{func link|seek()}}, but output operations will move the position back to the end of the file. The file is created if it does not exist.
+
{{!}} Opens a file for input and output operations. Output operations will append data to the end of the file. Input operations are affected by {{func link|seek()|page=this}}, but output operations will move the position back to the end of the file. The file is created if it does not exist.
 
{{!-}}
 
{{!-}}
 
{{!}} <code>rb</code>
 
{{!}} <code>rb</code>
Line 144: Line 143:  
{{!-}}
 
{{!-}}
 
{{!}} <code>a+b</code> ''or'' <code>ab+</code>
 
{{!}} <code>a+b</code> ''or'' <code>ab+</code>
{{!}} Opens a file for input and output operations, treating it as a binary file. Output operations will append data to the end of the file. Input operations are affected by {{func link|seek()}}, but output operations will move the position back to the end of the file. The file is created if it does not exist.
+
{{!}} Opens a file for input and output operations, treating it as a binary file. Output operations will append data to the end of the file. Input operations are affected by {{func link|seek()|page=this}}, but output operations will move the position back to the end of the file. The file is created if it does not exist.
 
{{!}}}
 
{{!}}}
 
|param1 = path
 
|param1 = path
Line 170: Line 169:  
{{Nasal doc
 
{{Nasal doc
 
|syntax = io.read(file, buf, len);
 
|syntax = io.read(file, buf, len);
|text = Reads a given number of bytes from the given file and places those bytes into the given buffer. The bytes will be read from the position of the position indicator (this can be changed using {{func link|seek}}). Failures are thrown as runtime errors. Returns the number of bytes successfully read.
+
|text = Reads a given number of bytes from the given file and places those bytes into the given buffer. The bytes will be read from the position of the position indicator (this can be changed using {{func link|seek()|page=this}}). Failures are thrown as runtime errors. Returns the number of bytes successfully read.
 
|param1 = file
 
|param1 = file
|param1text = File object as returned by {{func link|open}}.
+
|param1text = File object as returned by {{func link|open()|page=this}}.
 
|param2 = buf
 
|param2 = buf
 
|param2text = Buffer to read bytes into. A new buffer can be created using <code>bits.buf(size)</code>. Must not be smaller than '''len'''.  
 
|param2text = Buffer to read bytes into. A new buffer can be created using <code>bits.buf(size)</code>. Must not be smaller than '''len'''.  
Line 191: Line 190:  
{{Nasal doc
 
{{Nasal doc
 
|syntax = io.read_airport_properties(icao, fname[, target]);
 
|syntax = io.read_airport_properties(icao, fname[, target]);
 +
|version = 2.4
 +
|commit = {{fgdata commit|d4fb11|t=commit}}
 
|text = Loads an airport-related XML file. Paths will be concatenated in the following form: <tt>''[[$FG_SCENERY]]/Airports/'''''i'''''/'''''c'''''/'''''a'''''/'''''icao'''''.'''''fname'''''.xml''</tt>. Returns the data as a <code>props.Node</code> object or <code>'''nil'''</code> on error. Note that the file ''must'' be in the [[PropertyList XML files|PropertyList]] format, or else the function will fail.
 
|text = Loads an airport-related XML file. Paths will be concatenated in the following form: <tt>''[[$FG_SCENERY]]/Airports/'''''i'''''/'''''c'''''/'''''a'''''/'''''icao'''''.'''''fname'''''.xml''</tt>. Returns the data as a <code>props.Node</code> object or <code>'''nil'''</code> on error. Note that the file ''must'' be in the [[PropertyList XML files|PropertyList]] format, or else the function will fail.
 
|param1 = icao
 
|param1 = icao
|param1text = ICAO code of the airport.
+
|param1text = ICAO code of the airport as a string.
 
|param2 = fname
 
|param2 = fname
|param2text = Filename of the airport data file, e.g., "groundnet", "ils", "jetways", "rwyuse", "threshold", or "twr". See above for its use in the concatenation of the path.
+
|param2text = Filename of the airport data file as a string, e.g., "groundnet", "ils", "jetways", "rwyuse", "threshold", or "twr". See above for its use in the concatenation of the path.
 
|param3 = target
 
|param3 = target
|param3text = Optional place to put the results in the [[Property Tree]]. May be either a <code>props.Node</code> object or a property path.
+
|param3text = Optional place to put the results in the [[Property Tree]]. May be either a <code>props.Node</code> object pointing to a place in the Property Tree or a property path.
 
|example1 = var data = io.read_airport_properties("KSFO", "ils"); # the airport might need changing
 
|example1 = var data = io.read_airport_properties("KSFO", "ils"); # the airport might need changing
 
props.dump(data); # dump data
 
props.dump(data); # dump data
Line 209: Line 210:     
=== read_properties() ===
 
=== read_properties() ===
Load XML file in FlightGear's native <PropertyList> format.        
+
{{Nasal doc
If the second, optional target parameter is set, then the properties
+
|syntax = io.read_properties(path[, target]);
are loaded to this node in the global property tree. Otherwise they 
+
|text = Loads an XML file. Returns the data as a <code>props.Node</code> object on success or <code>'''nil'''</code> on error. Note that the file ''must'' be in the [[PropertyList XML files|PropertyList]] format, or else the function will fail.
are returned as a separate props.Node tree. Returns the data as a  
+
|param1 = path
props.Node on success or nil on error.
+
|param1text = Path to the XML file as a string.
<syntaxhighlight lang="nasal">
+
|param2 = target
Usage:  io.read_properties(<filename> [, <props.Node or property-path>]);
+
|param2text = Optional place to put the results in the [[Property Tree]]. May be either a <code>props.Node</code> object pointing to a place in the Property Tree or a property path.
</syntaxhighlight>
+
|example1 = var path = getprop("/sim/fg-root") ~ '/keyboard.xml';
 
+
var data = io.read_properties(path);
Examples:
+
props.dump(data); # dump data
<syntaxhighlight lang="nasal">
+
|example2 = var path = getprop("/sim/fg-root") ~ '/keyboard.xml';
var target = props.globals.getNode("/sim/model");          
+
var node = props.globals.getNode("demo", 1);
io.read_properties("/tmp/foo.xml", target);                
+
io.read_properties(path, node);
                                                           
+
props.dump(node); # dump data
var data = io.read_properties("/tmp/foo.xml", "/sim/model");
+
|example3 = var path = getprop("/sim/fg-root") ~ '/keyboard.xml';
var data = io.read_properties("/tmp/foo.xml");            
+
var node = "/demo";
</syntaxhighlight>
+
io.read_properties(path, node);
 +
props.dump(props.globals.getNode(node)); # dump data
 +
}}
    
=== readfile() ===
 
=== readfile() ===
Reads and returns a complete file as a string. Failures are thrown as runtime errors as per die().
+
{{Nasal doc
<syntaxhighlight lang="nasal">
+
|syntax = io.readfile(file);
io.readfile(file);
+
|text = Reads and returns a complete file as a string. Failures are thrown as runtime errors.
</syntaxhighlight>
+
|param1 = file
 +
|param1text = Path to the file as a string.
 +
|example1 = var file = getprop("/sim/fg-root") ~ '/Nasal/math.nas';
 +
file = io.readfile(file);
 +
print(file);
 +
}}
   −
=== readln(filehandle) ===
+
=== readln() ===
Reads and returns a single text line from the filehandle. Interprets both "\n" and "\r\n" as end of line markers, and does not include the "\r" or "\n" bytes in the returned string. End of file or error is signaled by returning nil.
+
{{Nasal doc
 +
|syntax = io.readln(file);
 +
|text = Reads and returns a single line from the file, advancing the position indicator. Accepts different {{wikipedia|newline}} types, including {{abbr|LF|line feed}}, {{abbr|CR|carriage return}}, and CR+LF. Does not include the EOL character(s) in the returned string. End of file or an error is signaled by returning <code>'''nil'''</code>.
 +
|param1 = file
 +
|param1text = File object as returned by {{func link|open()|page=this}}.
 +
|example1 = var path = getprop("/sim/fg-root") ~ '/Nasal/bits.nas';
 +
var file = io.open(path);
 +
var line = io.readln(file);
 +
print(line); # prints "var bit = [var _ = 1];"
 +
line = io.readln(file);
 +
print(line); # prints "for (var i = 1; i < 32; i += 1)"
 +
}}
    
=== readxml() ===
 
=== readxml() ===
Reads an XML file from an absolute path and returns it as property 
+
{{Nasal doc
tree. All nodes will be of type STRING. Data are only written to  
+
|syntax = io.readxml(path[, prefix]);
leafs. Attributes are written as regular nodes with the optional   
+
|text = Reads an XML file from an absolute path and returns it as a <code>props.Node</code> object. All nodes will be of the string type. Also, all attributes will be converted in subnodes with a prefix appended. Returns <code>'''nil'''</code> on error.
prefix prepended to the name. If the prefix is nil, then attributes  
+
|param1 = path
are ignored. Returns nil on error.
+
|param1text = Absolute path to the XML file.
<syntaxhighlight lang="nasal">
+
|param2 = prefix
Usage:  io.readxml(path[, prefix = "___"]);
+
|param2text = Optional prefix to give to the attribute nodes. If it is <code>'''nil'''</code>, then attributes will be ignored. Defaults to "___" (three underscores).
</syntaxhighlight>
+
|example1text = First, put the following code into <tt>''[[$FG_HOME]]/Export/demo.xml''</tt>:
<syntaxhighlight lang="nasal">
+
<syntaxhighlight lang="xml">
io.readxml(path,prefix);
+
<?xml version="1.0" encoding="UTF-8"?>
 +
 
 +
<foo>
 +
  <bar attr1="Hello" attr2="World">abc</bar>
 +
  <bar>xyz</bar>
 +
</foo>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
|example1 = var path = getprop("/sim/fg-home") ~ '/Export/demo.xml';
 +
var data = io.readxml(path);
 +
props.dump(data); # dump data
 +
}}
   −
=== seek(filehandle, position, whence) ===
+
=== seek() ===
As ANSI fseek(). Attempts to seek to the specified position based on the whence value (which must be one of io.SEEK_SET, io.SEEK_END, or io.SEEK_CUR).
+
{{Nasal doc
 +
|syntax = io.seek(file, position, whence);
 +
|text = Moves the pointer position to a specified place.
 +
|param1 = file
 +
|param1text = File object as returned by {{func link|open()|page=this}}.
 +
|param2 = position
 +
|param2text = Number of bytes offset from '''whence''' as an integer. If '''whence''' is {{func link|SEEK_SET|page=this}}, this cannot be negative.
 +
|param3 = whence
 +
|param3text = Specifies position to set the offset from. Must be one of {{func link|SEEK_SET|page=this}} (beginning of file), {{func link|SEEK_END|page=this}} (end of file), or {{func link|SEEK_CUR|page=this}} (current pointer position).
 +
|example1 = var path = getprop("/sim/fg-root") ~ '/Nasal/geo.nas';
 +
var file = io.open(path, "r"); # open file
 +
var len = 15;
 +
var buf = bits.buf(len);
 +
io.seek(file, 122, io.SEEK_SET); # set to the desired position
 +
io.read(file, buf, len); # read file
 +
print(buf); # prints "geo.Coord class"
 +
io.close(file); # close file
 +
}}
   −
=== stat(filename) ===
+
=== stat() ===
Calls unix or win32 stat() on the specified file name and returns a seven element array whose contents are, in order: dev, ino, mode, nlink, uid, gid, rdef, size, atime, mtime, ctime. Errors are signaled as exceptions as per die().
+
{{Nasal doc
 +
|syntax = io.stat(path);
 +
|text = Calls {{wikipedia|stat (system call)|stat}} and returns a vector containing 12 pieces of data. See the table below for a list of them in order from first in the vector to last. Returns <code>'''nil'''</code> if the file does not exist.
 +
{{{!}} class="wikitable"
 +
! Data !! Meaning
 +
{{!-}}
 +
{{!}} dev {{!!}} Identifier of device containing file
 +
{{!-}}
 +
{{!}} ino {{!!}} Inode number
 +
{{!-}}
 +
{{!}} mode {{!!}} Protection mode
 +
{{!-}}
 +
{{!}} nlink {{!!}} Reference count of hard links
 +
{{!-}}
 +
{{!}} uid {{!!}} User identifier of owner
 +
{{!-}}
 +
{{!}} gid {{!!}} Group identifier of owner
 +
{{!-}}
 +
{{!}} rdev {{!!}} Device identifier (if special file)
 +
{{!-}}
 +
{{!}} size {{!!}} Total file size, in bytes
 +
{{!-}}
 +
{{!}} atime {{!!}} Time of last access as a Unix timestamp
 +
{{!-}}
 +
{{!}} mtime {{!!}} Time of last modification as a Unix timestamp
 +
{{!-}}
 +
{{!}} ctime {{!!}} Time of last status change as a Unix timestamp
 +
{{!-}}
 +
{{!}} type {{!!}} Type of file. May be one of "unk", "reg", "dir", "chr", "blk", "fifo", "lnk", or "sock".<br>See {{simgear file|simgear/nasal/iolib.c|l=214}}.
 +
{{!}}}
 +
|param1 = path
 +
|param1text = Path to the file as a string.
 +
|example1 = var path = getprop("/sim/fg-root") ~ '/Nasal/geo.nas';
 +
var stat = io.stat(path);
 +
printf("File size: %s bytes", stat[7]); # prints file size
 +
}}
   −
=== tell(filehandle) ===
+
=== tell() ===
Returns the current seek position of the filehandle.
+
{{Nasal doc
 +
|syntax = io.tell(file);
 +
|text = Returns the current pointer position of the file.
 +
|param1 = file
 +
|param1text = File object as returned by {{func link|open()|page=this}}.
 +
|example1 = var path = getprop("/sim/fg-root") ~ '/Nasal/geo.nas';
 +
var file = io.open(path);
 +
io.seek(file, 2, io.SEEK_SET);
 +
print(io.tell(file)); # prints "2"
 +
io.close(file);
 +
}}
   −
=== write(filehandle, str) ===
+
=== write() ===
Attempts to write the entirety of the specified string to the filehandle. Failures are thrown as runtime errors as per die(). Returns the number of bytes successfully written.
+
{{Nasal doc
 +
|syntax = io.write(file, string);
 +
|text = Writes a string to a given file and returns the number of bytes successfully written.
 +
|param1 = file
 +
|param1text = File object as returned by {{func link|open()|page=this}}.
 +
|param2 = string
 +
|param2text = String to write to the file.
 +
{{tip|It is good practice to make sure that all lines, including the last one, end in a newline (<code>\n</code>). This will especially help if you will be calling {{func link|readln()|page=this}} on the file later.}}
 +
|example1 = var path = getprop("/sim/fg-home") ~ '/Export/demo.txt';
 +
var file = io.open(path, "wb"); # open in write mode
 +
var str = 'Hello World!' ~ "\n";
 +
io.write(file, str); # write the data
 +
io.close(file); # close (and flush) the file stream
 +
}}
    
=== write_properties() ===
 
=== write_properties() ===
Write XML file in FlightGear's native <PropertyList> format.  
+
{{Nasal doc
Returns the filename on success or nil on error. If the source is a props.Node that refers to a node in the main tree,  
+
|syntax = io.write_properties(path, prop);
then the data are directly written from the tree, yielding a more accurate result.
+
|text = Writes nodes from the [[Property Tree]] to an XML file in FlightGear's [[PropertyList XML files|PropertyList]] format. If the file does not exist, it will be created. If it does, all contents will be overwritten. Returns the filename on success or <code>'''nil'''</code> on error.
Otherwise the data need to be copied first, which may slightly change node types (FLOAT becomes DOUBLE etc.)
+
|param1 = path
<syntaxhighlight lang="nasal">
+
|param1text = Path of the file to write to as a string. If it does not have a <tt>.xml</tt> extension, <tt>.xml</tt> will be added to it.
Usage:  io.write_properties(<filename>, <props.Node or property-path>);
+
|param2 = prop
</syntaxhighlight>
+
|param2text = Either a property path or a <code>props.Node</code> object. Note that, when the latter is used, results will be more accurate if it refers to a node in the Property Tree, otherwise the node will have to be copied, which may change the node type.
Examples:
+
|example1 = var path = getprop("/sim/fg-home") ~ '/Export/demo.xml';
<syntaxhighlight lang="nasal">
+
var prop = "/position";
var data = props.Node.new({ a:1, b:2, c:{ d:3, e:4 } });  
+
print(io.write_properties(path, prop));
io.write_properties("/tmp/foo.xml", data);              
+
|example2 = var path = getprop("/sim/fg-home") ~ '/Export/demo.xml';
io.write_properties("/tmp/foo.xml", "/sim/model");      
+
var prop = props.globals.getNode("position");
</syntaxhighlight>
+
print(io.write_properties(path, prop));
 +
|example3 = var path = getprop("/sim/fg-home") ~ '/Export/demo.xml';
 +
var tree = {
 +
    "a": 12.34,
 +
    "b": "Hello, World!",
 +
    "c": {
 +
        "d": [1, 2, 3]
 +
    }
 +
};
 +
var prop = props.Node.new(tree);
 +
print(io.write_properties(path, prop));
 +
}}
    
=== writexml() ===
 
=== writexml() ===
Writes a property tree as returned by readxml() to a file. Children 
+
{{Nasal doc
with name starting with <prefix> are again turned into attributes of 
+
|syntax = io.basename(path, node[, indent[, prefix]]);
their parent. <node> must contain exactly one child, which will      
+
|text = Writes a node structure to an XML file.
become the XML file's outermost element.                            
+
|param1 = path
<syntaxhighlight lang="nasal">
+
|param1text = Path of the file to write to as a string. If it does not have a <tt>.xml</tt> extension, <tt>.xml</tt> will be added to it.
Usage: io.writexml(path, node[,indent = "\t"][, prefix = "___"]);
+
|param2 = node
</syntaxhighlight>
+
|param2text = <code>props.Node</code> object containing the data to write to the file. Attributes should be included as child nodes with a certain '''prefix'''. See also {{func link|readxml()|page=this}}. It must also have just one root node.
<syntaxhighlight lang="nasal">
+
|param3 = indent
io.writexml(path, node, indent,prefix);
+
|param3text = Optional string specifying what characters should be used to indent lines. Defaults to one horizontal tab character (<tt>\t</tt>).
</syntaxhighlight>
+
|param4 = prefix
 +
|param4text = Optional string specifying what prefixes attributes will have.
 +
|example1 = var path = getprop("/sim/fg-home") ~ '/Export/demo.xml';
 +
var tree = {
 +
    "source": {
 +
        ___type: "book", # will become an attribute
 +
        "title": "The Grand Book of Code",
 +
        "author-last": "Echter",
 +
        "author-first": "William C.",
 +
        "year": "2011",
 +
        "publisher": "Pen Publishers",
 +
        "city": "Manchester"
 +
    }
 +
};
 +
var node = props.Node.new(tree);
 +
io.writexml(path, node);
 +
|example2 = var path = getprop("/sim/fg-home") ~ '/Export/demo.xml';
 +
var tree = {
 +
    "source": {
 +
        _attr_type: "book",
 +
        "title": "The Grand Book of Code",
 +
        "author-last": "Echter",
 +
        "author-first": "William C.",
 +
        "year": "2011",
 +
        "publisher": "Pen Publishers",
 +
        "city": "Manchester"
 +
    }
 +
};
 +
var node = props.Node.new(tree);
 +
io.writexml(path, node, "  ", "_attr_"); # indent using two spaces
 +
}}
    
== Variables ==
 
== Variables ==
 
=== SEEK_CUR ===
 
=== SEEK_CUR ===
 +
{{Nasal doc
 +
|syntax = io.SEEK_CUR;
 +
|text = Used with {{func link|seek()|page=this}}. Means the offset will be counted from the current pointer postion.
 +
}}
 
=== SEEK_END ===
 
=== SEEK_END ===
 +
{{Nasal doc
 +
|syntax = io.SEEK_END;
 +
|text = Used with {{func link|seek()|page=this}}. Means the offset will be counted from the end of the file.
 +
}}
 
=== SEEK_SET ===
 
=== SEEK_SET ===
 +
{{Nasal doc
 +
|syntax = io.SEEK_SET;
 +
|text = Used with {{func link|seek()|page=this}}. Means the offset will be counted from the beginning of the file.
 +
}}
   −
[[Category:Nasal]]
+
{{Nasal namespaces}}

Navigation menu