Jump to content

Need Advice on ini's and arrays


Cue
 Share

Recommended Posts

I wanted to be able to read all keys and values in an ini file without knowing the section names and be able to access the value,key or section name in a logical manner. so i wrote a function Ini_to_Array to store the ini in a 3D array.

$Ini_file="vUDOHKGL.ini"
$Ini_Array = Ini_to_Array($Ini_file)

For $s=1 to $Ini_Array[0][0][0]
        $Key_String=""
        
        For $k=1 to $Ini_Array[$s][0][1]
            $Key_String = $Key_String & $Ini_Array[$s][$k][0] &"=" &$Ini_Array[$s][$k][1] & @CRLF ; key and value table FOR MSGBOX
        Next
        
        MsgBox(0,"Ini_to_Array Test Msg", "[" &$Ini_Array[$s][0][0] &"]: " &$Ini_Array[$s][0][1] &@CRLF &$Key_String) ;MSGBOX
Next


Func Ini_to_Array( $F_Ini_file)
    
    local $F_Ini_Ar[1][1][2]
    $SectionNames=IniReadSectionNames($F_Ini_file)
    $F_Ini_Ar[0][0][0]=$SectionNames[0]
    $F_Ini_Ar[0][0][1]=0
    
    For $s=1 to $SectionNames[0] ;save section name in ini array
        
        if $s = UBound($F_Ini_Ar,1) Then
            ReDim $F_Ini_Ar[UBound($F_Ini_Ar,1)+1][UBound($F_Ini_Ar,2)][UBound($F_Ini_Ar,3)]
        EndIf
        
        Local $Section_Ar_Temp = IniReadSection($F_Ini_file,$SectionNames[$s])
        
        $F_Ini_Ar[$s][0][0]= $SectionNames[$s] ;Store Section $s in ini array
        $F_Ini_Ar[$s][0][1]= $Section_Ar_Temp[0][0] ;Store number of keys in Section $s in ini array
        $F_Ini_Ar[0][0][1]=$F_Ini_Ar[0][0][1]+$Section_Ar_Temp[0][0]
        
        For $k=1 to $Section_Ar_Temp[0][0]
            if $k = UBound($F_Ini_Ar,2) then
                ReDim $F_Ini_Ar[UBound($F_Ini_Ar,1)][UBound($F_Ini_Ar,2)+1][UBound($F_Ini_Ar,3)]
            EndIf
            $F_Ini_Ar[$s][$k][0]= $Section_Ar_Temp[$k][0] ;Store key $k in Section $s in ini array
            $F_Ini_Ar[$s][$k][1]= $Section_Ar_Temp[$k][1] ;Store Value for key $k in Section $s in ini array
            
        Next
        
    Next
    Return $F_Ini_Ar
EndFunc


Func Ini_Read_Num($F_Ini_file,$S,$K,$V) ;Another way of getting values
    $SectionNames=IniReadSectionNames($F_Ini_file)
    $KeyName=IniReadSection($F_Ini_file,$SectionNames[$S])
    Return $KeyName[$K][$V]
EndFunc

so

$Ini_Array[0][0][0] = Number of Sections

$Ini_Array[0][1] = Number of keys in section s

$Ini_Array[0][0][1] = Total Number of keys

$Ini_Array[0][0] = Section Name

$Ini_Array[k][0] = Key k in section s

$Ini_Array[k][1] = Value of key k in section s

The problem is i think this function would waste memory. Is that correct?

An alternative would be to use Ini_Read_Num($F_Ini_file,$S,$K,$V) every time i need the value but would this be slower than getting the value from the array.

Iam fairly new to autoit and programming in general so please forgive any stupid mistakes.

Link to comment
Share on other sites

Thanks SmOke N

I seem to have a hard time finding what i want when searching the forum

you did the same thing with half the length of code and thanks for adding $aKeyValues[0][0][0] = Ubound($aKeyValues, 1) - 1.

Link to comment
Share on other sites

SmOke N If i am not mistaken your code assumes that all sections have the same number of keys. whereas the one above doesnt, I could be wrong.

If they dont have the same number of keys then it leads to array elements without assigned values which leads to a waste of memory. also since my array section dimension is non-zero based it leads to a further 2*k(max) elements without values.

After seeing your code, mine could do with alot of tidying.

Link to comment
Share on other sites

Here is the The more efficient version of the above code based on yours

$Ini_file="vUDOHKGL.ini"
$Ini_Array = Ini_to_Array($Ini_file)

For $s=1 to $Ini_Array[0][0][0]
        $Key_String=""
        For $k=1 to $Ini_Array[$s][0][1]
            $Key_String = $Key_String & $Ini_Array[$s][$k][0] &"=" &$Ini_Array[$s][$k][1] & @CRLF ; key and value table FOR MSGBOX
        Next
        MsgBox(0,"Ini_to_Array Test Msg", "[" &$Ini_Array[$s][0][0] &"]: " &$Ini_Array[$s][0][1] &@CRLF &$Key_String) ;MSGBOX
Next


Func Ini_to_Array( $F_Ini_file)
    $SectionNames=IniReadSectionNames($F_Ini_file)
    local $F_Ini_Ar[$SectionNames[0]+1][1][2]
    If @error Then Return SetError(1, 0, 0)
    $F_Ini_Ar[0][0][0]=$SectionNames[0] ;Store Number of sections 
    $F_Ini_Ar[0][0][1]=0 ;assign 0 for total number of keys
    
    For $s=1 to $SectionNames[0] ;save section name in ini array
        Local $Section_Ar_Temp = IniReadSection($F_Ini_file,$SectionNames[$s])
        $F_Ini_Ar[$s][0][0]= $SectionNames[$s] ;Store Section $s in ini array
        $F_Ini_Ar[$s][0][1]= $Section_Ar_Temp[0][0] ;Store number of keys in Section $s in ini array
        $F_Ini_Ar[0][0][1]=$F_Ini_Ar[0][0][1]+$Section_Ar_Temp[0][0]
        
        if $Section_Ar_Temp[0][0] >= UBound($F_Ini_Ar,2) then
            ReDim $F_Ini_Ar[UBound($F_Ini_Ar,1)][$Section_Ar_Temp[0][0]+1][UBound($F_Ini_Ar,3)]
        EndIf
        
        For $k=1 to $Section_Ar_Temp[0][0]
            $F_Ini_Ar[$s][$k][0]= $Section_Ar_Temp[$k][0] ;Store key $k in Section $s in ini array
            $F_Ini_Ar[$s][$k][1]= $Section_Ar_Temp[$k][1] ;Store Value for key $k in Section $s in ini array
        Next
    Next
    Return $F_Ini_Ar
EndFunc
Link to comment
Share on other sites

  • Moderators

SmOke N If i am not mistaken your code assumes that all sections have the same number of keys. whereas the one above doesnt, I could be wrong.

If they dont have the same number of keys then it leads to array elements without assigned values which leads to a waste of memory. also since my array section dimension is non-zero based it leads to a further 2*k(max) elements without values.

After seeing your code, mine could do with alot of tidying.

No it doesn't assume that, take a look there are 2 For/Next loops, and IniReadSection() is in one of those loops :lmao:

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

:lmao: Iam slightly confused.

say I have 2 sections one with four keys and one with two but the two appears after the one with four.

[section 1]

key1=v1

key2=v2

key3=v3

key4=v4

[section 2]

key1

key2

I seem to get an error when trying to read from the array key3 and key4 in section one. If you ReDim an array giving it smaller dimension values , ie from $Array[1][4][1] ReDim $Array[2][2][1] would it not just delete the ones from before, $Array[1][3][1] and $Array[1][4][1].

Is it the Autoit version Iam using maybe. Iam using the public release BTW v3.2.0.1 i think.

Link to comment
Share on other sites

  • Moderators

:lmao: Iam slightly confused.

say I have 2 sections one with four keys and one with two but the two appears after the one with four.

[section 1]

key1=v1

key2=v2

key3=v3

key4=v4

[section 2]

key1

key2

I seem to get an error when trying to read from the array key3 and key4 in section one. If you ReDim an array giving it smaller dimension values , ie from $Array[1][4][1] ReDim $Array[2][2][1] would it not just delete the ones from before, $Array[1][3][1] and $Array[1][4][1].

Is it the Autoit version Iam using maybe. Iam using the public release BTW v3.2.0.1 i think.

No, I think your just confusing yourself.

It doesn't matter how many keys it has, because it's all based off the section names.

Loop 1 = Section names (Primary)

Loop2 = Key ... which is also (or should be) = to Value

So, [section 1][Key 1][Value 1] is going to be different then lets say [section 2][Key 50][Value 50], now I'm starting to confuse myself on the explination... All in all the main focus is the [section N] not the [Key] or [Value], why not just use the example I have, I think it does what you are trying to do... Unless this is just an learning experiece.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

No, I think your just confusing yourself.

lol, yeah i usually end up doing that. :lmao:

why not just use the example I have, I think it does what you are trying to do... Unless this is just an learning experiece.

I tried using your example and i think its suppose to do what i want but i get an error.

Here is your example and the line i get an error at

IniWrite (@DesktopDir & '\MyIniTest.ini', "section 1", "Key" &$i, "val" &$i )
Next

for $i=1 to 3 
IniWrite (@DesktopDir & '\MyIniTest.ini', "section 2", "Key" &$i, "val" &$i )
Next


Global $IniInfo = _IniGetSKV(@DesktopDir & '\MyIniTest.ini')
MsgBox (0,"Test", $IniInfo[1][6][1]) ;ERROR HERE SINCE ARRAY DOESNT HAVE 6 th element in 2nd dimension i think



Func _IniGetSKV($hIniLocation)
    ;Get All Sections
    Local $aSections = IniReadSectionNames($hIniLocation)
    If @error Then Return SetError(1, 0, 0)
    ;Get All The Keys and Values for Each section
    Local $aKeyValues[$aSections[0]+1][1][3]
    For $iCount = 1 To $aSections[0]
        $aKV = IniReadSection($hIniLocation, $aSections[$iCount])
        ReDim $aKeyValues[$aSections[0]+1][$aKV[0][0]+1][3]
        For $xCount = 1 To $aKV[0][0]
            $aKeyValues[$iCount][$xCount][0] = $aSections[$iCount]
            $aKeyValues[$iCount][$xCount][1] = $aKV[$xCount][0]
            $aKeyValues[$iCount][$xCount][2] = $aKV[$xCount][1]
        Next
    Next
    $aKeyValues[0][0][0] = Ubound($aKeyValues, 1) - 1
    Return $aKeyValues ;Return a 3 Dimensional Array
EndFunc
Link to comment
Share on other sites

  • Moderators

lol, yeah i usually end up doing that. :lmao:

I tried using your example and i think its suppose to do what i want but i get an error.

Here is your example and the line i get an error at

IniWrite (@DesktopDir & '\MyIniTest.ini', "section 1", "Key" &$i, "val" &$i )
Next

for $i=1 to 3 
IniWrite (@DesktopDir & '\MyIniTest.ini', "section 2", "Key" &$i, "val" &$i )
Next
Global $IniInfo = _IniGetSKV(@DesktopDir & '\MyIniTest.ini')
MsgBox (0,"Test", $IniInfo[1][6][1]) ;ERROR HERE SINCE ARRAY DOESNT HAVE 6 th element in 2nd dimension i think
Func _IniGetSKV($hIniLocation)
    ;Get All Sections
    Local $aSections = IniReadSectionNames($hIniLocation)
    If @error Then Return SetError(1, 0, 0)
    ;Get All The Keys and Values for Each section
    Local $aKeyValues[$aSections[0]+1][1][3]
    For $iCount = 1 To $aSections[0]
        $aKV = IniReadSection($hIniLocation, $aSections[$iCount])
        ReDim $aKeyValues[$aSections[0]+1][$aKV[0][0]+1][3]
        For $xCount = 1 To $aKV[0][0]
            $aKeyValues[$iCount][$xCount][0] = $aSections[$iCount]
            $aKeyValues[$iCount][$xCount][1] = $aKV[$xCount][0]
            $aKeyValues[$iCount][$xCount][2] = $aKV[$xCount][1]
        Next
    Next
    $aKeyValues[0][0][0] = Ubound($aKeyValues, 1) - 1
    Return $aKeyValues ;Return a 3 Dimensional Array
EndFuncoÝ÷ Ûú®¢×¢½r¢èZ½ëayé^éíé»­Ê«{¦¦W¨¬,Ê°z{m£x§¶¢¿Í{e¢H¶§*.ßÚÞ¢÷«r©'¶)àÖ¥¢Ö§uúèg¬k(§ØZ´'£­ßÛ-®çyÆ®±â(~קvazƦzØb7ö÷«z׬µçmçîËb¢|"¶ay·¥£
)¶*'Ýý±ø§y©ÝÂ䱫ƵçT±ä×Ùh¢F­¶¨ºÚnµ«­¢+Ù½ÈÀÌØí¤ôÄQ¼Ì(%%¹¥]ɥѡͭѽÁ¥ÈµÀìÌäìÀäÈí5å%¹¥QÍй¥¹¤Ìäì°ÅÕ½ÐíÍÑ¥½¸ÄÅÕ½Ðì°ÅÕ½Ðí-äÅÕ½ÐìµÀìÀÌØí¤°ÅÕ½ÐíÙ°ÅÕ½ÐìµÀìÀÌØí¤¤)9áÐ)½ÈÀÌØí¤ôÄQ¼Ì(%%¹¥]ɥѡͭѽÁ¥ÈµÀìÌäìÀäÈí5å%¹¥QÍй¥¹¤Ìäì°ÅÕ½ÐíÍÑ¥½¸ÈÅÕ½Ðì°ÅÕ½Ðí-äÅÕ½ÐìµÀìÀÌØí¤°ÅÕ½ÐíÙ°ÅÕ½ÐìµÀìÀÌØí¤¤)9áÐ)±½°ÀÌØí%¹¥%¹¼ô}%¹¥ÑM-X¡Í­Ñ½Á¥ÈµÀìÌäìÀäÈí5å%¹¥QÍй¥¹¤Ìäì¤)½ÈÀÌØí¥àôÄQ¼U    ½Õ¹ ÀÌØí%¹¥%¹¼°Ä¤´Ä(%½ÈÀÌØí¤ôÄQ¼U ½Õ¹ ÀÌØí%¹¥%¹¼°È¤´Ä($%
½¹Í½±]ɥѡ1µÀìÌäíMÑ¥½¸ôÌäìµÀìÀÌØí%¹¥%¹½lÀÌØí¥áulÀÌØí¥ulÁtµÀì
HµÀì|($$$$Ìäí-äôÌäìµÀìÀÌØí%¹¥%¹½lÀÌØí¥áulÀÌØí¥ulÅtµÀì
HµÀìÌäíY±ÕôÌäìµÀìÀÌØí%¹¥%¹½lÀÌØí¥áulÀÌØí¥ulÉt¤(%9áÐ)9áÐ)Õ¹}%¹¥ÑM-X ÀÌØí¡%¹¥1½Ñ¥½¸¤($íб°MÑ¥½¹Ì(%1½°ÀÌØíMÑ¥½¹Ìô%¹¥IMÑ¥½¹9µÌ ÀÌØí¡%¹¥1½Ñ¥½¸¤(%%ÉɽÈQ¡¸IÑÕɸMÑÉÉ½È Ä°À°À¤($íб°Q¡-å̹Y±ÕÌ½È ÍÑ¥½¸(%1½°ÀÌØí-åY±ÕÍlÀÌØíMÑ¥½¹ÍlÁt¬ÅulÅulÍt(%½ÈÀÌØí¥
½Õ¹ÐôÄQ¼ÀÌØíMÑ¥½¹ÍlÁt($$ÀÌØí-Xô%¹¥IMÑ¥½¸ ÀÌØí¡%¹¥1½Ñ¥½¸°ÀÌØíMÑ¥½¹ÍlÀÌØí¥
½Õ¹Ñt¤($%I¥´ÀÌØí-åY±ÕÍlÀÌØíMÑ¥½¹ÍlÁt¬ÅulÀÌØí-YlÁulÁt¬ÅulÍt($%½ÈÀÌØíá
½Õ¹ÐôÄQ¼ÀÌØí-YlÁulÁt($$$ÀÌØí-åY±ÕÍlÀÌØí¥
½Õ¹ÑulÀÌØíá
½Õ¹ÑulÁtôÀÌØíMÑ¥½¹ÍlÀÌØí¥
½Õ¹Ñt($$$ÀÌØí-åY±ÕÍlÀÌØí¥
½Õ¹ÑulÀÌØíá
½Õ¹ÑulÅtôÀÌØí-YlÀÌØíá
½Õ¹ÑulÁt($$$ÀÌØí-åY±ÕÍlÀÌØí¥
½Õ¹ÑulÀÌØíá
½Õ¹ÑulÉtôÀÌØí-YlÀÌØíá
½Õ¹ÑulÅt($%9áÐ(%9áÐ($ÀÌØí-åY±ÕÍlÁulÁulÁtôU ½Õ¹ ÀÌØí-åY±Õ̰Ĥ´Ä(%IÑÕɸÀÌØí-åY±ÕÌíIÑÕɸ̥µ¹Í¥½¹°ÉÉä)¹Õ¹ìôôÐí}%¹¥ÑM-X
Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

oops for some reason i i didnt copy paste the top line. there is a next without the for. the first line of code in post #9 is suppose to include

For $i to 6

your code just above has the same number of keys in the 2 sections which was what i was trying to say. if the first section has a larger number of keys it will not work.

anyway my original question was will having an array with unassigned values waste memory.

Link to comment
Share on other sites

  • Moderators

I see what I did:

For $i = 1 To 6
    IniWrite(@DesktopDir & '\MyIniTest.ini', "section 1", "Key" & $i, "val" & $i)
Next
For $i = 1 To 3
    IniWrite(@DesktopDir & '\MyIniTest.ini', "section 2", "Key" & $i, "val" & $i)
Next
Global $IniInfo = _IniGetSKV(@DesktopDir & '\MyIniTest.ini')
For $ix = 1 To $IniInfo[0][0][0]
    For $i = 1 To $IniInfo[$ix][0][0]
        ConsoleWrite(@LF & 'Section = ' & $IniInfo[$ix][$i][0] & @CR & _
                'Key = ' & $IniInfo[$ix][$i][1] & @CR & 'Value = ' & $IniInfo[$ix][$i][2])
    Next
Next
Func _IniGetSKV($hIniLocation)
    ;Get All Sections
    Local $aSections = IniReadSectionNames($hIniLocation)
    If @error Then Return SetError(1, 0, 0)
    ;Get All The Keys and Values for Each section
    Local $aKeyValues[$aSections[0] + 1][1][3], $nCount;Added $nCount
    For $iCount = 1 To $aSections[0]
        $aKV = IniReadSection($hIniLocation, $aSections[$iCount])
        If $nCount < $aKV[0][0] Then;Added this condition statement
            $nCount = $aKV[0][0]
            ReDim $aKeyValues[$aSections[0] + 1][$aKV[0][0] + 1][3]
        EndIf
        $aKeyValues[$iCount][0][0] = $aKV[0][0];Added this
        For $xCount = 1 To $aKV[0][0]
            $aKeyValues[$iCount][$xCount][0] = $aSections[$iCount]
            $aKeyValues[$iCount][$xCount][1] = $aKV[$xCount][0]
            $aKeyValues[$iCount][$xCount][2] = $aKV[$xCount][1]
        Next
    Next
    $aKeyValues[0][0][0] = $aSections[0]
    Return $aKeyValues ;Return a 3 Dimensional Array
EndFunc   ;==>_IniGetSKV

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

  • Moderators

Here's an attempt at an Ini 3 Dim ArrayDisplay to show it better:

For $i = 1 To 6
    IniWrite(@DesktopDir & '\MyIniTest.ini', "section 1", "Key" & $i, "val" & $i)
Next
For $i = 1 To 3
    IniWrite(@DesktopDir & '\MyIniTest.ini', "section 2", "Key" & $i, "val" & $i)
Next
Global $IniInfo = _IniGetSKV(@DesktopDir & '\MyIniTest.ini')
_ArrayIniDisplay($IniInfo, 'IniInfo')
Func _IniGetSKV($hIniLocation)
    ;Get All Sections
    Local $aSections = IniReadSectionNames($hIniLocation)
    If @error Then Return SetError(1, 0, 0)
    ;Get All The Keys and Values for Each section
    Local $aKeyValues[$aSections[0] + 1][1][3], $nCount;Added $nCount
    For $iCount = 1 To $aSections[0]
        $aKV = IniReadSection($hIniLocation, $aSections[$iCount])
        If $nCount < $aKV[0][0] Then;Added this condition statement
            $nCount = $aKV[0][0]
            ReDim $aKeyValues[$aSections[0] + 1][$aKV[0][0] + 1][3]
        EndIf
        $aKeyValues[$iCount][0][0] = $aKV[0][0];Added this
        For $xCount = 1 To $aKV[0][0]
            $aKeyValues[$iCount][$xCount][0] = $aSections[$iCount]
            $aKeyValues[$iCount][$xCount][1] = $aKV[$xCount][0]
            $aKeyValues[$iCount][$xCount][2] = $aKV[$xCount][1]
        Next
    Next
    $aKeyValues[0][0][0] = $aSections[0]
    Return $aKeyValues ;Return a 3 Dimensional Array
EndFunc   ;==>_IniGetSKV


Func _ArrayIniDisplay($aArray, $sTitle = '')
    If Not IsArray($aArray) Then SetError(1, 0, 0)
    Local $sIni = '[0][0][0] = ' & $aArray[0][0][0] & ' Sections' & @CR
    For $xCC = 1 To $aArray[0][0][0]
        $sIni &= @CR & '[' & $xCC & '][0][0] = ' & $aArray[$xCC][0][0] & ' Keys/Values' & @CR & _
            '[' & $xCC & '][' & $xCC & '][0] = ' & $aArray[$xCC][$xCC][0] & @CR
        For $aCC = 1 To $aArray[$xCC][0][0]
            $sIni &= '[' & $xCC & '][' & $aCC & '][1] = ' & $aArray[$xCC][$aCC][1] & @CR & _
                '[' & $xCC & '][' & $aCC & '][2] = ' & $aArray[$xCC][$aCC][2] & @CR
        Next
    Next
    MsgBox(0, $sTitle, StringTrimRight($sIni, 1))
EndFunc
That should give you a better view.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

ok, glad thats been sorted out. the function _ArrayIniDisplay() is now very similar to the one I posted in #5 Ini_to_Array() which was based on yours but yours has an

If @error Then Return SetError(1, 0, 0)

so i think Ill use yours.

_ArrayIniDisplay() << nice func, Displays an Ini file very well instead of sections individually. will come in handy.

So the array $IniInfo has an element $IniInfo[2][6][1] but offcourse there is no key 6 in section 2. so my original question was would you advise using something like this since it will be wasting memory right?.

do you know how much memory if for example you had 10 sections varying in the amount of keys from around 2 to around 6 because if its very little then i would rather have the convinience of having this array.

Link to comment
Share on other sites

  • Moderators

ok, glad thats been sorted out. the function _ArrayIniDisplay() is now very similar to the one I posted in #5 Ini_to_Array() which was based on yours but yours has an

If @error Then Return SetError(1, 0, 0)

so i think Ill use yours.

_ArrayIniDisplay() << nice func, Displays an Ini file very well instead of sections individually. will come in handy.

So the array $IniInfo has an element $IniInfo[2][6][1] but offcourse there is no key 6 in section 2. so my original question was would you advise using something like this since it will be wasting memory right?.

do you know how much memory if for example you had 10 sections varying in the amount of keys from around 2 to around 6 because if its very little then i would rather have the convinience of having this array.

I'm not sure I'm following your question, but the minimal bytes of memory being used are of no concern if it's doing what you want it to do.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...