18.4.0 released Sep 25, 2023
Write string

Purpose: Create complex strings.

write-string [ define ] <string>

<any code>

end-write-string [ bytes-written [ define ] <bytes written> ] [ notrim ]

Output of any Vely code (that normally would go to a client) can be written into <string>, which can be created (if it doesn't exist) with "define". In between write-string and end-write-string you can write <any Vely code>. For instance you can use database queries, conditional statements, call C code etc., just as you would for any other Vely code. write-strings can be nested, meaning you can use write-string to write to a different string while within write-string, and presumably use that string to output it within the parent.

<string> is allocated memory.
Length of result
To get the length of the string written, use the optional "bytes-written" clause, in which case <bytes written> will have the number of bytes written, minus the trailing zero byte (i.e. it is the length of the string output). If <bytes written> is not defined, you can create it with "define" within the statement.
Shortcut code
Note that instead of write-string you can also use a shortcut "(("  (and instead of end-write-string you can use "))"  ), for example here a string "fname" holds a full path of a file named "config-install.vely" under the application home directory (see how-vely-works), and "bw" holds the number of bytes written:
get-app directory to define home_dir
(( fname
@<<p-out home_dir>>/config-install.vely
)) bytes-written define bw

Trimming
Just like with all other Vely code, every line is trimmed both on left and write, so this:
(( define mystr
@Some string
))

is the same as:
(( define mystr
        @Some string <whitespaces>
))

write-string (or "((") statement must always be on a line by itself (and so does end-write-string, or "))" statement). The string being built starts with the line following write-string, and ends with the line immediately prior to end-write-string.

All trailing empty lines are removed, for example:
(( define mystr
        @My string
        @
        @
))

the above string would have two trailing empty lines, however they will be removed. If you want to skip trimming the trailing whitespaces, use "notrim" clause in end-write-string.
Referencing result within write-string
The <string> pointer (i.e. the result) is set to an empty string at the beginning of write-string; only after end-write-string completes does it take the computed value. That's because using <string> within write-string is generally inefficient as it's value is copied to the result. If you must use the result recursively (which is not recommended), you can save the pointer to it and use it.
Examples
- Simple
A simple example:
char *my_str="world";
char *my_str1="and have a nice day too!";

write-string define result_str
@Hello <<p-out my_str>> (<<p-out my_str1>>)
end-write-string

p-out result_str

The output is
Hello world (and have a nice day too!)


- Using code inside
Here is using Vely code inside write-string, including database query and conditional statements to produce different strings at run-time:
input-param selector

char *my_str="world";

write-string define result_str
    if-string selector=="simple"
        @Hello <<p-out my_string>> (and have a nice day too!)
    else-if-string selector=="database"
        run-query @db="select name from employee"
            @Hello <<query-result name>>
            @<br/>
        end-query
    else
        @No message
    end-if
end-write-string

p-out result_str

If selector variable is "simple", as in URL
https://mysite.com/<app name>/some_service?selector=simple

the result is
Hello world (and have a nice day too!)

If selector variable is "database", as in URL
https://mysite.com/<app name>/some_service?selector=database

the result may be (assuming "Linda" and "John" are the two employees selected):
Hello Linda
<br/>
Hello John
<br/>

If selector variable is anything else, as in URL
https://mysite.com/<app name>/some_service?selector=something_else

the result is
No message

In the above example, "result_str" variable is defined on the spot, but it can also be defined elsewhere without using "define".

- Using function calls inside
The following uses functions inside write-string (note that "<<.func2();>>" is simply calling C code as inline-code):
void func1 ()
{
    char *result_str;

    write-string result_str
        @<<p-out "Result from func2()">> is <<.func2();>>
    end-write-string
    p-out result_str
}

void func2()
{
    p-out "Hello from func2"
}

The output from func1() is
Result from func2() is Hello from func2


- Nesting
An example to nest write-strings:
write-string define str1
    @Hi!
    write-string define str2
        @Hi Again!
   end-write-string
   p-out str2
end-write-string
p-out str1

The result is
Hi!
Hi Again!


- Returning result from function
The result of write-string can be returned from a function (because it is heap memory), as in this example:
void func1 ()
{
   write-string define result_str
       char *func2_result;
       @<<p-out "Result from func2()">> is <<p-out func2(&func2_result)>>
   end-write-string
   p-out result_str
}

char *func2(char **result)
{
   write-string *result
       @<hr/>
       run-query @db="select firstName from employee"
           @Hello <<query-result firstName>>
           @<br/>
       end-query
       @<hr/>
   end-write-string
   return *result;
}

The output from func1() is:
Result from func2() is <hr/>
Hello Linda
<br/>
Hello John
<br/>
<hr/>

See also
Strings
copy-string  
count-substring  
lower-string  
num-string  
split-string  
trim-string  
upper-string  
write-string    
See all
documentation


You are free to copy, redistribute and adapt this web page (even commercially), as long as you give credit and provide a link back to this page (dofollow) - see full license at CC-BY-4.0. Copyright (c) 2019-2023 Dasoftver LLC. Vely and elephant logo are trademarks of Dasoftver LLC. The software and information on this web site are provided "AS IS" and without any warranties or guarantees of any kind.