+namespace
+{
+
+/********************************************************************
+ * ModificationCheckingFileOutputStream
+ */
+
+class ModificationCheckingFileOutputStream : public TextOutputStream
+{
+ public:
+ ModificationCheckingFileOutputStream(
+ const char *path,
+ FileOutputRedirectorInterface *redirector)
+ : path_(path), redirector_(redirector)
+ {
+ }
+
+ virtual void write(const char *str) { contents_.write(str); }
+ virtual void close()
+ {
+ const std::string &newContents = contents_.toString();
+ // TODO: Redirect these for unit tests.
+ if (File::exists(path_))
+ {
+ const std::string originalContents_
+ = TextReader::readFileToString(path_);
+ if (originalContents_ == newContents)
+ {
+ return;
+ }
+ }
+ TextWriter writer(redirector_->openTextOutputFile(path_));
+ writer.writeString(newContents);
+ }
+
+ private:
+ std::string path_;
+ StringOutputStream contents_;
+ FileOutputRedirectorInterface *redirector_;
+};
+
+/********************************************************************
+ * ModificationCheckingFileOutputRedirector
+ */
+
+class ModificationCheckingFileOutputRedirector : public FileOutputRedirectorInterface
+{
+ public:
+ explicit ModificationCheckingFileOutputRedirector(
+ FileOutputRedirectorInterface *redirector)
+ : redirector_(redirector)
+ {
+ }
+
+ virtual TextOutputStream &standardOutput()
+ {
+ return redirector_->standardOutput();
+ }
+ virtual TextOutputStreamPointer openTextOutputFile(const char *filename)
+ {
+ return TextOutputStreamPointer(
+ new ModificationCheckingFileOutputStream(filename, redirector_));
+ }
+
+ private:
+ FileOutputRedirectorInterface *redirector_;
+};
+
+} // namespace
+