1 //===-- runtime/character.cpp -----------------------------------*- 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 9 #include "character.h" 10 #include "descriptor.h" 11 #include "terminator.h" 12 #include <algorithm> 13 #include <cstring> 14 15 namespace Fortran::runtime { 16 17 template <typename C> 18 inline int CompareToBlankPadding(const C *x, std::size_t chars) { 19 for (; chars-- > 0; ++x) { 20 if (*x < ' ') { 21 return -1; 22 } 23 if (*x > ' ') { 24 return 1; 25 } 26 } 27 return 0; 28 } 29 30 template <typename C, int shift> 31 static int Compare( 32 const C *x, const C *y, std::size_t xBytes, std::size_t yBytes) { 33 auto minBytes{std::min(xBytes, yBytes)}; 34 if constexpr (shift == 0) { 35 // don't use for kind=2 or =4, that would fail on little-endian machines 36 int cmp{std::memcmp(x, y, minBytes)}; 37 if (cmp < 0) { 38 return -1; 39 } 40 if (cmp > 0) { 41 return 1; 42 } 43 if (xBytes == yBytes) { 44 return 0; 45 } 46 x += minBytes; 47 y += minBytes; 48 } else { 49 for (std::size_t n{minBytes >> shift}; n-- > 0; ++x, ++y) { 50 if (*x < *y) { 51 return -1; 52 } 53 if (*x > *y) { 54 return 1; 55 } 56 } 57 } 58 if (int cmp{CompareToBlankPadding(x, (xBytes - minBytes) >> shift)}) { 59 return cmp; 60 } 61 return -CompareToBlankPadding(y, (yBytes - minBytes) >> shift); 62 } 63 64 extern "C" { 65 66 void RTNAME(CharacterConcatenate)(Descriptor & /*temp*/, 67 const Descriptor & /*operand*/, const char * /*sourceFile*/, 68 int /*sourceLine*/) { 69 // TODO 70 } 71 72 void RTNAME(CharacterConcatenateScalar)( 73 Descriptor & /*temp*/, const char * /*from*/, std::size_t /*byteLength*/) { 74 // TODO 75 } 76 77 void RTNAME(CharacterAssign)(Descriptor & /*lhs*/, const Descriptor & /*rhs*/, 78 const char * /*sourceFile*/, int /*sourceLine*/) { 79 // TODO 80 } 81 82 int RTNAME(CharacterCompareScalar)(const Descriptor &, const Descriptor &) { 83 // TODO real soon once there's type codes for character(kind=2 & 4) 84 return 0; 85 } 86 87 int RTNAME(CharacterCompareScalar1)( 88 const char *x, const char *y, std::size_t xBytes, std::size_t yBytes) { 89 return Compare<char, 0>(x, y, xBytes, yBytes); 90 } 91 92 int RTNAME(CharacterCompareScalar2)(const char16_t *x, const char16_t *y, 93 std::size_t xBytes, std::size_t yBytes) { 94 return Compare<char16_t, 1>(x, y, xBytes, yBytes); 95 } 96 97 int RTNAME(CharacterCompareScalar4)(const char32_t *x, const char32_t *y, 98 std::size_t xBytes, std::size_t yBytes) { 99 return Compare<char32_t, 2>(x, y, xBytes, yBytes); 100 } 101 102 void RTNAME(CharacterCompare)( 103 Descriptor &, const Descriptor &, const Descriptor &) { 104 // TODO real soon once there's type codes for character(kind=2 & 4) 105 } 106 107 std::size_t RTNAME(CharacterAppend1)(char *lhs, std::size_t lhsBytes, 108 std::size_t offset, const char *rhs, std::size_t rhsBytes) { 109 if (auto n{std::min(lhsBytes - offset, rhsBytes)}) { 110 std::memcpy(lhs + offset, rhs, n); 111 offset += n; 112 } 113 return offset; 114 } 115 116 void RTNAME(CharacterPad1)(char *lhs, std::size_t bytes, std::size_t offset) { 117 if (bytes > offset) { 118 std::memset(lhs + offset, ' ', bytes - offset); 119 } 120 } 121 } 122 } // namespace Fortran::runtime 123