Menu

InfoArray

InfoArray

Part of the data structures package.

Introduction

An InfoArray is an array, which is used for holding data in info classes. In other words, it is intended and optimized to read XML data and not be edited once set.

Note: all files mentioned here are in Data.

Setup

The class contain an array of tokens.

Tokens

A token is an array of shorts of length 1 to 4.

Declaration

An InfoArray is set as InfoArrayMod. This is a child class of InfoArray, which has the functions to modify the content. InfoArray itself can't modify itself, meaning passing a pointer to an InfoArray should be safe even if it isn't const.

The constructor takes 4 arguments, all of them JITarrayTypes. Those are used to tell which type each index in the token represents. Using JIT_ARRAY_NO_TYPE will reduce the size of the token and all but the first arguments defaults to JIT_ARRAY_NO_TYPE.

The JITarrayTypes enum is in MOD_enums.h

Reading from XML

In the reading class, call the read like this:

InfoArrayName.read(pXML, getType(), "Tag");

  • InfoArrayName is the variable name.
  • pXML is the interface to the XML file
  • getType() is the TYPE of the current class. Used for human readable assert messages
  • "Tag" is the tag, which should be read

That's it for reading. Based on the types given to the constructor, the read function will figure out how to read everything in Tag. There is no need to tell the code what the XML looks like as autodetection should take care of that.

XML types

The JITarrayTypes given to the constructor tells what each index in the token should contain. Set in MODS_enums.h, most of them links to an XML file. This mean the loader will assert if the string is not found as a type in the string in question. It will not care if the string is present as a type in another XML file.

There are a few types, which will not link to a file, but rather have a different meaning.

JIT_ARRAY_MODIFIER, JIT_ARRAY_ALLOW, JIT_ARRAY_INT

Reads as an int.

JIT_ARRAY_MODIFIER_FLOAT, JIT_ARRAY_FLOAT

The intention here is to read as a float. However the data is stored in a short. As a result, a float is read, multiplied by 100 and then stored as an int.

Technically it will be the same as storing an int, but it can produce more readable XML files. The first usage was for unit yield demands. For some reason some people had an issue figuring out that 100 meant using one yield/turn. Adding the demands as a float helped on the problem. If 10 units use 0.1 each, it is easier to read that they add up to 1 each turn.

XML formats

TODO write something on how the code will accept various XML layouts and what it will read in each case.

Reading from the InfoArray

There are just a few functions for getting info out of the array.

getLength

Tells how many tokens the array contain

getDimentions

Tells how many variables each token contain

getType(x)

Returns the types set by the constructor. Valid arguments are ints from 0 to 3.

get*(A, B = 0)

This will return the value of token A. B is the index inside the token and defaults to 0 as this is the most often used value.

The * part is because there is a get function for each type, at least if InfoArrayGet.h is filled out completely. The interesting part here is that this approach will set the return type to match the XML type, like if the index is of type JIT_ARRAY_UNIT_CLASS, then the return type will be UnitClassTypes.

Python

InfoArray is exported to python. However python isn't as strict with types and all get functions are merged into get(A, B).

Explained example of error detection

Say we need an array of free promotions. The first argument in the constructor will then be JIT_ARRAY_PROMOTION while the rest are default.

When reading, strings are read from XML. They are compared to types in GC.getPromotionInfo() to find a matching index and will assert if nothing is found. This mean it will not accept TERRAIN_GRASSLAND and convert that to a promotion index (vanilla will not detect the usage of a wrong type for this).

When reading, getPromotion(index) has to be used. Any other get function will cause an assert. The return type is PromotionTypes.

This highly strict type system is intended to catch bugs where XML or DLL modders mix up types. However python will not use this strict system, which mean the modders should be more careful.

Best practice when looping

It's actually fairly simple:

for (int i = 0; i < pInfoArray.getLength(); ++i)
value = get*(i)

What might be less obvious (to some) is that the pointer directly to the InfoArray can be cached

const InfoArray* pInfoArray = GC.getXMLFILEInfo().getInfoArray()

This way the computer will not have to fetch the pointer each time it has to use it and the code will run a bit faster. It will also make it easier to step in the debugger as the loop control will only call getLength(), which itself is just a get function for an int.

Technical setup

No need to understand this section. It's only added to tell what goes on behind the functions.

The code is written under the assumption that the array will be looped when used. Because of this, it is technically a single short array of length = (length * token length) where the shorts are placed token by token. Since the array is allocated in a single block of memory, looping it will ensure sequential memory access, which in turn gives ideal conditions to utilize hardware caches.


Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.