## Literals

### String literal

#### Overview

A string literal is used to define a string object (also called a string value) in the source code. Obix provides three ways to define string literals:

• the quoted string literal, used to define simple strings
• the triple apostrophed string literal, used to define more complex strings containing new lines and characters that would have to be escaped with the quoted string literal
• the triple quoted string literal, used to define dynamic literals containing expressions that will be evaluated at runtime

Strings can also be created from external resources, such as text files and URLs (e.g. a text file stored on a remote server).

#### Quoted string literal

##### Description

A quoted string literal consists of any number of Unicode characters and/or escape characters within double quotes.

##### Syntax

Table 16.3. Quoted string literal syntax

quoted_string_literal '"' ( Unicode_character | escape_character ) * '"'

remark: Unicode_character cannot be '"' or '\' or <carriage_return> or <line_feed>

the section called “Quoted string literal”
Unicode_characterany Unicode_character, like A, B, C, 1, 2, 3, +, -, %, and so on
escape_character

-> "\b"   /* backspace */ -> "\f"   /* form feed */ -> "\n"   /* line feed */ -> "\r"   /* carriage return */ -> "\t"   /* horizontal tab */ -> '\"'   /* quote (double quote) */ -> "\'"   /* apostrophe (single quote) */ -> "\\"   /* backslash */ -> "\u" hex_digit hex_digit hex_digit hex_digit   /* hexadecimal Unicode character definition */

##### Examples

Example 16.7. String literals

service string_literal_example

command string_literals
script
system.console.write_line ( "Hello" )        // Hello
system.console.write_line ( "" )             // <empty string>
system.console.write_line ( "\"" )           // <quote>
system.console.write_line ( "'" )            // <apostrophe>
system.console.write_line ( "\t1" )          // <horizontal tab>1
system.console.write_line ( "\r\n" )         // <carriage return><line feed>
system.console.write_line ( "Hello\\\nTom" ) // Hello\<line feed>Tom
system.console.write_line ( "\u0038\u0039\u002f there" ) // hi? there
end
end

end

Executing the above command will display the following on the system console:

Hello

"
'
1

Hello\
Tom
hi? there

##### Inconveniences

The quoted string literal in Obix is very similar to the classical string literal used in several popular programming languages, such as Java and C#. However, although every string can be defined using the quoted string literal, this notation suffers from the following inconveniences which occur frequently in practice:

1. Backslashes (\) and quotes (") must be escaped with the backslash, which makes string literals less writable and readable. This is annoying and error-prone, because backslashes are often used when specifying Windows directory and file names, quotes are always used when specifying XML attributes, and apostrophes and quotes are often used in SQL statements. For example, we cannot write:

XML_string = "<file name="c:\foo\bar.txt" />"

XML_string = "<file name=\"c:\\foo\\bar.txt\" />"

Moreover, escaping the backslash can become quite tricky in regular expressions, because they also escape characters with backslashes, which means that backslashes in regular expressions must be double-escaped. For example, a backslash in a regular expression becomes: \\\\.

2. New lines must also be escaped. Even worse, the new line in Windows is a <carriage return> followed by a <line feed>, whereas it is just a <line feed> on Linux and Unix systems. Hence, to create the following string:

line 1
line 2

we have to code:

"line 1\nline2"

on a Unix system, and:

"line 1\r\nline2"

on a Windows system.

A better approach is to use the service attribute se_string.a_new_line which automatically provides the correct new line, depending on the operating system the application is running on:

"line 1" & se_string.a_new_line & "line2"
3. There is no easy way to embed expressions (e.g. formatted string) within quoted string literals. We have to use the string concatenation operator, such as:

product_description = "Product " & product.identifier.to_string & "; " & product.name

However, string concatenations can dramatically decrease performance, because quoted string literals represent objects of type string, and those objects are immutable. Hence, each time a string is concatenated, a new string object must be allocated in memory. A solution is to use mutable strings instead of immutable ones, but this requires us to replace the above example of code with:

product_description = fa_mutable_string.co_create("Product ").append(product.identifier.to_string).append("; ").append(product.name).to_string

To eliminate the above inconveniences, Obix provides other notations to define string literals, as explained in the following sections.

#### Triple apostrophed string literal

##### Description

A triple apostrophed string literal consists of any number of Unicode characters enclosed by a pair of three apostrophes (''').

Triple apostrophed string literals are best suited whenever the string contains:

• characters that would have to be escaped in case of using quoted string literals (e.g. / and ")
• line breaks
##### Syntax

Table 16.4. Triple apostrophed string literal syntax

triple_apostrophed_string_literal "'''" Unicode_character * "'''"

remark: characters are never escaped (e.g. '''\\''' yields \\)

the section called “Triple apostrophed string literal”
Unicode_characterany Unicode_character, like A, B, C, 1, 2, 3, +, -, %, and so on

##### Examples

The following is an excerpt of the string literal tests contained in the Obix standard library. The code should be self-explanatory. For example, the instruction:

verify '''Hello''' =v "Hello"

verifies that the string created by the triple apostrophed literal '''Hello''' has the same value as the string created by the quoted literal "Hello".

Example 16.8. Triple apostrophed string literals

         // triple apostrophed string literal tests

// simple string
verify '''Hello''' =v "Hello"

// escape characters

// He said: "She said: 'How're you?'"
verify '''He said: "She said: 'How're you?'"''' =v "He said: \"She said: 'How're you?'\""

// file = "c:\foo\bar.txt"
verify '''file = "c:\foo\bar.txt"''' =v "file = \"c:\\foo\\bar.txt\""

// SELECT "customers"."name" from "customers" where "city" = 'Deland'
verify '''SELECT "customers"."name" from "customers" where "city" = 'Deland'''' =v &
"SELECT \"customers\".\"name\" from \"customers\" where \"city\" = 'Deland'"

// multi-line strings

// line 1
// line 2
verify '''line1
line2''' =v "line1" & se_string_constants.current_OS_new_line & "line2"

//
// line 1
// line 2
// line 3
//
verify '''
line1
line2
line3
''' =v se_string_constants.current_OS_new_line & "line1" & se_string_constants.current_OS_new_line & "line2" & se_string_constants.current_OS_new_line & "line3" & se_string_constants.current_OS_new_line

// special cases

// empty string
verify '''''' =v ""

// single characters
verify '''a''' =v "a"
verify '''\''' =v "\\"
verify '''"''' =v "\""
verify ''' ''' =v " "
verify ''''''' =v "'"

// weird
verify '''\/''' =v "\\/"
verify '''\\\""\\\''' =v "\\\\\\\"\"\\\\\\"


#### Triple quoted string literal

##### Description

A triple quoted string literal consists of any number of Unicode characters enclosed by a pair of three quotes (").

Triple quoted string literals extend the notation of the triple apostrophed string literal by adding the possibility to embed expressions that are evaluated at runtime. Hence, they are well suited to define strings that will be dynamically created at runtime.

Expressions are embedded between {{ and }} (two opening curly braces and two closing curly braces). The text between the opening and closing curly braces can be any valid expression that must evaluate to a non void object of type string.

Moreover, new lines appearing in a triple quoted string literal are automatically replaced at run-time by the operating system's new line character. This ensures portability of applications across different operating systems. Thus, if an application runs on a Unix/Linux system, the new lines in a triple quoted string literal are replaced with a line-feed character (LF), even if the source code was written on a Windows machine that uses a carriage-return + line-feed (CR+LF) combination.

##### Syntax

Table 16.5. Triple quoted string literal syntax

triple_quoted_string_literal '"""' ( Unicode_character | embedded_string_literal_expression ) * '"""'

remark: characters are never escaped (e.g. """\\""" yields \\)

the section called “Triple quoted string literal”
Unicode_characterany Unicode_character, like A, B, C, 1, 2, 3, +, -, %, and so on
embedded_string_literal_expression "{{" expression "}}"

remark: expression must be of type string

the section called “Triple quoted string literal”

##### Examples

The following is an excerpt of the string literal tests in the Obix standard library:

Example 16.9. Triple quoted string literals

         // triple quoted string literal tests

// simple string
verify """Hello""" =v "Hello"

// escape characters

// He said: "She said: 'How're you?'"
verify """He said: "She said: 'How're you?'"""" =v "He said: \"She said: 'How're you?'\""

// file = "c:\foo\bar.txt"
verify """file = "c:\foo\bar.txt"""" =v "file = \"c:\\foo\\bar.txt\""

// SELECT "customers"."name" from "customers" where "city" = 'Deland'
verify """SELECT "customers"."name" from "customers" where "city" = 'Deland'""" =v &
"SELECT \"customers\".\"name\" from \"customers\" where \"city\" = 'Deland'"

// multi-line strings

// line 1
// line 2
verify """line1
line2""" =v "line1" & se_string_constants.current_OS_new_line & "line2"

//
// line 1
// line 2
// line 3
//
verify """
line1
line2
line3
""" =v se_string_constants.current_OS_new_line & "line1" & se_string_constants.current_OS_new_line & "line2" & se_string_constants.current_OS_new_line & "line3" & se_string_constants.current_OS_new_line

// embedded expressions

const string first_name = "Linus"
verify """Hi {{c_first_name}}!""" =v "Hi Linus!"

// triple apostrophed strings cannot contain embedded expressions
verify '''Hi {{c_first_name}}!''' =v "Hi {{c_first_name}}!"

const positive32 identifier = 123
const string last_name = "Torvalds"
const string embedded = """
<person id="{{ (identifier + 1).to_string }}">
<first_name>{{first_name}}</first_name>
<last_name>{{last_name}}</last_name>
</person>"""
const string non_embedded = '''
<person id="124">
<first_name>Linus</first_name>
<last_name>Torvalds</last_name>
</person>'''
verify embedded =v non_embedded

// following instruction will not compile
//console.message("""{{void}}""")

var string void_string = void
// following instruction will produce runtime error
se_system.out.write ( string = """{{void_string}}""" ) on_error:continue
verify v_program_error_ #r void


#### Configurable string literal

Note This kind of string literal is not yet available at the time of writing and will possibly appear in a future version of Obix.

The idea of the configurable string literal is to extend the notation of the triple quoted string literal by adding the possibility to specify any arbitrary text used to

• end the string literal
• start an embedded expressions
• end an embedded expressions

Configurable string literals should be needed rarely in practice. A concrete example would be source code that defines a string which represents itself source code containing triple quoted strings.

#### Externally defined strings

##### Description

Besides the possibility to hardcode string literals in the source code, Obix provides a number of ways to get strings from external resources, such as text files or URL contents. However, the scope of this chapter is not to fully describe these possibilities. For further information, please refer to the API documentation.

Here is a simple example (without file input/output error handling):

Example 16.10. Read a string from a file and write it to another file

// file to read from
var file input_file = fa_file.create ( '''c:\Documents and Settings\Jerome\My Documents\text_file.txt'''~ )

// read text from input_file into string
var string text_in_file
se_text_file_IO.restore_string_from_file ( &
file = input_file ) &
( text_in_file = result &
// error handling
exit script
end if

// display text on screen
system.console.write ( """Contents of file {{input_file}}:
{{text_in_file}}"""  )

// file to write to
var file output_file = fa_file.create ( '''d:\copy of text_file.txt'''~ )

// save text to output_file
var resource_error write_error = se_text_file_IO.store_string_to_new_or_existing_file ( &
string = text_in_file &
file = output_file )
if write_error #r void then
// error handling
exit script
end if