| author | wenzelm |
| Sun, 09 Jun 2024 21:16:38 +0200 | |
| changeset 80313 | a828e47c867c |
| parent 76351 | 2cee31cd92f0 |
| child 80436 | 6e865cd22349 |
| permissions | -rw-r--r-- |
| 43780 | 1 |
/* Title: Pure/General/properties.scala |
2 |
Author: Makarius |
|
3 |
||
4 |
Property lists. |
|
5 |
*/ |
|
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
| 75393 | 10 |
object Properties {
|
| 65624 | 11 |
/* entries */ |
12 |
||
| 43780 | 13 |
type Entry = (java.lang.String, java.lang.String) |
14 |
type T = List[Entry] |
|
15 |
||
| 75393 | 16 |
object Eq {
|
|
73715
bf51c23f3f99
clarified signature -- avoid odd warning about scala/bug#6675;
wenzelm
parents:
73712
diff
changeset
|
17 |
def apply(a: java.lang.String, b: java.lang.String): java.lang.String = a + "=" + b |
|
bf51c23f3f99
clarified signature -- avoid odd warning about scala/bug#6675;
wenzelm
parents:
73712
diff
changeset
|
18 |
def apply(entry: Entry): java.lang.String = apply(entry._1, entry._2) |
| 73712 | 19 |
|
| 75393 | 20 |
def unapply(str: java.lang.String): Option[Entry] = {
|
| 73712 | 21 |
val i = str.indexOf('=')
|
22 |
if (i <= 0) None else Some((str.substring(0, i), str.substring(i + 1))) |
|
23 |
} |
|
24 |
} |
|
25 |
||
| 64358 | 26 |
def defined(props: T, name: java.lang.String): java.lang.Boolean = |
27 |
props.exists({ case (x, _) => x == name })
|
|
28 |
||
29 |
def get(props: T, name: java.lang.String): Option[java.lang.String] = |
|
30 |
props.collectFirst({ case (x, y) if x == name => y })
|
|
31 |
||
| 75393 | 32 |
def put(props: T, entry: Entry): T = {
|
| 64358 | 33 |
val (x, y) = entry |
34 |
def update(ps: T): T = |
|
35 |
ps match {
|
|
36 |
case (p @ (x1, _)) :: rest => |
|
37 |
if (x1 == x) (x1, y) :: rest else p :: update(rest) |
|
38 |
case Nil => Nil |
|
39 |
} |
|
40 |
if (defined(props, x)) update(props) else entry :: props |
|
41 |
} |
|
42 |
||
43 |
||
| 65857 | 44 |
/* external storage */ |
45 |
||
|
75794
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
46 |
def encode(ps: T): Bytes = {
|
|
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
47 |
if (ps.isEmpty) Bytes.empty |
|
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
48 |
else Bytes(YXML.string_of_body(XML.Encode.properties(ps))) |
|
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
49 |
} |
| 65857 | 50 |
|
|
75794
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
51 |
def decode(bs: Bytes, cache: XML.Cache = XML.Cache.none): T = {
|
|
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
52 |
if (bs.is_empty) Nil |
|
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
53 |
else cache.props(XML.Decode.properties(YXML.parse_body(bs.text))) |
|
1c3c31319974
more robust data representation: notably for Store.read_session_timing with database_server;
wenzelm
parents:
75393
diff
changeset
|
54 |
} |
| 65857 | 55 |
|
| 68018 | 56 |
def compress(ps: List[T], |
|
76351
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
wenzelm
parents:
76350
diff
changeset
|
57 |
options: Compress.Options = Compress.Options(), |
|
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
wenzelm
parents:
76350
diff
changeset
|
58 |
cache: Compress.Cache = Compress.Cache.none |
| 75393 | 59 |
): Bytes = {
|
| 65857 | 60 |
if (ps.isEmpty) Bytes.empty |
| 68018 | 61 |
else {
|
62 |
Bytes(YXML.string_of_body(XML.Encode.list(XML.Encode.properties)(ps))). |
|
63 |
compress(options = options, cache = cache) |
|
64 |
} |
|
| 65857 | 65 |
} |
66 |
||
| 75393 | 67 |
def uncompress(bs: Bytes, cache: XML.Cache = XML.Cache.none): List[T] = {
|
| 72885 | 68 |
if (bs.is_empty) Nil |
| 65857 | 69 |
else {
|
| 68018 | 70 |
val ps = |
|
73031
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
wenzelm
parents:
73024
diff
changeset
|
71 |
XML.Decode.list(XML.Decode.properties)( |
|
76351
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
wenzelm
parents:
76350
diff
changeset
|
72 |
YXML.parse_body(bs.uncompress(cache = cache.compress).text)) |
|
73031
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
wenzelm
parents:
73024
diff
changeset
|
73 |
if (cache.no_cache) ps else ps.map(cache.props) |
| 65857 | 74 |
} |
75 |
} |
|
76 |
||
77 |
||
| 65624 | 78 |
/* multi-line entries */ |
79 |
||
| 65932 | 80 |
def encode_lines(props: T): T = props.map({ case (a, b) => (a, Library.encode_lines(b)) })
|
81 |
def decode_lines(props: T): T = props.map({ case (a, b) => (a, Library.decode_lines(b)) })
|
|
| 65624 | 82 |
|
83 |
def lines_nonempty(x: java.lang.String, ys: List[java.lang.String]): Properties.T = |
|
84 |
if (ys.isEmpty) Nil else List((x, cat_lines(ys))) |
|
85 |
||
86 |
||
87 |
/* entry types */ |
|
| 64358 | 88 |
|
| 75393 | 89 |
class String(val name: java.lang.String) {
|
| 43780 | 90 |
def apply(value: java.lang.String): T = List((name, value)) |
91 |
def unapply(props: T): Option[java.lang.String] = |
|
92 |
props.find(_._1 == name).map(_._2) |
|
| 72137 | 93 |
def get(props: T): java.lang.String = unapply(props).getOrElse("")
|
| 43780 | 94 |
} |
95 |
||
| 75393 | 96 |
class Boolean(val name: java.lang.String) {
|
| 48344 | 97 |
def apply(value: scala.Boolean): T = List((name, Value.Boolean(value))) |
98 |
def unapply(props: T): Option[scala.Boolean] = |
|
99 |
props.find(_._1 == name) match {
|
|
100 |
case None => None |
|
101 |
case Some((_, value)) => Value.Boolean.unapply(value) |
|
102 |
} |
|
| 72137 | 103 |
def get(props: T): scala.Boolean = unapply(props).getOrElse(false) |
| 48344 | 104 |
} |
105 |
||
| 75393 | 106 |
class Int(val name: java.lang.String) {
|
| 43780 | 107 |
def apply(value: scala.Int): T = List((name, Value.Int(value))) |
108 |
def unapply(props: T): Option[scala.Int] = |
|
109 |
props.find(_._1 == name) match {
|
|
110 |
case None => None |
|
111 |
case Some((_, value)) => Value.Int.unapply(value) |
|
112 |
} |
|
| 72137 | 113 |
def get(props: T): scala.Int = unapply(props).getOrElse(0) |
| 43780 | 114 |
} |
115 |
||
| 75393 | 116 |
class Long(val name: java.lang.String) {
|
| 43780 | 117 |
def apply(value: scala.Long): T = List((name, Value.Long(value))) |
118 |
def unapply(props: T): Option[scala.Long] = |
|
119 |
props.find(_._1 == name) match {
|
|
120 |
case None => None |
|
121 |
case Some((_, value)) => Value.Long.unapply(value) |
|
122 |
} |
|
| 72137 | 123 |
def get(props: T): scala.Long = unapply(props).getOrElse(0) |
| 43780 | 124 |
} |
125 |
||
| 75393 | 126 |
class Double(val name: java.lang.String) {
|
| 43780 | 127 |
def apply(value: scala.Double): T = List((name, Value.Double(value))) |
128 |
def unapply(props: T): Option[scala.Double] = |
|
129 |
props.find(_._1 == name) match {
|
|
130 |
case None => None |
|
131 |
case Some((_, value)) => Value.Double.unapply(value) |
|
132 |
} |
|
| 72137 | 133 |
def get(props: T): scala.Double = unapply(props).getOrElse(0.0) |
| 43780 | 134 |
} |
135 |
} |