initial commit
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "sedpp/Command.h"
|
||||
#include "sedpp/Input.h"
|
||||
#include "sedpp/Options.h"
|
||||
|
||||
namespace sedpp {
|
||||
|
||||
// Executes a compiled sed program against the loaded input records. This class
|
||||
// owns the mutable pieces of sed state: hold space, last successful substitution,
|
||||
// last regex, per-command ranges, and read offsets for R commands.
|
||||
class Runner {
|
||||
public:
|
||||
Runner(Options options, Program program,
|
||||
std::unordered_map<std::string, std::size_t> labels);
|
||||
|
||||
[[nodiscard]] int run();
|
||||
|
||||
private:
|
||||
// One sed cycle starts with a single input record in pattern space. Commands
|
||||
// may append more input (N/n), delete the cycle, or request a quit before the
|
||||
// automatic print phase.
|
||||
struct Cycle {
|
||||
std::string pattern;
|
||||
bool hadDelimiter = false;
|
||||
std::string fileName;
|
||||
std::uint64_t lineNumber = 0;
|
||||
std::uint64_t fileLineNumber = 0;
|
||||
bool lastInFile = false;
|
||||
bool lastOverall = false;
|
||||
bool deleted = false;
|
||||
bool quit = false;
|
||||
int exitCode = 0;
|
||||
std::vector<std::string> appendQueue;
|
||||
};
|
||||
|
||||
// runRecords is shared by normal output and in-place editing so in-place mode
|
||||
// can render to memory before atomically replacing the source file.
|
||||
[[nodiscard]] std::string runRecords(std::vector<Record> records);
|
||||
[[nodiscard]] bool commandApplies(Command &command, const Cycle &cycle);
|
||||
[[nodiscard]] bool addressMatches(const Address &address, const Cycle &cycle);
|
||||
void execute(Command &command, Cycle &cycle, std::size_t &pc,
|
||||
std::vector<Record> &records, std::size_t &recordIndex,
|
||||
class Output &output);
|
||||
bool substitute(Command &command, Cycle &cycle, class Output &output);
|
||||
std::string executeShell(const std::string &command,
|
||||
bool stripTrailingDelimiter = true) const;
|
||||
void emitAppendQueue(Cycle &cycle, class Output &output);
|
||||
void queueFile(Cycle &cycle, const std::string &path);
|
||||
void queueNextFileLine(Cycle &cycle, const std::string &path);
|
||||
|
||||
Options options_;
|
||||
Program program_;
|
||||
std::unordered_map<std::string, std::size_t> labels_;
|
||||
// Branch commands t/T observe whether any s command has succeeded since the
|
||||
// last input-cycle start or branch test.
|
||||
bool lastSubstitutionSucceeded_ = false;
|
||||
// Empty regex addresses and empty s patterns reuse this value, matching sed's
|
||||
// "last regular expression" rule.
|
||||
std::string lastRegex_;
|
||||
// Hold space has its own delimiter bit because pattern/hold exchanges must
|
||||
// preserve whether the original input ended with a record separator.
|
||||
std::string holdSpace_;
|
||||
bool holdHadDelimiter_ = true;
|
||||
// R reads one line per invocation per path; offsets remember the next line.
|
||||
std::unordered_map<std::string, std::size_t> readOffsets_;
|
||||
int finalStatus_ = 0;
|
||||
};
|
||||
|
||||
} // namespace sedpp
|
||||
Reference in New Issue
Block a user