Some function for recognizing numbers and text


#1

Is there some function ( like isnumber ) in openAT ?
In fact, i need one function for testing if the input is text or number …


#2

Why don’t you write one for yourself? It’s just a few lines of code, and you perfectly know what it does.
For me, I’ve developed a family of functions that take ascii **ptr as the main input, and perform various things, like consuming an integer in a string, while advancing the pointer to the next token:

void SkipSpaces(ascii **ptr, ascii *white);
bool SkipPrefix(ascii **ptr, ascii *skip); //true->all found
bool SkipString(ascii **ptr, ascii *delims); //true->delim found
int CutInteger(ascii **ptr, int def, int radix, bool skipLast);

If you need to know if the ptr points to an integer (an odd task, IMHO), you’d use

//now ptr points to somewhere in the string
  ascii *tmpPtr=ptr;
  CutInteger(&tmpPtr, -1, 10, false); //expect a 10-base; stop at the first non-numeric character;
    //if a number is not found, it won't advance the pointer at all
  if ((tmpPtr>ptr) && (*tmpPtr==','))
   {
    //it was an integer, terminated with a comma
   };

If I need to parse a string \r\n+CMTI: “SM”,2\r\n, it goes as follows:

bool AnyUnsoHandler(adl_atUnsolicited_t *Data)
 {
  ascii *ptr=Data->StrData;
  SkipSpaces(&ptr, " \t\n\r"); //skip any insignificant characters
  if (SkipPrefix(&ptr, "+CMTI: ")) //skip if found, or leave ptr as-is if not found
   {
    ascii *MemStart=ptr;
    SkipString(&ptr, ", "); //skip characters until a space or a comma is found
    if ((ptr-2>=MemStart+1) && (*MemStart=='"') && (*(ptr-2)=='"))
     {
      int MemLen=ptr-MemStart-1;
      int MemIndex=CutInteger(&ptr, -1, 10, true); //if it's not a number, return -1;
      //expect a 10-base; and do skip the character that terminated the number
      if (MemIndex>0)
       {
        //now MemStart points to the "ME" string including the quotes
        //MemLen is the length of that string
        //and MemIndex is the index
       };
     };
   }
  else if (SkipPrefix(&ptr, "+CUSD: "))
    ...
 }

You could do it in many different ways, add more error testing etc. if you wanted to.

These functions do take some code space, but I’m very happy with them.

Milan

If you’re interested:

bool CharInString(ascii ch, const ascii *str)
 {
  while ((*str!=0) && (*str!=ch))
    str++;
  return (*str==ch);  
 }

void SkipSpaces(ascii **ptr, ascii *white)
 {
  while ((**ptr!=0) && (CharInString(**ptr, white)))
    (*ptr)++;
 }
 
bool SkipPrefix(ascii **ptr, ascii *skip) //true->all found
 {
  ascii *backup=*ptr;
  do
   {
    if (*skip==0)
      return true;
    if (**ptr!=*skip)
     {
      *ptr=backup;
      return false;
     };
    (*ptr)++;
    skip++;
   }
  while (true);
 }

bool SkipString(ascii **ptr, ascii *delims) //true->delim found
 {
  while ((**ptr!=0) && (!CharInString(**ptr, delims)))
    (*ptr)++;
  if (**ptr!=0)
   {
    (*ptr)++;
    return true;
   }
  else
    return false;
 }

static bool CutIntegerHelper(int *value, int radix, int toadd)
 {
  if (radix==0)
    return false;;
  if ((*value<0) || ( (((u32)(-1))-(u32)toadd)/(u32)radix<(u32)*value))
    return false;;
  *value=*value*radix+toadd;
  return true;
 }
 
int CutInteger(ascii **ptr, int def, int radix, bool skipLast)
 {
  int result=0;
  bool negative=false;
  bool some=false;
  enum { stUnk, stUnk0, st10, st16, stFail } state;

  if (radix==10)
    state=st10;
  else if (radix==16)
    state=st16;
  else
    state=stUnk;
  for(;;)
   {
    switch (**ptr) 
     {
      case '-':
       {
        if (!some)
          negative=!negative;
        else
          state=stFail;
       } break;
      case '0':
       {
        some=true;
        if ((state==stUnk) || (state==stUnk0))
          state=stUnk0;
        else
         {
          if (!CutIntegerHelper(&result, radix, 0))
           {
            state=stFail;
            some=false;
           };
         }
       } break;
      case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
       {
        some=true;
        if ((state==stUnk) || (state==stUnk0))
         {
          state=st10;
          radix=10;
         };
        if (!CutIntegerHelper(&result, radix, **ptr-'0'))
         {
          state=stFail;
          some=false;
         };
       } break;
      case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
       {
        if ((state==st16))
         {
          some=true;
          if (!CutIntegerHelper(&result, radix, **ptr-'A'+10))
           {
            state=stFail;
            some=false;
           };
         }
        else
          state=stFail;
       } break;
      case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': 
       {
        if ((state==st16))
         {
          some=true;
          if (!CutIntegerHelper(&result, radix, **ptr-'a'+10))
           {
            state=stFail;
            some=false;
           };
         }
        else
          state=stFail;
       } break;
      case 'x': case 'X':
       {
        if (state==stUnk0)
         {
          state=st16;
          radix=16;
         }
        else
          state=stFail;
       } break;
      default:
        state=stFail;
     };
    if (state==stFail)
     {
      if ((**ptr!=0) && skipLast)
        (*ptr)++;
      break;
     };
    (*ptr)++;
   }
  if (some)
    return negative ? -result : result;
  else
    return def;
 }

#3

The standard ‘C’ library functions are available,

Wavecom also provides some extras like wm_isphonestring - these are described under Standard Library in the Basic Development Guide.
These functions can also be used in ADL.


#4

Hi Milan_va and awneil !

Milan_va, your idea is great but i think that for now i can do this simpler.
But anyway, i will use your code for future use.

Ok guys, tell me one thing…

If i use sscanf or isdigit for recognizing delimiters and text/numbers in openAT then i get such errors:
error: conflicting types for ‘sscanf’ [Conflicting names] [test.c]

so i guess im making wrong declaration.
If i run the same program in some other compiler, then there is no problem. :confused: :question: