// Convert an array of char* strings into a single string, separated by spaces, with a passed maximum length
// RJM Programming 15/11/2013 ... as per http://au.answers.yahoo.com/question/index?qid=20131112144151AA92GN0

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* concatenate_into_buffer(char** buffer, char* inarr[], int maxlen, int *elen, char* prevc) {
    // buffer is Pointer to pointer to buffer
    // inarr[] is String array of char*'s
    // maxlen is Maximum allowable buffer length (allowing for zero byte at end)
    // *elen is Pointer to length of buffer
    // prevc is Parent's memory of the last buffer returned, for reruns
    char* endptr = NULL, *inp = NULL, fmt[20];
    int i=0, ilen=0, setaside=0;
    bool firstgo = true;
    if (inp == NULL && strlen(inarr[0])) {   // if there is input data ...
        inp = inarr[0];
        while (strlen(inp) && ilen != maxlen) {   // while there is input data for this String array element ...
            if (!*buffer) {  // inside here is first go for unassigned memory scenarios the first time ...
                firstgo = false;
                ilen = strlen(inp) + 1;
                if (ilen > maxlen) {   // overshooting length inside here ...
                    ilen = maxlen;
                    *buffer = (char*) malloc(ilen);
                    sprintf(fmt, "%s%d%s", "%.", (maxlen - 1), "s");
                    sprintf((char*)*buffer, fmt, inp);
                } else {  // else first time malloc to allocate memory for buffer
                    //printf("Len=%d Inp=%s Ilen=%d\n", strlen(inarr[i]), inp, ilen);
                    *buffer = (char*) malloc(ilen);
                    sprintf((char*)*buffer, "%s", inp);  // write to buffer ...
                }
            } else {  // else here for situations where malloc has already been called ...
                if (ilen == 0) {
                    ilen = strlen((char*)*buffer) + 1;
                }
                ilen += strlen(inp) + 1;
                if (ilen > maxlen) {  // overshooting buffer length inside here ...
                    ilen = maxlen;
                    if (ilen > setaside) realloc((char*)*buffer, ilen);
                    sprintf(fmt, "%s%d%s", "%s %.", (maxlen - strlen((char*)*buffer) - 2), "s");
                    sprintf((char*)*buffer, fmt, (char*)*buffer, inp);  // append to buffer ...
                } else {  // no overshooting inside here ...
                    //printf("len=%d inp=%s ilen=%d buffer=%s\n", strlen(inarr[i]), inp, ilen, (char*)*buffer);
                    if (firstgo && strlen(prevc) > 0) {  // inside here is a rerun of this function recalled by parent ...
                        //printf("Len=%d inp=%s ilen=%d buffer=%s\n", strlen(inarr[i]), inp, ilen, (char*)*buffer);
                        *buffer = (char*) malloc(maxlen);
                        setaside = maxlen;
                        sprintf((char*)*buffer, "%s\0", prevc);
                    } else { // first pass realloc call to get more memory ...
                        if (ilen > setaside) realloc((char*)buffer, ilen);
                    }
                    firstgo = false;
                    sprintf((char*)*buffer, "%s %s", (char*)*buffer, inp);   // append to buffer ...
                }
            }
            i++;   // increment current input array counter, of interest ...
            endptr = *buffer + strlen((char*)*buffer) + 1;  // determine and return the pointer to end of buffer ...
            inp = inarr[i];   // update pointer to next string of input array ...
            //printf("buffer=%s %ld\n", *buffer, endptr);
        }
    }
    *elen = strlen((char*)*buffer) + 1;   // fill in value for length of buffer (available for parent)
    *endptr = 0;  // end of buffer should be zero byte
    return endptr;  // return end of buffer pointer
}


int main(int argc, char** argv) {
    char* strs[] = {"firststring\0", "secondstring\0", "thirdstring\0" "fourthstring\0", "\0"};
    //char *strs[] = {"f\0", "s\0", "t\0" "f\0", "\0"};
    char *buff=NULL, *ebuff="\0";
    char **mybuff = &buff;
    int jlen = 0;
    ebuff = concatenate_into_buffer(mybuff, strs, 10, &jlen, (ebuff - jlen));
    printf("Buffer=%s\n", buff);
    ebuff = concatenate_into_buffer(mybuff, strs, 1000, &jlen, (ebuff - jlen));
    printf("Buffer=%s\n", buff);
    ebuff = concatenate_into_buffer(mybuff, strs, 1000, &jlen, (ebuff - jlen));
    printf("Buffer=%s\n", buff);
    
}