peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 1 | //===-- runtime/connection.h ------------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 9 | // Fortran I/O connection state (abstracted over internal & external units) |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 10 | |
| 11 | #ifndef FORTRAN_RUNTIME_IO_CONNECTION_H_ |
| 12 | #define FORTRAN_RUNTIME_IO_CONNECTION_H_ |
| 13 | |
| 14 | #include "format.h" |
| 15 | #include <cinttypes> |
| 16 | #include <optional> |
| 17 | |
| 18 | namespace Fortran::runtime::io { |
| 19 | |
Peter Klausler | e782360 | 2021-11-03 22:33:29 | [diff] [blame] | 20 | class IoStatementState; |
| 21 | |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 22 | enum class Direction { Output, Input }; |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 23 | enum class Access { Sequential, Direct, Stream }; |
| 24 | |
| 25 | inline bool IsRecordFile(Access a) { return a != Access::Stream; } |
| 26 | |
| 27 | // These characteristics of a connection are immutable after being |
Peter Klausler | 06ca9f2 | 2021-12-03 00:36:09 | [diff] [blame] | 28 | // established in an OPEN statement. |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 29 | struct ConnectionAttributes { |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 30 | Access access{Access::Sequential}; // ACCESS='SEQUENTIAL', 'DIRECT', 'STREAM' |
peter klausler | 199a623 | 2021-05-05 18:33:00 | [diff] [blame] | 31 | std::optional<bool> isUnformatted; // FORM='UNFORMATTED' if true |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 32 | bool isUTF8{false}; // ENCODING='UTF-8' |
Peter Klausler | 06ca9f2 | 2021-12-03 00:36:09 | [diff] [blame] | 33 | std::optional<std::int64_t> openRecl; // RECL= on OPEN |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 34 | }; |
| 35 | |
| 36 | struct ConnectionState : public ConnectionAttributes { |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 37 | bool IsAtEOF() const; // true when read has hit EOF or endfile record |
Peter Klausler | ac4202f | 2022-01-07 18:29:23 | [diff] [blame] | 38 | bool IsAfterEndfile() const; // true after ENDFILE until repositioned |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 39 | std::size_t RemainingSpaceInRecord() const; |
peter klausler | 6a1c3ef | 2021-05-05 18:37:49 | [diff] [blame] | 40 | bool NeedAdvance(std::size_t) const; |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 41 | void HandleAbsolutePosition(std::int64_t); |
| 42 | void HandleRelativePosition(std::int64_t); |
| 43 | |
peter klausler | 37f98f6 | 2020-07-02 21:11:14 | [diff] [blame] | 44 | void BeginRecord() { |
| 45 | positionInRecord = 0; |
| 46 | furthestPositionInRecord = 0; |
| 47 | leftTabLimit.reset(); |
| 48 | } |
| 49 | |
Peter Klausler | 06ca9f2 | 2021-12-03 00:36:09 | [diff] [blame] | 50 | std::optional<std::int64_t> EffectiveRecordLength() const { |
| 51 | // When an input record is longer than an explicit RECL= from OPEN |
| 52 | // it is effectively truncated on input. |
| 53 | return openRecl && recordLength && *openRecl < *recordLength ? openRecl |
| 54 | : recordLength; |
| 55 | } |
| 56 | |
| 57 | std::optional<std::int64_t> recordLength; |
| 58 | |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 59 | // Positions in a record file (sequential or direct, not stream) |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 60 | std::int64_t currentRecordNumber{1}; // 1 is first |
| 61 | std::int64_t positionInRecord{0}; // offset in current record |
peter klausler | 2750556 | 2020-06-18 19:19:49 | [diff] [blame] | 62 | std::int64_t furthestPositionInRecord{0}; // max(position+bytes) |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 63 | |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 64 | // Set at end of non-advancing I/O data transfer |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 65 | std::optional<std::int64_t> leftTabLimit; // offset in current record |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 66 | |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 67 | // currentRecordNumber value captured after ENDFILE/REWIND/BACKSPACE statement |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 68 | // or an end-of-file READ condition on a sequential access file |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 69 | std::optional<std::int64_t> endfileRecordNumber; |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 70 | |
Peter Klausler | e782360 | 2021-11-03 22:33:29 | [diff] [blame] | 71 | // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT |
| 72 | MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP |
| 73 | |
peter klausler | dfea011 | 2021-08-16 20:15:01 | [diff] [blame] | 74 | // Set when processing repeated items during list-directed & NAMELIST input |
| 75 | // in order to keep a span of records in frame on a non-positionable file, |
| 76 | // so that backspacing to the beginning of the repeated item doesn't require |
| 77 | // repositioning the external storage medium when that's impossible. |
Peter Klausler | e782360 | 2021-11-03 22:33:29 | [diff] [blame] | 78 | bool pinnedFrame{false}; |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 79 | }; |
peter klausler | b8452db | 2021-10-20 20:56:47 | [diff] [blame] | 80 | |
| 81 | // Utility class for capturing and restoring a position in an input stream. |
| 82 | class SavedPosition { |
| 83 | public: |
Peter Klausler | e782360 | 2021-11-03 22:33:29 | [diff] [blame] | 84 | explicit SavedPosition(IoStatementState &); |
| 85 | ~SavedPosition(); |
peter klausler | b8452db | 2021-10-20 20:56:47 | [diff] [blame] | 86 | |
| 87 | private: |
Peter Klausler | e782360 | 2021-11-03 22:33:29 | [diff] [blame] | 88 | IoStatementState &io_; |
| 89 | ConnectionState saved_; |
peter klausler | b8452db | 2021-10-20 20:56:47 | [diff] [blame] | 90 | }; |
| 91 | |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 92 | } // namespace Fortran::runtime::io |
| 93 | #endif // FORTRAN_RUNTIME_IO_CONNECTION_H_ |