1 //===-- runtime/emit-encoded.h ----------------------------------*- C++ -*-===//
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
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"
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
)) {
38 if (connection
.useUTF8
<CHAR
>()) {
39 using UnsignedChar
= std::make_unsigned_t
<CHAR
>;
40 const UnsignedChar
*uData
{reinterpret_cast<const UnsignedChar
*>(data
)};
44 auto len
{EncodeUTF8(buffer
+ at
, *uData
++)};
46 if (at
+ maxUTF8Bytes
> sizeof buffer
) {
47 if (!to
.Emit(buffer
, at
)) {
53 return at
== 0 || to
.Emit(buffer
, at
);
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
));
60 // CHARACTER kind conversion for internal output
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
)) {
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
);
83 return EmitEncoded(to
, data
, chars
);
87 template <typename CONTEXT
>
88 bool EmitRepeated(CONTEXT
&to
, char ch
, std::size_t n
) {
92 ConnectionState
&connection
{to
.GetConnectionState()};
93 if (connection
.internalIoCharKind
<= 1 &&
94 connection
.access
!= Access::Stream
) {
95 // faster path, no encoding needed
97 if (!to
.Emit(&ch
, 1)) {
103 if (!EmitEncoded(to
, &ch
, 1)) {
111 } // namespace Fortran::runtime::io
112 #endif // FORTRAN_RUNTIME_EMIT_ENCODED_H_