blob: 1b988d994eb65932ac4fd57458e24c07fe0540e5 [file] [log] [blame]
//===-- runtime/tools.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef FORTRAN_RUNTIME_TOOLS_H_
#define FORTRAN_RUNTIME_TOOLS_H_
#include "cpp-type.h"
#include "descriptor.h"
#include "memory.h"
#include "terminator.h"
#include <functional>
#include <map>
#include <type_traits>
namespace Fortran::runtime {
class Terminator;
std::size_t TrimTrailingSpaces(const char *, std::size_t);
OwningPtr<char> SaveDefaultCharacter(
const char *, std::size_t, const Terminator &);
// For validating and recognizing default CHARACTER values in a
// case-insensitive manner. Returns the zero-based index into the
// null-terminated array of upper-case possibilities when the value is valid,
// or -1 when it has no match.
int IdentifyValue(
const char *value, std::size_t length, const char *possibilities[]);
// Truncates or pads as necessary
void ToFortranDefaultCharacter(
char *to, std::size_t toLength, const char *from);
// Utility for dealing with elemental LOGICAL arguments
inline bool IsLogicalElementTrue(
const Descriptor &logical, const SubscriptValue at[]) {
// A LOGICAL value is false if and only if all of its bytes are zero.
const char *p{logical.Element<char>(at)};
for (std::size_t j{logical.ElementBytes()}; j-- > 0; ++p) {
if (*p) {
return true;
}
}
return false;
}
// Check array conformability; a scalar 'x' conforms. Crashes on error.
void CheckConformability(const Descriptor &to, const Descriptor &x,
Terminator &, const char *funcName, const char *toName,
const char *fromName);
// Validate a KIND= argument
void CheckIntegerKind(Terminator &, int kind, const char *intrinsic);
template <typename TO, typename FROM>
inline void PutContiguousConverted(TO *to, FROM *from, std::size_t count) {
while (count-- > 0) {
*to++ = *from++;
}
}
static inline std::int64_t GetInt64(const char *p, std::size_t bytes) {
switch (bytes) {
case 1:
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 1> *>(p);
case 2:
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 2> *>(p);
case 4:
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 4> *>(p);
case 8:
return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 8> *>(p);
default:
Terminator{__FILE__, __LINE__}.Crash(
"GetInt64: no case for %zd bytes", bytes);
}
}
template <typename INT>
inline bool SetInteger(INT &x, int kind, std::int64_t value) {
switch (kind) {
case 1:
reinterpret_cast<CppTypeFor<TypeCategory::Integer, 1> &>(x) = value;
return true;
case 2:
reinterpret_cast<CppTypeFor<TypeCategory::Integer, 2> &>(x) = value;
return true;
case 4:
reinterpret_cast<CppTypeFor<TypeCategory::Integer, 4> &>(x) = value;
return true;
case 8:
reinterpret_cast<CppTypeFor<TypeCategory::Integer, 8> &>(x) = value;
return true;
default:
return false;
}
}
} // namespace Fortran::runtime
#endif // FORTRAN_RUNTIME_TOOLS_H_