duangsuse::Echo
719 subscribers
4.28K photos
130 videos
583 files
6.49K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
这让我想到了对软件工程来说,也有『IO 密集型应用』和『计算密集型应用』... 这么说,其实自己被『996』,虽然企业不对,可自己对自己毕生工作的态度也未必就能让人感到满意。 🤔
停,现在是 DJson 的设计时间。今天暂时只来设计。 #Java

Json 是什么呢? json.org

Json 里可以有这些类型的『数据』
DJson 称之为『Type』,都可能为 null(为了方便,和 JSON 定义相称)

ObjectJ<Type>
ArrayJ<Type>
String
Number
Boolean


DJson 应该继承于一个 Text ParserCombinator 库,此库应该接受这些参数类型的 Constructor

java.io.DataInput
java.io.InputStream
java.io.File
java.lang.String
byte[]
java.net.URL

应该支持 UTF8 解码(或许利用 InputStreamReader),并且对于 InputStream、URL 支持顺带指定大小的 Buffer 快捷方式(利用 BufferedInputStream 机制)


它应该记录:
+ 输入流
+ 当前读取的文件名 fileName
+ 当前流位置 offset
+ 当前读取的行号 lineN
+ 当前读取的列号 columnN
+ 当前解析状态栈 stateStack
+ 当前解析标记栈 positionStack

它应该支持这些 combinator 方法(其实... 和 Haskell 的 ReadP 还是有很大区别的,但其实也能写 combinator style 的 parser...)

boolean eof()
int available()
void close()

char getChar()
char offset(int n)
void next()
void skip(int n)

StringBuilder lookAheadN(int n)
char lookAhead1()

boolean char(char x)
boolean containsIn(char... xs)
boolean containsIn(Set<Character> xs)
boolean lookAhead(String x)
boolean lookAhead(char x)

StringBuilder takeWhile(Consumer<Char> p)
StringBuilder takeUntil(Consumer<Char> p)

StringBuilder logWhile(Consumer<Char> p)
StringBuilder logUntil(Consumer<Char> p)

void dropWhile(Consumer<Char> p)
void dropUntil(Consumer<Char> p)

int tell()
void seek(int pos)

void begin(String state)
String readState()
void done()

void pushPosition()
int lastPosition()
void loadPosition()

void debug(String debugMessage)
void debug(String debugMessage, PrintStream output)
void fail(String message) throws TextCombinatorError
void asserts(boolean p, String message) throws TextCombinatorError

static Set<Character> range(char i1, char i2)

然后还有真正的 parser 的组合函数,要用到 Java 8 的 :: 语法

<T> T maybe(Parser<T>... parsers)

这样就可以这么匹配,不过只能

in.maybe(
charP("("),
satisfy((c) -> c == "A"),
some(element("1", "2", "3")),
many(elemnet(range("A", "Z"))))

这样,可以这么写一个 Json String Parser:

string
= " character* "

character
= ['0020' .. '10ffff'] - ["\]
| '\' escape

escape
= ["\/bnrt]
| u hex hex hex hex

hex
= digit
| [A-F] | [a-f]

digit = 0 | onenine
onenine
= [1-9]

如果不能匹配就 reset 到之前的位置,两种 combinator style 都支持,一个作为后端(TextInputStream, TextReadStream)一个作为前面的封装(TextCombinator)... 🤔
duangsuse::Echo
停,现在是 DJson 的设计时间。今天暂时只来设计。 #Java Json 是什么呢? json.org Json 里可以有这些类型的『数据』 DJson 称之为『Type』,都可能为 null(为了方便,和 JSON 定义相称) ObjectJ<Type> ArrayJ<Type> String Number Boolean DJson 应该继承于一个 Text ParserCombinator 库,此库应该接受这些参数类型的 Constructor java.io.DataInput j…
顺便一说,DJson 希望有泛型的 ObjectJ<T extends Type> 什么的其实是希望可以这样: 😫

DJson
.fromString("{a:1}")
.into(new ObjectJ<Number>())
.doParse();

然后假设这么干可以边解析边检查类型(

但是... 其实 Java 没有真泛型,是泛型擦除实现的泛型... 没有办法拿到 Tjava.lang.Class<T> 实例...
我开始是想 interface 里也能为类指定 static 方法限定的... 这样我用 T.getClass() 什么的就可以进行类型检查了
可是真的不可以啊... 泛型里无法拿到任何的类型参数信息呢,除非用 Kotlin reified Generics

后来... 我觉得还是专门设立一个类似 hamcrest 的 pattern match 检查器好,多道 pass 也没什么的

这样可以

DJson
.fromString("{ary:[1]}")
.typed(new ObjectJ(new ArrayJ(new NumberJ())))
.doParse()

或许好一点吧...
#pl #cs #plt #recommended https://tinyurl.com/y8xdlfug

冰封的简历... 人家 18 年去宾夕法尼亚州立大学学计算机科学现在有半年多了呃...

IDE 和 Parser、Compiler、Type system、静态分析什么的自然是编译器工程师必须要会的了... 可是冰封还有 Rust 和分布式计算、并行计算、计算机网络、图形前端开发、形式化验证、二进制级别理解等技能,真的是让人... 不可理喻啊 🤪

不过话说起来,复杂的都能解决了这些码农级别或者算法的东西也就不成问题了,何况曾经写过 #OI...

看份简历,居然顺便知道了到底啥是 (依赖类型术语) dependent product type (Pi type) 啥是 dependent pair type(Sigma type),还顺带了解了啥是 Sum type (Tagged Union) 啥是 Product type 啥是 case split... 果然是 🐮🍺 啊....
https://github.com/duangsuse/AXMLEdit/issues/2

其实这玩意都快把我的眼睛看瞎了,这种代码... 不必要的复杂性... emmmm...

StartTagChunk startChunk = StartTagChunk.createChunk(name, attCount, -1, attribute);
// 构造一个新的 chunk 之后, 开始写入
if (isNotAppTag(tagName)) {
ChunkParser.xmlStruct.byteSrc = Utils.insertByte(ChunkParser.xmlStruct.byteSrc, subTagChunkOffsets, startChunk.getChunkBytes());
subTagChunkOffsets += startChunk.getChunkBytes().length;
} else {
ChunkParser.xmlStruct.byteSrc = Utils.insertByte(ChunkParser.xmlStruct.byteSrc, subAppTagChunkOffset, startChunk.getChunkBytes());
subAppTagChunkOffset += startChunk.getChunkBytes().length;
}

这都是啥辣鸡代码 #Java

https://github.com/duangsuse/AXMLEdit/blob/master/src/main/java/cn/wjdiankong/axmledit/helper/AXmlEditor.java#L84

前面使用的算法大概是:

XmlPull 标签开始:
size tagName = makeStrPoolRef(parser.getName())
int count = parser.getAttrCount()
byte[count * 20] attrbytes
for (int i : count)
size uri= makeStrPoolRef(prefixStr)
int[] type = getAttrType(attrValue[i])
String[] attrName = attrName[i].split()

int aname = attrName[1]
int avalue = attrValue[i]
int atype = type[0]
int adata = type[1]

AttrData data(uri, aname, avalue, atype, adata)
attrbytes = bytecat(attrbytes, data.bytes, i * data.len)

为啥非得建立这么多 byte 数组?难道不能用 OutputStream 吗?

TagStart:
int tagName = axml.strPoolRef(parser.getName())
final int count = parser.getAttrCount()
for (int i : count)
String attr_name = attrName[i].split()
int[] attr_type = toAttrType(attrValue[i])

int aname = attr_name[1], avalue = attrValue[i], atype = type[0], adata = type[1];

new AttrData(uriRef, aname ,avalue, atype, adata).writes(axml)

如果有不能立刻写的数据,那就保存好晚点结束生成的时候再写,比如 string pool...
为什么要不断去手算偏移量... 能流式就不要不断去做乘除法
duangsuse::Echo
停,现在是 DJson 的设计时间。今天暂时只来设计。 #Java Json 是什么呢? json.org Json 里可以有这些类型的『数据』 DJson 称之为『Type』,都可能为 null(为了方便,和 JSON 定义相称) ObjectJ<Type> ArrayJ<Type> String Number Boolean DJson 应该继承于一个 Text ParserCombinator 库,此库应该接受这些参数类型的 Constructor java.io.DataInput j…
Parser<String> stringP() {
return () -> { charP('"'); manyConcat(jsonCharP()); charP('"'); }
}

Parser<Character> jsonCharP() {
return () -> {
return maybe(sequence(charP('\\'), jsonEscapeP()),
all(notElement("\"\\"), element(range(0x0020, 0x10ffff))));
};
}

Parser<Character> jsonEscapeP() {
return () -> {
return maybe(element("\"/\\bnrt"), sequence(charP("u"), repeats(4, hexCharP())));
};
}

Parser<Character> hexCharP() {
return () -> {
return maybe(digitP(), element(range("a", "f")), element(range("A", "F")));
};
}

Parser<Character> digitP() {
return () -> {
return maybe(charP('0'), element(range('1', '9')));
};
}
我得再去考虑一下 Parser 应该怎么抽象,然后 DJson 就可以使用这种 combinator 风格的 parser 库了

@FunctionalInterface
interface Parser<? extends R> {
@Nullable R match(TextReadStream reader);
}

🤔 charP 是什么呢? 一个 Parser<Character>, 就是说它的匹配结果是 Character

.... 不应该接受任何的额外参数,所以不如这么说:

@FunctionalInterface
interface Parser<? extends R> {
@Nullable R match();
}

class MyParser extemds TextCombinator {
Parser<Character> charP(char x) {
return () -> { return getChar() == x ? getChar() : null; }
}

Parser<Void> helloP() {
return () -> {
sequence(charP("h"), charP("e"), charP("l"), charP("l"), charP("o"));
return null;
};
}

Parser<Integer> manyHelloP() {
return () -> {
ManyMatch hellos = many(helloP());
return hellos.length
};
}
}

这样就可以了

MyParser parser = new MyParser(System.in);
System.out.println(parser.manyHelloP());

hellohellohellohello
...

处理 EOF:

sequence 里默认一个一个 match,EOF 则直接不 match,使用 eofP 来匹配结束吧...(说说而已,我觉得应该专门使用一种方式)
mustSequence 里可以提供一个函数来指示错误信息,Unexpected EOF

比如一个简单的语法结构:

<def> <name> <(> { arg } <)> <=> <value>

就是:

mustSequence(
keywordP(DEF), ws(),
nameP(), ws(),
parenLP(),
many(argP()),
parenRP(), ws(),
eqP(),
valueP()
).except((n) -> switch (n) {
case 0: return expect("def keyword");
case 2: return expect("variable name");
case 4: return expect("(");
case 6: return expect(")");
case 8: return expect("=");
case 9: return expect("variable value");
})

假设用户只输入了

def a

就 EOF 了,实际上最后一个状态是 ws(), 倒数第二个是 definitionP
这样,mustSequence 就可以给出错误信息:
duangsuse::Echo
我得再去考虑一下 Parser 应该怎么抽象,然后 DJson 就可以使用这种 combinator 风格的 parser 库了 @FunctionalInterface interface Parser<? extends R> { @Nullable R match(TextReadStream reader); } 🤔 charP 是什么呢? 一个 Parser<Character>, 就是说它的匹配结果是 Character .... 不应该接受任何的额外参数,所以不如这么说: @Fu…
@FunctionalInterface
interface Parser<R> {
@Nullable <? extends R> match();
}

@FunctionalInterface
interface Matcher<R> {
@Nullable boolean matches(<? super R> value);
}

所以提供的 parser combinator 方法都有

Parser<R> satisfy(Matcher<Character> predicate);
charP

SequenceParser<R> maySequence(Parser<R> parsers...);
SequenceParser<R> sequence(Parser<R> parsers...);

all
maybe
sequenceFilterConcat
exclusiveOr
not

repeats

some
many
manyConcat

element
notElement
range

看看这道题

Regex 子集的

data RegExp
= Normal Char
-- ^ A character that is not in "()*|."
| Any
-- ^ Any character
| ZeroOrMore RegExp
-- ^ Zero or more occurances of the same regexp
| Or RegExp RegExp
-- ^ A choice between 2 regexps
| Str [RegExp]
-- ^ A sequence of regexps.

Normal 就是 charP
Any 没有默认定义,但是可以这么写
Parser<Character> any() { return satisfy((x) -> true); }

ZeroOrMore 就是 many
Or 就是 maybe
Str 就是 sequence

这个 Parser 也可以用来解析 Regex 所能解析的东西:

"ab*" -> sequence(charP("a"), many(charP("b")))
"(ab)+" -> some(sequence(charP("a"), charP("b")))
"(a.*)|(bb)" ->
maybe(
sequence(charP('a'), many(any())),
sequence(charP('b'), charP('b'))))
草,没时间写了
#backend #java 🤔 异步拖长了,用消息队列(
... 那客户端一定要同步查询也得 keep 一大堆 alive 的 HTTP connection...

说到底是 GitHub 连接慢了?emmm
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (YuutaW 鱼塔)
仔细观察了日志,发现日志从 28% 到结尾均有各种 Vertx Thread Blocked 异常,从 5s ~ 12s 不等。同时在 Arrays#copyOf、vertx-blocked-thread-checker 线程、OkHttp ConnectionPool 线程、vert.x-eventloop-thread-0 等地方均发生 OOM 异常。
其实只需要做前端的工作的.. #Android #net
Forwarded from YuutaW 鱼塔
理解 SS 源码困难(
辣鸡。 #security #web 连 XXS 都不防
我们这里也搞过,后来我强行卸了硬盘保护系统... 结果辣鸡 BIOS 只能从 PCI 启动,电脑坏了... 后来老师拆了还原卡又重装了保护系统... 所以我只能 VM #School
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (YuutaW 鱼塔)
雾草 学校电脑 🐮🍺,从 U 盘启动需要管理员密码 🌚
#freedom 总算能用了.... 蓐羊毛翻墙日益艰难?🌚🐕