Mercurial > cgi-bin > hgweb.cgi > PassMan
comparison src/main/kotlin/name/blackcap/passman/See.kt @ 3:eafa3779aef8
More bug fixes, quote strings in diagnostics.
author | David Barts <n5jrn@me.com> |
---|---|
date | Sun, 11 Sep 2022 20:36:06 -0700 |
parents | a6cfdffcaa94 |
children | 02b101422726 |
comparison
equal
deleted
inserted
replaced
2:3c792ad36b3d | 3:eafa3779aef8 |
---|---|
1 package name.blackcap.passman | 1 package name.blackcap.passman |
2 | |
3 /* Would be nice if there was a more programmatic and comprehensive way of | |
4 doing this, but alas. Even the oft-recommended StringEscapeUtils does | |
5 something cruder than the below. Le sigh. */ | |
2 | 6 |
3 import java.util.Formatter | 7 import java.util.Formatter |
4 | 8 |
5 private val UNPRINTABLE = setOf<Character.UnicodeBlock>( | 9 private const val DELIM = '"' |
6 Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS, | |
7 Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS_EXTENDED, | |
8 Character.UnicodeBlock.COMBINING_HALF_MARKS, | |
9 Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS_SUPPLEMENT, | |
10 Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, | |
11 Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES, | |
12 Character.UnicodeBlock.HIGH_SURROGATES, | |
13 Character.UnicodeBlock.LOW_SURROGATES, | |
14 Character.UnicodeBlock.PRIVATE_USE_AREA, | |
15 Character.UnicodeBlock.SPECIALS, | |
16 | 10 |
17 ) | 11 private val STD_ESC_MAP = mapOf<Char, Char>('\t' to 't', '\b' to 'b', '\n' to 'n', |
12 '\r' to 'r', '\u000c' to 'f', '\"' to '"', '\\' to '\\') | |
13 private const val MIN_ASCII = ' ' | |
14 private const val MAX_ASCII = '~' | |
15 private const val MIN_8859 = '\u00a1' | |
16 private const val MAX_8859 = '\u00ff' | |
17 private const val SHY = '\u00ad' | |
18 | 18 |
19 private val DELIM = '"' | 19 fun see(input: String, simple: Boolean = false): String = |
20 if (simple) seeSimple(input) else seeAggressive(input) | |
20 | 21 |
21 private val EXEMPT = setOf<Char>(' ') | 22 private fun seeSimple(input: String): String = StringBuilder().run { |
22 private val PREFIXED = setOf<Char>(DELIM, '\\') | 23 append(DELIM) |
24 append(input) | |
25 append(DELIM) | |
26 toString() | |
27 } | |
23 | 28 |
24 fun see(input: String): String { | 29 private fun seeAggressive(input: String): String { |
25 val accum = StringBuilder() | 30 val accum = Formatter() |
26 val formatter = Formatter(accum) | 31 accum.format("%c", DELIM) |
27 accum.append(DELIM) | |
28 for (ch in input) { | 32 for (ch in input) { |
29 val block = Character.UnicodeBlock.of(ch) | 33 if ((ch in MIN_ASCII..MAX_ASCII) || ((ch != SHY) && (ch in MIN_8859 .. MAX_8859))) { |
30 if (ch in EXEMPT) { | 34 accum.format("%c", ch) |
31 accum.append(ch) | 35 continue |
32 } else if (block == null || block in UNPRINTABLE || Character.isSpaceChar(ch) || Character.isWhitespace(ch)) { | 36 } |
33 formatter.format("\\u%04x", ch.code) | 37 val mapped = STD_ESC_MAP[ch] |
34 } else if (ch in PREFIXED) { | 38 if (mapped != null) { |
35 accum.append('\\') | 39 accum.format("\\%c", mapped) |
36 accum.append(ch) | |
37 } else { | 40 } else { |
38 accum.append(ch) | 41 accum.format("\\u%04x", ch.code) |
39 } | 42 } |
40 } | 43 } |
41 accum.append(DELIM) | 44 accum.format("%c", DELIM) |
42 return accum.toString() | 45 return accum.toString() |
43 } | 46 } |
44 | |
45 fun dump(input: String): String { | |
46 val accum = StringBuilder() | |
47 var needSpace = false | |
48 for (ch in input) { | |
49 if (needSpace) { | |
50 accum.append(' ') | |
51 } | |
52 accum.append(ch.code) | |
53 needSpace = true | |
54 } | |
55 return accum.toString() | |
56 } |