Path: blob/main/system/lib/libcxxabi/src/demangle/Utility.h
6174 views
//===--- Utility.h ----------------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Provide some utility classes for use in the demangler.9// There are two copies of this file in the source tree. The one in libcxxabi10// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update11// the copy. See README.txt for more details.12//13//===----------------------------------------------------------------------===//1415#ifndef DEMANGLE_UTILITY_H16#define DEMANGLE_UTILITY_H1718#include "DemangleConfig.h"1920#include <array>21#include <cstdint>22#include <cstdlib>23#include <cstring>24#include <limits>25#include <string_view>2627DEMANGLE_NAMESPACE_BEGIN2829class Node;3031// Stream that AST nodes write their string representation into after the AST32// has been parsed.33class OutputBuffer {34char *Buffer = nullptr;35size_t CurrentPosition = 0;36size_t BufferCapacity = 0;3738// Ensure there are at least N more positions in the buffer.39void grow(size_t N) {40size_t Need = N + CurrentPosition;41if (Need > BufferCapacity) {42// Reduce the number of reallocations, with a bit of hysteresis. The43// number here is chosen so the first allocation will more-than-likely not44// allocate more than 1K.45Need += 1024 - 32;46BufferCapacity *= 2;47if (BufferCapacity < Need)48BufferCapacity = Need;49Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));50if (Buffer == nullptr)51std::abort();52}53}5455OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {56std::array<char, 21> Temp;57char *TempPtr = Temp.data() + Temp.size();5859// Output at least one character.60do {61*--TempPtr = char('0' + N % 10);62N /= 10;63} while (N);6465// Add negative sign.66if (isNeg)67*--TempPtr = '-';6869return operator+=(70std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));71}7273public:74OutputBuffer(char *StartBuf, size_t Size)75: Buffer(StartBuf), BufferCapacity(Size) {}76OutputBuffer(char *StartBuf, size_t *SizePtr)77: OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}78OutputBuffer() = default;79// Non-copyable80OutputBuffer(const OutputBuffer &) = delete;81OutputBuffer &operator=(const OutputBuffer &) = delete;8283virtual ~OutputBuffer() {}8485operator std::string_view() const {86return std::string_view(Buffer, CurrentPosition);87}8889/// Called by the demangler when printing the demangle tree. By90/// default calls into \c Node::print{Left|Right} but can be overriden91/// by clients to track additional state when printing the demangled name.92virtual void printLeft(const Node &N);93virtual void printRight(const Node &N);9495/// Called when we write to this object anywhere other than the end.96virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {}9798/// Called when we make the \c CurrentPosition of this object smaller.99virtual void notifyDeletion(size_t /*OldPos*/, size_t /*NewPos*/) {}100101/// If a ParameterPackExpansion (or similar type) is encountered, the offset102/// into the pack that we're currently printing.103unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();104unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();105106/// When zero, we're printing template args and '>' needs to be parenthesized.107/// Use a counter so we can simply increment inside parentheses.108unsigned GtIsGt = 1;109110bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }111112void printOpen(char Open = '(') {113GtIsGt++;114*this += Open;115}116void printClose(char Close = ')') {117GtIsGt--;118*this += Close;119}120121OutputBuffer &operator+=(std::string_view R) {122if (size_t Size = R.size()) {123grow(Size);124std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);125CurrentPosition += Size;126}127return *this;128}129130OutputBuffer &operator+=(char C) {131grow(1);132Buffer[CurrentPosition++] = C;133return *this;134}135136OutputBuffer &prepend(std::string_view R) {137size_t Size = R.size();138if (!Size)139return *this;140141grow(Size);142std::memmove(Buffer + Size, Buffer, CurrentPosition);143std::memcpy(Buffer, &*R.begin(), Size);144CurrentPosition += Size;145146notifyInsertion(/*Position=*/0, /*Count=*/Size);147148return *this;149}150151OutputBuffer &operator<<(std::string_view R) { return (*this += R); }152153OutputBuffer &operator<<(char C) { return (*this += C); }154155OutputBuffer &operator<<(long long N) {156return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);157}158159OutputBuffer &operator<<(unsigned long long N) {160return writeUnsigned(N, false);161}162163OutputBuffer &operator<<(long N) {164return this->operator<<(static_cast<long long>(N));165}166167OutputBuffer &operator<<(unsigned long N) {168return this->operator<<(static_cast<unsigned long long>(N));169}170171OutputBuffer &operator<<(int N) {172return this->operator<<(static_cast<long long>(N));173}174175OutputBuffer &operator<<(unsigned int N) {176return this->operator<<(static_cast<unsigned long long>(N));177}178179void insert(size_t Pos, const char *S, size_t N) {180DEMANGLE_ASSERT(Pos <= CurrentPosition, "");181if (N == 0)182return;183184grow(N);185std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);186std::memcpy(Buffer + Pos, S, N);187CurrentPosition += N;188189notifyInsertion(Pos, N);190}191192size_t getCurrentPosition() const { return CurrentPosition; }193void setCurrentPosition(size_t NewPos) {194notifyDeletion(CurrentPosition, NewPos);195CurrentPosition = NewPos;196}197198char back() const {199DEMANGLE_ASSERT(CurrentPosition, "");200return Buffer[CurrentPosition - 1];201}202203bool empty() const { return CurrentPosition == 0; }204205char *getBuffer() { return Buffer; }206char *getBufferEnd() { return Buffer + CurrentPosition - 1; }207size_t getBufferCapacity() const { return BufferCapacity; }208};209210template <class T> class ScopedOverride {211T &Loc;212T Original;213214public:215ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}216217ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {218Loc_ = std::move(NewVal);219}220~ScopedOverride() { Loc = std::move(Original); }221222ScopedOverride(const ScopedOverride &) = delete;223ScopedOverride &operator=(const ScopedOverride &) = delete;224};225226DEMANGLE_NAMESPACE_END227228#endif229230231