duangsues.is_a? SaltedFish
60 subscribers
609 photos
6 videos
91 files
562 links
🌶🐔🐟 duangsuse 的日常
尤其喜欢发些奇奇怪怪的东西
和转载别人的东西
Download Telegram
#web #dev #Kotlin 插播一条消息
Forwarded from dnaugsuz
https://github.com/JetBrains/Exposed#sql-dsl-sample

好耶,比某些 Annotation based AOP 框架高到不知哪里去了

object Users : Table() {
// Column<out T>
val id = varchar("id", 10).primaryKey()
val name = varchar("name", length = 50)
val cityId = (integer("city_id") references Cities.id).nullable()
}

object Cities : Table() {
val id = integer("id").autoIncrement().primaryKey()
val name = varchar("name", 50)
}

...
Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")

transaction {
SchemaUtils.create (Cities, Users)

val saintPetersburgId = Cities.insert { it[name] = "St. Petersburg" } get Cities.id
Users.insert { it[id] = "andrey"; it[name] = "Andrey"; it[cityId] = saintPetersburgId }
}

...

for (city in Cities.selectAll()) println("${city[Cities.id]}: ${city[Cities.name]}")


本来就应该使用这种风格的

然后还可以使用 DataAccessObjects 的风格

object Users : IntIdTable() {
val name = varchar("name", 50).index()
val city = reference("city", Cities)
val age = integer("age")
}

class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)

var name by Users.name
var city by (City referencedOn Users.city).nullable()
var age by Users.age
}

...
User.new {
name = "duangsuse"
age = 17
}
内存区域限制技能 get
Forwarded from dnaugsuz
关键是这个判断

if (retv && inlen >= value_len + 1)
  // strncpy (retv, value, strlen(value) +1);

原来可能就没有,所以有时候 strncpy (它的意思是从 src 复制 n 个 char 到 dst,这里 C 的『字符串长度』因为字符串是 NUL 结尾的,得加上 NUL 字符的长度 1,可惜作者弄错了或者说故意弄的,原因在后面)

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0')

strncpy
:
If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.

但是 strlen 不包含 NUL byte '\0' 长度, 所以作者 strncpy 时加上是正确的

但这样
(调用 strncpy, 写到指针, 但是指针是不定长无限制的)实际上就可能 overflow 了 retv: 本来它可能(是在其他函数里)分配了未知长度的内存,可是我们居然可以随便按照 value 字符串的长度复制
这是不安全的操作,所以 CC 阻止了编译,但它是没有问题的

找不到 inlen 的话就定义栈帧 auto 变量

size_t inlen = strlen(retv);
size_t value_len = strlen(value);

它可以 suppress
看起来就算是没有刻意用 GoF 的 OOP 设计模式,你也是会正常的 OO 吗,难道 FlarumSDK 的

public class FlarumException extends Exception
int status, code; List<Error> allErrors;

public class Result<T>
int id;
okhttp3.Response rawResponse;
JSONAPIObject object;
T mainAttr;

public class RequestBuilder<T>
final Flarum flarum;
final ObjectParser.JsonObjectConverter<TYPE> converter;
final String method, urlEndpoint;
final RequestBody body;

public static class RequestBuilder$BaseRequest<TYPE>

private okhttp3.Request.Builder baseBuilder ()
这一类虽然算法比较简单(几个顺序分支;和 Kotlin 里 thread 辅助函数的差不多,按需设置对象)但是没有一点意识也是写不出来的啦

public interface Callback<T> 这个看起来像是复制的(

可是怎么看都用了正常的面向对象编程啊;media type & converter、token getter、tasks & executor

还有 JSON response parser, Json Object converter...

这类代码都不能算是了解面向对象编程了吗,看起来菜鸡是不可能哪怕是不包括型变的泛型和 converter 这种东西...(虽然 converter 好像懂泛型能抽提就可以了)
要是真正的菜鸡大概是这些都不可能会的
Forwarded from dnaugsuz
文档在这里... 刚刚看了一下 Kotlin 语义上 execute 后两个参数是 producer 和 job 都在 worker 里执行,执行完可以给 futuer 的 consumer 处理

然后 kotlin.native.concurrent.Worker.execute must take an unbound, non-capturing function or lambda

emmm...

val descriptor = expression.descriptor.original

if (irCallableReference == null || irCallableReference.getArguments().isNotEmpty())

??? 🌚

看起来像是没有参数的,不过我知道其实第二个块有一个默认参数 itT2

但是我觉得它是在说第一个没有参数的块...

上面的 message 是告诉你:这个(编译后)的函数指针不能有参数,比如 self、比如 captures
所以... 我们看看 Worker#execute 的实现算了

首先 Kotlin 的 Instrinsics 函数 external internal fun executeInternal

execute 它是编译器的 Instrinsics 方法...

@TypedIntrinsic(IntrinsicType.WORKER_EXECUTE)

就是我刚才给你看的具体实现
Forwarded from dnaugsuz
比如这个 onclick 其实也就是缩短了一点标识符而已

(j :: DOMElement).onclick = () => { it.forEach((x) => {
if (x === h.value) return f(m.err_uin)
if (x === i.value) return f(m.err_password)
});
}

实际上就是让你把 f(_) 的逻辑内联到这里面来,程序变换的方法很多的,比如 f 是这样的

const f = (res) => switch (res) { case m.err_uin: console.log('error') }

最后实际上 onclick 逻辑就等价

j.onclick = () => { it.forEach(
(x) => {
if (x === i.value) console.log('error')

//if (x === h.value) {}
});
}

!1 是对二进制数值 0b1 取反,但是没有多大用处,可以去掉就好了,不过也要相应的去除一些数值

只是说对编译原理的学习者来说,IDE 的重构功能肯定是不会缺少的,何况工具也会多一点,这样专门的反混淆器也不难开发的
Forwarded from dnaugsuz
指针一直以来不是最高大上的概念啊,稍微对现代电子计算机存储器结构、冯诺伊曼计算机结构有点感觉的人都会觉得指针实际上非常符合直觉
因为内存就是一大打能够以某种最小粒度(很多时候是 char,一个字节)访问(读写)存储器的集合而已,只要你知道可随机访问的存储器一般以某种(整型数值上)连续的方式编址可访问就好了
然后 C 只要不弄出悬垂指针、空指针也是最吼滴,对新手最大的问题可能是动态内存分配和“为什么我不能返回一个本地变量 char *a”?(他们实际上看不到运行时有个叫做栈(stack) 的东西.... 也不知道有 GC, garbage collector 编程语言里所谓的对象在 C 里都是必须弄明白他们到底应该被『存储』在哪里的,要不然下面的机器没办法执行)

然后 C 的 struct, union, array 什么的内存布局也没有那么奇怪,也提供了 &* 直接对其他对象取地址的方式,不会指针运算双重指针(int **)也总是会的吧。

void swap(int *a, int *b) {
auto int saved_a = *a;
*a = *b;
*b = saved_a;
}

注意这里 * 有两种含义:
在编程语言理论里,int* 类型的东西是可以同时作为左值 (lhs, {get;set;}) 和右值 (rhs {get;}) 使用的(而 const int* 就不可以,只能当左值取值不能赋值)
*a 出现在需要左值的位置时,* 操作符的语义实际上是『“ptr write”』给指针赋值,比如 *a=-1;
反之,它的含义是解指针(ptr read)比如上面的
*a = *b;
等号右边 *b 就是 deref 操作。

(当然这个函数也可以用 C11 的新特性 _Generic 写,不过这里是作为示范就先不写)
然后那个 auto 是存储位置的修饰符,这个是默认的,表示不刻意指定
要是刻意指定可以写 register 机器寄存器、static 常量(一般存在 ELF 的 .bss, block started by symbol 端)、extern 外部编译单元可见等等
Forwarded from dnaugsuz
KN 不是基于 JVM 的,对于 executable 它翻译到 LLVM 表示后就直接发射机器码了,但是你可以注意到 KN 也提供 GC
KN 远比 JVM 上的 Kotlin 提供的底层控制多,比如它好像还可以给本地栈指定什么参数?

runtime/src/main/cpp/Memory.h

readelf -s ./build/bin/linuxX64/releaseExecutable/secure-desktop.kexe|grep Kotlin

102: 00000000002289b0 146 FUNC GLOBAL DEFAULT 15 Kotlin_destroyRuntime
111: 00000000002288c0 5 FUNC GLOBAL DEFAULT 15 Kotlin_createRuntime

(注意这不是 java.lang.Runtime)
我上次写的没有用到动态内存管理,但是 KN 是有 runtime 的,它不像 Rust 的 runtime 很小,而且甚至可以去掉,毕竟是要和 JVM/JS 版兼容的
Forwarded from Richard Yu
因为不是C/C++,谁知道有没有指针?没的话那就传个0吧。C++我会写nullptr。
Forwarded from dnaugsuz
如果没有指针类型的话也是可能的,但是,如果是我也会搞个全局的常量 nullptr, 尽可能避免混淆

如果类型系统菜,程序员负责给它洗地
Forwarded from Richard Yu
"" 不代表 nullptr,它是有一个地址的。
Forwarded from dnaugsuz
是啊,所以我说是一个常量

const char *EMPTY_CHARP = "";

这里我没有指定具体分配位置,但它是常量,换句话说编译器喜欢内联也可以直接翻译成

GetModuleHandle("");

或者

const static char EMPTY_CHARP[] = {'\0'};

然后
GetModuleHandle(EMPTY_CHARP);
Forwarded from dnaugsuz
是啊,所以 "" 不是一个地址指针嘛?即便它可能被分配在本地
Forwarded from Richard Yu
那结果就和直接传0不一样了。
Forwarded from Yuuta
看神仙讨论中(
Forwarded from dnaugsuz
printf(EMPTY_CHARP); 的 x86 翻译结果是

mov rdi, qword ptr [EMPTY_CHARP]
mov dword ptr [rbp - 4], eax # 4-byte Spill
mov al, 0
call printf
xor ecx, ecx
mov dword ptr [rbp - 8], eax # 4-byte Spill

上面一句 printf("");

movabs rdi, offset .L.str
mov al, 0
call printf

似乎和 printf(0); 是有区别的

mov al, 0
call printf