File: XMLWriter.h

package info (click to toggle)
audacity 3.2.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 106,704 kB
  • sloc: cpp: 277,038; ansic: 73,623; lisp: 7,761; python: 3,305; sh: 2,715; perl: 821; xml: 275; makefile: 119
file content (188 lines) | stat: -rw-r--r-- 5,420 bytes parent folder | download
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
/**********************************************************************

  Audacity: A Digital Audio Editor

  XMLWriter.h

  Leland Lucius, Dmitry Vedenko

**********************************************************************/
#ifndef __AUDACITY_XML_XML_FILE_WRITER__
#define __AUDACITY_XML_XML_FILE_WRITER__

#include <vector>
#include <wx/ffile.h> // to inherit

#include <string_view> // For UTF8 writer
#include "MemoryStream.h"

#include "FileException.h"

#include "Identifier.h"

///
/// XMLWriter
///
class XML_API XMLWriter /* not final */ {

 public:

   XMLWriter();
   virtual ~XMLWriter();

   virtual void StartTag(const wxString &name);
   virtual void EndTag(const wxString &name);

   // nonvirtual pass-through
   void WriteAttr(const wxString &name, const Identifier &value)
      // using GET once here, permitting Identifiers in XML,
      // so no need for it at each WriteAttr call
      { WriteAttr( name, value.GET() ); }

   virtual void WriteAttr(const wxString &name, const wxString &value);
   virtual void WriteAttr(const wxString &name, const wxChar *value);

   virtual void WriteAttr(const wxString &name, int value);
   virtual void WriteAttr(const wxString &name, bool value);
   virtual void WriteAttr(const wxString &name, long value);
   virtual void WriteAttr(const wxString &name, long long value);
   virtual void WriteAttr(const wxString &name, size_t value);
   virtual void WriteAttr(const wxString &name, float value, int digits = -1);
   virtual void WriteAttr(const wxString &name, double value, int digits = -1);

   virtual void WriteData(const wxString &value);

   virtual void WriteSubTree(const wxString &value);

   virtual void Write(const wxString &data) = 0;

 private:
   // Escape a string, replacing certain characters with their
   // XML encoding, i.e. '<' becomes '&lt;'
   static wxString XMLEsc(const wxString & s);

 protected:

   bool mInTag;
   int mDepth;
   wxArrayString mTagstack;
   std::vector<int> mHasKids;

};

///
/// XMLFileWriter
///

/// This writes to a provisional file, and replaces the previously existing
/// contents by a file rename in Commit() only after all writes succeed.
/// The original contents may also be retained at a backup path name, as
/// directed by the optional constructor argument.
/// If it is destroyed before Commit(), then the provisional file is removed.
/// If the construction and all operations are inside a GuardedCall or event
/// handler, then the default delayed handler action in case of exceptions will
/// notify the user of problems.
class XML_API XMLFileWriter final : private wxFFile, public XMLWriter {

 public:

   /// The caption is for message boxes to show in case of errors.
   /// Might throw.
   XMLFileWriter(
      const FilePath &outputPath, const TranslatableString &caption,
      bool keepBackup = false );

   virtual ~XMLFileWriter();

   /// Close all tags and then close the file.
   /// Might throw.  If not, then create
   /// or modify the file at the output path.
   /// Composed of two steps, PreCommit() and PostCommit()
   void Commit();

   /// Does the part of Commit that might fail because of exhaustion of space
   void PreCommit();

   /// Does other parts of Commit that are not likely to fail for exhaustion
   /// of space, but might for other reasons
   void PostCommit();

   /// Write to file. Might throw.
   void Write(const wxString &data) override;

   FilePath GetBackupName() const { return mBackupName; }

 private:

   void ThrowException(
      const wxFileName &fileName, const TranslatableString &caption)
   {
      throw FileException{ FileException::Cause::Write, fileName, caption };
   }

   /// Close file without automatically ending tags.
   /// Might throw.
   void CloseWithoutEndingTags(); // for auto-save files

   const FilePath mOutputPath;
   const TranslatableString mCaption;
   FilePath mBackupName;
   const bool mKeepBackup;

   wxFFile mBackupFile;

   bool mCommitted{ false };
};

///
/// XMLStringWriter
///
class XML_API XMLStringWriter final : public wxString, public XMLWriter {

 public:

   XMLStringWriter(size_t initialSize = 0);
   virtual ~XMLStringWriter();

   void Write(const wxString &data) override;

 private:

};

class XML_API XMLUtf8BufferWriter final
{
public:
   void StartTag(const std::string_view& name);
   void EndTag(const std::string_view& name);

   void WriteAttr(const std::string_view& name, const Identifier& value);
   // using GET once here, permitting Identifiers in XML,
   // so no need for it at each WriteAttr call

   void WriteAttr(const std::string_view& name, const std::string_view& value);

   void WriteAttr(const std::string_view& name, int value);
   void WriteAttr(const std::string_view& name, bool value);
   void WriteAttr(const std::string_view& name, long value);
   void WriteAttr(const std::string_view& name, long long value);
   void WriteAttr(const std::string_view& name, size_t value);
   void WriteAttr(const std::string_view& name, float value, int digits = -1);
   void WriteAttr(const std::string_view& name, double value, int digits = -1);

   void WriteData(const std::string_view& value);

   void WriteSubTree(const std::string_view& value);

   void Write(const std::string_view& value);

   MemoryStream ConsumeResult();
private:
   void WriteEscaped(const std::string_view& value);

   MemoryStream mStream;

   bool mInTag { false };
};

#endif