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

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

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

File size: 7.4 KB
Line 
1/*
2 * TOPPERS Software
3 * Toyohashi Open Platform for Embedded Real-Time Systems
4 *
5 * Copyright (C) 2005-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
38/*
39 * toppers/s_record.cpp
40 */
41#include "toppers/s_record.hpp"
42#include <istream>
43#include <algorithm>
44#include <iterator>
45#include <cctype>
46#include <cstring>
47
48namespace toppers
49{
50
51 /*!
52 * \brief Sレコードのロード
53 * \param istr 入力ストリーム
54 */
55 void s_record::load( std::istream& istr )
56 {
57 int type = -1;
58
59 while ( istr )
60 {
61 std::string buf;
62 std::getline( istr, buf );
63 if ( buf.empty() )
64 {
65 break;
66 }
67 record rec = read_record( buf );
68
69 // あまり厳密には処理しない
70 if ( '1' <= rec.type && rec.type <= '3' )
71 {
72 bool done = false;
73 typedef std::vector< value_type >::iterator iterator;
74 for ( iterator iter( data_.begin() ), last( data_.end() ); iter != last; ++iter )
75 {
76 if ( rec.address == iter->first + iter->second.size() )
77 {
78 std::copy( rec.data.begin(), rec.data.end(), std::back_inserter( iter->second ) );
79 done = true;
80 }
81 }
82 if ( !done )
83 {
84 data_.push_back( value_type( rec.address, std::vector< unsigned char >( rec.data.begin(), rec.data.end() ) ) );
85 }
86 }
87 type = rec.type;
88 }
89
90 cache_ = data_.begin();
91 }
92
93 /*!
94 * \brief 指定アドレスのバイトデータ取得
95 * \param address アドレス指定
96 * \return address で指定したアドレスのバイトデータを返す
97 */
98 int s_record::operator[]( size_type address ) const
99 {
100 typedef std::vector< value_type >::const_iterator const_iterator;
101 if ( cache_ != data_.end() )
102 {
103 const_iterator iter( cache_ );
104 if ( iter->first <= address && address < iter->first + iter->second.size() )
105 {
106 return iter->second.at( address - iter->first );
107 }
108 }
109 for ( const_iterator iter( cache_ ), last( data_.end() ); iter != last; ++iter )
110 {
111 if ( iter->first <= address && address < iter->first + iter->second.size() )
112 {
113 cache_ = iter;
114 return iter->second.at( address - iter->first );
115 }
116 }
117 for ( const_iterator iter( data_.begin() ), last( cache_ ); iter != last; ++iter )
118 {
119 if ( iter->first <= address && address < iter->first + iter->second.size() )
120 {
121 cache_ = iter;
122 return iter->second.at( address - iter->first );
123 }
124 }
125 return -1;
126 }
127
128 /*!
129 * \brief Sレコード中の整数値読み込み
130 * \param base 読み込み位置の先頭アドレス
131 * \param size 整数値のバイト数
132 * \param little_endian リトルエンディアンなら true、ビッグエンディアンなら false を指定
133 * \return 読み込んだ整数値を返す
134 */
135 boost::uintmax_t s_record::get_value( std::size_t base, std::size_t size, bool little_endian ) const
136 {
137 boost::uintmax_t value = 0;
138 if ( little_endian )
139 {
140 for ( long j = static_cast< long >( size-1 ); j >= 0; j-- )
141 {
142 int t = ( *this )[ base + j ];
143 if ( t < 0 )
144 {
145 throw data_error();
146 }
147 value = ( value << 8 ) | ( t & 0xff );
148 }
149 }
150 else
151 {
152 for ( std::size_t j = 0; j < size; j++ )
153 {
154 int t = ( *this )[ base + j ];
155 if ( t < 0 )
156 {
157 throw data_error();
158 }
159 value = ( value << 8 ) | ( t & 0xff );
160 }
161 }
162 return value;
163 }
164
165 unsigned long s_record::lower_bound() const
166 {
167 return data_.front().first;
168 }
169
170 unsigned long s_record::upper_bound() const
171 {
172 return data_.back().first + data_.back().second.size();
173 }
174
175 /*!
176 * \brief Sレコードの1行読み込み
177 * \param rec_buf 1行バッファ
178 * \return 読み込み結果を返す
179 */
180 s_record::record const s_record::read_record( std::string const& rec_buf )
181 {
182 std::string buf( rec_buf );
183
184 // 行末に'\r'または'\n'が残留している場合の対策
185 while ( std::isspace( static_cast< unsigned char >( *buf.rbegin() ) ) )
186 {
187 buf = buf.substr( 0, buf.size()-1 );
188 }
189
190 if ( buf.size() < 10 || buf[0] != 'S' )
191 {
192 throw format_error();
193 }
194 int ch = static_cast< unsigned char >( buf[1] );
195 int address_length = 4;
196 std::string::size_type size = buf.size();
197
198 switch ( ch )
199 {
200 case '1':
201 case '9':
202 address_length = 4;
203 break;
204 case '2':
205 case '8':
206 address_length = 6;
207 break;
208 case '3':
209 case '7':
210 address_length = 8;
211 break;
212 default:
213 if ( !std::isdigit( static_cast< unsigned char >( ch ) ) )
214 {
215 throw format_error();
216 }
217 break;
218 }
219
220 record rec;
221 rec.type = ch;
222 rec.length = xdigit_to_int( buf[2] ) << 4 | xdigit_to_int( buf[3] );
223 if ( rec.length * 2u + 4 != buf.size() )
224 {
225 throw format_error();
226 }
227 rec.length -= address_length/2 + 1; // アドレスとチェックサムの長さを引いて、データ長に直す
228
229 rec.address = 0;
230 int base = 4;
231 for ( int i = 0; i < address_length; i++ )
232 {
233 rec.address = rec.address << 4 | xdigit_to_int( buf[base+i] );
234 }
235
236 base += address_length;
237 rec.data.reserve( rec.length );
238 for ( int i = 0; i < rec.length; i++ )
239 {
240 rec.data.push_back( static_cast< unsigned char >( xdigit_to_int( buf[base+i*2] ) << 4 | xdigit_to_int( buf[base+i*2+1] ) ) );
241 }
242
243 rec.checksum = xdigit_to_int( buf[size-2] ) << 4 | xdigit_to_int( buf[size-1] );
244
245 // チェックサム判定は省略
246
247 return rec;
248 }
249
250 /*!
251 * \brief 十六進数字から数値への変換
252 * \param ch 十六進数字(文字)
253 * \return ch に対応する数値
254 */
255 int s_record::xdigit_to_int( int ch )
256 {
257 static char const xdigits[] = "0123456789abcdef";
258
259 ch = std::tolower( static_cast< unsigned char >( ch ) );
260 char const* s = std::strchr( xdigits, ch );
261 if ( s == 0 )
262 {
263 return -1;
264 }
265 return s - xdigits;
266 }
267
268}
Note: See TracBrowser for help on using the repository browser.