Raised This Month: $ Target: $400
 0% 

Parsing KeyValue File


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
CrimsonGT
Veteran Member
Join Date: Oct 2007
Location: Gainesville, FL
Old 10-11-2010 , 08:10   Parsing KeyValue File
Reply With Quote #1

Is there any way to properly parse a key value structure such as the following? The amount of Key/Value lines per section will be varying, so I cannot simply call GetValueString() a set number of times. I cannot find anyway to loop through as it doesn't seem I can iterate over each key/value line. I have also tried just turning the values into sub-sections and reading them that way, but I would like to avoid forcing the user to place {} after every line. I would also like to avoid having to write an XML extension if possible.

In this case, the 'key' is irrelevant. I simply need to get the values, but to do so I must be able to iterate over each line in some manner.

Code:
"ROOT"
{
    "SECTION1"
    {
        "1"            "value1"
        "2"            "value2"
        "3"            "value3"
    }
    "SECTION2"
    {
        "1"            "value1"
        "2"            "value2"
        "3"            "value3"
    }
    "SECTION3"
    {
        "1"            "value1"
        "2"            "value2"
        "3"            "value3"
    }
}
CrimsonGT is offline
Monkeys
Veteran Member
Join Date: Jan 2010
Old 10-11-2010 , 10:10   Re: Parsing KeyValue File
Reply With Quote #2

You coud use default properties for finding out if the value existed or not?

PHP Code:
new SectionC 1KeyC 1;
decl String:SectionBuffer[32], String:KeyBuffer[32];
new 
String:Output[32];

Format(SectionBuffersizeof(SectionBuffer), "Section%d"SectionC);
StringToInt(KeyCKeyBuffersizeof(KeyBuffer));

while(
KvJumpToKey(KeyValueHandleSectionBufferfalse))
{
    
KvGetString(KeyValueHandleKeyBufferOutputsizeof(Output), "N/A");
    while(!
StrEqual(Output"N/A"))
    {
        
/*
        Do what you need to do with the Output
        */
        
        
KeyC++;
        
StringToInt(KeyCKeyBuffersizeof(KeyBuffer));
        
KvGetString(KeyValueHandleKeyBufferOutputsizeof(Output), "N/A");
    }
    
KvGoBack(KeyValueHandle);
    
SectionC++;
    
Format(SectionBuffersizeof(SectionBuffer), "Section%d"SectionC);

^ Something like that should work if your names are all uniform.
But if they're not, you'll need to use http://wiki.alliedmods.net/KeyValues...erative_Lookup
(Unless that's what you tried already, ofcourse)
__________________
Get a lid on that zombie,
he's never gonna be alri-i-ight.
Oooh get a lid on that zombie,
or he's gonna feed all night.

Last edited by Monkeys; 10-11-2010 at 10:12. Reason: Forgot a KvGoBack. Those kill >:/
Monkeys is offline
CrimsonGT
Veteran Member
Join Date: Oct 2007
Location: Gainesville, FL
Old 10-11-2010 , 13:25   Re: Parsing KeyValue File
Reply With Quote #3

I thought that was going to work, but ran into the same issue since the Section names are not uniform. Before posting I was looking at doing while(KvGetString()) but that didn't return a value. The KvJumpToKey() looked like a solid approach, but since my Section names aren't (and can't be) uniform, that won't work either.

The actual file looks like this...

Code:
"MapGroups"
{
    "Capture the Flag (CTF)"
    {
        "1"            "ctf_2fort"
        "2"            "ctf_doublecross"
        "3"            "ctf_sawmill"
    }
    "Control Point (CP)"
    {
        "1"            "cp_badlands"
        "2"            "cp_dustbowl"
        "3"            "cp_granary"
    }
    "Arena"
    {
        "1"            "arena_badlands"
        "2"            "arena_granary"
        "3"            "arena_lumberyard"
    }
    "Payload"
    {
        "1"            "pl_badwater"
        "2"            "pl_goldrush"
        "3"            "pl_hoodoo_final"
    }
    "King of the Hill (KoTH)"
    {
        "1"            "koth_nucleus"
        "2"            "koth_sawmill"
        "3"            "koth_viaduct"
    }
    "Territory Control (TC)"
    {
        "1"            "tc_hydro"
    }
}
Iterative lookup won't work either since since I don't know what the user may change the section names to. The section names are used as menu categories, and the key/value pairs are options. If I can't think of a better way to do this, I might just have to make the Section names uniform, make the first key/value pair of each section the menu title, and go from there.
CrimsonGT is offline
CrimsonGT
Veteran Member
Join Date: Oct 2007
Location: Gainesville, FL
Old 10-11-2010 , 13:37   Re: Parsing KeyValue File
Reply With Quote #4

Actually, after thinking about it a bit more, I figured out another way to do it. I figured I would post it incase someone stumbles across this in the future and needs to do the same thing. It is not exactly optimal, but I rarely call this function so it isn't an issue.

I am still having a problem where it doesn't iterate the sections properly. It handles the first Section, gets all of the key/value pairs, then just ends. I am still trying to hunt that issue down, so don't use the code directly.

PHP Code:
    if(KvGotoFirstSubKey(kv))
    {
        
decl String:szGroupName[255], String:szMapName[64];

        do
        {
            
KvGetSectionName(kvszGroupNamesizeof(szGroupName)); //Capture the Flag (CTF)
            
PushArrayString(g_MapGroupListszGroupName);
            
PrintToServer("GroupName: %s"szGroupName);

            new 
iMapIndex 1;
            
decl String:szIndexBuffer[3];

            do
            {
                
Format(szIndexBuffersizeof(szIndexBuffer), "%d"iMapIndex);
                
KvGetString(kvszIndexBufferszMapNamesizeof(szMapName), "none");

                if(!
StrEqual(szMapName"none"))
                {
                    
PushArrayString(g_MapGroupFileszMapName);
                    
PrintToServer("KeyName: %s MapName: %s"szIndexBufferszMapName);
                    
iMapIndex++;
                }
            }
            while (!
StrEqual(szMapName"none"false));

            
KvGoBack(kv);
        }
        while (
KvGotoNextKey(kv));
    } 
CrimsonGT is offline
psychonic

BAFFLED
Join Date: May 2008
Old 10-11-2010 , 13:41   Re: Parsing KeyValue File
Reply With Quote #5

Why not just use the SMC parser? It already reads iteratively and tells you all the section names and key names as it reads them rather than you having to know them.
psychonic is offline
Monkeys
Veteran Member
Join Date: Jan 2010
Old 10-11-2010 , 13:42   Re: Parsing KeyValue File
Reply With Quote #6

Oh, my bad. I linked to the wrong section.
Fully traversal should cover it all.
But you're best of using a hybrid suited for your ends.

Here's how I would do it (not garanteed to be the most efficient, but it should work, I guess) with a file like yours:

PHP Code:
new KeyC 1;
decl String:KeyBuffer[12];
new 
String:Output[32];

if(
KvGoToFirstSubKey(KeyValueHandle))
{
    do
    {
        
StringToInt(KeyCKeyBuffersizeof(KeyBuffer));
        
KvGetString(KeyValueHandleKeyBufferOutputsizeof(Output), "N/A");
        while(!
StrEqual(Output"N/A"))
        {
            
/*
            Do what you need to do with the Output
            */
            
            
KeyC++;
            
StringToInt(KeyCKeyBuffersizeof(KeyBuffer));
            
KvGetString(KeyValueHandleKeyBufferOutputsizeof(Output), "N/A");
        }
    }while(
KvGoToNextKey(KeyValueHandle));

Edit: I got ninja'd...


Edit2: But aha! I know how to fix your issue, I believe :p
Remove the KvGoBack(kv);
I do believe KvGoToNextKey already covers that.
__________________
Get a lid on that zombie,
he's never gonna be alri-i-ight.
Oooh get a lid on that zombie,
or he's gonna feed all night.

Last edited by Monkeys; 10-11-2010 at 13:46.
Monkeys is offline
CrimsonGT
Veteran Member
Join Date: Oct 2007
Location: Gainesville, FL
Old 10-11-2010 , 13:46   Re: Parsing KeyValue File
Reply With Quote #7

Quote:
Originally Posted by psychonic View Post
Why not just use the SMC parser? It already reads iteratively and tells you all the section names and key names as it reads them rather than you having to know them.
Because since I had used KV files 100 times in the past (although it was quite a while ago) and I have never touched SMC, I figured I would just get in and get it done quick. Little did I remember the limitations that came along with KV files.

*Edit*

Okay, To be honest, I forgot about the SMC parser as well.
CrimsonGT is offline
psychonic

BAFFLED
Join Date: May 2008
Old 10-11-2010 , 13:48   Re: Parsing KeyValue File
Reply With Quote #8

Quote:
Originally Posted by CrimsonGT View Post
Because since I had used KV files 100 times in the past (although it was quite a while ago) and I have never touched SMC, I figured I would just get in and get it done quick. Little did I remember the limitations that came along with KV files.
YMMV, but I find it much easier to use/understand than the KV system, especially if you're just reading it all-at-once into memory anyway.
psychonic is offline
rhelgeby
Veteran Member
Join Date: Oct 2008
Location: 0x4E6F72776179
Old 10-12-2010 , 11:53   Re: Parsing KeyValue File
Reply With Quote #9

Does the SMC parser catch syntax errors like missing quotes or braces? That would really help, because Valve's parser just crash the server in some cases.
__________________
Richard Helgeby

Zombie:Reloaded | PawnUnit | Object Library
(Please don't send private messages for support, they will be ignored. Use the forum.)
rhelgeby is offline
Send a message via MSN to rhelgeby
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 05:28.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode