File I/O

P* provides a unique way of handling reading and writing files. With maximum simplicity you can go through a file line by line and edit, delete or insert new lines. You do not need to worry about joining strings together in the correct order or storing the file temporarily, P* will do that for you.

The FILE type

The FILE type is the main filehandle, used to open and close files. Files may be opened read-only, read/write and may be truncated. Here is the syntax for the different open methods.

SCENE main {
	FILE file;

	/* Open a file read-only */
	if (!file->open_ro("my_file")) {
		errcho "Could not open my_file: " . file->error() . "\n";
		return 1;
	}
	file->close();

	/* Open a file for reading and writing */
	if (!file->open_rw("my_file")) {
		errcho "Could not open my_file: " . file->error() . "\n";
		return 1;
	}
	file->close();

	/* Open a file read-write and truncate it on open */
	if (!file->open_truncate("my_file")) {
		errcho "Could not open my_file: " . file->error() . "\n";
		return 1;
	}
	file->close();

	return 0;
}

The LINE type

The LINE type is used to read a file line by line and to modify it. The LINE does not work on its own, and has to be bound to a FILE object like this:

LINE line = file;

Initially, the line does not point to any particular position in the FILE. To make it point to the first line, use the ++-operator like this:

LINE line = file;
line++;

The LINE object now points to the first line of the file. If the file is empty, it points to the beginning.

The ++ operator returns the number of bytes read into the LINE object. This can be used in a loop to break the loop when it reaches the last line.

LINE line = file;
while (line++) {
	echo "Found a line: $line\n";
}

Trailing newlines (\n) are not removed when lines are read in.

You can make a LINE object point to the end of a file by using line = file->end(), which is useful for appending to files.

The LINE object can also traverse a file line by line in reverse order, using the line---operator. The LINE object will point to the previous line from the current position. When no more lines can be read, the LINE object will point to the beginning of the file, but it will not contain any data.

Edit files using the LINE object

It's possible to edit a file using the LINE object by setting it's value to something else. The changes then have to be queued for update in the FILE object using the syntax file->update(line);. After you've added all the changes, they must be written out using file->flush().

Here is an example which adds a # at the beginning of lines which have numbers in them.

SCENE main {
	FILE file;

	/* Open a file read-write, we will modify it */
	if (!file->open_rw("my_file")) {
		errcho "Could not open my_file: " . file->error() . "\n";
		return 1;
	}

	/* Initialize some variables */
	LINE line = file;

	int lines = 0;
	int modified = 0;

	/* Loop through all lines of the file */
	while (line++) {
		lines++;

		/* Check if the line contains numbers and does not already begin with a # */
		if (line =~ /\d/ && line !~ /^#/) {
			/* Add the # to the line */
			line = "# $line";

			/* Queue the updated LINE object for writing */
			file->update(line);

			modified++;
		}
	}

	/* Print out some stats */
	echo "Modified $modified of total $lines lines.\n";

	/* Write the changes out and close the file */
	file->flush();
	file->close();

	return 0;
}

If you need to write to an empty file, just write all your data to the LINE object right after the line++-operation. You can also use line = file->begin(), the result will be the same. You can insert or append new lines to a file by adding data to the LINE objects at desired locations. Original data will be overwritten.