Home AMX User Forum NetLinx Studio
Options

Incoming String Parsing - String.Includes Method

What is the best way to search for String within a String? This comes from my JavaScript projects, but I find it tremendously useful when dealing with highly chatty, and sometimes unreliable/over-innundated/un-buffered equipment connections.

Example:
char myString[30] = 'The quick brown fox jumped over the fence'
myBoolean = myString.Includes('fox jumped', 1)

myBoolean would evaluate as true in the above example. I've also seen indexOf used this way.

The problem is that some equipment I work with may report it's input state in any one of about 30 different response strings depending on how its being used. I could search for every single version of that dialog using COMPARE_STRING, even if I have to substitute '?', but sometime the Input starts at character[5], sometimes at character[35] and sometimes, not until after a stack of carriage returns (in which case I would create a string buffer and concatenate before evaluating).

Searching this way would also make the script more version resistant because the manufacturer could change/expand the response order, but I would still only be looking for that one small snippet of dialog relevant to my function.

Of course, as an AMX beginner, I'm probably just not fully understanding the capabilities of a certain command.
As always, any help or insight is very much appreciated!

Comments

  • Options
    DHawthorneDHawthorne Posts: 4,584
    I use FIND_STRING(). It will return the index of where your distinctive search begins, and you can take it from there.
  • Options
    alecgalecg Posts: 30
    I see where you're going with this Dave - break it into multiple parts. I could even break that processing off into an include, right?

    I'll try it, thanks!
  • Options
    chillchill Posts: 186
    I do a create_buffer on the device; then
    data_event[some_dev]
    {
      string :
      {
        local_var char dev_sample[64]
       
        while(find_string(dev_buffer,"cr",1))
        {
          dev_sample = remove_string(dev_buffer,"cr",1)
          select
          {
            active(find_string(dev_sample,'brown',1)) :
            // do something
            active(find_string(dev_sample,'fox',1)) :
            // do something else
            active(find_string(dev_sample,'brown fox',1)) :
            // do some other thing
          }
      }
    }
    

    Note that with select - active, the first match wins. In the example above, the third active() will never run. If your device reliably terminates each message with a carriage return (or some other known string), even if some messages are otherwise null, this technique works well. I've been using it for years.

    HTH.
    .
  • Options
    a_riot42a_riot42 Posts: 1,624
    chill wrote: »
    I do a create_buffer on the device; then
    data_event[some_dev]
    {
      string :
      {
        local_var char dev_sample[64]
       
        while(find_string(dev_buffer,"cr",1))
        {
          dev_sample = remove_string(dev_buffer,"cr",1)
          select
          {
            active(find_string(dev_sample,'brown',1)) :
            // do something
            active(find_string(dev_sample,'fox',1)) :
            // do something else
            active(find_string(dev_sample,'brown fox',1)) :
            // do some other thing
          }
      }
    }
    

    Note that with select - active, the first match wins. In the example above, the third active() will never run. If your device reliably terminates each message with a carriage return (or some other known string), even if some messages are otherwise null, this technique works well. I've been using it for years.

    HTH.
    .

    find_string can burn you at times though. With Denon receivers for instance, they can have a response of Stereo and 5 CH Stereo. If you use find_string for both responses, and the Stereo check is first, then the second one will never run when 5 CH Stereo is sent.
    Paul
  • Options
    chillchill Posts: 186
    a_riot42 wrote: »
    find_string can burn you at times though. With Denon receivers for instance, they can have a response of Stereo and 5 CH Stereo. If you use find_string for both responses, and the Stereo check is first, then the second one will never run when 5 CH Stereo is sent.
    Paul

    Exactly my point in saying that the third active() will never run. You have to watch the order in which you put them. I had this driven into my head years ago while coding for a projector that might respond to an input status query with 'video' or 'svideo'. If you put `active(find_string(foo,'video',1))` first, then the 'svideo' one never hits.
    .
  • Options
    a_riot42a_riot42 Posts: 1,624
    chill wrote: »
    Exactly my point in saying that the third active() will never run. You have to watch the order in which you put them. I had this driven into my head years ago while coding for a projector that might respond to an input status query with 'video' or 'svideo'. If you put `active(find_string(foo,'video',1))` first, then the 'svideo' one never hits.
    .

    I don't like it when order matters, so I try to avoid that. Instead of using find_string I just compare the text:

    if (sResponse == 'Stereo')
    else if (sResponse == '5 CH Stereo')

    etc, although I usually use an array of strings rather than hard coding them like above.

    Paul
  • Options
    alecgalecg Posts: 30
    Can I search the data for a comparison to a Multi-Dimensional array?

    Example:
    Define_Constant
    char Input_Name[32][32]=
    {
         {'Bob'},
         {'Sue'),
         etc.
    }
    
    DATA_EVENT[my_device]
    {
        STRING:
        {
            LOCAL_VAR Buffer[100]
            STACK_VAR received_string[100]
    
            WHILE (FIND_STRING (DATA.TEXT,"$0d",1))
            {
    
                received_string = "Buffer, REMOVE_STRING (DATA.TEXT,"$0d",1)"
                CLEAR_BUFFER Buffer
                SELECT
                {
                    ACTIVE (find_string(received_string, Input_Name, 1):
                    {
                          //***********LOGIC*************
                    }
            }
        }
    } 
    

    Would Find_String actually search the whole "Input_Name" array for a match?
    If so, how would I know which member of the array returned a hit?

    I'm doing this right now by simple running the entire Array thru a FOR "loop" and comparing each value, but this seems like an awful lot of work for the processor if there is a streamlined method.

    Any thoughts?
  • Options
    jjamesjjames Posts: 2,908
    alecg wrote: »
    Can I search the data for a comparison to a Multi-Dimensional array?
    No, you need to loop through the array and do your search.

    Edit: removed code - didn't realize you said you were already looping.
  • Options
    alecgalecg Posts: 30
    Thanks jjames! Doesn't hurt to ask, right?
Sign In or Register to comment.