Parsing Question

I am working on parsing a GET sim.php?cmd=cmd&p1=p1&p2=p2&p3=p3 HTTP/1.1". And I am trying to break it apart into cmd, p1, p2, p3. I am working on the scenario when I might not send all variables and would still like to be able to parse it correctly. The question comes if I only do ...

"GET sim.php?cmd=test"

void ParseReceivedRequest()
  Serial.println("Parsing Get Request");
  Serial.println(buffer); //returns GET sim.php?cmd=test HTTP/1.1

  char* equal1;
  char* and1;

  equal1 = strstr(buffer, "=") + 1; //Looks for the first equal starting at the buffer.
  and1 = strstr(equal1, "&") + 1; //Looks for the first & starting from the first equal.
  PrintString("equal1",equal1); //returns test HTTP/1.1
  Serial.println(and1); //returns unknown

What is and1 actually returning? Null? New line? Nothing? And how can I incorporate that into an if statement?

if (and1 == "") Serial.println("Do Something");

If the searched for string does not exist, strstr returns NULL. To determine if the pointer is valid:

  // It is. Do something...

A pointer will never equal "", so your test would never be true.

If you take the null pointer returned by strstr() when it fails to find something and add 1 to it you are not going to have a null pointer you can test. Best to test the pointer BEFORE you add one:

  char* equal1;
  char* and1;

  char * pos = strstr(buffer, "="); //Looks for the first '=' in the buffer.
  if (pos)
     equal1 = pos+1;  // Point to the character after the first '='
   //  Whatever you need to do when the parse fails.

I think you're making more work for yourself than you need - what you are looking for is several text strings ending in '=' sign - so how about a helper function to do most of the work:

bool grabParam(const char *input,const char *cmd,char *buff,int len)
  // return false if not found, or true and buff contains parameter found
  // note cmd passed in must include '=' at end
  const char *ptr=strstr(input,cmd); // find command
  if ( NULL==ptr ) // not found?
    return false;
  ptr+=strlen(cmd); // skip command text; point to param
  int i=0;
  while ( '\0'!=ptr[i] && '&'!=ptr[i] ) // find full param
  i=min(len-1,i); // make sure we don't overflow buff
  strncpy(buff,ptr,i); // copy it over
  return true;

You call it like this:

bool found=false;
const char *text="GET sim.php?cmd=cmd&p1=p1&p2=p2&p3=p3 HTTP/1.1"; // data to parse
char buff2[40]=""; // where result is placed
int len=sizeof(buff2)/sizeof(buff2[0]);
// now grab entries
if (found)
// use buff2 - param for 'cmd'
if (found)
// use buff2 - param for 'p1'
if (found)
// use buff2 - param for 'p2'

So for instance if you did it for "p3=" you'd get "p3 HTTP/1.1" in buff2.

It works because parameters are the only place that '=' should appear - so if you look for a cmd= string, what follows (at least until '&' or end of line) is your parameter. Note the buff is reused, so make sure you use the information before the next call, or store it, or use another buffer.

Thanks for the help guys a parameter function would probably be cleaner I was just more stumped at the time as why it wasn't Null as I thought I tested that. The if statement in my question was just an example. But of course retrying it a 3rd time worked. Thanks again.