![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Code golf для мінімального cp(1)
Пачіняючі прімус, тобто шукаючи причину чому прибацаний файловий диспетчер KDE Dolphin не хотів копіювати файли, коли виконувався не з KDE, мені спало на думку, як би виглядав мінімальний аналог cp(1) на C, вихідний код якого <= 280 байт.
Ла спеціфікасьйон:
mycp src dest
;- src та dest то є лише файли;
- компілюватися "
clang -Wall mycp.c -o mycp
" має з 0 попереджень з лайнакса чи мак'ос; - показувати помилку коли (та вертати exit code >= 1):
- src/dest є неприпустимі (файл не існує, є директорією, немає дозволу на читання/запис, тощо);
- src == dest (ув мінімальному вигляді, не треба різолвіти шлях/сімлінка);
- шось погане трапилося під час копіювання.
- не створювати dest розміром 0 байт, якщо src є дефективне.
Версія clang у мене
$ clang --version | head -1
clang version 16.0.5 (Fedora 16.0.5-1.fc38)
Хфінальний результата виглядає ось так
$ cminify mycp.c | wc -c
280
$ cminify mycp.c | clang-format
#include <err.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(int c, char **v) {
c - 3 || !strcmp(v[1], v[2]) ? errx(1, "?") : 0;
int b[65536], s = open(v[1], O_RDWR), d;
s < 0 ? err(2, "") : 0;
d = open(v[2], O_RDWR | O_CREAT | O_TRUNC, 420);
while ((c = read(s, b, 65536)))
c - write(d, b, c) ? err(3, "") : 0;
}
cminify то є якийсь пáйфонівський скрипта з ґітхабу, якщо хтось знає ліпший варіянт, скажіть. Чому для clang-format немає якогось uglify стилю ув комплекті, то це є цікаве питання також.
Енівей, code golf технікс, які були використані:
страшенна економія ув 1 байт:
- октал 0644 → десяткове 420
a==b
→a-b
if (a)b();
→a?b():0;
(шкода що не можна опустити нуль після:
)
кома;
хвункції з err.h, які не є позіксом per se, але є всюди, окрім віндюка.
Дуже дратує, що не виходить позбутися #include ...
без вказання
версії C якось печерного 1989 року. Замість O_RDWR і ко можна було б
вказати число, але портáбільність тоді миттєво гасне.
Тести:
$ ./mycp
mycp: ?
$ ./mycp 1 1
mycp: ?
$ ./mycp /root/nope 1
mycp: : Permission denied
$ ./mycp mycp.c .
mycp: : Bad file descriptor
$ ./mycp . 1
mycp: : Is a directory
$ ./mycp BUGUS 1
mycp: : No such file or directory
1 GB мотлоху має скопіюватися без помилок:
$ head -c $((1024*1024*1024)) /dev/urandom > 1
$ ./mycp 1 2
$ cmp 1 2
$ echo $?
0
Мініфікаційна версія як гарний svg:
$ pango-view -q --font='Ubuntu Mono 24' --rotate 10 --margin=0 <(cminify mycp.c | fold -w18) -o mycp.svg
no subject
Популярный трюк в шелл-скриптах.
no subject
В SQL ще можна юзати тризначний XOR із NULL, і я навіть в одному проекті його дуже ефективно використав замість каскаду CASE WHHEN THEN, але читабельність коду впала до нуля і мені досі соромно за той код.
no subject
> a?b():0;
Можна a&&b();
(Хоча в даному випадку не допоможе)
no subject
c-3||!strcmp(...)?errx(...):0;
→
c>2&&strcmp(...)||errx(...);
no subject
no subject
no subject
no subject
Ну, воно мабуть обох до void зводить.