ini2array.inc - Short example

A forum for macro code snippets to be used in writing other macros. Post routines or .inc files here only, completed macros go to the Macro Depot. MQ2Data format only!

Moderator: MacroQuest Developers

Preocts
a snow griffon
a snow griffon
Posts: 312
Joined: Thu Jan 29, 2004 1:02 pm

ini2array.inc - Short example

Post by Preocts » Mon May 03, 2004 11:11 am

Was feeling creative last night.

Code: Select all

|**
  By: Preocts

  A quick example of how to read an entire KeyName from and ini file to an array
  This example actually sets the size of the array according to the number of Value Names
  it reads in from the ini file.

  Quick Reminder of IniFile Structure:
  /ini [FileName] [SectionName] [KeyName] [Value]
  [SectionName]
  [KeyName]=[Value]

**|

Sub ReadIni(FileName,SectionName)
|Does the key exist?
  /if (${Ini[${FileName},${SectionName},-1,NO].Equal[NO]}) {
    /echo KeyName not valid
    /return
  }
  /declare nValues int local 1
  /declare KeySet string local ${Ini[${FileName},${SectionName}]}
| Sets KeySet. This will be a single string of all the KeyNames in the ini.
| Ex) KeySet = KeyName1|KeyName2||

  :CounterLoop
| Using the Arg function, count how many different Values there are.
    /if (!${KeySet.Arg[${nValues},|].Length}) {
      /varcalc nValues ${nValues}-1
      /goto :MakeArray
    }
    /varcalc nValues ${nValues}+1
  /goto :CounterLoop  

  :MakeArray
    /if (!${nValues}) /return
    /declare nArray int local
| Declare the array now that we know the size. Can be int or string
    /declare MyArray[${nValues}] string outer
| Set back through the ini, this time filling in the array with the values
    /for nArray 1 to ${nValues}
      /varset MyArray[${nArray}] ${Ini[${FileName},${SectionName},${KeySet.Arg[${nArray},|]},NULL]}
    /next nArray
/return
Edit: Changed some naming schemes to make things less confusing.
Last edited by Preocts on Mon May 03, 2004 12:30 pm, edited 1 time in total.

LordGiddion
a snow griffon
a snow griffon
Posts: 352
Joined: Sat Sep 13, 2003 6:12 pm
Contact:

Post by LordGiddion » Mon May 03, 2004 11:34 am

Preocts: just to reduce confusion I wanted to point out your terminology is a bit off:

Code: Select all

[section name]
keyname=value
so normally you use a section name to get a list of keyname and then use the keynames to get their values.

Preocts
a snow griffon
a snow griffon
Posts: 312
Joined: Thu Jan 29, 2004 1:02 pm

Post by Preocts » Mon May 03, 2004 12:26 pm

That makes sense too. :)

hiipii
a ghoul
a ghoul
Posts: 93
Joined: Sat Jun 19, 2004 5:01 pm

Post by hiipii » Wed Jul 14, 2004 4:42 pm

Can someone explain how the counter works? I am having some major trouble figureing this out but would love to incorperate it into some macros. I just don't want to use something that I don't understand.

Also in this line
/if (${Ini[${FileName},${SectionName},-1,NO].Equal[NO]}) {
What does this check for? I don't understand the syntax of ,-1,NO.

Oh yea and can someone explain what this does please?
${Ini[${FileName},${SectionName},${KeySet.Arg[${nArray},|]},NULL]}
Thanks for the help...and sorry for all the questions just trying to understand.

User avatar
Zornecro
a ghoul
a ghoul
Posts: 82
Joined: Sun Sep 19, 2004 10:19 pm
Location: El Paso, TX

My spin on INI reading

Post by Zornecro » Mon Oct 04, 2004 9:55 pm

I think all that's really very different from what's above is there are more comments in the code to help you understand what it's doing, and some comments can be replaced with /echo to help you debug it if it's not working as you intended.

Code: Select all

|-------------------------------------------------------------------------------- 
|Code: Read an INI File with given sectionName
|Returns: A (created) array of newArray populated with values found in that section
|
|Let's say Example.INI contains:
|[GoodSection]
|Pimp1="Yowza"
|Pimp2="Hot diggity!"
|Pimp3="We b stylin'!"
|
|You would do /call ReadIni "example.ini" "GoodSection" Pimp
|It would create Pimp[3] string outer populated with the 3 strings you see in order.
|Unfortunately, when creating the INI file you have to follow the ArrayName+ArrayNumber pattern
|IN SEQUENCE. You duplicate a number or skip some, it stops counting/populating right there.
|Also, if that section had Daddy1=42 in the middle, that would stop the Pimp array construction.
|But sometimes in the same section you want 2 or more arrays defined, so you'd just call it again
|using Daddy as the last parameter. (And you'd APPEND the Daddy= lines to the bottom of Pimp.)
|-------------------------------------------------------------------------------- 

|Programmers note: some comments below can be changed to /echo to help you debug.

Sub ReadINI(string fileName, string SectionName, newArray) 
	|Attempting to Read Section [${SectionName}] from ${fileName}... 
	/if (${Ini[${fileName},${SectionName},-1,NO].Equal[NO]}) { 
		|Section [${SectionName}] wasn't found in File:${fileName}
		/return 
	}
	/declare newArraySize int local 1 
	/declare indx int local 0 
:CounterLoop 
	/if (${String[${Ini[${fileName},${SectionName},${newArray}${newArraySize}]}].Equal[null]}) { 
		/varcalc newArraySize ${newArraySize}-1 
		/goto :MakeArray 
	} 
	/varcalc newArraySize ${newArraySize}+1 
	/goto :CounterLoop 
:MakeArray 
	|${newArray}[${newArraySize}]
	/if (${newArraySize}<=0) /return 

	|Declaring ${newArray}[${newArraySize}] string outer... 
	/if (${Defined[${newArray}]}) /deletevar ${newArray}
	/declare ${newArray}[${newArraySize}] string outer 

	/for indx 1 to ${newArraySize} 
		/varset ${newArray}[${indx}] ${Ini[${fileName},${SectionName},${newArray}${indx}]} 
		|${newArray}[${indx}]=${${newArray}[${indx}]}
	/next indx 
	|[${SectionName}] info Read Successfully from ${fileName}.
/return 
- Zornecro Mancer, Retired EQ1 Veeshan
- Unktehila, Redtigre, Twinaxe, EQ2 Crushbone

User avatar
Zornecro
a ghoul
a ghoul
Posts: 82
Joined: Sun Sep 19, 2004 10:19 pm
Location: El Paso, TX

Post by Zornecro » Mon Oct 04, 2004 10:08 pm

hiipii wrote:/if (${Ini[${FileName},${SectionName},-1,NO].Equal[NO]}) {
What does this check for? I don't understand the syntax of ,-1,NO.
-1 is part of the Ini TLO that means you don't care what that parameter is (this is in the TLO doc for INI on the MQ2 helpfile atm). Basically, if the section name regardless of any content has nothing in it, the result is NO because you specified the default as NO. The default value is the last thing specified in that INI object.
hiipii wrote:Oh yea and can someone explain what this does please?
${Ini[${FileName},${SectionName},${KeySet.Arg[${nArray},|]},NULL]}
This is checking for "multiple responses" from the section name search. They will be separated with | (same character you use for macro comments). Then you can proceed to pull apart every individual entry matching that search by using | as a token.

Agreed, that can be slicker than my snippet, but I'm happy with how mine works, even if it does make you type in keys with numbers in sequence under the [section] headings.

Here's a sample INI file I use with mine:

Code: Select all

; Zornecro, 4 Oct 2004
; In the lines following [WantToBuy], you put gimme1="this" and gimme2="that"
; and so forth, the item names you want to buy in order.

[WantToBuy]
gimme1="Spell: Ferocity"
gimme2="Spell: Chill Bones"
gimme3="of Cazic Thule"
gimme4="Spiroc Feathers"
gimme5="Silver Disc"
gimme6="Golden Idol of Tunare"

; Here is where the maxprice stuff is defined. In pp, maxprice1 is your limit for gimme1, etc.
; For each gimme, there has to be a maxprice. gimme1="Blue Diamond" maxprice1=1
; That would shop for a Blue Diamond selling for 1 pp (or less).
; I was too lazy to make it simpler than this atm.

[PriceLimits]
maxprice1=7000
maxprice2=500
maxprice3=50000
maxprice4=5000
maxprice5=5000
maxprice6=1200

;If the length of maxprice is shorter than gimme, it will assume you'll pay any price for it.
;If the length of maxprice is longer, wtf? It will not use it for anything helpful.
So, in my macro, I have function calls like this:

Code: Select all

/call ReadINI "shopping.ini" "WantToBuy" wantList
/call ReadINI "shopping.ini" "PriceLimits" maxprice
I end up with a new string array of wantList[6] and maxprice[6]. Despite both being string arrays, I usually can include ${maxprice[${n}]} in most calculations, for loop limits, comparisons, etc., without a problem.
- Zornecro Mancer, Retired EQ1 Veeshan
- Unktehila, Redtigre, Twinaxe, EQ2 Crushbone

echoism
a ghoul
a ghoul
Posts: 131
Joined: Tue Oct 19, 2004 9:59 am

Post by echoism » Wed Mar 23, 2005 11:55 pm

Instead of doing:

Code: Select all

(${String[${Ini[${fileName},${SectionName},${newArray}${newArraySize}]}].Equal[null]}) {
      /varcalc newArraySize ${newArraySize}-1
      /goto :MakeArray
   }
   /varcalc newArraySize ${newArraySize}+1
   /goto :CounterLoop
Wouldn't it be easier to just count the number of | minus 1 in the string?

Code: Select all

/vardata newArraySize Math.Calc[${Ini[${filename},${SectionName}].Count[|]}-1].Int
Or is there some benefit to actually looping through that I'm missing?

Grumpy
a hill giant
a hill giant
Posts: 167
Joined: Sun Nov 10, 2002 4:22 pm

Keep in mind

Post by Grumpy » Thu Mar 24, 2005 2:11 pm

That max string length is either 1024 or 2048 (forget which offhand), and if you have more items in the ini file section than can be read into a single string (with seperators), the routine will bomb (you'll be missing the last seperator, and it work work right).

Someone else and I (cronic? can't remember) used a similar routine for a bazaar price checking macro, and putting more than 90 or so items in a section will usually make it bomb out (depends on length of item names of course).

Took me a while to figure out why the macro was barfing, just thought I'd share.

echoism
a ghoul
a ghoul
Posts: 131
Joined: Tue Oct 19, 2004 9:59 am

Post by echoism » Thu Mar 24, 2005 3:21 pm

Ah, thanks.
Good to know.