1 /* port.h -*- mode:c; coding:utf-8; -*- 2 * 3 * Copyright (c) 2010-2021 Takashi Kato <ktakashi@ymail.com> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: $ 29 */ 30 #ifndef SAGITTARIUS_PRIVATE_PORT_H_ 31 #define SAGITTARIUS_PRIVATE_PORT_H_ 32 33 #include "sagittariusdefs.h" 34 #include "thread.h" 35 #include "clos.h" 36 #include "file.h" 37 #include "vm.h" 38 #include "system.h" 39 40 typedef enum SgFileLockType SgPortLockType; 41 42 typedef enum { 43 SG_INPUT_PORT = 1UL, 44 SG_OUTPUT_PORT = 1UL<<1, 45 SG_IN_OUT_PORT = SG_INPUT_PORT | SG_OUTPUT_PORT, 46 /* input/output port + alpha */ 47 SG_BIDIRECTIONAL_PORT = 1UL<<2 | SG_IN_OUT_PORT 48 } SgPortDirection; 49 50 typedef enum { 51 SG_PORT_OPEN = 0, 52 SG_PORT_PSEUDO = 1, 53 SG_PORT_CLOSED = 2 54 } SgPortClosedType; 55 56 #define SG_STREAM_BUFFER_SIZE 32 57 58 #define SG_MAKE_STREAM_BUFFER(type, data) \ 59 typedef struct type##_rec \ 60 { \ 61 int position; \ 62 data buf[SG_STREAM_BUFFER_SIZE]; \ 63 struct type##_rec *next; \ 64 } type; 65 66 SG_MAKE_STREAM_BUFFER(byte_buffer, uint8_t); 67 SG_MAKE_STREAM_BUFFER(char_buffer, SgChar); 68 69 #define SG_STREAM_BUFFER_PUT_REC(type, r, _buf, c) \ 70 do { \ 71 type *__tmp = (_buf); \ 72 if (__tmp->position >= SG_STREAM_BUFFER_SIZE) { \ 73 if (__tmp->next == NULL) { \ 74 __tmp->next = SG_NEW(type); \ 75 } \ 76 __tmp->next->position = 0; \ 77 (r) = __tmp = __tmp->next; \ 78 } \ 79 __tmp->buf[__tmp->position++] = (c); \ 80 } while(0) 81 82 #define SG_STREAM_BUFFER_PUTB(r, buf, b) \ 83 SG_STREAM_BUFFER_PUT_REC(byte_buffer, r, buf, b) 84 #define SG_STREAM_BUFFER_PUTC(r, buf, c) \ 85 SG_STREAM_BUFFER_PUT_REC(char_buffer, r, buf, c) 86 87 88 #define SG_STREAM_BUFFER_COUNT_REC(type, r, start) \ 89 do { \ 90 type *__t = (start); \ 91 for ((r)=0;__t && __t &&__t->next; __t=__t->next,(r)++); \ 92 (r) *= SG_STREAM_BUFFER_SIZE; \ 93 if (__t) (r) += __t->position; \ 94 } while (0) 95 #define SG_STREAM_BUFFER_COUNTC(r, start) \ 96 SG_STREAM_BUFFER_COUNT_REC(char_buffer, r, start) 97 #define SG_STREAM_BUFFER_COUNTB(r, start) \ 98 SG_STREAM_BUFFER_COUNT_REC(byte_buffer, r, start) 99 100 #define SG_STREAM_BUFFER_POSITION_REC(type, r, start, current) \ 101 do { \ 102 type *__t = (start); \ 103 for ((r)=0LL;__t && __t == (current); __t=__t->next,(r)++); \ 104 (r) *= SG_STREAM_BUFFER_SIZE; \ 105 if (__t) (r) += __t->position; \ 106 } while (0) 107 #define SG_STREAM_BUFFER_POSITIONC(r, start, current) \ 108 SG_STREAM_BUFFER_POSITION_REC(char_buffer, r, start, current) 109 #define SG_STREAM_BUFFER_POSITIONB(r, start) \ 110 SG_STREAM_BUFFER_POSITION_REC(byte_buffer, r, start, current) 111 112 113 114 #define SG_STREAM_BUFFER_GET_BUFFER_REC(buftype, type, r, start) \ 115 do { \ 116 int __off; \ 117 type *__t = (start); \ 118 for (__off=0; __t && __t->position >= SG_STREAM_BUFFER_SIZE; \ 119 __t=__t->next,__off+=SG_STREAM_BUFFER_SIZE) { \ 120 memcpy((r)+__off, __t->buf, sizeof(buftype)*SG_STREAM_BUFFER_SIZE); \ 121 } \ 122 if (__t) memcpy((r)+__off, __t->buf,sizeof(buftype)*__t->position); \ 123 } while (0) 124 125 #define SG_STREAM_BUFFER_GET_BUFFERB(r, start) \ 126 SG_STREAM_BUFFER_GET_BUFFER_REC(uint8_t, byte_buffer, r, start) 127 128 #define SG_STREAM_BUFFER_GET_BUFFERC(r, start) \ 129 SG_STREAM_BUFFER_GET_BUFFER_REC(SgChar, char_buffer, r, start) 130 131 #define SG_STREAM_BUFFER_SET_POSITION_REC(type, start, cur, pos) \ 132 do { \ 133 type *__t = (start); \ 134 int __c = (int)(pos)/SG_STREAM_BUFFER_SIZE; \ 135 int __o = (int)(pos)%SG_STREAM_BUFFER_SIZE; \ 136 int __i; \ 137 for (__i = 0; __i < __c; __i++, __t =__t->next) { \ 138 __t->position = SG_STREAM_BUFFER_SIZE; \ 139 if (!__t->next) __t->next = SG_NEW(type); \ 140 } \ 141 __t->position = __o; \ 142 (cur) = __t; \ 143 } while(0) \ 144 145 #define SG_STREAM_BUFFER_SET_POSITIONB(start, cur, pos) \ 146 SG_STREAM_BUFFER_SET_POSITION_REC(byte_buffer, start, cur, pos) 147 #define SG_STREAM_BUFFER_SET_POSITIONC(start, cur, pos) \ 148 SG_STREAM_BUFFER_SET_POSITION_REC(char_buffer, start, cur, pos) 149 150 /* 151 Port 152 153 On Sagittarius, port has the following class hierarchy. 154 155 + port 156 + bytevector port 157 + string port 158 + file port 159 + custom port 160 + buffered port 161 162 Buffer mode from R6RS is handled in 'buffered port'. 163 */ 164 /* base port class */ 165 SG_CLASS_DECL(Sg_PortClass); 166 #define SG_CLASS_PORT (&Sg_PortClass) 167 168 typedef struct SgPortTableRec 169 { 170 void (*flush)(SgObject); 171 int (*close)(SgObject); 172 int (*ready)(SgObject); 173 int (*lockPort)(SgObject, SgPortLockType); 174 int (*unlockPort)(SgObject); 175 /* 176 portPosition used to have whence however it's rather useless. 177 say whence is current then it always return 0. 178 if the whence is end, where should it be especially the 179 port is input port and contains infinite data. 180 */ 181 int64_t (*portPosition)(SgObject); 182 void (*setPortPosition)(SgObject, int64_t, SgWhence); 183 /* port operations */ 184 int (*open)(SgObject); 185 186 /* Binary port operations */ 187 /* reads byte arrey from port */ 188 int64_t (*readb)(SgObject, uint8_t *, int64_t); 189 /* reads all bytes from port */ 190 int64_t (*readbAll)(SgObject, uint8_t **); 191 /* writes bytes to port */ 192 int64_t (*writeb)(SgObject, uint8_t *, int64_t); 193 194 /* Textual port operations */ 195 /* reads string from port */ 196 int64_t (*reads)(SgObject, SgChar *, int64_t); 197 int64_t (*writes)(SgObject, SgChar *, int64_t); 198 } SgPortTable; 199 200 struct SgPortRec 201 { 202 SG_INSTANCE_HEADER; /* can be extended */ 203 SgPortTable *vtbl; 204 SgPortDirection direction; 205 /* we may want to use bit field but for now no need for it */ 206 /* port closed type but for future extension (may not happen) 207 it's int. (for bit field) 208 */ 209 int closed; 210 SgChar peek; /* this can be char or byte */ 211 /* Assosiated transcoder: 212 #f : no transcoder (binary port) 213 #t : string port 214 transcoder: transcoded textual port 215 */ 216 SgObject transcoder; 217 unsigned int readLockCount; 218 unsigned int writeLockCount; 219 SgVM *readLockOwner; 220 SgVM *writeLockOwner; 221 222 readtable_t *readtable; 223 SgObject reader; 224 SgObject data; /* alist of port data */ 225 226 /* 227 The actual locks are emulated by above VM instances. 228 This mutex is the actual lock to obtain them. Unlike 229 the emulated locks, the actual lock can only be one 230 since the port lock macro always releases the mutex 231 in very short time (only just setting VM instances). 232 Thus holding 2 mutex would more cost than waiting 233 the period. 234 */ 235 SgInternalMutex lock; 236 int64_t position; /* current position */ 237 int64_t lineNo; /* line no */ 238 }; 239 240 #define SG_PORT(obj) ((SgPort*)obj) 241 #define SG_PORTP(obj) SG_ISA(obj, SG_CLASS_PORT) 242 #define SG_PORT_VTABLE(obj) SG_PORT(obj)->vtbl 243 #define SG_PORT_READER(obj) SG_PORT(obj)->reader 244 #define SG_PORT_READTABLE(obj) SG_PORT(obj)->readtable 245 #define SG_PORT_DATA(obj) SG_PORT(obj)->data 246 247 #define SG_PORT_HAS_U8_AHEAD(obj) (SG_PORT(obj)->peek != EOF) 248 #define SG_PORT_U8_AHEAD(obj) (SG_PORT(obj)->peek) 249 #define SG_PORT_HAS_CHAR_AHEAD(obj) (SG_PORT(obj)->peek != EOF) 250 #define SG_PORT_CHAR_AHEAD(obj) (SG_PORT(obj)->peek) 251 252 /* port type */ 253 #define SG_BINARY_PORTP(obj) \ 254 ((SG_PORTP(obj)) && SG_FALSEP(SG_PORT(obj)->transcoder)) 255 #define SG_TEXTUAL_PORTP(obj) \ 256 ((SG_PORTP(obj)) && !SG_FALSEP(SG_PORT(obj)->transcoder)) 257 258 /* port direction */ 259 #define SG_INPUT_PORTP(obj) \ 260 (SG_PORTP(obj) && SG_PORT(obj)->direction & SG_INPUT_PORT) 261 #define SG_OUTPUT_PORTP(obj) \ 262 (SG_PORTP(obj) && SG_PORT(obj)->direction & SG_OUTPUT_PORT) 263 #define SG_IN_OUT_PORTP(obj) \ 264 (SG_PORTP(obj) && \ 265 (SG_PORT(obj)->direction & SG_IN_OUT_PORT) == SG_IN_OUT_PORT) 266 #define SG_BIDIRECTIONAL_PORTP(obj) \ 267 (SG_PORTP(obj) && \ 268 (SG_PORT(obj)->direction & SG_BIDIRECTIONAL_PORT) == SG_BIDIRECTIONAL_PORT) 269 270 271 typedef struct SgFilePortRec 272 { 273 SgPort parent; 274 SgFile *file; 275 } SgFilePort; 276 277 #define SG_FILE_PORT(obj) ((SgFilePort *)obj) 278 279 typedef struct SgBytePortRec 280 { 281 SgPort parent; 282 union { 283 struct { 284 byte_buffer *start; 285 byte_buffer *current; 286 } /* out */ ; 287 struct { 288 uint8_t *buf; 289 uint8_t *end; 290 size_t index; 291 } /* in */ ; 292 } buffer; 293 } SgBytePort; 294 295 #define SG_BYTE_PORT(obj) ((SgBytePort *)obj) 296 297 typedef struct SgStringPortRec 298 { 299 SgPort parent; 300 union { 301 struct { 302 char_buffer *start; 303 char_buffer *current; 304 } /* out */ ; 305 struct { 306 SgChar *buf; 307 SgChar *end; 308 size_t index; 309 } /* in */ ; 310 } buffer; 311 } SgStringPort; 312 313 #define SG_STRING_PORT(obj) ((SgStringPort *)obj) 314 315 316 /* to create fresh port by transcoded-port 317 it's rather silly but no choice. 318 */ 319 typedef struct SgTranscodedPortRec 320 { 321 SgPort parent; 322 SgPort *port; 323 } SgTranscodedPort; 324 #define SG_TRANSCODED_PORT(o) ((SgTranscodedPort *)o) 325 #define SG_TRANSCODED_PORT_UNGET(o) SG_PORT(o)->peek 326 #define SG_TRANSCODED_PORT_PORT(o) SG_TRANSCODED_PORT(o)->port 327 #define SG_TRANSCODED_PORT_LINE_NO(o) SG_PORT(o)->lineNo 328 #define SG_TRANSCODED_PORT_TRANSCODER(o) SG_PORT(o)->transcoder 329 330 #define SG_PORT_DEFAULT_BUFFER_SIZE 8196 331 332 typedef enum { 333 SG_BUFFER_MODE_NONE = 0x01, 334 SG_BUFFER_MODE_LINE = 0x02, 335 SG_BUFFER_MODE_BLOCK = 0x03 336 } SgBufferMode; 337 338 typedef struct SgBufferedPortRec 339 { 340 SgPort parent; 341 SgPort *src; /* src port */ 342 SgBufferMode mode; /* mode */ 343 uint8_t *buffer; /* buffer */ 344 size_t size; /* allocated buffer size */ 345 int64_t bufferSize; /* read buffer size */ 346 int64_t index; /* buffer index */ 347 int dirty; /* TRUE if port position is changed */ 348 } SgBufferedPort; 349 #define SG_BUFFERED_PORT(obj) ((SgBufferedPort *)obj) 350 #define SG_BUFFERED_PORT_SRC(obj) SG_BUFFERED_PORT(obj)->src 351 352 #define SG_CUSTOM_PORT_TYPE_BINARY 0 353 #define SG_CUSTOM_PORT_TYPE_TEXTUAL 1 354 typedef struct SgCustomPortSpecRec 355 { 356 int type; /* type. binary or texual */ 357 int direction; 358 SgString *id; /* id must be string */ 359 /* common procs */ 360 SgObject getPosition; /* get-position */ 361 SgObject setPosition; /* set-position! */ 362 SgObject close; /* close */ 363 /* for input port */ 364 SgObject read; /* read */ 365 /* for output port */ 366 SgObject write; /* write */ 367 SgObject ready; /* u8 or char ready */ 368 SgObject flush; /* flush */ 369 /* vtable, if this is NULL, then get from type */ 370 SgPortTable *table; 371 int wrap; /* wrap set position */ 372 } SgCustomPortSpec; 373 374 typedef struct SgCustomPortRec 375 { 376 SgPort parent; 377 SgString *id; /* id must be string */ 378 /* common procs */ 379 SgObject getPosition; /* get-position */ 380 SgObject setPosition; /* set-position! */ 381 SgObject close; /* close */ 382 /* for input port */ 383 SgObject read; /* read */ 384 /* for output port */ 385 SgObject write; /* write */ 386 SgObject ready; /* u8 or char ready */ 387 SgObject flush; /* flush */ 388 389 /* custom port buffer */ 390 union { 391 SgString *textualBuffer; /* buffer for custom textual port */ 392 SgByteVector *binaryBuffer; /* buffer for custom binary port */ 393 }; 394 } SgCustomPort; 395 #define SG_CUSTOM_PORT(obj) ((SgCustomPort *)obj) 396 397 SG_CLASS_DECL(Sg_FilePortClass); 398 SG_CLASS_DECL(Sg_BytePortClass); 399 SG_CLASS_DECL(Sg_StringPortClass); 400 SG_CLASS_DECL(Sg_CustomPortClass); 401 SG_CLASS_DECL(Sg_BufferedPortClass); 402 SG_CLASS_DECL(Sg_TranscodedPortClass); 403 /* This is not a real port but only marking to make get-bytevector-n 404 or get-string-n related procedure read only once even though the 405 port isn't reached to EOF. This is useful when the port has an 406 indefinite stream source such socket. 407 */ 408 SG_CLASS_DECL(Sg_ReadOncePortClass); 409 410 #define SG_CLASS_FILE_PORT (&Sg_FilePortClass) 411 #define SG_CLASS_BYTE_PORT (&Sg_BytePortClass) 412 #define SG_CLASS_STRING_PORT (&Sg_StringPortClass) 413 #define SG_CLASS_CUSTOM_PORT (&Sg_CustomPortClass) 414 #define SG_CLASS_BUFFERED_PORT (&Sg_BufferedPortClass) 415 #define SG_CLASS_TRANSCODED_PORT (&Sg_TranscodedPortClass) 416 #define SG_CLASS_READ_ONCE_PORT (&Sg_ReadOncePortClass) 417 418 #define SG_FILE_PORTP(o) SG_ISA(o, SG_CLASS_FILE_PORT) 419 #define SG_BYTE_PORTP(o) SG_ISA(o, SG_CLASS_BYTE_PORT) 420 #define SG_STRING_PORTP(o) SG_ISA(o, SG_CLASS_STRING_PORT) 421 #define SG_CUSTOM_PORTP(o) SG_ISA(o, SG_CLASS_CUSTOM_PORT) 422 #define SG_BUFFERED_PORTP(o) SG_ISA(o, SG_CLASS_BUFFERED_PORT) 423 #define SG_TRANSCODED_PORTP(o) SG_ISA(o, SG_CLASS_TRANSCODED_PORT) 424 425 /* from Gauche but we need to manage both read and write lock */ 426 #define SG_PORT_LOCK_REC(port, owner__, counter__) \ 427 do { \ 428 SgVM *vm = Sg_VM(); \ 429 if ((port)-> owner__ != vm) { \ 430 for (;;) { \ 431 SgVM *owner_; \ 432 Sg_LockMutex(&(port)->lock); \ 433 owner_ = (port)-> owner__; \ 434 if (owner_ == NULL \ 435 || (owner_->threadState == SG_VM_TERMINATED)) { \ 436 (port)-> owner__ = vm; \ 437 (port)-> counter__ = 1; \ 438 } \ 439 Sg_UnlockMutex(&(port)->lock); \ 440 if ((port)-> owner__ == vm) break; \ 441 Sg_YieldCPU(); \ 442 } \ 443 } else { \ 444 (port)-> counter__ ++; \ 445 } \ 446 } while (0) 447 448 #define SG_PORT_UNLOCK_REC(port, owner__, counter__) \ 449 do { \ 450 if (--(port)-> counter__ <= 0) (port)-> owner__ = NULL; \ 451 } while (0) 452 453 #define SG_PORT_LOCK_READ(port) \ 454 SG_PORT_LOCK_REC(port, readLockOwner, readLockCount) 455 #define SG_PORT_UNLOCK_READ(port) \ 456 SG_PORT_UNLOCK_REC(port, readLockOwner, readLockCount) 457 458 #define SG_PORT_LOCK_WRITE(port) \ 459 do { \ 460 if (SG_BIDIRECTIONAL_PORTP(port)) { \ 461 SG_PORT_LOCK_REC(port, writeLockOwner, writeLockCount); \ 462 } else { \ 463 SG_PORT_LOCK_READ(port); \ 464 } \ 465 } while (0) 466 467 #define SG_PORT_UNLOCK_WRITE(port) \ 468 do { \ 469 if (SG_BIDIRECTIONAL_PORTP(port)) { \ 470 SG_PORT_UNLOCK_REC(port, writeLockOwner, writeLockCount); \ 471 } else { \ 472 SG_PORT_UNLOCK_READ(port); \ 473 } \ 474 } while (0) 475 476 #define SG_INIT_PORT(port, clazz, d, tbl, tr) \ 477 do { \ 478 SG_SET_CLASS((port), (clazz)); \ 479 SG_PORT(port)->direction = (d); \ 480 SG_PORT(port)->position = 0; \ 481 SG_PORT(port)->vtbl = (tbl); \ 482 SG_PORT(port)->transcoder = (tr); \ 483 SG_PORT(port)->reader = SG_FALSE; \ 484 SG_PORT(port)->closed = SG_PORT_OPEN; \ 485 SG_PORT(port)->data = SG_NIL; \ 486 SG_PORT(port)->readtable = NULL; \ 487 SG_PORT(port)->readLockCount = 0; \ 488 SG_PORT(port)->readLockOwner = NULL; \ 489 SG_PORT(port)->writeLockCount = 0; \ 490 SG_PORT(port)->writeLockOwner = NULL; \ 491 SG_PORT(port)->lineNo = -1; \ 492 SG_PORT(port)->peek = EOF; \ 493 Sg_InitMutex(&SG_PORT(port)->lock, TRUE); \ 494 } while (0) 495 496 #define SG_INIT_BINARY_PORT(bp, t) \ 497 do { \ 498 (bp)->type = (t); \ 499 (bp)->buffer = NULL; \ 500 (bp)->bufferSize = 0; \ 501 (bp)->bufferIndex = 0; \ 502 (bp)->position = 0; \ 503 (bp)->dirty = FALSE; \ 504 (bp)->closed = SG_BPORT_OPEN; \ 505 } while (0) 506 507 508 #define SG_CLEAN_PORT_LOCK(port) \ 509 do { \ 510 Sg_DestroyMutex(&(port)->lock); \ 511 } while (0) 512 513 /* for GC friendliness */ 514 /* The src is union so it is enough to make first 2 words NULL */ 515 #define SG_CLEAN_BYTE_PORT(bp) \ 516 do { \ 517 SG_BYTE_PORT(bp)->buffer.start = NULL; \ 518 SG_BYTE_PORT(bp)->buffer.current = NULL; \ 519 } while (0) 520 #define SG_CLEAN_TRANSCODED_PORT(tp) \ 521 do { \ 522 SG_TRANSCODED_PORT(tp)->port = NULL; \ 523 SG_PORT(tp)->transcoder = SG_TRUE; \ 524 } while (0) 525 #define SG_CLEAN_STRING_PORT(tp) \ 526 do { \ 527 (tp)->buffer.start = NULL; \ 528 (tp)->buffer.current = NULL; \ 529 } while (0) 530 531 SG_CDECL_BEGIN 532 533 SG_EXTERN SgObject Sg_MakeFileBinaryInputPort(SgFile *file, int bufferMode); 534 SG_EXTERN SgObject Sg_MakeFileBinaryOutputPort(SgFile *file, int bufferMode); 535 SG_EXTERN SgObject Sg_MakeFileBinaryInputOutputPort(SgFile *file, 536 int bufferMode); 537 SG_EXTERN SgObject Sg_InitFileBinaryPort(SgFilePort *port, 538 SgFile *file, 539 SgPortDirection d, 540 SgBufferedPort *bufferedPort, 541 SgBufferMode mode, 542 uint8_t *buffer, 543 size_t bufferSize); 544 /* Sg_MakeByteVectorInputPort is just for bytevector->string to avoid an 545 allocation. so we don't provide output and input/output port for it. 546 */ 547 SG_EXTERN SgObject Sg_MakeByteVectorInputPort(SgByteVector *bv, 548 int64_t start, int64_t end); 549 SG_EXTERN SgObject Sg_MakeByteArrayInputPort(uint8_t *src, int64_t size); 550 /* We can't make common byte array initialisation function... */ 551 SG_EXTERN SgObject Sg_InitByteArrayInputPort(SgBytePort *port, 552 uint8_t *src, 553 size_t start, size_t end); 554 SG_EXTERN SgObject Sg_MakeByteArrayOutputPort(size_t bufferSize); 555 SG_EXTERN SgObject Sg_InitByteArrayOutputPort(SgBytePort *port, 556 size_t bufferSize); 557 558 SG_EXTERN SgObject Sg_MakeTranscodedPort(SgPort *port, 559 SgTranscoder *transcoder); 560 SG_EXTERN SgObject Sg_InitTranscodedPort(SgTranscodedPort *port, 561 SgPort *src, 562 SgTranscoder *transcoder, 563 SgPortDirection direction); 564 565 /* buffer size is not used yet */ 566 SG_EXTERN SgObject Sg_MakeStringOutputPort(size_t bufferSize); 567 SG_EXTERN SgObject Sg_InitStringOutputPort(SgStringPort *port, 568 size_t bufferSize); 569 SG_EXTERN SgObject Sg_MakeStringInputPort(SgString *in, 570 int64_t start, int64_t end); 571 SG_EXTERN SgObject Sg_InitStringInputPort(SgStringPort *port, SgString *in, 572 int64_t start, int64_t end); 573 /* For convenience and future improvement */ 574 SG_EXTERN SgObject Sg_ConvertToStringOutputPort(SgChar *buf, int bufferSize); 575 576 /* custom ports */ 577 SG_EXTERN SgObject Sg_MakeCustomBinaryPort(SgString *id, 578 int direction, 579 SgObject read, 580 SgObject write, 581 SgObject getPosition, 582 SgObject setPosition, 583 SgObject close, 584 SgObject ready); 585 SG_EXTERN SgObject Sg_MakeCustomTextualPort(SgString *id, 586 int direction, 587 SgObject read, 588 SgObject write, 589 SgObject getPosition, 590 SgObject setPosition, 591 SgObject close, 592 SgObject ready); 593 /* easier */ 594 SG_EXTERN SgObject Sg_MakeCustomPort(SgCustomPortSpec *spec); 595 596 /* buffered port */ 597 SG_EXTERN SgObject Sg_MakeBufferedPort(SgPort *src, SgBufferMode mode, 598 uint8_t *buffer, size_t size); 599 SG_EXTERN SgObject Sg_InitBufferedPort(SgBufferedPort *port, 600 SgBufferMode mode, SgPort *src, 601 uint8_t *buffer, size_t size); 602 603 SG_EXTERN uint8_t* Sg_GetByteArrayFromBinaryPort(SgBytePort *port); 604 SG_EXTERN SgObject Sg_GetByteVectorFromBinaryPort(SgBytePort *port); 605 SG_EXTERN SgObject Sg_GetStringFromStringPort(SgStringPort *port); 606 607 SG_EXTERN void Sg_ClosePort(SgPort *port); 608 SG_EXTERN void Sg_PseudoClosePort(SgPort *port); 609 SG_EXTERN int Sg_PortClosedP(SgPort *port); 610 SG_EXTERN int Sg_PseudoPortClosedP(SgPort *port); 611 612 SG_EXTERN SgObject Sg_StandardOutputPort(); 613 SG_EXTERN SgObject Sg_StandardInputPort(); 614 SG_EXTERN SgObject Sg_StandardErrorPort(); 615 616 /* accessor */ 617 SG_EXTERN SgObject Sg_PortTranscoder(SgObject port); 618 619 SG_EXTERN int Sg_ReadOncePortP(SgPort *port); 620 621 /* utility methods */ 622 SG_EXTERN int Sg_LockPortResource(SgPort *port, SgPortLockType lockType); 623 SG_EXTERN int Sg_UnlockPortResouce(SgPort *port); 624 SG_EXTERN int Sg_PortReady(SgPort *port); 625 SG_EXTERN int Sg_UTF16ConsolePortP(SgPort *port); 626 SG_EXTERN void Sg_FlushPort(SgPort *port); 627 SG_EXTERN void Sg_FlushAllPort(int exitting); 628 SG_EXTERN int Sg_Getb(SgPort *port); 629 SG_EXTERN int Sg_Peekb(SgPort *port); 630 SG_EXTERN int64_t Sg_Readb(SgPort *port, uint8_t *buf, int64_t size); 631 SG_EXTERN int64_t Sg_ReadbAll(SgPort *port, uint8_t **buf); 632 SG_EXTERN void Sg_Writeb(SgPort *port, uint8_t *b, 633 int64_t start, int64_t count); 634 SG_EXTERN void Sg_Putb(SgPort *port, uint8_t b); 635 SG_EXTERN void Sg_Putbv(SgPort *port, SgByteVector *bv); 636 SG_EXTERN SgChar Sg_Getc(SgPort *port); 637 SG_EXTERN SgChar Sg_Peekc(SgPort *port); 638 SG_EXTERN void Sg_Putc(SgPort *port, SgChar ch); 639 SG_EXTERN void Sg_Putz(SgPort *port, const char *str); 640 SG_EXTERN void Sg_Putuz(SgPort *port, const SgChar *str); 641 SG_EXTERN void Sg_Puts(SgPort *port, SgString *str); 642 643 SG_EXTERN void Sg_PutbUnsafe(SgPort *port, uint8_t b); 644 SG_EXTERN void Sg_PutbvUnsafe(SgPort *port, SgByteVector *bv); 645 SG_EXTERN void Sg_WritebUnsafe(SgPort *port, uint8_t *b, int64_t start, 646 int64_t count); 647 /* for textual port */ 648 SG_EXTERN void Sg_Writes(SgPort *port, SgChar *s, int64_t count); 649 SG_EXTERN void Sg_WritesUnsafe(SgPort *port, SgChar *s, int64_t count); 650 SG_EXTERN int64_t Sg_Reads(SgPort *port, SgChar *s, int64_t count); 651 SG_EXTERN int64_t Sg_ReadsUnsafe(SgPort *port, SgChar *s, int64_t count); 652 653 SG_EXTERN void Sg_PutcUnsafe(SgPort *port, SgChar ch); 654 SG_EXTERN void Sg_PutzUnsafe(SgPort *port, const char *str); 655 /* is this too similar? */ 656 SG_EXTERN void Sg_PutuzUnsafe(SgPort *port, const SgChar *str); 657 SG_EXTERN void Sg_PutsUnsafe(SgPort *port, SgString *str); 658 SG_EXTERN SgChar Sg_GetcUnsafe(SgPort *port); 659 SG_EXTERN int Sg_GetbUnsafe(SgPort *port); 660 SG_EXTERN int64_t Sg_ReadbUnsafe(SgPort *port, uint8_t *buf, int64_t size); 661 SG_EXTERN int64_t Sg_ReadbAllUnsafe(SgPort *port, uint8_t **buf); 662 SG_EXTERN void Sg_UngetcUnsafe(SgPort *port, SgChar ch); 663 SG_EXTERN int Sg_PeekbUnsafe(SgPort *port); 664 SG_EXTERN SgChar Sg_PeekcUnsafe(SgPort *port); 665 666 /* seek/tell */ 667 SG_EXTERN int Sg_HasPortPosition(SgPort *port); 668 SG_EXTERN int Sg_HasSetPortPosition(SgPort *port); 669 SG_EXTERN int64_t Sg_PortPosition(SgPort *port); 670 SG_EXTERN void Sg_SetPortPosition(SgPort *port, int64_t offset, 671 SgWhence whence); 672 673 SG_EXTERN int64_t Sg_LineNo(SgPort *port); 674 SG_EXTERN SgObject Sg_FileName(SgPort *port); 675 SG_EXTERN SgObject Sg_PortFile(SgPort *port); 676 677 /* for user defined port */ 678 SG_EXTERN int Sg_AddPortCleanup(SgPort *port); 679 680 /* misc */ 681 SG_EXTERN int Sg_PortCaseInsensitiveP(SgPort *port); 682 SG_EXTERN SgObject Sg_ReadLine(SgPort *port, SgEolStyle eolStyle); 683 SG_EXTERN SgObject Sg_ReadbUntil(SgPort *port, SgByteVector *eol); 684 SG_EXTERN void Sg_DefaultPortPrinter(SgObject obj, SgPort *port, 685 SgWriteContext *ctx); 686 687 688 SG_CDECL_END 689 690 #endif /* SAGITTARIUS_PORT_H_ */ 691 692 /* 693 end of file 694 Local Variables: 695 coding: utf-8-unix 696 End: 697 */ 698