perlapio
СОДЕРЖАНИЕ
НАЗВАНИЕ
perlapio - интерфейс абстракции ввода-вывода Perl.
СИНТАКСИС
#define PERLIO_NOT_STDIO 0 /* For co-existence with stdio only */
#include <perlio.h> /* Usually via #include <perl.h> */
PerlIO *PerlIO_stdin(void);
PerlIO *PerlIO_stdout(void);
PerlIO *PerlIO_stderr(void);
PerlIO *PerlIO_open(const char *path,const char *mode);
PerlIO *PerlIO_fdopen(int fd, const char *mode);
PerlIO *PerlIO_reopen(const char *path, /* deprecated */
const char *mode, PerlIO *old);
int PerlIO_close(PerlIO *f);
int PerlIO_stdoutf(const char *fmt,...)
int PerlIO_puts(PerlIO *f,const char *string);
int PerlIO_putc(PerlIO *f,int ch);
SSize_t PerlIO_write(PerlIO *f,const void *buf,size_t numbytes);
int PerlIO_printf(PerlIO *f, const char *fmt,...);
int PerlIO_vprintf(PerlIO *f, const char *fmt, va_list args);
int PerlIO_flush(PerlIO *f);
int PerlIO_eof(PerlIO *f);
int PerlIO_error(PerlIO *f);
void PerlIO_clearerr(PerlIO *f);
int PerlIO_getc(PerlIO *d);
int PerlIO_ungetc(PerlIO *f,int ch);
SSize_t PerlIO_read(PerlIO *f, void *buf, size_t numbytes);
int PerlIO_fileno(PerlIO *f);
void PerlIO_setlinebuf(PerlIO *f);
Off_t PerlIO_tell(PerlIO *f);
int PerlIO_seek(PerlIO *f, Off_t offset, int whence);
void PerlIO_rewind(PerlIO *f);
int PerlIO_getpos(PerlIO *f, SV *save); /* prototype changed */
int PerlIO_setpos(PerlIO *f, SV *saved); /* prototype changed */
int PerlIO_fast_gets(PerlIO *f);
int PerlIO_has_cntptr(PerlIO *f);
SSize_t PerlIO_get_cnt(PerlIO *f);
char *PerlIO_get_ptr(PerlIO *f);
void PerlIO_set_ptrcnt(PerlIO *f, char *ptr, SSize_t count);
int PerlIO_canset_cnt(PerlIO *f); /* deprecated */
void PerlIO_set_cnt(PerlIO *f, int count); /* deprecated */
int PerlIO_has_base(PerlIO *f);
char *PerlIO_get_base(PerlIO *f);
SSize_t PerlIO_get_bufsiz(PerlIO *f);
PerlIO *PerlIO_importFILE(FILE *stdio, const char *mode);
FILE *PerlIO_exportFILE(PerlIO *f, const char *mode);
FILE *PerlIO_findFILE(PerlIO *f);
void PerlIO_releaseFILE(PerlIO *f,FILE *stdio);
int PerlIO_apply_layers(PerlIO *f, const char *mode,
const char *layers);
int PerlIO_binmode(PerlIO *f, int ptype, int imode,
const char *layers);
void PerlIO_debug(const char *fmt,...) ОПИСАНИЕ
Исходный код Perl и расширения, требующие максимальной переносимости, должны использовать вышеперечисленные функции вместо функций, определенных в ANSI C's stdio.h. Заголовки Perl (в частности, "perlio.h") #define их к механизму ввода-вывода, выбранному на этапе конфигурации.
Функции моделируются по функциям из stdio.h, но порядок параметров был немного "приведён в порядок".
PerlIO * заменяет FILE *. Как и FILE *, его следует рассматривать как непрозрачный (вероятно, безопасно предположить, что это указатель на что-то).
В настоящее время существуют две реализации:
- 1. USE_STDIO
-
Все вышеперечисленные функции определены через функции stdio или являются тривиальными оберточными функциями, которые вызывают stdio. В этом случае только PerlIO * является FILE *. Это была реализация по умолчанию с момента введения абстракции в perl5.003_02.
- 2. USE_PERLIO
-
Представленная сразу после perl5.7.0, это пере реализация вышеупомянутой абстракции, которая позволяет perl больше контролировать то, как выполняется ввод-вывод, так как она отвязывает ввод-вывод от того, как операционная система и библиотека C выбирают это делать. Для USE_PERLIO PerlIO * имеет дополнительный уровень косвенности - это указатель на указатель. Это позволяет PerlIO * сохранять известное значение, в то время как реализация меняется во время выполнения. В этом случае все вышеперечисленное являются истинными (но очень простыми) функциями, которые вызывают базовую реализацию.
Эта реализация является единственной, для которой
PerlIO_apply_layers()делает что-то «интересное».Реализация USE_PERLIO описана в perliol.
Поскольку "perlio.h" является тонким слоем (для повышения эффективности), семантика этих функций в некоторой степени зависит от базовой реализации. Там, где эти отличия понятны, они указаны ниже.
Если не указано иное, функции возвращают 0 при успехе или отрицательное значение (обычно EOF которое обычно равно -1) и устанавливают errno при ошибке.
- PerlIO_stdin(), PerlIO_stdout(), PerlIO_stderr()
-
Используйте их вместо
stdin,stdout,stderr. Они написаны так, чтобы выглядеть как «вызовы функций», а не как переменные, потому что это упрощает превращение их в вызовы функций, если платформа не может экспортировать данные загруженным модулям или если (скажем) различные «потоки» могут иметь разные значения. - PerlIO_open(path, mode), PerlIO_fdopen(fd,mode)
-
Они соответствуют fopen()/fdopen(), и аргументы одинаковы. Возвращает
NULLи устанавливаетerrnoпри ошибке. Может быть ограничение по количеству открытых дескрипторов, которое может быть меньше лимита на количество открытых файлов -errnoможет не быть установлено, когдаNULLвозвращается, если этот лимит превышен. - PerlIO_reopen(path,mode,f)
-
Хотя в настоящее время это существует в обеих реализациях, сам perl его не использует. Так как perl не использует его, он не хорошо протестирован.
Perl предпочитает
dupновый низкоуровневый дескриптор дескриптору, используемому существующим PerlIO. В будущем это может стать поведением этой функции. - PerlIO_printf(f,fmt,...), PerlIO_vprintf(f,fmt,a)
-
Эти функции эквивалентны fprintf()/vfprintf().
- PerlIO_stdoutf(fmt,...)
-
Это эквивалент printf(). printf определён через эту функцию, поэтому (в настоящее время) разрешается использовать
printf(fmt,...)в исходных кодах perl. - PerlIO_read(f,buf,count), PerlIO_write(f,buf,count)
-
Функционально они соответствуют fread() и fwrite(), но аргументы и возвращаемые значения отличаются. Подписи PerlIO_read() и PerlIO_write() были смоделированы по более разумным низкоуровневым функциям read() и write(): аргумент «файл» передаётся первым, есть только один «count», и возвращаемое значение может различать ошибку и
EOF.Возвращает количество байтов при успехе (которое может быть нулём или положительным), возвращает отрицательное значение и устанавливает
errnoпри ошибке. В зависимости от реализацииerrnoможет бытьEINTRесли операция была прервана сигналом. - PerlIO_close(f)
-
В зависимости от реализации
errnoможет бытьEINTRесли операция была прервана сигналом. - PerlIO_puts(f,s), PerlIO_putc(f,c)
-
Они соответствуют fputs() и fputc(). Обратите внимание, что аргументы были пересмотрены, чтобы иметь «файл» первым.
- PerlIO_ungetc(f,c)
-
Это соответствует ungetc(). Обратите внимание, что аргументы были пересмотрены, чтобы иметь «файл» первым. Организует, чтобы следующая операция чтения вернула байт c. Несмотря на подразумеваемый «символ» в названии, определены только значения в диапазоне 0..0xFF. Возвращает байт c при успехе или -1 (
EOF) при ошибке. Количество байтов, которые могут быть «возвращены назад», может меняться, только 1 символ является определённым, и только если это последний символ, который был прочитан из потока. - PerlIO_getc(f)
-
Это соответствует getc(). Несмотря на c в названии, поддерживается только диапазон байтов 0..0xFF. Возвращает прочитанный символ или -1 (
EOF) при ошибке. - PerlIO_eof(f)
-
Это соответствует feof(). Возвращает true/false, указывающее, находится ли поток в конце файла. Для устройств терминала это может быть или не быть «прилипчивым» в зависимости от реализации. Флаг очищается функциями PerlIO_seek() или PerlIO_rewind().
- PerlIO_error(f)
-
Это соответствует ferror(). Возвращает true/false, указывающее, была ли ошибка ввода-вывода в потоке.
- PerlIO_fileno(f)
-
Это соответствует fileno(), обратите внимание, что на некоторых платформах значение «fileno» может не совпадать с Unix. Возвращает -1, если у потока нет связанного с ним дескриптора.
- PerlIO_clearerr(f)
-
Это соответствует clearerr(), т.е. очищает флаги «ошибка» и (обычно) «eof» для «потока». Не возвращает значение.
- PerlIO_flush(f)
-
Это соответствует fflush(). Отправляет все буферизованные данные записи в базовый файл. Если вызвана с
NULL, это может сбросить все открытые потоки (или привести к сбою ядра с некоторыми реализациями USE_STDIO). Вызов для потока, открытого только для чтения, или для которого последняя операция была чтением, может привести к неопределённому поведению в некоторых реализациях USE_STDIO. Реализация USE_PERLIO (слоёв) пытается вести себя лучше: она сбрасывает все открытые потоки при передачеNULL, и пытается сохранить данные в потоках чтения либо в буфере, либо с помощью перемещения указателя потока к текущему логическому положению. - PerlIO_seek(f,offset,whence)
-
Это соответствует fseek(). Отправляет буферизованные данные записи в базовый файл или отбрасывает буферизованные данные чтения, затем устанавливает дескриптор файла по указанным offset и whence (sic). Это правильное действие при переключении между чтением и записью в одном и том же потоке (см. проблемы с PerlIO_flush() выше). Смещение имеет тип
Off_t, что является значением конфигурации perl, которое может не совпадать со значениемoff_tstdio. - PerlIO_tell(f)
-
Это соответствует ftell(). Возвращает текущую позицию файла или (Off_t) -1 при ошибке. Может просто вернуть значение, которое система «знает», не выполняя системный вызов или не проверяя базовый дескриптор файла (поэтому использование на общих дескрипторах не безопасно без PerlIO_seek()). Возвращаемое значение имеет тип
Off_t, который является значением конфигурации perl, которое может не совпадать со значениемoff_tstdio. - PerlIO_getpos(f,p), PerlIO_setpos(f,p)
-
Они (с некоторыми оговорками) соответствуют fgetpos() и fsetpos(). Вместо Fpos_t stdio они ожидают «Perl Scalar Value». Содержимое этой переменной следует рассматривать как непрозрачные данные. Формат данных может различаться от потока к потоку. При отсутствии stdio или если на платформе отсутствуют stdio-вызовы, они реализуются через PerlIO_tell() и PerlIO_seek().
- PerlIO_rewind(f)
-
Это соответствует rewind(). Обычно оно определяется как
PerlIO_seek(f,(Off_t)0L, SEEK_SET); PerlIO_clearerr(f); - PerlIO_tmpfile()
-
Это соответствует tmpfile(), т.е. возвращает анонимный PerlIO или NULL при ошибке. Система попытается автоматически удалить файл при закрытии. В Unix файл обычно
unlinkсразу после создания, поэтому неважно, как он закрывается. На других системах файл может быть удалён только при закрытии через PerlIO_close() и/или завершении программы с помощьюexit. В зависимости от реализации могут быть «гонки», которые позволяют другим процессам получить доступ к файлу, хотя, как правило, он будет безопаснее в этом отношении, чем самодельные схемы. - PerlIO_setlinebuf(f)
-
Это соответствует setlinebuf(). Не возвращает значение. Что считается «строкой», зависит от реализации, но обычно означает, что запись «\n» сбрасывает буфер. Что происходит с такими вещами, как «это\nто», не определено. (Perl core использует его только при «выводе»; это никак не связано с автоматическим сбросом $|.)
Совместное использование с stdio
Существует начальная поддержка совместного использования PerlIO с stdio. Очевидно, что если PerlIO реализован через stdio, проблем нет. Однако в других случаях должны существовать механизмы для создания FILE *, который можно передать коду библиотеки, который будет использовать stdio-вызовы.
Первый шаг - добавить эту строку:
#define PERLIO_NOT_STDIO 0 до включения любых заголовков perl. (Вероятно, это станет значением по умолчанию в какой-то момент). Это предотвращает попытку "perlio.h" определения функций stdio через функции PerlIO.
Код XS, вероятно, лучше использовать «typemap», если он ожидает аргументы FILE *. Стандартный typemap будет изменён для понимания любых изменений в этой области.
- PerlIO_importFILE(f,mode)
-
Используется для получения PerlIO * из FILE *.
Аргумент mode должен быть строкой, как и при передаче в fopen/PerlIO_open. Если он равен NULL, то — для поддержки старых версий — код попытается (в зависимости от платформы и реализации) эмпирически определить режим открытия f или использовать "r+" для обозначения потока чтения/записи.
После вызова FILE * следует ТОЛЬКО закрывать, вызывая
PerlIO_close()на возвращённом PerlIO *.PerlIO устанавливается в текстовый режим. Используйте PerlIO_binmode, если требуется другой режим.
Это не обратное преобразование PerlIO_exportFILE().
- PerlIO_exportFILE(f,mode)
-
Дано PerlIO *, создать «родной» FILE *, подходящий для передачи коду, ожидающему компиляцию и связывание с ANSI C stdio.h. Аргумент mode должен быть строкой, как при передаче в fopen/PerlIO_open. Если он равен NULL, то — для поддержки старых версий — FILE * открывается в том же режиме, что и PerlIO *.
Факт, что такой FILE * был «экспортирован», регистрируется (обычно путём добавления нового «слоя» :stdio к PerlIO *), что может повлиять на будущие операции PerlIO над исходным PerlIO *. Не следует вызывать
fclose()на файле, если не вызватьPerlIO_releaseFILE()для разъединения его от PerlIO *. (Не используйте PerlIO_importFILE() для разъединения.)Повторный вызов этой функции создаст FILE * на каждом вызове (и добавит слой :stdio каждый раз).
- PerlIO_releaseFILE(p,f)
-
Вызов PerlIO_releaseFILE сообщает PerlIO, что все использование FILE * завершено. Он удаляется из списка «экспортированных» FILE *, и связанный PerlIO * должен вернуться к своему исходному поведению.
Используйте это для разъединения файла от PerlIO *, который был связан с помощью PerlIO_exportFILE().
- PerlIO_findFILE(f)
-
Возвращает «родной» FILE *, используемый слоем stdio. Если такового нет, он создаётся с помощью PerlIO_exportFILE. В любом случае FILE * следует считать принадлежащим подсистеме PerlIO и закрывать только вызовом
PerlIO_close().
Функции «быстрого чтения строк»
В дополнение к стандартному API, определённому выше, существует интерфейс «реализации», который позволяет Perl получить доступ к внутренностям PerlIO. Следующие вызовы соответствуют различным макросам FILE_xxx, определяемым Configure — или их эквивалентам в других реализациях. Этот раздел интересен только тем, кто интересуется подробным поведением Perl-ядра, реализацией сопоставления PerlIO или разработкой кода, который может использовать «предварительное чтение», выполненное системой ввода-вывода так же, как и Perl. Обратите внимание, что любой код, использующий эти интерфейсы, должен быть готов выполнять операции традиционным способом, если дескриптор не поддерживает их.
- PerlIO_fast_gets(f)
-
Возвращает true, если реализация имеет все необходимые интерфейсы, чтобы позволить Perl's
sv_gets«обойти» механизм ввода-вывода. Это может различаться в зависимости от дескриптора.PerlIO_fast_gets(f) = PerlIO_has_cntptr(f) && \ PerlIO_canset_cnt(f) && \ 'Can set pointer into buffer' - PerlIO_has_cntptr(f)
-
Реализация может вернуть указатель на текущую позицию в «буфере» и количество доступных байтов в буфере. Не используйте это — используйте PerlIO_fast_gets.
- PerlIO_get_cnt(f)
-
Возвращает количество читаемых байтов в буфере. Ноль или отрицательное значение означает, что больше байтов недоступно.
- PerlIO_get_ptr(f)
-
Возвращает указатель на следующий читаемый байт в буфере. Доступ к данным через указатель (разыменование) безопасен только если PerlIO_get_cnt() вернуло положительное значение. Разрешены только положительные смещения до значения, возвращённого PerlIO_get_cnt().
- PerlIO_set_ptrcnt(f,p,c)
-
Устанавливает указатель в буфер и количество байтов, ещё находящихся в буфере. Следует использовать только для установки указателя в диапазон, определённый предыдущими вызовами
PerlIO_get_ptrиPerlIO_get_cnt. Два значения должны быть согласованы (реализация может использовать только одно или другое, или требовать обоих). - PerlIO_canset_cnt(f)
-
Реализация может скорректировать своё представление о количестве байтов в буфере. Не используйте это — используйте PerlIO_fast_gets.
- PerlIO_set_cnt(f,c)
-
Неясно — устанавливает количество байтов в буфере. Устарело. Используется только если PerlIO_canset_cnt() возвращает true. В настоящее время используется только в doio.c для принудительного установления значения меньше -1 в -1. Возможно, следовало бы использовать PerlIO_set_empty или подобное. Этот вызов может фактически ничего не сделать, если «количество» выводится из указателя и «лимита». Не используйте это — используйте PerlIO_set_ptrcnt().
- PerlIO_has_base(f)
-
Возвращает true, если реализация имеет буфер и может вернуть указатель на весь буфер и его размер. Используется Perl для тестов -T / -B. Другие применения будут очень необычными…
- PerlIO_get_base(f)
-
Возвращает начало буфера. Доступ только к положительным смещениям в буфере до значения, возвращённого PerlIO_get_bufsiz().
- PerlIO_get_bufsiz(f)
-
Возвращает общее количество байтов в буфере. Это ни количество, которое можно прочитать, ни объём памяти, выделенной под буфер. Скорее, это то, что операционная система и/или реализация сделали
read()(или что-то подобное) в последний раз, когда был запрошен ввод-вывод.
Другие функции
- PerlIO_apply_layers(f,mode,layers)
-
Новый интерфейс для реализации USE_PERLIO. Слои ":crlf" и ":raw" — единственные разрешённые для других реализаций, и они игнорируются. (Начиная с perl5.8 ":raw" устарела.) Используйте PerlIO_binmode() ниже для портативного случая.
- PerlIO_binmode(f,ptype,imode,layers)
-
Обработчик, используемый Perl's оператором
binmode. ptype — символ Perl для типа ввода-вывода:- Чтение '<'
- Запись '>'
- Чтение/запись '+'
imode —
O_BINARYилиO_TEXT.layers — строка слоёв для применения, только ":crlf" имеет смысл в случае без USE_PERLIO. (Начиная с perl5.8 ":raw" устарела в пользу передачи NULL.)
Портативные случаи:
PerlIO_binmode(f,ptype,O_BINARY,NULL); and PerlIO_binmode(f,ptype,O_TEXT,":crlf");В Unix эти вызовы, вероятно, не оказывают никакого влияния. В других случаях они изменяют перевод "\n" на CR,LF и, возможно, вызывают запись или учёт специального текстового индикатора «конец файла» при чтении. Эффект вызова после выполнения любых операций ввода-вывода с дескриптором зависит от реализации. (Он может быть проигнорирован, повлиять на любые данные, которые уже буферизованы, или применяться только к последующим данным.)
- PerlIO_debug(fmt,...)
-
PerlIO_debug — функция типа printf(), которая может использоваться для отладки. Не возвращает значения. Основное применение — внутри PerlIO, где использование реальных printf, warn() и т. п. вызывало бы рекурсивный вызов PerlIO и было бы проблемой.
PerlIO_debug записывает в файл, указанный в $ENV{'PERLIO_DEBUG'} или по умолчанию в stderr, если переменная окружения не определена. Типичное использование может быть
Bourne shells (sh, ksh, bash, zsh, ash, ...): PERLIO_DEBUG=/tmp/perliodebug.log ./perl -Di somescript some args Csh/Tcsh: setenv PERLIO_DEBUG /tmp/perliodebug.log ./perl -Di somescript some args If you have the "env" utility: env PERLIO_DEBUG=/tmp/perliodebug.log ./perl -Di somescript args Win32: set PERLIO_DEBUG=perliodebug.log perl -Di somescript some argsВ Perl, скомпилированном без
-DDEBUGGING, или когда-Diне указана в командной строке, или при наличии проверки целостности, PerlIO_debug() — это пустая операция.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/perlapio