source: cfg_itronx+oil_gcc/toppers/output_file.cpp@ 165

Last change on this file since 165 was 54, checked in by ertl-ishikawa, 12 years ago

cfg+oil対応コンフィギュレータを追加

File size: 8.0 KB
RevLine 
[54]1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2007-2011 by TAKAGI Nobuhisa
6 *
7 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
8 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
9 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
10 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
11 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
12 * スコード中に含まれていること.
13 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
14 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
15 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
16 * の無保証規定を掲載すること.
17 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
18 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
19 * と.
20 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
21 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
22 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
23 * 報告すること.
24 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
25 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
26 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
27 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
28 * 免責すること.
29 *
30 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
31 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
32 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
33 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
34 * の責任を負わない.
35 *
36 */
37#include <map>
38#include <iostream>
39#include <sstream>
40#include <boost/filesystem/path.hpp>
41#include <boost/filesystem/operations.hpp>
42#include "toppers/workaround.hpp"
43#include "toppers/output_file.hpp"
44#include "toppers/io.hpp"
45#include "toppers/global.hpp"
46#include "toppers/diagnostics.hpp"
47
48namespace toppers
49{
50 namespace
51 {
52 struct context
53 {
54 std::ostringstream ostr;
55 std::string tempname;
56 };
57
58 typedef std::map< std::string, std::tr1::shared_ptr< context > > context_map;
59
60 inline context_map& get_context_map()
61 {
62 static context_map m;
63 return m;
64 }
65 }
66
67 /*!
68 * \brief 出力ストリームの参照
69 * \return 出力ストリーム
70 *
71 * 設定されているファイルに出力するための出力ストリームを返す。
72 * 既に出力ストリームが生成されている場合はその参照を返し、そうでなければ新たに出力ストリームを生成する。
73 *
74 * ファイル名として、"stdout"が設定されていれば標準出力、"stderr"が設定されていれば標準エラー出力になる。
75 */
76 std::ostream& output_file::ostr() const
77 {
78 if ( filename_ == "stdout" )
79 {
80 return std::cout;
81 }
82 else if ( filename_ == "stderr" )
83 {
84 return std::cerr;
85 }
86
87 std::string path( path_name( filename_ ) );
88 context_map::const_iterator iter( get_context_map().find( path ) );
89 if ( iter == get_context_map().end() )
90 {
91 std::tr1::shared_ptr< context > ctx( new context );
92 get_context_map().insert( std::make_pair( path, ctx ) );
93 return ctx->ostr;
94 }
95 return iter->second->ostr;
96 }
97
98 /*!
99 * \brief メモリ上に格納されている内容を実際にファイルに出力する。
100 *
101 * context_map としてメモリ上に格納された内容を、それぞれのファイルに対して出力する。
102 * 出力するにあたり、まず元のファイルを .org を付けたファイル名に変更する。
103 * ここで、以前にあった .org は破壊される。
104 * ファイルを順に書き込み、途中でエラーが発生した場合は、.org を元のファイル名に戻す。
105 * 途中でひとつでもエラーが発生した場合は、全ファイルについて .org を元に戻す。
106 * 以前にあった .org は復活しない。
107 */
108 void output_file::save()
109 {
110 namespace fs = boost::filesystem;
111 std::vector< std::string > saved_files;
112
113 try
114 {
115 for ( context_map::const_iterator iter( get_context_map().begin() ), last( get_context_map().end() );
116 iter != last;
117 ++iter )
118 {
119 if ( iter->first != "" )
120 {
121// fs::path filename( iter->first, fs::native );
122 fs::path filename( iter->first ); // filesystem3対応
123// fs::path backup( iter->first + ".org", fs::native );
124 fs::path backup( iter->first + ".org" ); // filesystem3対応
125 bool existed = fs::exists( filename );
126
127 try
128 {
129// std::string file( filename.native_file_string() );
130 std::string file( filename.string() ); // filesystem3対応
131 if ( existed )
132 {
133 fs::rename( filename, backup );
134 }
135 write( file, iter->second->ostr.str() ); // ここで書き込む
136 saved_files.push_back( file );
137 fs::remove( backup );
138 }
139 catch ( ... )
140 {
141 if ( existed )
142 {
143 fs::remove( filename );
144 fs::rename( backup, filename );
145 }
146 throw;
147 }
148 }
149 }
150 }
151 catch ( ... )
152 {
153 // すでに書き込んだファイルを元に戻す。
154 for ( std::vector< std::string >::const_iterator iter( saved_files.begin() ), last( saved_files.end() );
155 iter != last;
156 ++iter )
157 {
158// fs::path filename( *iter, fs::native );
159 fs::path filename( *iter ); // filesystem3対応
160 fs::remove( filename );
161// fs::path backup( *iter + ".org", fs::native );
162 fs::path backup( *iter + ".org" ); // filesystem3対応
163 if ( fs::exists( backup ) )
164 {
165 fs::rename( backup, filename );
166 }
167 }
168 throw;
169 }
170 }
171
172 /*!
173 * \brief 指定したファイル名に対応したパス名を返す。
174 * \param[in] filename ファイル名
175 * \return パス名
176 *
177 * --output-directory オプションで指定した出力先ディレクトリを反映したパス名を生成する。
178 * ただし、下記のファイル名の場合はそのままの文字列を返す。
179 * - "stdout"
180 * - "stderr"
181 * - ""
182 */
183 std::string output_file::path_name( std::string const& filename )
184 {
185 if ( filename == "stdin" || filename == "stderr" || filename == "" )
186 {
187 return filename;
188 }
189 namespace fs = boost::filesystem;
190 boost::any output_directory = global( "output-directory" );
191 if ( output_directory.empty() )
192 {
193 return filename;
194 }
195// fs::path dir( get_global< std::string >( "output-directory" ), fs::native );
196 fs::path dir( get_global< std::string >( "output-directory" ) ); // filesystem3対応
197// return ( dir/filename ).native_file_string();
198 return ( dir/filename ).string(); // filesystem3対応
199 }
200
201 /*!
202 * \brief 指定ファイルへの書き込みデータを参照
203 * \param[in] filename 出力先のファイル名
204 * \return 書き込みデータ
205 */
206 std::string output_file::get_file_data( std::string const& filename )
207 {
208 context_map::const_iterator iter( get_context_map().find( path_name( filename ) ) ), last( get_context_map().end() );
209 if ( iter != last )
210 {
211 return iter->second->ostr.str();
212 }
213 return "";
214 }
215
216 /*!
217 * \brief 指定ファイルへの書き込みデータを設定
218 * \param[in] filename 出力先のファイル名
219 * \param[in] data 書き込みデータ
220 * \retval true 設定成功
221 * \retval false 設定失敗
222 */
223 bool output_file::set_file_data( std::string const& filename, std::string const& data )
224 {
225 output_file ofile( filename, std::ios_base::out );
226 dynamic_cast< std::ostringstream& >( ofile.ostr() ).str( data );
227 return true;
228 }
229
230 /*!
231 * \brief メモリ上に格納されている書き込みようデータを消去
232 * \param[in] filename 出力先のファイル名
233 * \retval true データの消去成功
234 * \retval false 指定したファイルへの出力データが存在しない
235 */
236 bool output_file::clear_file_data( std::string const& filename )
237 {
238 context_map::const_iterator iter( get_context_map().find( path_name( filename ) ) ), last( get_context_map().end() );
239 if ( iter != last )
240 {
241 iter->second->ostr.str( "" );
242 return true;
243 }
244 return false;
245 }
246
247}
Note: See TracBrowser for help on using the repository browser.