0

I am having a very difficult time with this issue and need some help. I have a variable that is declared as this:

char *var_val = "";

This variable is later defined (in Asterisk) as:

var_val = S_OR(pair, "");

In this case, the pair variable represents a valid string (ie: SIP/221[|]Custom:DND221[|]Custom:USER221).

I am wanting to replace all occurrences of [|] with &

In PHP, I would just write var_val = str_replace("[|]", "&", var_val), which would yield SIP/221&Custom:DND221&Custom:USER221

I have tried to do this in C, but am failing miserably. Either the compiler throws all types of warnings, outright errors, or compiles fine but the var_val is left unchanged when the script runs. Can someone please provide me the C code needed to accomplish this task?

Given that I know var_val="SIP/221[|]Custom:DND221[|]Custom:USER221", my attempts have all been derived around some form of the following:

// create a buffer to hold the new string
char buffer[strlen(var_val)];

// in C strings are basically arrays so we need an index to run through
// the original string
int i = 0;

// loop through original string
while (*var_val) {
    
    // does the needle exist in the string?     
    if (strstr(var_val, "[|]") == (char *)"[|]") { 

        // it does so we want to replace [|] with & and 
        // skip ahead 3 positions in the original string    
        strcpy(&buffer[i], "&");
                    
        i += 1;
                        
        var_val += 3;
    }

    // needle is not found at this spot so copy one character from 
    // source string into buffer
    else
        buffer[i++] = *var_val++;
    }

}

// finish our buffer with trailing 0 to indicate end of string
buffer[i] = '\0';


// point our original string to our new string
var_val = (char *)buffer;

EDIT


Thanks to comments from both @Jonathan Leffler and @Dante Culaciati, here is a function that does work (What function is to replace a substring from a string in C?), although it generates one compiler warning about placing parenthesis around the while (needle = .... construct. I also had to replace malloc() with ast_malloc() and realloc() with ast_realloc() since this is being used within Asterisk.

static char *dull_replace(const char *in, const char *pattern, const char *by)
{
    size_t outsize = strlen(in) + 1;
    // TODO maybe avoid reallocing by counting the non-overlapping occurences of pattern
    char *res = malloc(outsize);
    // use this to iterate over the output
    size_t resoffset = 0;

    char *needle;
    while (needle = strstr(in, pattern)) {
        // copy everything up to the pattern
        memcpy(res + resoffset, in, needle - in);
        resoffset += needle - in;

        // skip the pattern in the input-string
        in = needle + strlen(pattern);

        // adjust space for replacement
        outsize = outsize - strlen(pattern) + strlen(by);
        res = realloc(res, outsize);

        // copy the pattern
        memcpy(res + resoffset, by, strlen(by));
        resoffset += strlen(by);
    }

    // copy the remaining input
    strcpy(res + resoffset, in);

    return res;
}

To use the function, I pass var_val to it, and it returns the updated or unmodified original string:

var_val = dull_replace(var_val, "[|]", "&");

Anyone know how to interpret this compiler warning and correct the code?

res_config_curl.c: In function ‘dull_replace’:
res_config_curl.c:526:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     while (needle = strstr(in, pattern)) {
     ^
Chance
  • 45
  • 6
  • 2
    Note that `char buffer[strlen(var_val)];` is one character too short to hold the whole string, which will be necessary if there are no replacements to perform. – Jonathan Leffler Apr 13 '21 at 03:20
  • I'm not sure if that way to check if the needle exists in the string is going to work. `strstr` returns `NULL` when there is no substring found, so you can just check that. – mediocrevegetable1 Apr 13 '21 at 03:21
  • 1
    This test `if (strstr(var_val, "[|]") == (char *)"[|]") {` is wrong. You should probably capture the return value from `strstr()` in a variable and test whether it is NULL (no match) or not (match starting at returned pointer position). – Jonathan Leffler Apr 13 '21 at 03:22
  • 1
    I know the following question is closed, but maybe it can help you: [What function is to replace a substring from a string in C?](https://stackoverflow.com/questions/779875/what-function-is-to-replace-a-substring-from-a-string-in-c). – Dante Culaciati Apr 13 '21 at 03:22
  • Note that you're dealing with the easy case, where the replacement string is shorter than the string being replaced (the same length is equally easy). If the replacement string is longer than the string being replaced, you're faced with a bunch of memory management problems. As a general case solution, you normally end up with the 'replace all occurrences' function doing dynamic memory allocation (`malloc()` et al) and returning a pointer to the allocated memory. – Jonathan Leffler Apr 13 '21 at 03:26
  • 1
    @DanteCulaciati: It is weird that the question you suggest is closed. It is closed as 'needs focus', yet it is hard to imagine a much more focussed question. I've voted to reopen; I hope some other people with the privilege will do so too. – Jonathan Leffler Apr 13 '21 at 03:28
  • @JonathanLeffler: Thank you for providing so much help. I knew I was close with what I had already. – Chance Apr 13 '21 at 14:51
  • 1
    @DanteCulaciati: I followed that link and was able to use one of the many functions provided to get the desired result. However, there is one compiler warning with that function but it does compile and it does work. – Chance Apr 13 '21 at 14:53
  • 2
    You can either add parentheses to suppress the compiler warning or use the idiom: `while( (needle = strstr(in, pattern)) != NULL ) {` – William Pursell Apr 13 '21 at 15:26
  • You know, at this point you should self-answer your question. – Joshua Apr 13 '21 at 15:28
  • At this stage — no up-votes, no down-votes, no answers — I recommend deleting this question altogether and asking a new one. – Jonathan Leffler Apr 13 '21 at 15:34

1 Answers1

0

Thanks to several commentators, I was able to get this working. The function used came from the link provided by Dante. The link and the working function are in my original question (edited).

Chance
  • 45
  • 6