| //===- IntegerInclusiveInterval.cpp -----------------------------*- 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 | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements utilities for handling lists of inclusive integer | |
| // intervals, such as parsing interval strings like "1-10,20-30,45", which are | |
| // used in debugging and bisection tools. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Support/IntegerInclusiveInterval.h" | |
| #include "llvm/ADT/StringExtras.h" | |
| #include "llvm/Support/Error.h" | |
| #include "llvm/Support/Regex.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include <string> | |
| using namespace llvm; | |
| namespace llvm::IntegerInclusiveIntervalUtils { | |
| Expected<IntervalList> parseIntervals(StringRef Str, char Separator) { | |
| IntervalList Intervals; | |
| if (Str.empty()) | |
| return std::move(Intervals); | |
| // Regex to match either single number or interval "num1-num2". | |
| const Regex IntervalRegex("^([0-9]+)(-([0-9]+))?$"); | |
| for (StringRef Part : llvm::split(Str, Separator)) { | |
| Part = Part.trim(); | |
| if (Part.empty()) | |
| continue; | |
| SmallVector<StringRef, 4> Matches; | |
| if (!IntervalRegex.match(Part, &Matches)) | |
| return createStringError(std::errc::invalid_argument, | |
| "Invalid interval format: '%s'", | |
| Part.str().c_str()); | |
| int64_t Begin, End; | |
| if (Matches[1].getAsInteger(10, Begin)) | |
| return createStringError(std::errc::invalid_argument, | |
| "Failed to parse number: '%s'", | |
| Matches[1].str().c_str()); | |
| if (!Matches[3].empty()) { | |
| // Interval format "begin-end". | |
| if (Matches[3].getAsInteger(10, End)) | |
| return createStringError(std::errc::invalid_argument, | |
| "Failed to parse number: '%s'", | |
| Matches[3].str().c_str()); | |
| if (Begin >= End) | |
| return createStringError(std::errc::invalid_argument, | |
| "Invalid interval: %lld >= %lld", Begin, End); | |
| } else | |
| // Single number. | |
| End = Begin; | |
| // Check ordering constraint (intervals must be in increasing order). | |
| if (!Intervals.empty() && Begin <= Intervals.back().getEnd()) | |
| return createStringError( | |
| std::errc::invalid_argument, | |
| "Expected intervals to be in increasing order: %lld <= %lld", Begin, | |
| Intervals.back().getEnd()); | |
| Intervals.push_back(IntegerInclusiveInterval(Begin, End)); | |
| } | |
| return Intervals; | |
| } | |
| bool contains(ArrayRef<IntegerInclusiveInterval> Intervals, int64_t Value) { | |
| for (const IntegerInclusiveInterval &It : Intervals) { | |
| if (It.contains(Value)) | |
| return true; | |
| } | |
| return false; | |
| } | |
| void printIntervals(raw_ostream &OS, | |
| ArrayRef<IntegerInclusiveInterval> Intervals, | |
| char Separator) { | |
| if (Intervals.empty()) { | |
| OS << "empty"; | |
| return; | |
| } | |
| std::string Sep(1, Separator); | |
| ListSeparator LS(Sep); | |
| for (const IntegerInclusiveInterval &It : Intervals) { | |
| OS << LS; | |
| It.print(OS); | |
| } | |
| } | |
| IntervalList | |
| mergeAdjacentIntervals(ArrayRef<IntegerInclusiveInterval> Intervals) { | |
| if (Intervals.empty()) | |
| return {}; | |
| IntervalList Result; | |
| Result.push_back(Intervals[0]); | |
| for (const IntegerInclusiveInterval &Current : Intervals.drop_front()) { | |
| IntegerInclusiveInterval &Last = Result.back(); | |
| // Check if current interval is adjacent to the last merged interval. | |
| if (Current.getBegin() == Last.getEnd() + 1) { | |
| // Merge by extending the end of the last interval. | |
| Last.setEnd(Current.getEnd()); | |
| } else { | |
| // Not adjacent, add as separate interval. | |
| Result.push_back(Current); | |
| } | |
| } | |
| return Result; | |
| } | |
| } // end namespace llvm::IntegerInclusiveIntervalUtils |