PDA

Просмотр полной версии : [Вопрос] ulong (оператор #emit)



tnc
08.04.2020, 02:27
Доброго времени суток. Хотелось бы узнать, как можно в ulong (https://github.com/tdworg/samp-include-ulong)от VVWVV конвертировать строку в ulong? Там нет для этого функционала, но как можно написать аналог strval для ulong?

vvw
09.04.2020, 12:47
давно я не писал на pawn, попробую написать.

Что-то такое должно получиться:

stock ulong:ulong_strval(str[], bool:ispacked=false, off=0, size=sizeof str)
{
new ulong:result;
new c;
new pos=off;
while ('0'<=(c=str[pos])<='9') {
#emit load.s.pri result
#emit const.alt 10
#emit umul
#emit push.pri
#emit load.s.pri c
#emit const.alt '0'
#emit sub
#emit pop.alt
#emit add
#emit stor.s.pri result
pos++;
}
return result;
}


Это unsafe функция.

DC. заметил, что ispacked подсвечивается в списке формальных аргументов?

Daniel_Cortez
09.04.2020, 16:28
Во-первых, искренне не понимаю, откуда вообще взялось название "ulong". Если рассматривать это с позиции разработчика, знакомого как минимум с C/C++, слово "long" подразумевает тип данных большего размера, т.е. не 4 байта (размер ячейки), а 8. Здесь же тип "ulong" ограничен всё теми же 4 байтами и является просто чем-то вроде беззнакового типа данных ("чем-то вроде", потому что в Pawn нет типов данных как таковых - есть теги) и было бы логичнее назвать его "ucell" (т.е. "беззнаковая ячейка"; кстати, именно так этот тип данных и называется в исходниках Pawn). Впрочем, это так, небольшая придирка, на работе инклуда это не сказывается =)
Да и вообще, это ничто на фоне других популярных инклудов/плагинов - взять, к примеру, небезызвестные плагины с нелепыми хайповыми названиями, начинающимися на "Pawn.*", как будто они являются частью проекта Pawn (т.е. наравне с компилятором, интерпретатором и стандартными библиотеками; не говоря уже о том, что это тянет на недобросовестное использование торговой марки "Pawn").

Во-вторых,

ulong:ulong_strval(str[], bool:ispacked=false, off=0, size=sizeof str)
если передаваемый в функцию массив используется только для чтения, его следует помечать как "const" (т.е. в данном случае - "const str[]").

В-третьих,

new ulong:result;
https://pro-pawn.ru/showthread.php?16839-warning-210-%28-%29

В-четвёртых, зачем нужен параметр "off", если функцию можно использовать так:

new ulong:result = ulong_strval(inputtext[4]);
?

В-пятых, не используется параметр "size" (ты это имел в виду под "unsafe-функция"?), но он и не нужен - строка всё равно заканчивается нуль-символом, на котором выполнение цикла while прервётся, так что ситуация с OOB исключена. По этой же причине и у стандартной функции strval() нет параметра "size".

В-шестых, параметр "ispacked" тоже не особо нужен, упакованность строки можно проверить и внутри самой функции.

И, наконец, в-седьмых, с помощью оператора __emit вычитание кода символа "0" можно записать так:

add.c (-'0')

, т.е. без загрузки значения в ALT, благодаря чему не нужно лишний раз сохранять другое значение из PRI в стек.

В итоге у меня получилась такая функция:

stock ulong:ulong_strval(const str[])
{
new const bool:packed = (str[0] & ~0xFF != 0);
new ulong:result = ulong:0;
new pos = 0;
new c;
while ('0' <= (c = (packed ? str{pos} : str[pos])) <= '9') {
__emit load.s.pri result;
__emit const.alt 10;
__emit umul;
__emit move.alt;
__emit load.s.pri c;
__emit add.c (-'0');
__emit add;
__emit stor.s.pri result;
pos++;
}
return result;
}



DC. заметил, что ispacked подсвечивается в списке формальных аргументов?
А что ты ожидал? =)
Подсветка работает на простой замене текста, ибо полноценный анализ синтаксиса => неоправданная нагрузка на сервер (либо на клиент, если делать клиент-сайдом на js).

tnc
09.04.2020, 17:24
спасибо. проверю, как будет время.

vvw
12.04.2020, 00:36
Во-первых, искренне не понимаю, откуда вообще взялось название "ulong". Если рассматривать это с позиции разработчика, знакомого как минимум с C/C++, слово "long" подразумевает тип данных большего размера, т.е. не 4 байта (размер ячейки), а 8. Здесь же тип "ulong" ограничен всё теми же 4 байтами и является просто чем-то вроде беззнакового типа данных ("чем-то вроде", потому что в Pawn нет типов данных как таковых - есть теги) и было бы логичнее назвать его "ucell" (т.е. "беззнаковая ячейка"; кстати, именно так этот тип данных и называется в исходниках Pawn). Впрочем, это так, небольшая придирка, на работе инклуда это не сказывается =)
Да и вообще, это ничто на фоне других популярных инклудов/плагинов - взять, к примеру, небезызвестные плагины с нелепыми хайповыми названиями, начинающимися на "Pawn.*", как будто они являются частью проекта Pawn (т.е. наравне с компилятором, интерпретатором и стандартными библиотеками; не говоря уже о том, что это тянет на недобросовестное использование торговой марки "Pawn").

Во-вторых,

если передаваемый в функцию массив используется только для чтения, его следует помечать как "const" (т.е. в данном случае - "const str[]").

В-третьих,

https://pro-pawn.ru/showthread.php?16839-warning-210-%28-%29

В-четвёртых, зачем нужен параметр "off", если функцию можно использовать так:

?

В-пятых, не используется параметр "size" (ты это имел в виду под "unsafe-функция"?), но он и не нужен - строка всё равно заканчивается нуль-символом, на котором выполнение цикла while прервётся, так что ситуация с OOB исключена. По этой же причине и у стандартной функции strval() нет параметра "size".

В-шестых, параметр "ispacked" тоже не особо нужен, упакованность строки можно проверить и внутри самой функции.

И, наконец, в-седьмых, с помощью оператора __emit вычитание кода символа "0" можно записать так:

add.c (-'0')

, т.е. без загрузки значения в ALT, благодаря чему не нужно лишний раз сохранять другое значение из PRI в стек.

В итоге у меня получилась такая функция:

stock ulong:ulong_strval(const str[])
{
new const bool:packed = (str[0] & ~0xFF != 0);
new ulong:result = ulong:0;
new pos = 0;
new c;
while ('0' <= (c = (packed ? str{pos} : str[pos])) <= '9') {
__emit load.s.pri result;
__emit const.alt 10;
__emit umul;
__emit move.alt;
__emit load.s.pri c;
__emit add.c (-'0');
__emit add;
__emit stor.s.pri result;
pos++;
}
return result;
}



А что ты ожидал? =)
Подсветка работает на простой замене текста, ибо полноценный анализ синтаксиса => неоправданная нагрузка на сервер (либо на клиент, если делать клиент-сайдом на js).

"давно я не писал на pawn, попробую написать." =) я знал, что ты это исправишь, спасибо.