32 #ifndef _QORE_INTERN_QORE_QF_PRIVATE_H 33 #define _QORE_INTERN_QORE_QF_PRIVATE_H 35 #include "qore/intern/QC_Queue.h" 37 #include "qore/intern/QC_TermIOS.h" 40 #include "qore/intern/StringReaderHelper.h" 48 #include <sys/types.h> 53 #elif defined HAVE_SELECT 54 #include <sys/select.h> 55 #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 58 #error no async I/O APIs available 61 #ifndef DEFAULT_FILE_BUFSIZE 62 #define DEFAULT_FILE_BUFSIZE 16384 65 hashdecl qore_qf_private {
68 bool special_file =
false;
72 Queue* cb_queue =
nullptr;
74 DLLLOCAL qore_qf_private(
const QoreEncoding* cs) : charset(cs) {
77 DLLLOCAL ~qore_qf_private() {
84 DLLLOCAL
int close_intern(
bool detach =
false) {
94 do_close_event_unlocked();
104 DLLLOCAL
int redirect(qore_qf_private& file,
ExceptionSink* xsink) {
113 int rc = dup2(file.fd, fd);
118 filename = file.filename;
123 DLLLOCAL
int open_intern(
const char* fn,
int flags,
int mode,
const QoreEncoding* cs) {
131 if (!(flags & O_TEXT))
135 do_open_event_unlocked(fn, flags, mode, cs);
137 fd = ::open(fn, flags, mode);
141 do_opened_event_unlocked(fn, flags, mode, cs);
150 DLLLOCAL
int open(
const char* fn,
int flags,
int mode,
const QoreEncoding* cs) {
151 if (!fn || special_file)
155 return open_intern(fn, flags, mode, cs);
163 xsink->
raiseException(
"FILE-READ-ERROR",
"file has not been opened");
172 xsink->
raiseException(
"FILE-WRITE-ERROR",
"file has not been opened");
181 xsink->
raiseException(
"FILE-OPERATION-ERROR",
"file has not been opened");
185 DLLLOCAL
bool isOpen()
const {
189 DLLLOCAL
bool isDataAvailable(
int timeout_ms,
ExceptionSink *xsink)
const {
192 if (check_read_open(xsink))
195 return isDataAvailableIntern(timeout_ms,
"isDataAvailable", xsink);
204 DLLLOCAL
int select(
int timeout_ms,
bool read,
const char* mname,
ExceptionSink* xsink)
const {
206 if (check_open(xsink))
209 #if defined HAVE_POLL 210 return poll_intern(timeout_ms, read, mname, xsink);
211 #elif defined HAVE_SELECT 212 return select_intern(timeout_ms, read, mname, xsink);
214 #error no async I/O operations supported 218 #if defined HAVE_POLL 219 DLLLOCAL
int poll_intern(
int timeout_ms,
bool read,
const char* mname,
ExceptionSink* xsink)
const {
221 pollfd fds = {fd, (short)(read ? POLLIN : POLLOUT), 0};
223 rc = poll(&fds, 1, timeout_ms);
224 if (rc == -1 && errno == EINTR)
229 xsink->
raiseException(
"FILE-SELECT-ERROR",
"poll(2) returned an error in call to File::%s()", mname);
230 else if (!rc && ((fds.revents & POLLHUP) || (fds.revents & (POLLERR|POLLNVAL))))
235 #elif defined HAVE_SELECT 236 DLLLOCAL
int select_intern(
int timeout_ms,
bool read,
const char* mname,
ExceptionSink* xsink)
const {
237 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 242 if (fd >= FD_SETSIZE) {
244 xsink->
raiseException(
"FILE-SELECT-ERROR",
"fd is %d in call to File::%s() which is >= %d; contact the Qore developers to implement an alternative to select() on this platform", fd, mname, FD_SETSIZE);
256 tv.tv_sec = timeout_ms / 1000;
257 tv.tv_usec = (timeout_ms % 1000) * 1000;
259 rc = read ? ::select(fd + 1, &sfs, 0, 0, &tv) : ::select(fd + 1, 0, &sfs, 0, &tv);
260 if (rc >= 0 || errno != EINTR)
265 xsink->
raiseException(
"FILE-SELECT-ERROR",
"select(2) returned an error in call to File::%s()", mname);
274 DLLLOCAL
bool isDataAvailableIntern(
int timeout_ms,
const char* mname,
ExceptionSink *xsink)
const {
275 return select(timeout_ms,
true, mname, xsink);
278 #ifdef HAVE_TERMIOS_H 279 DLLLOCAL
int setTerminalAttributes(
int action, QoreTermIOS* ios,
ExceptionSink* xsink)
const {
282 if (check_open(xsink))
285 return ios->set(fd, action, xsink);
288 DLLLOCAL
int getTerminalAttributes(QoreTermIOS* ios,
ExceptionSink* xsink)
const {
291 if (check_open(xsink))
294 return ios->get(fd, xsink);
302 rc = ::read(fd, buf, bs);
304 if (rc >= 0 || errno != EINTR)
309 do_read_event_unlocked(rc, rc, bs);
318 rc = ::write(fd, buf, len);
320 if (rc >= 0 || errno != EINTR)
325 do_write_event_unlocked(rc, rc, len);
326 else if (xsink && rc < 0)
327 xsink->
raiseErrnoException(
"FILE-WRITE-ERROR", errno,
"failed writing " QSD
" byte%s to File", len, len == 1 ?
"" :
"s");
333 DLLLOCAL
int readChar()
const {
334 unsigned char ch = 0;
335 if (read(&ch, 1) != 1)
341 DLLLOCAL
int readUnicode(
int* n_len = 0)
const;
345 if (timeout_ms >= 0 && !isDataAvailableIntern(timeout_ms, mname, xsink)) {
347 xsink->
raiseException(
"FILE-READ-TIMEOUT",
"timeout limit exceeded (%d ms) reading file block in ReadOnlyFile::%s()", timeout_ms, mname);
353 rc = ::read(fd, dest, limit);
357 if (errno != EINTR) {
358 xsink->
raiseErrnoException(
"FILE-READ-ERROR", errno,
"error reading file in ReadOnlyFile::%s()", mname);
367 return q_read_string(xsink, size, charset, std::bind(&qore_qf_private::readData,
this, _1, _2, timeout_ms, mname, _3));
371 qore_size_t bs = size > 0 && size < DEFAULT_FILE_BUFSIZE ? size : DEFAULT_FILE_BUFSIZE;
373 char* buf = (
char* )malloc(
sizeof(
char) * bs);
378 if (timeout_ms >= 0 && !isDataAvailableIntern(timeout_ms, mname, xsink)) {
380 xsink->
raiseException(
"FILE-READ-TIMEOUT",
"timeout limit exceeded (%d ms) reading file block in ReadOnlyFile::%s()", timeout_ms, mname);
387 rc = ::read(fd, buf, bs);
391 if (errno != EINTR) {
392 xsink->
raiseErrnoException(
"FILE-READ-ERROR", errno,
"error reading file after " QSD
" bytes read in File::%s()", br, mname);
401 bbuf = (
char* )realloc(bbuf, br + rc + 1);
403 memcpy(bbuf + br, buf, rc);
406 do_read_event_unlocked(rc, br, size);
428 int rc = readLine(**str, incl_eol);
431 xsink->
raiseException(
"FILE-READLINE-ERROR",
"file has not been opened");
435 return rc == -1 ? 0 : str.release();
438 DLLLOCAL
int readLine(
QoreString& str,
bool incl_eol =
true) {
446 bool tty = (bool)isatty(fd);
450 while ((ch = readChar()) >= 0) {
466 lseek(fd, -1, SEEK_CUR);
485 DLLLOCAL
int readUntil(
char byte,
QoreString& str,
bool incl_byte =
true) {
495 while ((ch = readChar()) >= 0) {
513 int rc = readUntil(bytes, **str, incl_bytes);
516 xsink->
raiseException(
"FILE-READLINE-ERROR",
"file has not been opened");
520 return rc == -1 ? 0 : str.release();
523 DLLLOCAL
int readLineUnicode(
QoreString& str,
bool incl_eol =
true) {
531 bool tty = (bool)isatty(fd);
535 while ((ch = readUnicode()) >= 0) {
549 char c = str[str.
size() - 1];
555 ch = readUnicode(&len);
563 lseek(fd, -len, SEEK_CUR);
582 DLLLOCAL
int readUntilUnicode(
char byte,
QoreString& str,
bool incl_byte =
true) {
592 while ((ch = readUnicode()) >= 0) {
614 DLLLOCAL
int readUntilUnicode(
const char* bytes,
QoreString& str,
bool incl_bytes) {
627 while ((ch = readUnicode()) >= 0) {
641 if (ch == bytes[pos]) {
656 if (!strncmp(str.
getBuffer() + ps, bytes, pos - ps)) {
676 DLLLOCAL
int readUntil(
const char* bytes,
QoreString& str,
bool incl_bytes) {
678 return readUntil(bytes[0], str, incl_bytes);
692 while ((ch = readChar()) >= 0) {
698 if (c == bytes[pos]) {
713 if (!strncmp(str.
getBuffer() + ps, bytes, pos - ps)) {
732 DLLLOCAL
bool isTty()
const {
738 return (
bool)isatty(fd);
741 DLLLOCAL
int detachFd() {
762 return lseek(fd, 0, SEEK_CUR);
765 DLLLOCAL
void setEventQueue(Queue* cbq,
ExceptionSink* xsink) {
768 cb_queue->deref(xsink);
783 cb_queue->pushAndTakeRef(h);
786 cb_queue->deref(xsink);
791 DLLLOCAL
void do_open_event_unlocked(
const char* fn,
int flags,
int mode,
const QoreEncoding* enc)
const {
801 cb_queue->pushAndTakeRef(h);
805 DLLLOCAL
void do_opened_event_unlocked(
const char* fn,
int flags,
int mode,
const QoreEncoding* enc)
const {
808 h->
setKeyValue(
"event", QORE_EVENT_FILE_OPENED, 0);
815 cb_queue->pushAndTakeRef(h);
819 DLLLOCAL
void do_close_event_unlocked()
const {
822 h->
setKeyValue(
"event", QORE_EVENT_CHANNEL_CLOSED, 0);
825 cb_queue->pushAndTakeRef(h);
829 DLLLOCAL
void do_read_event_unlocked(
int bytes_read,
int total_read,
int bufsize)
const {
839 cb_queue->pushAndTakeRef(h);
843 DLLLOCAL
void do_write_event_unlocked(
int bytes_written,
int total_written,
int bufsize)
const {
847 h->
setKeyValue(
"event", QORE_EVENT_DATA_WRITTEN, 0);
853 cb_queue->pushAndTakeRef(h);
860 if (check_read_open(xsink))
864 if (fstat(fd, &sbuf)) {
869 return stat_to_list(sbuf);
875 if (check_read_open(xsink))
879 if (fstat(fd, &sbuf)) {
884 return stat_to_hash(sbuf);
887 #ifdef Q_HAVE_STATVFS 891 if (check_read_open(xsink))
894 hashdecl statvfs vfs;
895 #ifdef HAVE_SYS_STATVFS_H 896 if (fstatvfs(fd, &vfs)) {
901 if (q_fstatvfs(filename.c_str(), &vfs)) {
907 return statvfs_to_hash(vfs);
defines string encoding functions in Qore
Definition: QoreEncoding.h:83
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
This is the hash or associative list container type in Qore, dynamically allocated only...
Definition: QoreHashNode.h:50
DLLEXPORT const QoreEncoding * QCS_UTF16
UTF-16 (only UTF-8 and UTF-16* are multi-byte encodings)
DLLEXPORT int setKeyValue(const char *key, QoreValue value, ExceptionSink *xsink)
sets the value of "key" to "value"
size_t qore_size_t
used for sizes (same range as a pointer)
Definition: common.h:73
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
DLLEXPORT AbstractQoreNode * raiseErrnoException(const char *err, int en, const char *fmt,...)
appends a Qore-language exception to the list and appends the result of strerror(errno) to the descri...
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
DLLEXPORT const char * getBuffer() const
returns the string's buffer; this data should not be changed
DLLEXPORT void concat(const QoreString *str, ExceptionSink *xsink)
concatenates a string and converts encodings if necessary
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack...
Definition: QoreThreadLock.h:128
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
DLLEXPORT qore_size_t strlen() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT const char * getCode() const
returns the string code (ex: "UTF-8") for the encoding
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
DLLEXPORT void terminate(qore_size_t size)
terminates the string at byte position "size", the string is reallocated if necessary ...
intptr_t qore_offset_t
used for offsets that could be negative
Definition: common.h:76
DLLEXPORT int concatUnicode(unsigned code, ExceptionSink *xsink)
append a character sequence from a unicode code point (returns 0 for OK, -1 for exception) ...
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:47
DLLEXPORT const QoreEncoding * QCS_UTF16LE
UTF-16LE (only UTF-8 and UTF-16* are multi-byte encodings)
DLLEXPORT void clear()
reset string to zero length; memory is not deallocated; string encoding does not change ...
DLLEXPORT qore_size_t size() const
returns number of bytes in the string (not including the null pointer)