-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathConfigMaster.java
More file actions
173 lines (159 loc) · 5.86 KB
/
ConfigMaster.java
File metadata and controls
173 lines (159 loc) · 5.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package roj.config;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NotNull;
import roj.config.node.ConfigValue;
import roj.config.node.xml.Element;
import roj.config.node.xml.Node;
import roj.config.table.CsvParser;
import roj.io.IOUtil;
import roj.text.CharList;
import roj.text.ParseException;
import roj.text.TextWriter;
import roj.util.ByteList;
import roj.util.DynByteBuf;
import roj.util.Helpers;
import roj.util.OperationDone;
import java.io.*;
import java.util.TimeZone;
/**
* @author Roj234
* @since 2024/3/23 21:00
*/
public enum ConfigMaster {
BENCODE, NBT, XNBT, MSGPACK, JSON, YAML, XML, TOML, INI, CSV;
public static ConfigMaster fromExtension(File path) {
String ext = IOUtil.extensionName(path.getName());
return switch (ext) {
case "yml", "yaml" -> YAML;
case "xml" -> XML;
case "json", "json5" -> JSON;
case "toml" -> TOML;
case "ini" -> INI;
case "nbt" -> NBT;
case "torrent" -> BENCODE;
case "csv" -> CSV;
default -> throw new IllegalArgumentException("不支持的配置文件扩展名:"+ext);
};
}
/**
* @see #parser(int)
*/
public Parser parser() {return parser(0);}
/**
* 返回的实例并非线程安全
* @param initFlag 初始化标记,无法在解析时动态修改,目前仅有{@link TextParser#COMMENT}以支持注释
*/
public Parser parser(@MagicConstant(flags = TextParser.COMMENT) int initFlag) {
return switch (this) {
case JSON -> new JsonParser(initFlag);
case YAML -> new YamlParser(initFlag);
case XML -> new XmlParser();
case TOML -> new TomlParser(initFlag);
case INI -> new IniParser();
case CSV -> new CsvParser();
case NBT -> NbtParser.INSTANCE;
case XNBT -> NbtParserEx.INSTANCE;
case MSGPACK -> new MsgPackParser();
case BENCODE -> new BEncodeParser();
};
}
/**
* 创建一个到out的流式序列化器
* 不是所有格式都支持流式序列化
* @param out 可以是File、OutputStream或DynByteBuf
*/
public ValueEmitter serializer(Object out) { return serializer(out, ""); }
// 也不是所有格式都支持indent 哈哈
public ValueEmitter serializer(Object out, String indent) {
try {
return switch (this) {
case JSON -> new JsonSerializer(indent).to(textEncoder(out));
case YAML -> new YamlSerializer(indent).multiline(true).timezone(TimeZone.getDefault()).to(textEncoder(out));
case INI -> new IniSerializer().to(textEncoder(out));
case BENCODE -> new BEncodeEncoder(binaryEncoder(out));
case NBT, XNBT -> new NbtEncoder(binaryEncoder(out)).setXNbt(this == XNBT);
case MSGPACK -> new MsgPackEncoder.Compressed(binaryEncoder(out));
default -> throw new UnsupportedOperationException(this+"不支持流式序列化");
};
} catch (Exception e) {
Helpers.athrow(e);
throw OperationDone.NEVER;
}
}
public boolean hasSerializer() { return ordinal() >= NBT.ordinal() && ordinal() <= YAML.ordinal(); }
private static @NotNull DynByteBuf binaryEncoder(Object out) throws IOException {
return out instanceof DynByteBuf buf
? buf
: new ByteList.ToStream(out instanceof File f
? new FileOutputStream(f)
: (OutputStream) out);
}
private static @NotNull CharList textEncoder(Object out) throws IOException {
return out instanceof CharList sb
? sb
: out instanceof File f
? TextWriter.to(f)
: new TextWriter((Closeable) out, null);
}
/**
* 将entry序列化到out
* 不是所有格式都支持序列化
* @param out 可以是File、OutputStream或DynByteBuf
*/
public void serialize(Object out, ConfigValue entry) throws IOException {
switch (this) {
case JSON, YAML, INI, NBT, XNBT, MSGPACK, BENCODE -> {
try (var emitter = serializer(out)) {
entry.accept(emitter);
}
}
case TOML, XML -> {
try (TextWriter tw = out instanceof File f ? TextWriter.to(f) : new TextWriter((Closeable) out, null)) {
if (this == TOML) {
CharList tmp = new CharList();
entry.appendTOML(tw, tmp);
tmp._free();
} else {
((Element) entry).toXML(tw);
}
}
}
default -> throw new UnsupportedOperationException(this+"不支持序列化");
}
}
public void toFile(ConfigValue entry, File file) throws IOException { serialize(file, entry); }
public void toBytes(ConfigValue entry, OutputStream out) throws IOException { serialize(out, entry); }
public void toBytes(ConfigValue entry, DynByteBuf buf) throws IOException { serialize(buf, entry); }
public String toString(ConfigValue entry) { return toString(entry, IOUtil.getSharedCharBuf()).toString(); }
public String toString(ConfigValue entry, String indent) { return toString(entry, IOUtil.getSharedCharBuf(), indent).toString(); }
public CharList toString(ConfigValue entry, CharList out) { return toString(entry, out, ""); }
public CharList toString(ConfigValue entry, CharList out, String indent) {
switch (this) {
case JSON, YAML, INI -> entry.accept(serializer(out, indent));
case TOML -> entry.appendTOML(out, new CharList());
case XML -> {
Node node;
if (entry instanceof Node n) {
node = n;
} else {
// convert to xml
XmlEmitter sb = new XmlEmitter();
entry.accept(sb);
node = sb.get();
}
if (indent.isEmpty()) node.toCompatXML(out);
else node.toXML(out);
}
default -> throw new UnsupportedOperationException(this+"不支持序列化到字符串");
}
return out;
}
public ConfigValue parse(File key) throws IOException, ParseException { return parser().parse(key); }
public ConfigValue parse(InputStream key) throws IOException, ParseException { return parser().parse(key); }
public ConfigValue parse(DynByteBuf key) throws IOException, ParseException { return parser().parse(key); }
public ConfigValue parse(CharSequence text) throws ParseException {
Parser p = parser();
if (!(p instanceof TextParser tp)) throw new UnsupportedOperationException(this+"不是文本配置格式");
return tp.parse(text);
}
}