summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/include/TextScript.h
blob: 39fe92d6bbaddf0d34344c1e6e4dfcce9eb4b70c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/* $Id: TextScript.h $ */
/** @file
 * Classes for reading/parsing/saving text scripts (unattended installation, ++).
 */

/*
 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#ifndef MAIN_INCLUDED_TextScript_h
#define MAIN_INCLUDED_TextScript_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include "VirtualBoxBase.h"
#include <iprt/cpp/utils.h>
#include <vector>


/**
 * Base class for all the script readers/editors.
 *
 * @todo get rid of this silly bugger.
 */
class AbstractScript
    : public RTCNonCopyable
{
protected:
    /** For setting errors.
     * Yeah, class isn't entirely abstract now.  */
    VirtualBoxBase *mpSetError;

private: /* no default constructors for children. */
    AbstractScript() {}

public:
    DECLARE_TRANSLATE_METHODS(AbstractScript)

    AbstractScript(VirtualBoxBase *pSetError) : mpSetError(pSetError) {}
    virtual ~AbstractScript() {}

    /**
     * Read a script from a file
     */
    virtual HRESULT read(const Utf8Str &rStrFilename) = 0;

    /**
     * Read a script from a VFS file handle.
     */
    virtual HRESULT readFromHandle(RTVFSFILE hVfsFile, const char *pszFilename) = 0;

    /**
     * Parse the script
     */
    virtual HRESULT parse() = 0;

    /**
     * Save a script to a string.
     *
     * This is used by save() and later others to deloy the script.
     */
    virtual HRESULT saveToString(Utf8Str &rStrDst) = 0;

    /**
     * Save a script to a file.
     * @param   rStrPath        Where to save the script.  This normally points to a
     *                          file, but in a number of child use cases it's
     *                          actually giving a directory to put the script in
     *                          using the default deloyment filename.  One day we
     *                          might make the caller do this path joining.
     * @param   fOverwrite      Whether to overwrite the file or not.
     */
    virtual HRESULT save(const Utf8Str &rStrPath, bool fOverwrite) = 0;

    /**
     * Path where an actual script with user's data is located
     */
    virtual const Utf8Str &getActualScriptPath() const = 0;
};

/**
 * Base class for text based script readers/editors.
 *
 * This deals with reading the file into a string data member, writing it back
 * out to a file, and remember the filenames.
 */
class BaseTextScript : public AbstractScript
{
protected:
    const char * const mpszDefaultTemplateFilename; /**< The default template filename.  Can be empty. */
    const char * const mpszDefaultFilename;         /**< Filename to use when someone calls save() with a directory path.  Can be NULL. */
    RTCString   mStrScriptFullContent;  /**< Raw text file content.  Produced by read() and typically only used by parse(). */
    Utf8Str     mStrOriginalPath;       /**< Path where an original script is located (set by read()). */
    Utf8Str     mStrSavedPath;          /**< Path where an saved script with user's data is located (set by save()). */

public:
    DECLARE_TRANSLATE_METHODS(BaseTextScript)

    BaseTextScript(VirtualBoxBase *pSetError, const char *pszDefaultTemplateFilename, const char *pszDefaultFilename)
        : AbstractScript(pSetError)
        , mpszDefaultTemplateFilename(pszDefaultTemplateFilename)
        , mpszDefaultFilename(pszDefaultFilename)
    { }
    virtual ~BaseTextScript() {}

    HRESULT read(const Utf8Str &rStrFilename);
    HRESULT readFromHandle(RTVFSFILE hVfsFile, const char *pszFilename);
    HRESULT save(const Utf8Str &rStrFilename, bool fOverwrite);

    /**
     * Gets the default filename for this class of scripts (empty if none).
     *
     * @note Just the filename, no path.
     */
    const char *getDefaultFilename() const
    {
        return mpszDefaultFilename;
    }

    /**
     * Gets the default template filename for this class of scripts (empty if none).
     *
     * @note Just the filename, no path.
     */
    const char *getDefaultTemplateFilename() const
    {
        return mpszDefaultTemplateFilename;
    }

    /**
     * Path to the file we last saved the script as.
     */
    const Utf8Str &getActualScriptPath() const
    {
        return mStrSavedPath;
    }

    /**
     * Path where an original script is located
     */
    const Utf8Str &getOriginalScriptPath() const
    {
        return mStrOriginalPath;
    }
};


/**
 * Generic line based text script editor.
 *
 * This is used for editing isolinux configuratin files among other things.
 */
class GeneralTextScript : public BaseTextScript
{
protected:
    RTCList<RTCString>  mScriptContentByLines; /**< Content index by line. This contains the edited version. */
    bool                mfDataParsed;          /**< Indicates whether the script has been parse() yet.  */

public:
    DECLARE_TRANSLATE_METHODS(GeneralTextScript)

    GeneralTextScript(VirtualBoxBase *pSetError, const char *pszDefaultTemplateFilename = NULL, const char *pszDefaultFilename = NULL)
        : BaseTextScript(pSetError, pszDefaultTemplateFilename, pszDefaultFilename), mfDataParsed(false)
    {}
    virtual ~GeneralTextScript() {}

    HRESULT parse();
    HRESULT saveToString(Utf8Str &rStrDst);

    //////////////////New functions//////////////////////////////

    bool isDataParsed() const
    {
        return mfDataParsed;
    }

    /**
     * Returns the actual size of script in lines
     */
    size_t getLineNumbersOfScript() const
    {
        return mScriptContentByLines.size();
    }

    /**
     * Gets a read-only reference to the given line, returning Utf8Str::Empty if
     * idxLine is out of range.
     *
     * @returns Line string reference or Utf8Str::Empty.
     * @param   idxLine     The line number.
     *
     * @todo    RTCList doesn't allow this method to be const.
     */
    RTCString const &getContentOfLine(size_t idxLine);

    /**
     * Set new content of line
     */
    HRESULT setContentOfLine(size_t idxLine, const Utf8Str &newContent);

    /**
     * Find a substring in the script
     * Returns a list with the found lines
     * @throws std::bad_alloc
     */
    std::vector<size_t> findTemplate(const Utf8Str &rStrNeedle, RTCString::CaseSensitivity enmCase = RTCString::CaseSensitive);

    /**
     * In line @a idxLine replace the first occurence of @a rStrNeedle with
     * @a rStrRelacement.
     */
    HRESULT findAndReplace(size_t idxLine, const Utf8Str &rStrNeedle, const Utf8Str &rStrReplacement);

    /**
     * Append a string into the end of the given line.
     */
    HRESULT appendToLine(size_t idxLine, const Utf8Str &rStrToAppend);

    /**
     * Prepend a string in the beginning of the given line.
     */
    HRESULT prependToLine(size_t idxLine, const Utf8Str &rStrToPrepend);

    /**
     * Append a new line at the end of the list of line.
     */
    HRESULT appendLine(const Utf8Str &rStrLineToAppend);
    //////////////////New functions//////////////////////////////
};


#endif /* !MAIN_INCLUDED_TextScript_h */