JSON parsen mit AVR

Gast #4880774
Komplettes JSON passt wohl nicht so richtig in einen Mega88/168, aber 
letzendlich brauch ich das auch gar nicht. Sind auch nur sehr 
überschaubare Datensätze und leicht auseinander zu puzzeln. Allerdings 
kommt immer noch bisschen was dazu, und es unterscheidet sich auch von 
Gerätetyp zu Gerätetyp (RS485-Bus)

So funktioniert es bestens, gefällt mir aber nicht.
#define RD_cmd 1
#define VER_cmd 2
#define CONFIG_cmd 3
.
.
.
unsigned char parse_command (char * s)
{unsigned char command=0;
if (!(strncmpf (s, "\"RD\":", 5)))
   {command=RD_cmd;
    JsonPtr+=5;
   }
   else if (!(strncmpf (s, "\"VER\":", 6)))
      {...
      }
   .
   .

return (command);
}
Vergleicht also mit s mit <"RD":> (5 Zeichen) und erhöht bei Erfolg 
JsonPtr um 5. Und genau die magic number 5 ( oder 6, andere sind z.T. 
noch erheblich länger) sind mein  Problem. Lästig und fehleranfällig das 
abzuzählen....
Ideal wäre, auch den Vergleichsstring per #define anzugeben und der 
Compiler soll Vergleichslänge/offset selbst auskaspern. Geht das 
irgendwie?
Gerhard schrieb:
> Compiler soll Vergleichslänge/offset selbst auskaspern. Geht das
> irgendwie?
1
static const char MyCommand[] = "Command";
2
static const size_t MyCommandSize = sizeof(MyCommand);
3
static const size_t MyCommandLength = sizeof(MyCommand) - 1; // == strlen(MyCommand)

Damit kannst du alle Magic Numbers erschlagen, auch die Strings selbst. 
Ich empfehle die Variablen als static zu deklarieren, da ich annehme, 
dass die Variablen nur in dieser Funktion benötigt werden. Ansonsten 
werden sie bei jedem Funktionsaufruf neu initialisiert. Die Alternative 
wäre, die Variablen global zu definieren, evt. auch mit static.
Persönliche Seite
Gerhard schrieb:
> Lästig und fehleranfällig das abzuzählen....

Nimm strlen zusammen mit Makro oder Inline-Funktion.
1
#define strncmpf(S, STR) \
2
    strncmp_P (S, PSTR (STR), strlen (STR))
3

4
bool func (const char *str)
5
{
6
    if (!strncmpf (str, "abc"))
7
        return true;
8
    return false;
9
}

Ein Problem ist, dass es wegen PSTR keine Inline-Funktion sein kann. 
Evtl. kannst du das dann noch ausbauen so dass str um strlen(...) erhöht 
wird.
Persönliche Seite
...etwa so in GNU-C99:
 
1
#define MATCH(S, STR)                                       \
2
  ({                                                        \
3
      match_len = strlen (STR);                             \
4
      match = ! strncmp_P (S, PSTR (STR), match_len);       \
5
      match;                                                \
6
  })
7

8
bool func (const char *str)
9
{
10
    bool match;
11
    size_t match_len;
12
    
13
    if (MATCH (str, "abc"))
14
    {
15
        str += match_len;
16
        
17
        if (MATCH (str, "blabla"))
18
            return true;
19
    }
20
    return false;
21
}

Makros sind zwar hässlich, aber an dieser Stelle braucht man nur 
eines...
Gast
Be S. schrieb:
> Gerhard schrieb:
>> Compiler soll Vergleichslänge/offset selbst auskaspern. Geht das
>> irgendwie?
> static const char MyCommand[] = "Command";
> static const size_t MyCommandSize = sizeof(MyCommand);
> static const size_t MyCommandLength = sizeof(MyCommand) - 1; // ==
> strlen(MyCommand)
> Damit kannst du alle Magic Numbers erschlagen, auch die Strings selbst.
> Ich empfehle die Variablen als static zu deklarieren, da ich annehme,
> dass die Variablen nur in dieser Funktion benötigt werden. Ansonsten
> werden sie bei jedem Funktionsaufruf neu initialisiert. Die Alternative
> wäre, die Variablen global zu definieren, evt. auch mit static.

Perfekt, hätte ich selber drauf kommen können :-)
Danke.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.