rktio: further improve header declarations

Also, add variants of `rktio_read` and `rktio_write` that can be more
convenient to use through an FFI.
This commit is contained in:
Matthew Flatt 2017-06-23 19:50:19 -06:00
parent 316df0af7a
commit 990a1d7154
3 changed files with 188 additions and 53 deletions

View File

@ -1,10 +1,32 @@
#lang racket/base
(require racket/cmdline
racket/pretty
racket/list
racket/match
parser-tools/lex
(prefix-in : parser-tools/lex-sre)
parser-tools/yacc)
;; Parse "rktio.h" to produce a seqeuence
;; (define-constant <id> <const>) ...
;; <type-def> ...
;; <func-def> ...
;;
;; where
;; <type-def> = (define-type <id> <id>)
;; | (define-struct-type <id> ([<type> <name>] ...))
;;
;; <func-def> = (define-function <type> <id> ([<type> <arg-name>] ...))
;; => never fails
;; | (define-function/errno <err-v> <type> <id> ([<type> <arg-name>] ...))
;; => fails when result equals <err-v>
;; | (define-function/errno+step <err-v> <type> <id> ([<type> <arg-name>] ...))
;; => fails when result equals <err-v>, keep step
;;
;; <type> = <prim-type>
;; | (ref <type>) ; opaque, needs to be deallocated somehow
;; | (* <type>) ; transparent argument, can be represented by a byte string
(define output-file #f)
(define input-file
@ -22,7 +44,7 @@
(define-empty-tokens delim-tokens
(EOF WHITESPACE
OPEN CLOSE COPEN CCLOSE SEMI COMMA STAR LSHIFT EQUAL
__RKTIO_H__ EXTERN EXTERN/NOERR EXTERN/STEP
__RKTIO_H__ EXTERN EXTERN/NOERR EXTERN/STEP EXTERN/ERR
DEFINE TYPEDEF ENUM STRUCT VOID UNSIGNED SHORT INT CONST))
(define lex
@ -50,6 +72,7 @@
["RKTIO_EXTERN" 'EXTERN]
["RKTIO_EXTERN_NOERR" 'EXTERN/NOERR]
["RKTIO_EXTERN_STEP" 'EXTERN/STEP]
["RKTIO_EXTERN_ERR" 'EXTERN/ERR]
[(:seq (:or #\_ (:/ #\A #\Z #\a #\z))
(:* (:or #\_ (:/ #\A #\Z #\a #\z #\0 #\9))))
(token-ID (string->symbol lexeme))]
@ -77,11 +100,12 @@
(grammar
(<prog> [() null]
[(<decl> <prog>) (cons $1 $2)])
(<decl> [(DEFINE ID <expr>) `(define ,$2 ,$3)]
(<decl> [(DEFINE ID <expr>) `(define-constant ,$2 ,$3)]
[(DEFINE __RKTIO_H__ <expr>) #f]
[(DEFINE EXTERN ID) #f]
[(DEFINE EXTERN/NOERR EXTERN) #f]
[(DEFINE EXTERN/STEP EXTERN) #f]
[(DEFINE EXTERN/ERR OPEN ID CLOSE EXTERN) #f]
[(STRUCT ID SEMI) #f]
[(TYPEDEF <type> <id> SEMI)
(if (eq? $2 $3)
@ -92,12 +116,14 @@
`(define-struct-type ,$2 ,$4)
(error 'parse "typedef struct names don't match at ~s" $5))]
[(<extern> <return-type> <id> OPEN <params> SEMI)
(let ([r-type (shift-stars $3 $2)])
`(,(adjust-errno $1 r-type) ,r-type ,(unstar $3) ,$5))]
(let ([r-type (shift-stars $3 $2)]
[id (unstar $3)])
`(,@(adjust-errno $1 r-type id) ,r-type ,id ,$5))]
[(ENUM COPEN <enumeration> SEMI) `(begin . ,(enum-definitions $3))])
(<extern> [(EXTERN) 'define-function/errno]
[(EXTERN/STEP) 'define-function/errno+step]
[(EXTERN/NOERR) 'define-function])
[(EXTERN/NOERR) 'define-function]
[(EXTERN/ERR OPEN ID CLOSE) `(define-function/errno ,$3)])
(<params> [(VOID CLOSE) null]
[(<paramlist>) $1])
(<paramlist> [(<type> <id> CLOSE) `((,(shift-stars $2 $1) ,(unstar $2)))]
@ -130,11 +156,15 @@
[(STRUCT ID) $2])
(<return-type> [(<type>) $1]))))
(define (adjust-errno def-kind r)
(define (adjust-errno def-kind r id)
(cond
[(eq? r 'rktio_bool_t) 'define-function]
[(eq? r 'void) 'define-function]
[else def-kind]))
[(eq? id 'rktio_init) '(define-function)] ; init is special, because we can't get an error
[(eq? r 'rktio_bool_t) '(define-function)]
[(eq? r 'void) '(define-function)]
[(pair? def-kind) def-kind]
[(pair? r) '(define-function/errno NULL)]
[(eq? r 'rktio_ok_t) '(define-function/errno #f)]
[else (list def-kind)]))
(define (shift-stars from to)
(if (and (pair? from)
@ -155,16 +185,16 @@
[(pair? (car l))
(let ([i (cadar l)])
(cons
`(define ,(caar l) ,i)
`(define-constant ,(caar l) ,i)
(loop (cdr l) (add1 i))))]
[else
(cons
`(define ,(car l) ,i)
`(define-constant ,(car l) ,i)
(loop (cdr l) (add1 i)))])))
;; ----------------------------------------
(define content
(define unsorted-unflattened-content
(call-with-input-file input-file
(lambda (i)
(port-count-lines! i)
@ -175,14 +205,84 @@
[(eq? (position-token-token v) 'WHITESPACE) (loop)]
[else v]))))))))
(define unsorted-content
(for*/list ([l (in-list unsorted-unflattened-content)]
[e (in-list (if (and (pair? l)
(eq? 'begin (car l)))
(cdr l)
(list l)))])
e))
(define (constant-defn? e)
(and (pair? e)
(eq? (car e) 'define-constant)))
(define (type-defn? e)
(and (pair? e)
(or (eq? (car e) 'define-type)
(eq? (car e) 'define-struct-type))))
(define constant-content
(filter constant-defn? unsorted-content))
(define type-content
(filter type-defn? unsorted-content))
(define defined-types
(let ([ht (for/hash ([e (in-list type-content)])
(values (cadr e) #t))])
(for/fold ([ht ht]) ([t (in-list '(char int unsigned-short
intptr_t rktio_int64_t))])
(hash-set ht t #t))))
;; A pointer to a defined type in an argument position
;; is transparent, and it make sense to pass a byte
;; string directly (possibly to be filled in).
;; A pointer to an undefined type is opaque, and a pointer
;; to a defined type is "opaque" in a result position in
;; the sense that it should be explicitly dereferenced and
;; explicitly freed.
(define (update-type t #:as-argument? [as-argument? #f])
(cond
[(and (pair? t) (eq? (car t) '*))
(let ([s (update-type (cadr t))])
(if (and as-argument?
(or (pair? s)
(hash-ref defined-types s #f)))
`(* ,s)
`(ref ,s)))]
[else t]))
(define (update-bind a #:as-argument? [as-argument? #f])
`(,(update-type (car a) #:as-argument? as-argument?) ,(cadr a)))
(define (update-types e)
(match e
[`(,def ,ret ,name ,args)
`(,def ,(update-type ret) ,name
,(map (lambda (a) (update-bind a #:as-argument? #t)) args))]
[else e]))
(define (update-type-types e)
(match e
[`(define-struct-type ,name ,fields)
`(define-struct-type ,name ,(map update-bind fields))]
[else e]))
(define content
(append
constant-content
(map update-type-types type-content)
(map update-types
(filter (lambda (e) (not (or (constant-defn? e) (type-defn? e))))
unsorted-content))))
(define (show-content)
(printf "(begin\n")
(for ([e (in-list content)]
#:when e)
(if (and (pair? e)
(eq? 'begin (car e)))
(for ([e (in-list (cdr e))])
(pretty-write e))
(pretty-write e))))
(pretty-write e))
(printf ")\n"))
(if output-file
(with-output-to-file output-file

View File

@ -30,9 +30,10 @@ Return type conventions:
- A return type `rktio_tri_t` (alias for `int`) means that 0 is
returned for an expected failuree, some `RKTIO_...` (alias for 1)
is returned for success, and `RKTIO_...ERROR` (alias for -2) is
returned for some error. Use `rktio_get_last_error_kind` and
`rktio_get_last_error` for more information about a
`RKTIO_...ERROR` result.
returned for some error. The function will be annotated with
`RKTIO_EXTERN_ERR(...)` to indicate the error value. Use
`rktio_get_last_error_kind` and `rktio_get_last_error` for more
information about a `RKTIO_...ERROR` result.
- A return type `rktio_bool_t` means that the result is a simple 0 or
1, and no error is possible.
@ -82,8 +83,9 @@ Thread and signal conventions:
# define RKTIO_EXTERN extern
#endif
#define RKTIO_EXTERN_NOERR RKTIO_EXTERN
#define RKTIO_EXTERN_STEP RKTIO_EXTERN
#define RKTIO_EXTERN_ERR(n) RKTIO_EXTERN
#define RKTIO_EXTERN_NOERR RKTIO_EXTERN
#define RKTIO_EXTERN_STEP RKTIO_EXTERN
/*************************************************/
/* Initialization and general datatypes */
@ -95,7 +97,9 @@ typedef struct rktio_t rktio_t;
RKTIO_EXTERN rktio_t *rktio_init(void);
/* Call `rktio_init` before anything else. The first call to
`rktio_init` must return before any additional calls (in other
threads), but there's no ordering requirement after that. */
threads), but there's no ordering requirement after that.
If the result is NULL, then there's no way to get an error
code, so assume `RKTIO_ERROR_INIT_FAILED`. */
RKTIO_EXTERN void rktio_destroy(rktio_t *rktio);
/* Call `rktio_destroy` as the last thing. Everything else must be
@ -232,7 +236,8 @@ RKTIO_EXTERN rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which);
#define RKTIO_STDOUT 1
#define RKTIO_STDERR 2
RKTIO_EXTERN intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
RKTIO_EXTERN_ERR(RKTIO_READ_ERROR)
intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
/* Returns the number of bytes read, possibly 0, in non-blocking mode.
Alternatively, the result can be `RKTIO_READ_EOF` for end-of-file
or `RKTIO_READ_ERROR` for an error. Although rktio_read is intended
@ -242,7 +247,8 @@ RKTIO_EXTERN intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, i
#define RKTIO_READ_EOF (-1)
#define RKTIO_READ_ERROR (-2)
RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *buffer, intptr_t len);
RKTIO_EXTERN_ERR(RKTIO_WRITE_ERROR)
intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *buffer, intptr_t len);
/* Returns the number of bytes written, possibly 0, in non-blocking
mode. Alternatively, the result can be `RKTIO_WRITE_ERROR` for an
error. Although `rktio_write` is intended to write only bytes that
@ -253,32 +259,45 @@ RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *bu
#define RKTIO_WRITE_ERROR (-2)
RKTIO_EXTERN intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len,
char *is_converted);
RKTIO_EXTERN_ERR(RKTIO_READ_ERROR)
intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len,
char *is_converted);
/* Like `rktio_read`, but also reports whether each character was
originally two characters that were converted to a single newline for
text mode. */
RKTIO_EXTERN_ERR(RKTIO_READ_ERROR)
intptr_t rktio_read_in(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t start, intptr_t end);
RKTIO_EXTERN_ERR(RKTIO_WRITE_ERROR)
intptr_t rktio_write_in(rktio_t *rktio, rktio_fd_t *fd, const char *buffer, intptr_t start, intptr_t end);
/* Like `rktio_read` and `rktio_write`, but accepting start and end
positions within `buffer`. */
RKTIO_EXTERN_NOERR intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd);
/* Reports the number of bytes that are buffered from the file descriptor.
The result is normally zero, but text-mode conversion and the rare
uncooperative corner of an OS can make the result 1 byte. */
RKTIO_EXTERN rktio_tri_t rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN rktio_tri_t rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd);
/* Each polling function returns one of the following: */
#define RKTIO_POLL_NOT_READY 0
#define RKTIO_POLL_READY 1
#define RKTIO_POLL_ERROR (-2)
RKTIO_EXTERN rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd);
/* See `rktio_write` above. Currently, the result is `RKTIO_POLL_NO_READY`
only on Windows, and only for a pipe or similar non-regular file.
A pipe counts as "flushed" when the other end has received the data
(because the sent data doesn't persist beyond closing the pipe). */
RKTIO_EXTERN rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl);
RKTIO_EXTERN rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN_ERR(RKTIO_LOCK_ERROR)
rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl);
RKTIO_EXTERN_ERR(RKTIO_LOCK_ERROR)
rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
/* Advisory file locks, where `excl` attempts to claim an exclusive
lock. Whether these work in various situations depend on many OS
details, where the differences involve promoting from non-exlcusive
@ -335,7 +354,8 @@ RKTIO_EXTERN rktio_addrinfo_lookup_t *rktio_start_addrinfo_lookup(rktio_t *rktio
#define RKTIO_FAMILY_ANY (-1)
RKTIO_EXTERN_NOERR int rktio_get_ipv4_family(rktio_t *rktio);
RKTIO_EXTERN rktio_tri_t rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_addrinfo_lookup_ready(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
/* Check whether an address is available for a lookup request. */
RKTIO_EXTERN rktio_addrinfo_t *rktio_addrinfo_lookup_get(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup);
@ -358,7 +378,8 @@ RKTIO_EXTERN rktio_listener_t *rktio_listen(rktio_t *rktio, rktio_addrinfo_t *lo
RKTIO_EXTERN void rktio_listen_stop(rktio_t *rktio, rktio_listener_t *l);
/* Stops a listener. */
RKTIO_EXTERN rktio_tri_t rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener);
/* Returns one of `RKTIO_POLL_READY`, etc. */
RKTIO_EXTERN rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener);
@ -377,7 +398,8 @@ RKTIO_EXTERN rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *c
RKTIO_EXTERN void rktio_connect_stop(rktio_t *rktio, rktio_connect_t *conn);
/* Stops a connection whose result or error has not been received. */
RKTIO_EXTERN rktio_tri_t rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_connect_ready(rktio_t *rktio, rktio_connect_t *conn);
/* Returns one of `RKTIO_POLL_READY`, etc. */
RKTIO_EXTERN rktio_fd_t *rktio_connect_trying(rktio_t *rktio, rktio_connect_t *conn);
@ -405,8 +427,9 @@ RKTIO_EXTERN rktio_ok_t rktio_udp_bind(rktio_t *rktio, rktio_fd_t *rfd, rktio_ad
rktio_bool_t reuse);
RKTIO_EXTERN rktio_ok_t rktio_udp_connect(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr);
RKTIO_EXTERN intptr_t rktio_udp_sendto(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr,
const char *buffer, intptr_t len);
RKTIO_EXTERN_ERR(RKTIO_WRITE_ERROR)
intptr_t rktio_udp_sendto(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr,
const char *buffer, intptr_t len);
/* Extends `rktio_write` to accept a destination `addr`, and binds `rfd` if it
is not bound aready. The `addr` can be NULL if the socket is connected. */
@ -421,10 +444,9 @@ RKTIO_EXTERN rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rkt
be `RKTIO_ERROR_TRY_AGAIN` or `RKTIO_ERROR_INFO_TRY_AGAIN`, where
the latter can happen if the sock claims to be ready to read. */
/* The following accessors return `RKTIO_PROP_ERROR` on failure */
RKTIO_EXTERN rktio_tri_t rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN_ERR(RKTIO_PROP_ERROR) rktio_tri_t rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN rktio_ok_t rktio_udp_set_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd, rktio_bool_t on);
RKTIO_EXTERN rktio_tri_t rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN_ERR(RKTIO_PROP_ERROR) rktio_tri_t rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd);
RKTIO_EXTERN rktio_ok_t rktio_udp_set_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd, int ttl_val);
#define RKTIO_PROP_ERROR (-2)
@ -487,7 +509,7 @@ RKTIO_EXTERN char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, c
RKTIO_EXTERN void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, const char *name, const char *value);
/* Access/update environment-variables record by name. */
RKTIO_EXTERN intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars);
RKTIO_EXTERN_NOERR intptr_t rktio_envvars_count(rktio_t *rktio, rktio_envvars_t *envvars);
RKTIO_EXTERN char *rktio_envvars_name_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i);
RKTIO_EXTERN char *rktio_envvars_value_ref(rktio_t *rktio, rktio_envvars_t *envvars, intptr_t i);
/* Access/update environment-variables record by index. */
@ -576,7 +598,8 @@ RKTIO_EXTERN rktio_fs_change_t *rktio_fs_change(rktio_t *rktio, const char *path
RKTIO_EXTERN void rktio_fs_change_forget(rktio_t *rktio, rktio_fs_change_t *fc);
RKTIO_EXTERN rktio_tri_t rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc);
RKTIO_EXTERN_ERR(RKTIO_POLL_ERROR)
rktio_tri_t rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc);
/* Returns one of `RKTIO_POLL_READY`, etc. */
/*************************************************/
@ -703,7 +726,7 @@ RKTIO_EXTERN rktio_bool_t rktio_directory_exists(rktio_t *rktio, const char *dir
RKTIO_EXTERN rktio_bool_t rktio_link_exists(rktio_t *rktio, const char *filename);
RKTIO_EXTERN rktio_bool_t rktio_is_regular_file(rktio_t *rktio, const char *filename);
RKTIO_EXTERN rktio_ok_t rktio_delete_file(rktio_t *rktio, const char *fn, int enable_write_on_fail);
RKTIO_EXTERN rktio_ok_t rktio_delete_file(rktio_t *rktio, const char *fn, rktio_bool_t enable_write_on_fail);
RKTIO_EXTERN rktio_ok_t rktio_rename_file(rktio_t *rktio, const char *dest, const char *src, int exists_ok);
/* Can report `RKTIO_ERROR_EXISTS`. */
@ -757,7 +780,8 @@ RKTIO_EXTERN rktio_identity_t *rktio_path_identity(rktio_t *rktio, const char *p
#define RKTIO_PERMISSION_ERROR (-1)
RKTIO_EXTERN int rktio_get_file_or_directory_permissions(rktio_t *rktio, const char *filename, int all_bits);
RKTIO_EXTERN_ERR(RKTIO_PERMISSION_ERROR)
int rktio_get_file_or_directory_permissions(rktio_t *rktio, const char *filename, int all_bits);
/* Result is `RKTIO_PERMISSION_ERROR` for error, otherwise a combination of
bits. If not `all_bits`, then use constants above. */
@ -973,10 +997,11 @@ RKTIO_EXTERN rktio_converter_t *rktio_converter_open(rktio_t *rktio, const char
RKTIO_EXTERN void rktio_converter_close(rktio_t *rktio, rktio_converter_t *cvt);
/* Destroys an encoding converter. */
RKTIO_EXTERN intptr_t rktio_convert(rktio_t *rktio,
rktio_converter_t *cvt,
char **in, intptr_t *in_left,
char **out, intptr_t *out_left);
RKTIO_EXTERN_ERR(RKTIO_CONVERT_ERROR)
intptr_t rktio_convert(rktio_t *rktio,
rktio_converter_t *cvt,
char **in, intptr_t *in_left,
char **out, intptr_t *out_left);
/* Converts some bytes, following the icon protocol: each consumed by
increments `*in` and decrements `*in_left`, and each produced by
increments `*out` and decrements `*out_left`. In case of an error,
@ -1005,15 +1030,15 @@ RKTIO_EXTERN rktio_char16_t *rktio_recase_utf16(rktio_t *rktio,
Takes and optionally returns a length (`olen` can be NULL), but the
UTF-16 sequence is expected to have no nuls. */
RKTIO_EXTERN int rktio_locale_strcoll(rktio_t *rktio, char *s1, char *s2);
RKTIO_EXTERN_NOERR int rktio_locale_strcoll(rktio_t *rktio, char *s1, char *s2);
/* Returns -1 if `s1` is less than `s2` by the current locale's
comparison, positive is `s1` is greater, and 0 if the strings
are equal. */
RKTIO_EXTERN int rktio_strcoll_utf16(rktio_t *rktio,
rktio_char16_t *s1, intptr_t l1,
rktio_char16_t *s2, intptr_t l2,
rktio_bool_t cvt_case);
RKTIO_EXTERN_NOERR int rktio_strcoll_utf16(rktio_t *rktio,
rktio_char16_t *s1, intptr_t l1,
rktio_char16_t *s2, intptr_t l2,
rktio_bool_t cvt_case);
/* Compares two strings encoded in UTF-16 for the system's default
locale if the OS provided direct support for it. The
`RKTIO_CONVERT_STRCOLL_UTF16 property from

View File

@ -853,6 +853,16 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
return rktio_read_converted(rktio, rfd, buffer, len, NULL);
}
intptr_t rktio_read_in(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t start, intptr_t end)
{
return rktio_read_converted(rktio, rfd, buffer+start, end-start, NULL);
}
intptr_t rktio_write_in(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr_t start, intptr_t end)
{
return rktio_write(rktio, rfd, buffer+start, end-start);
}
RKTIO_EXTERN intptr_t rktio_buffered_byte_count(rktio_t *rktio, rktio_fd_t *fd)
{
#ifdef RKTIO_SYSTEM_UNIX