|
|
s_record.cpp00001 /* 00002 * TOPPERS/FDMP Kernel 00003 * Toyohashi Open Platform for Embedded Real-Time Systems/ 00004 * Function Distributed Multiprocessor Kernel 00005 * 00006 * Copyright (C) 2005 by Takagi Nobuhisa 00007 * 00008 * 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 00009 * によって公表されている GNU General Public License の Version 2 に記 00010 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア 00011 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下, 00012 * 利用と呼ぶ)することを無償で許諾する. 00013 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 00014 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー 00015 * スコード中に含まれていること. 00016 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 00017 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 00018 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 00019 * の無保証規定を掲載すること. 00020 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 00021 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ 00022 * と. 00023 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 00024 * 作権表示,この利用条件および下記の無保証規定を掲載すること. 00025 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに 00026 * 報告すること. 00027 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 00028 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. 00029 * 00030 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お 00031 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も 00032 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直 00033 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない. 00034 * 00035 */ 00036 00037 /* 00038 * toppers/s_record.cpp 00039 */ 00040 #include "toppers/s_record.hpp" 00041 #include <istream> 00042 #include <algorithm> 00043 #include <cctype> 00044 #include <cstring> 00045 00046 namespace toppers 00047 { 00048 00053 void s_record::load( std::istream& istr ) 00054 { 00055 int type = -1; 00056 00057 while ( istr ) 00058 { 00059 std::string buf; 00060 std::getline( istr, buf ); 00061 if ( buf.empty() ) 00062 { 00063 break; 00064 } 00065 record rec = read_record( buf ); 00066 00067 // あまり厳密には処理しない 00068 if ( '1' <= rec.type && rec.type <= '3' ) 00069 { 00070 bool done = false; 00071 typedef std::vector<value_type>::iterator iterator; 00072 for ( iterator iter( data_.begin() ), last( data_.end() ); iter != last; ++iter ) 00073 { 00074 if ( rec.address == iter->first + iter->second.size() ) 00075 { 00076 std::copy( rec.data, rec.data+rec.length, std::back_inserter( iter->second ) ); 00077 done = true; 00078 } 00079 } 00080 if ( !done ) 00081 { 00082 data_.push_back( value_type( rec.address, std::vector<unsigned char>( rec.data, rec.data+rec.length ) ) ); 00083 } 00084 } 00085 type = rec.type; 00086 } 00087 00088 cache_ = data_.begin(); 00089 } 00090 00096 int s_record::operator[]( size_type address ) const 00097 { 00098 typedef std::vector<value_type>::const_iterator const_iterator; 00099 if ( cache_ != data_.end() ) 00100 { 00101 const_iterator iter( cache_ ); 00102 if ( iter->first <= address && address < iter->first + iter->second.size() ) 00103 { 00104 return iter->second.at( address - iter->first ); 00105 } 00106 } 00107 for ( const_iterator iter( cache_ ), last( data_.end() ); iter != last; ++iter ) 00108 { 00109 if ( iter->first <= address && address < iter->first + iter->second.size() ) 00110 { 00111 cache_ = iter; 00112 return iter->second.at( address - iter->first ); 00113 } 00114 } 00115 for ( const_iterator iter( data_.begin() ), last( cache_ ); iter != last; ++iter ) 00116 { 00117 if ( iter->first <= address && address < iter->first + iter->second.size() ) 00118 { 00119 cache_ = iter; 00120 return iter->second.at( address - iter->first ); 00121 } 00122 } 00123 return -1; 00124 } 00125 00126 unsigned long s_record::lower_bound() const 00127 { 00128 return data_.front().first; 00129 } 00130 00131 unsigned long s_record::upper_bound() const 00132 { 00133 return data_.back().first + data_.back().second.size(); 00134 } 00135 00141 const s_record::record s_record::read_record( const std::string& rec_buf ) 00142 { 00143 std::string buf( rec_buf ); 00144 00145 // 行末に'\r'または'\n'が残留している場合の対策 00146 while ( std::isspace( static_cast<unsigned char>( *buf.rbegin() ) ) ) 00147 { 00148 buf = buf.substr( 0, buf.size()-1 ); 00149 } 00150 00151 if ( buf.size() < 10 || buf[0] != 'S' ) 00152 { 00153 throw format_error(); 00154 } 00155 int ch = static_cast<unsigned char>( buf[1] ); 00156 int address_length = 4; 00157 std::string::size_type size = buf.size(); 00158 00159 switch ( ch ) 00160 { 00161 case '1': 00162 case '9': 00163 address_length = 4; 00164 break; 00165 case '2': 00166 case '8': 00167 address_length = 6; 00168 break; 00169 case '3': 00170 case '7': 00171 address_length = 8; 00172 break; 00173 default: 00174 if ( !std::isdigit( ch ) ) 00175 { 00176 throw format_error(); 00177 } 00178 break; 00179 } 00180 00181 record rec; 00182 rec.type = ch; 00183 rec.length = xdigit_to_int( buf[2] ) << 4 | xdigit_to_int( buf[3] ); 00184 if ( rec.length * 2 + 4 != buf.size() ) 00185 { 00186 throw format_error(); 00187 } 00188 rec.length -= address_length/2 + 1; // アドレスとチェックサムの長さを引いて、データ長に直す 00189 00190 rec.address = 0; 00191 int base = 4; 00192 for ( int i = 0; i < address_length; i++ ) 00193 { 00194 rec.address = rec.address << 4 | xdigit_to_int( buf[base+i] ); 00195 } 00196 00197 base += address_length; 00198 for ( int i = 0; i < rec.length; i++ ) 00199 { 00200 rec.data[i] = xdigit_to_int( buf[base+i*2] ) << 4 | xdigit_to_int( buf[base+i*2+1] ); 00201 } 00202 00203 rec.checksum = xdigit_to_int( buf[size-2] ) << 4 | xdigit_to_int( buf[size-1] ); 00204 00205 // チェックサム判定は省略 00206 00207 return rec; 00208 } 00209 00215 int s_record::xdigit_to_int( int ch ) 00216 { 00217 static const char xdigits[] = "0123456789abcdef"; 00218 00219 ch = std::tolower( static_cast<unsigned char>( ch ) ); 00220 const char* s = std::strchr( xdigits, ch ); 00221 if ( s == 0 ) 00222 { 00223 return -1; 00224 } 00225 return s - xdigits; 00226 } 00227 00228 } Copyright © 2006 by TAKAGI Nobuhisa. このページは Wed Apr 12 16:31:57 2006 に Doxygen によって生成されました。 |