String.replace() crashes Photon

I’m using a webhook with response template;

"responseTemplate": "{{#Stations}}{{#VertrekkendeTrein}}{{RitNummer}}~{{VertrekTijd}}~{{VertrekVertraging}}~{{VertrekVertragingTekst}}~{{VertrekSpoor}}~{{/VertrekkendeTrein}}{{/Stations}}",

Where “VertrekVertraging” and “VertrekVertragingTekst” are only in the response when the API finds it needed.

So the response looks like this; (note the ~~~) where between the ~~ a value could be;

9684~2015-11-01T23:04:00+0100~~~1~9683~2015-11-01T23:26:00+0100~~~2~9688~2015-11-02T00:04:00+0100~~~1~709687~2015-11-02T00:26:00+0100~~~2~900872~2015-11-02T01:16:00+0100~~~[object Object]~9616~2015-11-02T06:04:00+0100~~~1~9615~2015-11-02T06:26:00+0100~~~2~9618~2015-11-02T06:34:00+0100~~~1~9617~2015-11-02T06:56:00+0100~~~2~9620~2015-11-02T07:04:00+0100~~~1~

What I do is fill the gaps with String.replace. After a few runs of the code my Photon crashes. The String.replace causes this because when removed all works fine.

Code sniped;

void NS_REPLY(const char *name, const char *data){
    Serial.println("Running NS_REPLY function");
    String str = String(data);
    str.replace("~~", "~0~");
    char strBuffer[1024] = "";
    str.toCharArray(strBuffer, 1024);
    //It will be a list of 10 trains.
    Serial.println(strBuffer);
    int RitNummer1 = atoi(strtok(strBuffer, "~"));
    String VertrekTijd1 = strtok(NULL, "~");
    String VertrekVertraging1 = strtok(NULL, "~");
    String VertrekVertragingTekst1 = strtok(NULL, "~");
    int VertrekSpoor1 = atoi(strtok(NULL, "~"));

Does anyone has an idea why the Photon would crash on this replace? :smiley:

Since you are replacing a short string with a longer one multiple times, each go will cause multiple relocations of the whole String object, resulting in heap fragmentation.
One way around this would be to have the original String allocated with enough extra space to accomodate all extra characters too (String::reserve()) .
But since you are only using replace for a constant expression and I don’t see a lot of other need for the use of String, I’d keep away from String completely and do it all the C way.

Understood the first part, sounds logical when you explained it like that. I’ll try that tomorrow, thanks!!

Would you be able to clarify that last part a bit, moving away from String and do it the C way?

You are already using strtok(), why not use the same aproach there too?
When you get strlen(strtok(NULL, '~')) == 0 you got one of your ~~ combos and can treat them accordingly.

Good approach! I’ll get tinkering tomorrow :slight_smile:

1 Like

Hi @ScruffR,

I’m not able to get it working nicely. I’m now thinking of adjusting the webhook responseTemplate and add a tailing character like “0”. Than just do a “strlen > 1” :slight_smile: … but thats more a workaround than a good fix.

So if you have something for me, than that would be appreciated!

To tackle this you’d need to define the default structure of one set of data to parse.
Looking at your sample there are several sets in one unbroken queue, but it’s not easy to tell if this structure is always exactly the same or if it might mutate slightly.
e.g. what is this [object Object]? It only appears once but somewhere in the middle. Does it belong to the first set of data sets or to the second and where is the one for the respective other?

But if you had a constant format, you could even look into sscanf() which is a powerful function for parsing such string data.
You’d just need to find the boundaries between individual datasets (e.g. strstr(data, "~~~")) and feed these individually into sscanf().

But maybe adding distinguishable seperators rather than only one (~) makes parsing easier too and strtok() can handle a set of seperators (e.g. "~;#!\n") just as well.