Home AMX User Forum NetLinx Studio

Issues with LENGTH_STRING accuracy

Hey Programmer types:

I'm hitting my head against a brick wall here: I must be missing something easy. Here's the scenario:
bufARQ1 is a CHAR array of size 256, that is linked via CREATE_BUFFER to the device dvARQ1, an AudioReQuest.

My DEFINE_PROGRAM is this: if(LENGTH_STRING(bufARQ1)) ARQ_PARSE();

ARQ_PARSE() does this:
DEFINE_FUNCTION ARQ_PARSE(){
    STACK_VAR CHAR thisMSG[100]
    
    if(!FIND_STRING(bufARQ1,"$FF,$FB",1)) return; // no terminator
    
    thisMSG = REMOVE_STRING(bufARQ1,"$FF,$FB",1);
    SEND_STRING 0, "'arqMSG[',itoa(LENGTH_STRING(thisMSG)),']:',thisMSG";
}
But sometimes the SEND_STRING 0 is reached when the terminator does not appear in bufARQ. Furthermore, when this happens, the length of the string thisMSG is being reported incorrectly!
Line     86 (16:05:47):: AudioReQuest 0:4:0 is ONLINE
Line     87 (16:05:47)::   IP:   10.1.10.65
Line     88 (16:05:47)::   PORT: 3663
Line     89 (16:05:47):: arqMSG[4]:s$F1$FF$FB
Line     90 (16:05:47):: arqMSG[13]:2!$01GRAPHIC$F1$FF$FB
Line     91 (16:05:47):: arqMSG[16]:2$12$07Artists =>$F1$FF$FB
Line     92 (16:05:47):: arqMSG[13]:2!$02GRAPHIC$F1$FF$FB
Line     93 (16:05:47):: arqMSG[15]:2$12$08Albums =>$F1$FF$FB
Line     94 (16:05:47):: arqMSG[13]:2!$03GRAPHIC$F1$FF$FB
Line     95 (16:05:47):: arqMSG[15]:2$12$09Genres =>$F1$FF$FB
Line     96 (16:05:47):: arqMSG[13]:2!$04GRAPHIC$F1$FF$FB
Line     97 (16:05:47):: arqMSG[17]:2$12$0ANow Playing$F1$FF$FB
Line     98 (16:05:47):: arqMSG[13]:2!$05GRAPHIC$F1$FF$FB
Line     99 (16:05:47):: arqMSG[18]:2$12$0BPlaylists =>$F1$FF$FB
Line    100 (16:05:47):: arqMSG[13]:2!$06GRAPHIC$F1$FF$FB
Line    101 (16:05:47):: arqMSG[6]:2$12$0C$F1$FF$FB
Line    102 (16:05:47):: arqMSG[6]:2$12$0D$F1$FF$FB
Line    103 (16:05:47):: arqMSG[14]:2!
Line    104 (16:05:47):: arqMSG[8]:2$12$03
Line    105 (16:05:47):: arqMSG[10]:2$12$02Home$F1$FF$FB
etc.
Regard lines 103 and 104. Is there some tricky thing with the length of the string going on? Anyone here know how this is possible?

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    mpullin wrote: »
    Regard lines 103 and 104. Is there some tricky thing with the length of the string going on? Anyone here know how this is possible?
    I?ll guess that there are NULLs in the string and SEND_STRING 0 is choking on them. Unfortunately SEND_STRING 0 treats strings as NULL terminated. I?ll bet the data is there and that LENGTH_STRING is correct. Instead of doing a SEND_STRING 0 try a SEND_STRING to a virtual device and watch that virtual device in Notifications, that?s the workaround I?ve been using. Notifications works properly. You can?t count on Diagnostics for cases like this.
  • viningvining Posts: 4,368
    I seem to recall a similiar problems with nulls that took forever to figure out. I probably just created a function to clean the string prior to sending.
  • mpullinmpullin Posts: 949
    :headslap:
    Joe Hebert wrote: »
    I?ll guess that there are NULLs in the string and SEND_STRING 0 is choking on them. Unfortunately SEND_STRING 0 treats strings as NULL terminated. I?ll bet the data is there and that LENGTH_STRING is correct. Instead of doing a SEND_STRING 0 try a SEND_STRING to a virtual device and watch that virtual device in Notifications, that?s the workaround I?ve been using. Notifications works properly. You can?t count on Diagnostics for cases like this.
    Thanks Joe. I remember now that Diagnostics stops printing when it sees $00... but for some reason I didn't think that my problem could be in the diagnostics step itself!

    If only we could see notifications from Ethernet devices directly.......
  • DHawthorneDHawthorne Posts: 4,584
    I routinely run my diagnostics messages through a little filter to avoid such issues:
    DEFINE_FUNCTION CHAR[5096] sCleanAscii (CHAR sString[])
    {
        STACK_VAR CHAR sTemp[5096] ;
        STACK_VAR INTEGER nCount ;
        
        FOR(nCount = 1; nCount <= LENGTH_STRING(sString); nCount ++)
        {
    	SELECT
    	{
    	    ACTIVE(sString[nCount] < 32) : // low order ASCII
    	    {
    		sTemp = "sTemp, '<', ITOA(sString[nCount]), '>'"
    	    }	
    	    ACTIVE(sString[nCount] > 126) : // high order ASCII
    	    {
    		sTemp = "sTemp, '<', ITOA(sString[nCount]), '>'"
    	    }	
    	    ACTIVE(TRUE) : sTemp = "sTemp, sString[nCount]" ;
    	}
        }
        
        RETURN sTemp ;
    }
    

    This would output '<0>' in place of any nulls without "breaking" the regular ASCII characters. I have another version that replaces the ITOA with ITOHEX if I want hex notation instead of decimal.
  • AMXJeffAMXJeff Posts: 450
    PrintHex

    I normally convert my strings to ASCII in order to make sure what I am actually getting when doing send string 0... Two of the function I tend to use...
    Define_Function Char[1000] PrintHex(Char cString[])
    {
      Stack_Var Char cTString[100],cHexString[1000],cChar;
      
      cTString = cString
      cHexString = '"'
      While(Length_String(cTString))
      {
        cChar = Get_Buffer_Char(cTString);
        cHexString = "cHexString,'$',Itohex(cChar/$10),Itohex(cChar&#37;$10),','"
      }
      Set_Length_String(cHexString,Length_String(cHexString)-1);
      cHexString = "cHexString,'"'";
      Return cHexString;
    }
    
    
    
    Define_Function Char[1000] PrintAsciiHex(Char cString[])
    {
      Stack_Var Char cTString[100],cHexString[1000],cChar;
      
      cTString = cString
      cHexString = '"'
      While(Length_String(cTString))
      {
        cChar = Get_Buffer_Char(cTString);
        
        IF (cChar >= 32 && cChar <= 126)
        {
          IF (cHexString[LENGTH_STRING(cHexString)-1] = 39) 
          { 
            Set_Length_String(cHexString,Length_String(cHexString)-2);
            cHexString = "cHexString,cChar,39,','"
          }
          ELSE
          {
            cHexString = "cHexString,39,cChar,39,','"      
          }
        }
        ELSE
        {
          cHexString = "cHexString,'$',Itohex(cChar/$10),Itohex(cChar%$10),','"
        }
      }
      
      Set_Length_String(cHexString,Length_String(cHexString)-1);
      cHexString = "cHexString,'"'";
      Return cHexString;
    }
    
    
Sign In or Register to comment.