Skip to content

Commit

Permalink
Documentation (Environment global properties, containers, file datast…
Browse files Browse the repository at this point in the history
…ream) (#83)

* Array: `insert_at`, `remove_at`, most other methods with their examples.

* dictionary, almost everything accept the indexing operator.

* Environment global properties: `PLATFORM`, `PLATFORM_DISPLAY_NAME`, `PLATFORM_VERSION`, `system_node_name`, and `system_node_id`.

* file datastream, including write method in the datastream documentation.

---------

Co-authored-by: Sam Tupy <webmaster@samtupy.com>
  • Loading branch information
harrymkt and samtupy authored Aug 22, 2024
1 parent 9f87d49 commit 64b4ae5
Show file tree
Hide file tree
Showing 29 changed files with 340 additions and 3 deletions.
25 changes: 25 additions & 0 deletions doc/src/references/builtin/!Containers/array/!array.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# array
This container stores a resizable list of elements that must all be the same type. In this documentation, "T" refers to the dynamic type that a given array was instanciated with.
1. `T[]();`
2. `array<T>();`
3. `array<T>(uint count);`
4. `array<T>({item1, item2, item3})`

## Arguments (3):
* uint count: The initial number of items in the array which will be set to their default value upon array instanciation.

## Arguments (4):
* {item}: A list of elements that the array should be initialized with.

## Remarks:
Items in an array are accessed using what's known as the indexing operator, that is, `arrayname[index]` where index is an integer specifying what item you wish to access within the array. The biggest thing to keep in mind is that unlike many functions in NVGT which will silently return a negative value or some other error form upon failure, arrays will actually throw exceptions if you try accessing data outside the array's bounds. Unless you handle such an exception with a try/catch block, this results in an unhandled exception dialog appearing where the user can choose to copy the call stack before the program exits. The easiest way to avoid this is by combining your array accesses with healthy usage of the array.length() method to make sure that you don't access out-of-bounds data in the first place.

Data in arrays is accessed using 0-based indexing. This means that if 5 items are in an array, you access the first item with `array[0]` and the last with `array[4]`. If you are a new programmer this might take you a second to get used to, but within no time your brain will be calculating this difference for you almost automatically as you write your code, it becomes second nature and is how arrays are accessed in probably 90+% of well known programming languages. Just remember to use `array[array.size() -1]` to access the last item in the array, not `array[array.length()]` which would cause an index out of bounds exception.

There is a possible confusion regarding syntax ambiguity when declaring arrays which should be cleared up. What is the difference between `array<string> items` and `string[] items` and when should either one be used?

At it's lowest level, an array is a template class, meaning it's a class that can accept a dynamic type `(array<T>)`. This concept also exists with the grid, async, and other classes in NVGT.

However, Angelscript provides a convenience feature called the default array type. This allows us to choose just one template class out of all the template classes in the entire engine, and to make that 1 class much easier to declare than all the others using the bracket syntax `(T[])`, and this array class happens to be our chozen default array type in NVGT.

Therefor, in reality `array<T>` and `T[]` do the exact same thing, it's just that the first one is the semantically correct method of declaring a templated class while the latter is a highly useful Angelscript shortcut. So now when you're looking at someone's code and you see a weird instance of `array<T>`, you can rest easy knowing that you didn't misunderstand the code and no you don't need to go learning some other crazy array type, that code author just opted to avoid using the Angelscript default array type shortcut for one reason or another.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
void array::erase(uint index);
## Arguments:
* uint index: the index of the item to delete.
## Remarks:
Passing an index that is less than 0 or greater or equal to the array's absolute length will result in an index out of bounds exception being thrown.
*/

// Example:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
Inserts an element into an array at a given position, moving other items aside to make room if necessary.
void array::insert_at(uint index, const T&in value);
## Arguments:
* uint index: the position to insert at.
* const T&in value: the element to be inserted.
## Remarks:
This method adds an element to the given position of an array. If you pass index 0, the item will be inserted at the beginning of the aray, and if you pass the array's absolute length, the item will be inserted at the end. Any values less than 0 or greater than the array's absolute length will result in an index out of bounds exception being thrown.
*/

// Example:
void main() {
string[] names = {"HTML", "CSS"};
names.insert_at(0,"Java Script");
names.insert_at(2, "php");
alert("Languages", join(names, ", "));
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
## Returns:
uint: the number of items in the array.
## Remarks:
This value is equal to the number of items in the array + 1.
This method returns the absolute number of elements in the array, that is, without taking 0-based indexing into account. For example an array containing {1, 2, 3} will have a length of 3, but you must access the last element with the index 2 and the first element with index 0, rather than using 3 for the last item and 1 for the first.
*/

// Example:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
Removes an element of an array by a given position.
void array::remove_at(uint index);
## Arguments:
* uint index: the position to be removed.
## Remarks:
Please note that the position value is 0 base, and failure to define correct index will cause NVGT to throw "index out of bounds" exception.
*/

// Example:
void main() {
string[] names = {"HTML", "CSS"};
names.remove_at(0);
alert("Languages", join(names, ", "));
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ Removes the last item from the array.

1. `void array::remove_last();`
2. `void array::pop_back();`

## Remarks:
Calling this method on an empty array will throw an index out of bounds exception.
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ allocates the memory needed to hold the given number of items, but doesn't initi

## Arguments:
* uint length: the size of the array you want to reserve.

## Remarks:
This method is provided because in computing, memory allocation is expensive. If you want to add 5000 elements to an array and you call array.insert_last() 5000 times without calling this reserve() method, you will also perform nearly 5000 memory allocations, and each one of those is a lot of work for the OS. Instead, you can call this function once with a value of 5000, which will perform only one expensive memory allocation, and now at least for the first 5000 calls to insert_last(), the array will not need to repetitively allocate tiny chunks of memory over and over again to add your intended elements. The importance of this cannot be stressed enough for large arrays, using the reserve() method particularly for bulk array inserts can literally speed your code up by hundreds of times in the area of array management.

Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# resize
Resizes the array to the specified size, and initializes all its elements to their default values.
Resizes the array to the specified size, and initializes all resulting new elements to their default values.

`void array::resize(uint length);`

## Arguments:
* uint length: how big to resize the array to

## Remarks:
If the new size is smaller than the existing number of elements, items will be removed from the bottom or the end of the aray until the array has exactly the number of items specified in the argument to this method.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
Reverses the array, so the last item becomes the first and vice versa.
void array::reverse();
## Remarks:
This method reverses the array in place rather than creating a new array and returning it.
*/

// Example:
Expand Down
16 changes: 16 additions & 0 deletions doc/src/references/builtin/!Containers/dictionary/!dictionary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# dictionary
This container stores multiple pieces of data of almost any type, which are stored and referenced by unique keys which are just arbitrary strings.
1. `dictionary();`
2. `dictionary({{"key1", value1}, {"key2", value2}});`

## Arguments (2):
* {{"key", value}}: default values to set in the dictionary, provided in the format shown.

## Remarks:
The idea behind a dictionary, or hash map / hash table as they are otherwise called, is that one can store some data referenced by a certain ID or key, before later retrieving that data very quickly given that same key used to store it.

Though explaining the details and guts of how hash maps work internally is beyond the scope of this documentation, here is an [overly in depth wikipedia article](https://en.wikipedia.org/wiki/Hash_table) that is sure to teach you more than you ever wished to know about this data structure. Honestly unless you wish to write your own dictionary implementation yourself in a low level language and/or are specifically worried about the efficiency of storing vast amounts of similar data which could stress the algorithm, it's enough to know that the dictionary internally turns your string keys into integer hashes, which are a lot faster for the computer to compare than the characters in the key strings themselves. Combine this with clever use of small lists or buckets determined by even more clever use of bitwise operations and other factors, and what you're left with is a structure that can store thousands of keys while still being able to look up a value given a key so quickly it's like magic, at least compared to the least efficient alternative which is looping through your thousands of data points and individually comparing them in order to find just one value you wish to look up.

NVGT's dictionaries are unordered, meaning that the get_keys() method will likely not return a list of keys in the order that you added them. In cases where this is very important to you, you can create a string array along side your dictionary and manually store key names yourself and then loop through that array instead of the output of get_keys() when you want to enumerate a dictionary in an ordered fassion. Note, of course, that this makes the entire system less efficient as now deleting or updating a key in the dictionary requires you to loop through your string array and find the key that needs deleting or updating, and dictionaries exist exactly to avoid such an expensive loop, though the same efficiency is preserved when simply looking up a key in the dictionary without writing to it, which can be enough in many cases. While in most cases it's best to write code that does not rely on the ordering of items in a dictionary, this at least provides an option to choose between ordering and better efficiency, should you really need such a thing.

Look at the individual documented methods of this class for examples of it's usage.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
This method deletes the given key from the dictionary.
bool dictionary::delete(const string &in key);
## Arguments:
* const string &in key: the key to delete.
## Returns:
bool: true if the key was successfully deleted, false otherwise.
*/

// Example:
void main() {
dictionary data;
data.set("nvgt", "An audiogame engine using AngelScript");
alert("Information", data.delete("nvgt")); //true
alert("Information", data.delete("nvgt")); //false because the key is already deleted, another word, it does not exist.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# delete_all
This method deletes all keys from the dictionary.

`bool dictionary::delete_all();`
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
Returns whether a given key exists in the dictionary.
bool dictionary::exists(const string &in key);
## Arguments:
* const string &in key: the key to look for.
## Returns:
bool: true if the key exists, false otherwise.
*/

// Example:
void main() {
dictionary data;
data.set("nvgt", "An audiogame engine using AngelScript");
alert("Information", data.exists("nvgt")); //true
alert("Information", data.exists("gameengine")); //false
}
22 changes: 22 additions & 0 deletions doc/src/references/builtin/!Containers/dictionary/Methods/get.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
Gets the data from a given key.
bool dictionary::get(const string &in key, ?&out value);
## Arguments:
* const string &in key: the key to look for.
* ?&out value: the variable for the value to be associated, see remarks.
## Returns:
bool: true if the dictionary retrieves the value of the key, false otherwise.
## Remarks:
Please note that the value parameter should be a variable to receive the value. This means that dictionary will write to the variable, not read from.
*/

// Example:
void main() {
dictionary data;
data.set("nvgt", "An audiogame engine using AngelScript");
string result;
if (!data.get("nvgt", result))
alert("Error", "Failed to retrieve the value of the key");
else
alert("Result is", result);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
Returns a string array containing the key names in the dictionary.
string[]@ dictionary::get_keys();
## Returns:
string[]@: the list of keys in the dictionary on success, 0 otherwise.
*/

// Example:
void main() {
dictionary data;
data.set("nvgt", "An audiogame engine using AngelScript");
string[]@ keys = data.get_keys();
alert("Keys", join(keys, ", "));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
Returns the size of the dictionary.
uint dictionary::get_size();
## Returns:
uint: the size of the dictionary, another word, the total keys on success, 0 otherwise.
*/

// Example:
void main() {
dictionary data;
data.set("nvgt", "An audiogame engine using AngelScript");
alert("Dictionary size is", data.get_size());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
Returns whether the dictionary is empty.
bool dictionary::is_empty();
## Returns:
bool: true if the dictionary is empty, false otherwise.
*/

// Example:
void main() {
dictionary data;
data.set("nvgt", "An audiogame engine using AngelScript");
alert("Information", data.is_empty()); //false
data.delete_all();
alert("Information", data.is_empty()); //true
}
11 changes: 11 additions & 0 deletions doc/src/references/builtin/!Containers/dictionary/Methods/set.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# set
Sets the data into a given key.

`void dictionary::set(const string &in key, const ?&in value);`

## Arguments:
* const string &in key: the key to use.
* const ?&in value: the value to set into this key.

## Remarks:
If the key already exists in the dictionary, its value will be overwritten.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
3. You want to use a placeholder more than once in a string.
*/

// Example
// Example:
void main() {
string[] greetings = {"Hello %0! How are you?", "Hola %0! ¿Cómo estás?"};
string[] messages = {"You have %0 health", "%0 health"};
Expand Down
20 changes: 20 additions & 0 deletions doc/src/references/builtin/!Streams/datastream/Methods/write.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
Write raw bytes to a stream.
uint write(string content);
## Arguments:
* string content: the content that is to be written.
## Returns:
uint: the number of bytes written.
## Remarks:
If needed, you can use the returned value to verify whether the data you intended to write to the stream was written successfully by checking whether the return value of this function matches the length of the data you passed to it.
*/

// Example:
void main() {
// This time we'll use a file which is another type of datastream to show how the functions in this datastream class work on it's children.
file f("test.txt", "wb");
string data = "This is a test file";
bool success = f.write(data) == data.length();
f.close();
alert("Information", "The file with the data has been " + (success? "successfully" : "unsuccessfully") + " written");
}
22 changes: 22 additions & 0 deletions doc/src/references/builtin/!Streams/file/!file.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# file
The file datastream is used to read and write files stored on the hard disk.

1. `file();`
2. `file(const string path, const string mode);`

## Arguments (1):
* const string path: the filename to open.

## Arguments (2):
* const string path: the filename to open.
* const string mode: the mode to open as.

## Remarks:
Usually when the file object is first created, it will not be active, that is, it will not be associated with a file on disk. To activate it, use the following methods:

* Call the open function.
* use the second constructor.

Please note that both methods require the filename that is to be associated and the mode to open, with the only difference being that it is harder to tell whether the file was opened successfully if you use the constructor rather than the open method. Using the second constructor makes it 1 line shorter. The possible open modes will not be documented in this remarks, you can see it in `file::open` method.

Remember that as with all datastreams, all methods in the base datastream class will work on the file class unless noted otherwise and thus will not be redocumented here.
27 changes: 27 additions & 0 deletions doc/src/references/builtin/!Streams/file/Methods/open.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
This method will open a file for reading or writing.
bool file::open(string filename, string open_mode);
## Arguments:
* string filename: the name of the file to open. This can be either an absolute or relative path.
* string open_mode: the mode to open, see remarks.
## Returns:
bool: true on success, false on failure.
## Remarks:
While on some operating systems (mostly windows) both the slash(`/`), and the backslash(`\`) can be used to specify the filename, it is very strongly recommended to use the / character for greatest cross platform compatibility.
The following is a list of valid open modes.
* a: append.
* w: write.
* r: read.
* r+: read and write.
For backwards compatibility with code that used a version of the file object from when there was a difference between text and binary file open modes, a b character is also accepted (for example rb) to indicate binary. The current stream implementation ignores this character other than to gracefully accept it rather than complaining that it is an invalid mode. You can use other text encoding APIs such as string_recode and the line_converting_reader if you really need to try recreating something similar to the old behavior.
The file will be created if the file does not exist if opened in either write or append mode. When opened in read mode, the file must exist in order to be successful.
*/

// Example:
void main() {
file f;
f.open("test.txt", "wb");
f.write("This is a test");
f.close();
alert("Information", "The file has been written");
}
19 changes: 19 additions & 0 deletions doc/src/references/builtin/!Streams/file/Properties/size.nvgt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
Determine the size (in bytes) of the file that is currently associated with this stream.
const uint64 size;
## Remarks:
This property will be 0 if no file is associated with this stream, in which case you can use the datastream::active property on it to check the difference between a 0 byte file and an eronious result.
When files are opened in write mode, there could be periods where the written data has not yet been flushed to disk in which case this property may have a value which is a little bit behind. Experiments seem to indicate that this rarely if never happens, however it's worth putting the note here just encase anyone runs into it.
Note that a file_get_size() function exists in the engine which is usually better than this property unless you need to do more with a file than just get it's size.
*/

// Example:
void main() {
file f("size.nvgt", "rb");
if (!f.active) {
alert("oops", "couldn't load the file");
return;
}
alert("size.nvgt is", f.size + "b");
f.close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
This property returns a string containing the current platform, such as "Windows NT".
const string PLATFORM;
*/

// example:
void main() {
alert("Your current Platform is", PLATFORM);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
This property returns a string containing the current platform display name, such as "Windows 8".
const string PLATFORM_DISPLAY_NAME;
## Remarks:
Due to a backwards compatibility problem in windows, this function by default will cap out at Windows 8 even if the user is running a newer version of Windows. If determining the most modern windows version on the user's system is important to you, you can create a gamename.exe.manifest file to target your app for modern windows. Here is some [microsoft documentation](https://learn.microsoft.com/en-us/windows/win32/sysinfo/targeting-your-application-at-windows-8-1) that explains how, you can probably just use the example manifest provided there.
*/

// example:
void main() {
alert("Your current Platform display name is", PLATFORM_DISPLAY_NAME);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
This property returns a string containing the current platform version, such as "6.2 (Build 9200)".
const string PLATFORM_VERSION;
*/

// example:
void main() {
alert("Your current Platform version is", PLATFORM_VERSION);
}
Loading

0 comments on commit 64b4ae5

Please sign in to comment.