0
# String & Text Processing
1
2
String handling utilities including case-insensitive operations, HTML processing, and multi-value string collections. Provides a comprehensive system for managing collections of string values with support for case-insensitive operations.
3
4
## Capabilities
5
6
### StringValues Interface
7
8
Core interface for associating string names with lists of string values, commonly used for headers, parameters, and form data.
9
10
```kotlin { .api }
11
/**
12
* Data structure for associating a String with a List of Strings
13
*/
14
interface StringValues {
15
/** Specifies if map has case-sensitive or case-insensitive names */
16
val caseInsensitiveName: Boolean
17
18
/** Gets first value associated with name, or null if not present */
19
operator fun get(name: String): String?
20
21
/** Gets all values associated with name, or null if not present */
22
fun getAll(name: String): List<String>?
23
24
/** Gets all names from the map */
25
fun names(): Set<String>
26
27
/** Gets all entries from the map */
28
fun entries(): Set<Map.Entry<String, List<String>>>
29
30
/** Checks if the given name exists in the map */
31
operator fun contains(name: String): Boolean
32
33
/** Checks if the given name and value pair exists */
34
fun contains(name: String, value: String): Boolean
35
36
/** Iterates over all entries calling body for each pair */
37
fun forEach(body: (String, List<String>) -> Unit)
38
39
/** Checks if this map is empty */
40
fun isEmpty(): Boolean
41
}
42
```
43
44
**Usage Examples:**
45
46
```kotlin
47
import io.ktor.util.*
48
49
// Create StringValues with case-insensitive names
50
val headers = StringValues.build(caseInsensitiveName = true) {
51
append("Content-Type", "application/json")
52
append("Accept", "application/json")
53
append("Accept", "text/html")
54
}
55
56
// Access values
57
println(headers["content-type"]) // "application/json" (case-insensitive)
58
println(headers.getAll("Accept")) // ["application/json", "text/html"]
59
60
// Check existence
61
if ("Content-Type" in headers) {
62
println("Content-Type header is present")
63
}
64
65
// Iterate over entries
66
headers.forEach { name, values ->
67
println("$name: ${values.joinToString(", ")}")
68
}
69
```
70
71
### StringValuesBuilder Interface
72
73
Builder interface for constructing StringValues instances with mutable operations.
74
75
```kotlin { .api }
76
/**
77
* Builder interface for constructing StringValues
78
*/
79
interface StringValuesBuilder {
80
val caseInsensitiveName: Boolean
81
82
/** Gets all values associated with name */
83
fun getAll(name: String): List<String>?
84
85
/** Checks if name exists */
86
operator fun contains(name: String): Boolean
87
88
/** Checks if name and value pair exists */
89
fun contains(name: String, value: String): Boolean
90
91
/** Gets all names */
92
fun names(): Set<String>
93
94
/** Checks if builder is empty */
95
fun isEmpty(): Boolean
96
97
/** Gets all entries */
98
fun entries(): Set<Map.Entry<String, List<String>>>
99
100
/** Sets single value for name (replaces existing) */
101
operator fun set(name: String, value: String)
102
103
/** Gets first value for name */
104
operator fun get(name: String): String?
105
106
/** Appends value to name */
107
fun append(name: String, value: String)
108
109
/** Appends all values from another StringValues */
110
fun appendAll(stringValues: StringValues)
111
112
/** Appends all values for name from iterable */
113
fun appendAll(name: String, values: Iterable<String>)
114
115
/** Appends missing values from another StringValues */
116
fun appendMissing(stringValues: StringValues)
117
118
/** Appends missing values for name from iterable */
119
fun appendMissing(name: String, values: Iterable<String>)
120
121
/** Removes all values for name */
122
fun remove(name: String)
123
124
/** Removes keys with no entries */
125
fun removeKeysWithNoEntries()
126
127
/** Removes specific name-value pair */
128
fun remove(name: String, value: String): Boolean
129
130
/** Clears all entries */
131
fun clear()
132
133
/** Builds final StringValues instance */
134
fun build(): StringValues
135
}
136
```
137
138
**Usage Examples:**
139
140
```kotlin
141
import io.ktor.util.*
142
143
// Build StringValues step by step
144
val builder = StringValuesBuilderImpl(caseInsensitiveName = true)
145
146
// Add values
147
builder.append("header1", "value1")
148
builder.append("header1", "value2")
149
builder["header2"] = "single-value"
150
151
// Modify values
152
builder.remove("header1", "value1") // Remove specific value
153
builder.appendAll("header3", listOf("a", "b", "c"))
154
155
// Build final result
156
val result = builder.build()
157
```
158
159
### StringValues Factory Functions
160
161
Convenient functions for creating StringValues instances.
162
163
```kotlin { .api }
164
/**
165
* Build StringValues from vararg pairs
166
*/
167
fun valuesOf(
168
vararg pairs: Pair<String, List<String>>,
169
caseInsensitiveKey: Boolean = false
170
): StringValues
171
172
/**
173
* Build StringValues from single name-value pair
174
*/
175
fun valuesOf(name: String, value: String, caseInsensitiveKey: Boolean = false): StringValues
176
177
/**
178
* Build StringValues from single name with multiple values
179
*/
180
fun valuesOf(name: String, values: List<String>, caseInsensitiveKey: Boolean = false): StringValues
181
182
/**
183
* Build empty StringValues
184
*/
185
fun valuesOf(): StringValues
186
187
/**
188
* Build StringValues from map
189
*/
190
fun valuesOf(map: Map<String, Iterable<String>>, caseInsensitiveKey: Boolean = false): StringValues
191
```
192
193
**Usage Examples:**
194
195
```kotlin
196
import io.ktor.util.*
197
198
// Create from pairs
199
val headers1 = valuesOf(
200
"Content-Type" to listOf("application/json"),
201
"Accept" to listOf("application/json", "text/html"),
202
caseInsensitiveKey = true
203
)
204
205
// Create from single value
206
val headers2 = valuesOf("Content-Type", "application/json")
207
208
// Create from multiple values
209
val headers3 = valuesOf("Accept", listOf("json", "html"))
210
211
// Create empty
212
val empty = valuesOf()
213
214
// Create from map
215
val map = mapOf(
216
"Content-Type" to listOf("application/json"),
217
"Accept" to listOf("application/json", "text/html")
218
)
219
val headers4 = valuesOf(map, caseInsensitiveKey = true)
220
```
221
222
### StringValues Extension Functions
223
224
Utility functions for working with StringValues instances.
225
226
```kotlin { .api }
227
/**
228
* Copy values to a new independent map
229
*/
230
fun StringValues.toMap(): Map<String, List<String>>
231
232
/**
233
* Copy values to a list of name-value pairs
234
*/
235
fun StringValues.flattenEntries(): List<Pair<String, String>>
236
237
/**
238
* Invoke block function for every name-value pair
239
*/
240
fun StringValues.flattenForEach(block: (String, String) -> Unit)
241
242
/**
243
* Create filtered StringValues by predicate
244
*/
245
fun StringValues.filter(
246
keepEmpty: Boolean = false,
247
predicate: (String, String) -> Boolean
248
): StringValues
249
```
250
251
**Usage Examples:**
252
253
```kotlin
254
import io.ktor.util.*
255
256
val headers = valuesOf(
257
"Accept" to listOf("application/json", "text/html"),
258
"Content-Type" to listOf("application/json")
259
)
260
261
// Convert to map
262
val map = headers.toMap()
263
264
// Flatten to pairs
265
val pairs = headers.flattenEntries()
266
// Result: [("Accept", "application/json"), ("Accept", "text/html"), ("Content-Type", "application/json")]
267
268
// Process each name-value pair
269
headers.flattenForEach { name, value ->
270
println("$name: $value")
271
}
272
273
// Filter values
274
val jsonOnly = headers.filter { name, value ->
275
value.contains("json")
276
}
277
```
278
279
### StringValuesBuilder Extension Functions
280
281
Additional utility functions for building StringValues.
282
283
```kotlin { .api }
284
/**
285
* Append values from source filtering by predicate
286
*/
287
fun StringValuesBuilder.appendFiltered(
288
source: StringValues,
289
keepEmpty: Boolean = false,
290
predicate: (String, String) -> Boolean
291
)
292
293
/**
294
* Append all values from another builder
295
*/
296
fun StringValuesBuilder.appendAll(builder: StringValuesBuilder): StringValuesBuilder
297
298
/**
299
* Append name-value pair if name is absent
300
*/
301
fun StringValuesBuilder.appendIfNameAbsent(name: String, value: String): StringValuesBuilder
302
303
/**
304
* Append name-value pair if both name and value are absent
305
*/
306
fun StringValuesBuilder.appendIfNameAndValueAbsent(name: String, value: String): StringValuesBuilder
307
308
/**
309
* Append multiple key-value pairs
310
*/
311
fun StringValuesBuilder.appendAll(vararg values: Pair<String, String>): StringValuesBuilder
312
313
/**
314
* Append multiple key-value pairs where values are Iterable
315
*/
316
fun StringValuesBuilder.appendAll(vararg values: Pair<String, Iterable<String>>): StringValuesBuilder
317
318
/**
319
* Append from map where values are Iterable
320
*/
321
fun StringValuesBuilder.appendAll(values: Map<String, Iterable<String>>): StringValuesBuilder
322
323
/**
324
* Append from map with single string values
325
*/
326
fun StringValuesBuilder.appendAll(values: Map<String, String>): StringValuesBuilder
327
```
328
329
**Usage Examples:**
330
331
```kotlin
332
import io.ktor.util.*
333
334
val builder = StringValuesBuilderImpl()
335
336
// Append conditionally
337
builder.appendIfNameAbsent("Content-Type", "application/json")
338
builder.appendIfNameAndValueAbsent("Accept", "text/html")
339
340
// Append multiple pairs
341
builder.appendAll(
342
"header1" to "value1",
343
"header2" to "value2"
344
)
345
346
// Append from map
347
val additionalHeaders = mapOf(
348
"Cache-Control" to "no-cache",
349
"User-Agent" to "Ktor Client"
350
)
351
builder.appendAll(additionalHeaders)
352
```
353
354
### Text Processing Utilities
355
356
Additional text processing functions for HTML and case conversion.
357
358
```kotlin { .api }
359
/**
360
* Escape HTML special characters in string
361
*/
362
fun String.escapeHTML(): String
363
364
/**
365
* Convert to lowercase preserving ASCII rules
366
*/
367
fun String.toLowerCasePreservingASCIIRules(): String
368
```
369
370
**Usage Examples:**
371
372
```kotlin
373
import io.ktor.util.*
374
375
// HTML escaping
376
val html = "<script>alert('xss')</script>"
377
val escaped = html.escapeHTML()
378
println(escaped) // "<script>alert('xss')</script>"
379
380
// Case conversion
381
val mixed = "Content-TYPE"
382
val lower = mixed.toLowerCasePreservingASCIIRules()
383
println(lower) // "content-type"
384
```
385
386
## Implementation Classes
387
388
```kotlin { .api }
389
/**
390
* Default implementation of StringValues
391
*/
392
open class StringValuesImpl(
393
override val caseInsensitiveName: Boolean = false,
394
values: Map<String, List<String>> = emptyMap()
395
) : StringValues
396
397
/**
398
* Optimized StringValues for single name-value mapping
399
*/
400
open class StringValuesSingleImpl(
401
override val caseInsensitiveName: Boolean,
402
val name: String,
403
val values: List<String>
404
) : StringValues
405
406
/**
407
* Default builder implementation
408
*/
409
open class StringValuesBuilderImpl(
410
override val caseInsensitiveName: Boolean = false,
411
size: Int = 8
412
) : StringValuesBuilder
413
```