[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / flang / runtime / emit-encoded.h
blob864848c3b19c67ebda731be195a1c372553e3f91
1 //===-- runtime/emit-encoded.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 //===----------------------------------------------------------------------===//
9 // Templates for emitting CHARACTER values with conversion
11 #ifndef FORTRAN_RUNTIME_EMIT_ENCODED_H_
12 #define FORTRAN_RUNTIME_EMIT_ENCODED_H_
14 #include "connection.h"
15 #include "environment.h"
16 #include "tools.h"
17 #include "utf.h"
19 namespace Fortran::runtime::io {
21 template <typename CONTEXT, typename CHAR>
22 bool EmitEncoded(CONTEXT &to, const CHAR *data, std::size_t chars) {
23 ConnectionState &connection{to.GetConnectionState()};
24 if (connection.access == Access::Stream &&
25 connection.internalIoCharKind == 0) {
26 // Stream output: treat newlines as record advancements so that the left tab
27 // limit is correctly managed
28 while (const CHAR * nl{FindCharacter(data, CHAR{'\n'}, chars)}) {
29 auto pos{static_cast<std::size_t>(nl - data)};
30 if (!EmitEncoded(to, data, pos)) {
31 return false;
33 data += pos + 1;
34 chars -= pos + 1;
35 to.AdvanceRecord();
38 if (connection.useUTF8<CHAR>()) {
39 using UnsignedChar = std::make_unsigned_t<CHAR>;
40 const UnsignedChar *uData{reinterpret_cast<const UnsignedChar *>(data)};
41 char buffer[256];
42 std::size_t at{0};
43 while (chars-- > 0) {
44 auto len{EncodeUTF8(buffer + at, *uData++)};
45 at += len;
46 if (at + maxUTF8Bytes > sizeof buffer) {
47 if (!to.Emit(buffer, at)) {
48 return false;
50 at = 0;
53 return at == 0 || to.Emit(buffer, at);
54 } else {
55 std::size_t internalKind = connection.internalIoCharKind;
56 if (internalKind == 0 || internalKind == sizeof(CHAR)) {
57 const char *rawData{reinterpret_cast<const char *>(data)};
58 return to.Emit(rawData, chars * sizeof(CHAR), sizeof(CHAR));
59 } else {
60 // CHARACTER kind conversion for internal output
61 while (chars-- > 0) {
62 char32_t buffer = *data++;
63 char *p{reinterpret_cast<char *>(&buffer)};
64 if constexpr (!isHostLittleEndian) {
65 p += sizeof(buffer) - internalKind;
67 if (!to.Emit(p, internalKind)) {
68 return false;
71 return true;
76 template <typename CONTEXT>
77 bool EmitAscii(CONTEXT &to, const char *data, std::size_t chars) {
78 ConnectionState &connection{to.GetConnectionState()};
79 if (connection.internalIoCharKind <= 1 &&
80 connection.access != Access::Stream) {
81 return to.Emit(data, chars);
82 } else {
83 return EmitEncoded(to, data, chars);
87 template <typename CONTEXT>
88 bool EmitRepeated(CONTEXT &to, char ch, std::size_t n) {
89 if (n <= 0) {
90 return true;
92 ConnectionState &connection{to.GetConnectionState()};
93 if (connection.internalIoCharKind <= 1 &&
94 connection.access != Access::Stream) {
95 // faster path, no encoding needed
96 while (n-- > 0) {
97 if (!to.Emit(&ch, 1)) {
98 return false;
101 } else {
102 while (n-- > 0) {
103 if (!EmitEncoded(to, &ch, 1)) {
104 return false;
108 return true;
111 } // namespace Fortran::runtime::io
112 #endif // FORTRAN_RUNTIME_EMIT_ENCODED_H_