SYCL: Avoid using no_init read accessor in rocFFT
[alexxy/gromacs.git] / src / gromacs / utility / textwriter.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2015,2016,2017,2018,2019,2021, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \internal \file
36  * \brief
37  * Implements gmx::TextWriter.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \ingroup module_utility
41  */
42 #include "gmxpre.h"
43
44 #include "textwriter.h"
45
46 #include <cstring>
47
48 #include "gromacs/utility/filestream.h"
49 #include "gromacs/utility/nodelete.h"
50 #include "gromacs/utility/stringutil.h"
51 #include "gromacs/utility/textstream.h"
52
53 namespace gmx
54 {
55
56 class TextWriter::Impl
57 {
58 public:
59     explicit Impl(const TextOutputStreamPointer& stream) :
60         stream_(stream), newLineCount_(2), currentLineLength_(0), pendingNewLine_(false)
61     {
62         wrapper_.settings().setKeepFinalSpaces(true);
63     }
64
65     void writeRawString(const char* str)
66     {
67         if (pendingNewLine_ && str[0] != '\n')
68         {
69             stream_->write("\n");
70         }
71         pendingNewLine_         = false;
72         const char* lastNewLine = std::strrchr(str, '\n');
73         if (lastNewLine == nullptr)
74         {
75             newLineCount_ = 0;
76             currentLineLength_ += std::strlen(str);
77         }
78         else if (lastNewLine[1] != '\0')
79         {
80             newLineCount_ = 0;
81             currentLineLength_ += std::strlen(lastNewLine + 1);
82         }
83         else
84         {
85             currentLineLength_ = 0;
86             int newLineCount   = 0;
87             while (lastNewLine >= str && *lastNewLine == '\n')
88             {
89                 ++newLineCount;
90                 --lastNewLine;
91             }
92             if (lastNewLine >= str)
93             {
94                 newLineCount_ = 0;
95             }
96             newLineCount_ += newLineCount;
97         }
98         stream_->write(str);
99     }
100     void writeRawString(const std::string& str) { writeRawString(str.c_str()); }
101
102     void writeWrappedString(const std::string& str)
103     {
104         if (newLineCount_ > 0)
105         {
106             writeRawString(wrapper_.wrapToString(str));
107         }
108         else
109         {
110             writeRawString(str);
111         }
112     }
113
114     TextOutputStreamPointer stream_;
115     TextLineWrapper         wrapper_;
116     int                     newLineCount_;
117     int                     currentLineLength_;
118     bool                    pendingNewLine_;
119 };
120
121 // static
122 void TextWriter::writeFileFromString(const std::string& filename, const std::string& text)
123 {
124     TextWriter file(filename);
125     file.writeString(text);
126     file.close();
127 }
128
129 TextWriter::TextWriter(const std::string& filename) :
130     impl_(new Impl(TextOutputStreamPointer(new TextOutputFile(filename))))
131 {
132 }
133
134 TextWriter::TextWriter(FILE* fp) : impl_(new Impl(TextOutputStreamPointer(new TextOutputFile(fp))))
135 {
136 }
137
138 TextWriter::TextWriter(TextOutputStream* stream) :
139     impl_(new Impl(TextOutputStreamPointer(stream, no_delete<TextOutputStream>())))
140 {
141 }
142
143 TextWriter::TextWriter(const TextOutputStreamPointer& stream) : impl_(new Impl(stream)) {}
144
145 TextWriter::~TextWriter() {}
146
147 TextLineWrapperSettings& TextWriter::wrapperSettings()
148 {
149     return impl_->wrapper_.settings();
150 }
151
152 void TextWriter::writeString(const char* str)
153 {
154     if (impl_->wrapper_.isTrivial())
155     {
156         impl_->writeRawString(str);
157     }
158     else
159     {
160         impl_->writeWrappedString(str);
161     }
162 }
163
164 void TextWriter::writeString(const std::string& str)
165 {
166     impl_->writeWrappedString(str);
167 }
168
169 void TextWriter::writeStringFormatted(const char* fmt, ...)
170 {
171     va_list ap;
172
173     va_start(ap, fmt);
174     writeString(formatStringV(fmt, ap));
175     va_end(ap);
176 }
177
178 void TextWriter::writeLine(const char* line)
179 {
180     writeString(line);
181     ensureLineBreak();
182 }
183
184 void TextWriter::writeLine(const std::string& line)
185 {
186     writeString(line);
187     ensureLineBreak();
188 }
189
190 void TextWriter::writeLineFormatted(const char* fmt, ...)
191 {
192     va_list ap;
193
194     va_start(ap, fmt);
195     writeString(formatStringV(fmt, ap));
196     va_end(ap);
197     ensureLineBreak();
198 }
199
200 void TextWriter::writeLine()
201 {
202     impl_->writeRawString("\n");
203 }
204
205 void TextWriter::ensureLineBreak()
206 {
207     if (impl_->newLineCount_ == 0)
208     {
209         impl_->writeRawString("\n");
210     }
211 }
212
213 void TextWriter::ensureEmptyLine()
214 {
215     ensureLineBreak();
216     if (impl_->newLineCount_ < 2)
217     {
218         impl_->pendingNewLine_ = true;
219     }
220 }
221
222 void TextWriter::close()
223 {
224     impl_->stream_->close();
225 }
226
227 } // namespace gmx