/*************************************************************** MPU-GENOPS.C This file contains generic stream dispatch operations. PART OF : MPUIO - library . USAGE : Internal only . NOTE : Backend-specific operations are selected through the FILE_plus jump table. Copyright (C) 2000 - 2026 by Andrey V.Kosteltsev. All Rights Reserved. ***************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include /*************************************************************** Finish backend-specific stream state before close/destruction. ***************************************************************/ int __mpu_IO_finish_unlocked( mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->finish == (int (*)(mpu_FILE *))0 ) return( 0 ); return( (*__MPU_IO_JUMPS( stream )->finish)( stream ) ); } /* End of __mpu_IO_finish_unlocked() */ /*************************************************************** Dispatch stream buffer configuration through the backend. ***************************************************************/ int __mpu_IO_setbuf_unlocked( mpu_FILE *stream, unsigned char *buf, int mode, size_t size ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->setbuf == (int (*)(mpu_FILE *, unsigned char *, int, size_t))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( -1 ); } return( (*__MPU_IO_JUMPS( stream )->setbuf)( stream, buf, mode, size ) ); } /* End of __mpu_IO_setbuf_unlocked() */ /*************************************************************** Seek relative to an origin and return the resulting position. ***************************************************************/ off_t __mpu_IO_seekoff_unlocked( mpu_FILE *stream, off_t offset, int whence ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->seekoff == (off_t (*)(mpu_FILE *, off_t, int))0 ) { errno = ESPIPE; stream->_flags |= __MPU_IO_ERR_SEEN; return( (off_t)-1 ); } return( (*__MPU_IO_JUMPS( stream )->seekoff)( stream, offset, whence ) ); } /* End of __mpu_IO_seekoff_unlocked() */ /*************************************************************** Seek to an absolute stream position and return that position. ***************************************************************/ off_t __mpu_IO_seekpos_unlocked( mpu_FILE *stream, off_t position ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->seekpos == (off_t (*)(mpu_FILE *, off_t))0 ) { errno = ESPIPE; stream->_flags |= __MPU_IO_ERR_SEEN; return( (off_t)-1 ); } return( (*__MPU_IO_JUMPS( stream )->seekpos)( stream, position ) ); } /* End of __mpu_IO_seekpos_unlocked() */ /*************************************************************** Dispatch an input-buffer underflow operation through the backend. ***************************************************************/ int __mpu_IO_underflow_unlocked( mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->underflow == (int (*)(mpu_FILE *))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } return( (*__MPU_IO_JUMPS( stream )->underflow)( stream ) ); } /* End of __mpu_IO_underflow_unlocked() */ /*************************************************************** Dispatch an output-buffer overflow operation through the backend. ***************************************************************/ int __mpu_IO_overflow_unlocked( mpu_FILE *stream, int c ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->overflow == (int (*)(mpu_FILE *, int))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } return( (*__MPU_IO_JUMPS( stream )->overflow)( stream, c ) ); } /* End of __mpu_IO_overflow_unlocked() */ /*************************************************************** Dispatch a stream synchronization operation through the backend. ***************************************************************/ int __mpu_IO_sync_unlocked( mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->sync == (int (*)(mpu_FILE *))0 ) return( 0 ); return( (*__MPU_IO_JUMPS( stream )->sync)( stream ) ); } /* End of __mpu_IO_sync_unlocked() */ /*************************************************************** Dispatch the legacy flush operation through the backend. ***************************************************************/ int __mpu_IO_flush_unlocked( mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->flush == (int (*)(mpu_FILE *))0 ) return( 0 ); return( (*__MPU_IO_JUMPS( stream )->flush)( stream ) ); } /* End of __mpu_IO_flush_unlocked() */ /*************************************************************** Read one raw byte through the selected stream backend. ***************************************************************/ int __mpu_IO_get_byte_unlocked( mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->get_byte == (int (*)(mpu_FILE *))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } return( (*__MPU_IO_JUMPS( stream )->get_byte)( stream ) ); } /* End of __mpu_IO_get_byte_unlocked() */ /*************************************************************** Write one raw byte through the selected stream backend. ***************************************************************/ int __mpu_IO_put_byte_unlocked( unsigned char c, mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->put_byte == (int (*)(unsigned char, mpu_FILE *))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } return( (*__MPU_IO_JUMPS( stream )->put_byte)( c, stream ) ); } /* End of __mpu_IO_put_byte_unlocked() */ /*************************************************************** Read a raw byte block through the stream jump table. Backends without xsgetn support fall back to get_byte operations. ***************************************************************/ size_t __mpu_IO_xsgetn_unlocked( mpu_FILE *stream, void *data, size_t size ) { unsigned char *p = (unsigned char *)data; size_t done = 0; if( __MPU_IO_JUMPS( stream ) != (const struct __mpu_IO_jump_t *)0 && __MPU_IO_JUMPS( stream )->xsgetn != (size_t (*)(mpu_FILE *, void *, size_t))0 ) return( (*__MPU_IO_JUMPS( stream )->xsgetn)( stream, data, size ) ); while( done < size ) { int c = __mpu_IO_get_byte_unlocked( stream ); if( c == mpu_EOF ) break; p[done++] = (unsigned char)c; } return( done ); } /* End of __mpu_IO_xsgetn_unlocked() */ /*************************************************************** Write a raw byte block through the stream jump table. Backends without xsputn support fall back to put_byte operations. ***************************************************************/ size_t __mpu_IO_xsputn_unlocked( mpu_FILE *stream, const void *data, size_t size ) { const unsigned char *p = (const unsigned char *)data; size_t done = 0; if( __MPU_IO_JUMPS( stream ) != (const struct __mpu_IO_jump_t *)0 && __MPU_IO_JUMPS( stream )->xsputn != (size_t (*)(mpu_FILE *, const void *, size_t))0 ) return( (*__MPU_IO_JUMPS( stream )->xsputn)( stream, data, size ) ); while( done < size ) { if( __mpu_IO_put_byte_unlocked( p[done], stream ) == mpu_EOF ) break; ++done; } return( done ); } /* End of __mpu_IO_xsputn_unlocked() */ /*************************************************************** Return one UCS-2 character from STREAM. Characters saved by __mpu_IO_unget_char_unlocked() are returned before the backend. ***************************************************************/ int __mpu_IO_get_char_unlocked( mpu_FILE *stream, __mpu_char16_t *wc ) { if( stream->_unget_count ) { *wc = stream->_unget_chars[--stream->_unget_count]; stream->_flags &= ~__MPU_IO_EOF_SEEN; return( 0 ); } if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->get_char == (int (*)(mpu_FILE *, __mpu_char16_t *))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } return( (*__MPU_IO_JUMPS( stream )->get_char)( stream, wc ) ); } /* End of __mpu_IO_get_char_unlocked() */ /*************************************************************** Push one UCS-2 character back to STREAM. The internal stack permits scanner rollback of short prefixes/exponents; callers may rely on at least one character of public mpu_ungetc(). ***************************************************************/ int __mpu_IO_unget_char_unlocked( __mpu_char16_t wc, mpu_FILE *stream ) { if( stream->_unget_count >= sizeof(stream->_unget_chars) / sizeof(stream->_unget_chars[0]) ) { errno = ENOSPC; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } if( wc >= (__mpu_char16_t)0xd800 && wc <= (__mpu_char16_t)0xdfff ) { errno = EILSEQ; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } stream->_unget_chars[stream->_unget_count++] = wc; stream->_flags &= ~__MPU_IO_EOF_SEEN; return( (int)wc ); } /* End of __mpu_IO_unget_char_unlocked() */ /*************************************************************** Write one UCS-2 character through the selected stream backend. ***************************************************************/ int __mpu_IO_put_char_unlocked( __mpu_char16_t wc, mpu_FILE *stream ) { if( __MPU_IO_JUMPS( stream ) == (const struct __mpu_IO_jump_t *)0 || __MPU_IO_JUMPS( stream )->put_char == (int (*)(__mpu_char16_t, mpu_FILE *))0 ) { errno = EINVAL; stream->_flags |= __MPU_IO_ERR_SEEN; return( mpu_EOF ); } return( (*__MPU_IO_JUMPS( stream )->put_char)( wc, stream ) ); } /* End of __mpu_IO_put_char_unlocked() */ /*************************************************************** Hide internal symbols: ***************************************************************/ __mpu_hidden_decl(__mpu_IO_finish_unlocked); __mpu_hidden_decl(__mpu_IO_flush_unlocked); __mpu_hidden_decl(__mpu_IO_get_byte_unlocked); __mpu_hidden_decl(__mpu_IO_get_char_unlocked); __mpu_hidden_decl(__mpu_IO_overflow_unlocked); __mpu_hidden_decl(__mpu_IO_put_byte_unlocked); __mpu_hidden_decl(__mpu_IO_put_char_unlocked); __mpu_hidden_decl(__mpu_IO_seekoff_unlocked); __mpu_hidden_decl(__mpu_IO_seekpos_unlocked); __mpu_hidden_decl(__mpu_IO_setbuf_unlocked); __mpu_hidden_decl(__mpu_IO_sync_unlocked); __mpu_hidden_decl(__mpu_IO_underflow_unlocked); __mpu_hidden_decl(__mpu_IO_unget_char_unlocked); __mpu_hidden_decl(__mpu_IO_xsgetn_unlocked); __mpu_hidden_decl(__mpu_IO_xsputn_unlocked); /* End of hide internal symbols. ***************************************************************/ /* End of mpu-genops.c */