[8] | 1 | /*
|
---|
| 2 | * TOPPERS Software
|
---|
| 3 | * Toyohashi Open Platform for Embedded Real-Time Systems
|
---|
| 4 | *
|
---|
| 5 | * Copyright (C) 2005-2008 by TAKAGI Nobuhisa
|
---|
| 6 | *
|
---|
| 7 | * ãLì ÒÍCȺÌ(1)`(4)Ìðð½·êÉÀèC{\tgEF
|
---|
| 8 | * Ai{\tgEFAðüϵ½àÌðÜÞDȺ¯¶jðgpE¡»Eü
|
---|
| 9 | * ÏEÄzziȺCpÆÄÔj·é±Æð³Åø·éD
|
---|
| 10 | * (1) {\tgEFAð\[XR[hÌ`Åp·éêÉÍCãLÌì
|
---|
| 11 | * \¦C±Ìpð¨æѺL̳ÛØKèªC»ÌÜÜÌ`Å\[
|
---|
| 12 | * XR[hÉÜÜêÄ¢é±ÆD
|
---|
| 13 | * (2) {\tgEFAðCCu`®ÈÇC¼Ì\tgEFAJÉg
|
---|
| 14 | * pÅ«é`ÅÄzz·éêÉÍCÄzzɺ¤hL
|
---|
| 15 | gip
|
---|
| 16 | * Ò}j
|
---|
| 17 | AÈÇjÉCãLÌì \¦C±Ìpð¨æѺL
|
---|
| 18 | * ̳ÛØKèðfÚ·é±ÆD
|
---|
| 19 | * (3) {\tgEFAðC@íÉgÝÞÈÇC¼Ì\tgEFAJÉg
|
---|
| 20 | * pÅ«È¢`ÅÄzz·éêÉÍCÌ¢¸ê©Ìðð½·±
|
---|
| 21 | * ÆD
|
---|
| 22 | * (a) Äzzɺ¤hL
|
---|
| 23 | gipÒ}j
|
---|
| 24 | AÈÇjÉCãLÌ
|
---|
| 25 | * ì \¦C±Ìpð¨æѺL̳ÛØKèðfÚ·é±ÆD
|
---|
| 26 | * (b) ÄzzÌ`ÔðCÊÉèßéû@ÉæÁÄCTOPPERSvWFNgÉ
|
---|
| 27 | * ñ·é±ÆD
|
---|
| 28 | * (4) {\tgEFAÌpÉæè¼ÚIܽÍÔÚIɶ¶é¢©Èé¹
|
---|
| 29 | * Q©çàCãLì Ò¨æÑTOPPERSvWFNgðÆÓ·é±ÆD
|
---|
| 30 | * ܽC{\tgEFAÌ[UܽÍGh[U©çÌ¢©Èé
|
---|
| 31 | * RÉîÿ©çàCãLì Ò¨æÑTOPPERSvWFNgð
|
---|
| 32 | * ÆÓ·é±ÆD
|
---|
| 33 | *
|
---|
| 34 | * {\tgEFAÍC³ÛØÅñ³êÄ¢éàÌÅ éDãLì Ò¨
|
---|
| 35 | * æÑTOPPERSvWFNgÍC{\tgEFAÉÖµÄCÁèÌgpÚI
|
---|
| 36 | * ÉηéK«àÜßÄC¢©ÈéÛØàsíÈ¢DܽC{\tgEF
|
---|
| 37 | * AÌpÉæè¼ÚIܽÍÔÚIɶ¶½¢©Èé¹QÉÖµÄàC»
|
---|
| 38 | * ÌÓCðíÈ¢D
|
---|
| 39 | *
|
---|
| 40 | */
|
---|
| 41 |
|
---|
| 42 | /*
|
---|
| 43 | * toppers/s_record.cpp
|
---|
| 44 | */
|
---|
| 45 | #include "toppers/s_record.hpp"
|
---|
| 46 | #include <istream>
|
---|
| 47 | #include <algorithm>
|
---|
| 48 | #include <cctype>
|
---|
| 49 | #include <cstring>
|
---|
| 50 |
|
---|
| 51 | namespace toppers
|
---|
| 52 | {
|
---|
| 53 |
|
---|
| 54 | /*!
|
---|
| 55 | * \brief SR[hÌ[h
|
---|
| 56 | * \param istr üÍXg[
|
---|
| 57 | */
|
---|
| 58 | void s_record::load( std::istream& istr )
|
---|
| 59 | {
|
---|
| 60 | int type = -1;
|
---|
| 61 |
|
---|
| 62 | while ( istr )
|
---|
| 63 | {
|
---|
| 64 | std::string buf;
|
---|
| 65 | std::getline( istr, buf );
|
---|
| 66 | if ( buf.empty() )
|
---|
| 67 | {
|
---|
| 68 | break;
|
---|
| 69 | }
|
---|
| 70 | record rec = read_record( buf );
|
---|
| 71 |
|
---|
| 72 | // Ü赧É͵Ȣ
|
---|
| 73 | if ( '1' <= rec.type && rec.type <= '3' )
|
---|
| 74 | {
|
---|
| 75 | bool done = false;
|
---|
| 76 | typedef std::vector< value_type >::iterator iterator;
|
---|
| 77 | for ( iterator iter( data_.begin() ), last( data_.end() ); iter != last; ++iter )
|
---|
| 78 | {
|
---|
| 79 | if ( rec.address == iter->first + iter->second.size() )
|
---|
| 80 | {
|
---|
| 81 | std::copy( rec.data.begin(), rec.data.end(), std::back_inserter( iter->second ) );
|
---|
| 82 | done = true;
|
---|
| 83 | }
|
---|
| 84 | }
|
---|
| 85 | if ( !done )
|
---|
| 86 | {
|
---|
| 87 | data_.push_back( value_type( rec.address, std::vector< unsigned char >( rec.data.begin(), rec.data.end() ) ) );
|
---|
| 88 | }
|
---|
| 89 | }
|
---|
| 90 | type = rec.type;
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | cache_ = data_.begin();
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | /*!
|
---|
| 97 | * \brief wèAhXÌoCgf[^æ¾
|
---|
| 98 | * \param address AhXwè
|
---|
| 99 | * \return address Åwèµ½AhXÌoCgf[^ðÔ·
|
---|
| 100 | */
|
---|
| 101 | int s_record::operator[]( size_type address ) const
|
---|
| 102 | {
|
---|
| 103 | typedef std::vector< value_type >::const_iterator const_iterator;
|
---|
| 104 | if ( cache_ != data_.end() )
|
---|
| 105 | {
|
---|
| 106 | const_iterator iter( cache_ );
|
---|
| 107 | if ( iter->first <= address && address < iter->first + iter->second.size() )
|
---|
| 108 | {
|
---|
| 109 | return iter->second.at( address - iter->first );
|
---|
| 110 | }
|
---|
| 111 | }
|
---|
| 112 | for ( const_iterator iter( cache_ ), last( data_.end() ); iter != last; ++iter )
|
---|
| 113 | {
|
---|
| 114 | if ( iter->first <= address && address < iter->first + iter->second.size() )
|
---|
| 115 | {
|
---|
| 116 | cache_ = iter;
|
---|
| 117 | return iter->second.at( address - iter->first );
|
---|
| 118 | }
|
---|
| 119 | }
|
---|
| 120 | for ( const_iterator iter( data_.begin() ), last( cache_ ); iter != last; ++iter )
|
---|
| 121 | {
|
---|
| 122 | if ( iter->first <= address && address < iter->first + iter->second.size() )
|
---|
| 123 | {
|
---|
| 124 | cache_ = iter;
|
---|
| 125 | return iter->second.at( address - iter->first );
|
---|
| 126 | }
|
---|
| 127 | }
|
---|
| 128 | return -1;
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | /*!
|
---|
| 132 | * \brief SR[hÌ®lÇÝÝ
|
---|
| 133 | * \param base ÇÝÝÊuÌæªAhX
|
---|
| 134 | * \param size ®lÌoCg
|
---|
| 135 | * \param little_endian gGfBAÈç trueArbOGfBAÈç false ðwè
|
---|
| 136 | * \return ÇÝñ¾®lðÔ·
|
---|
| 137 | */
|
---|
| 138 | boost::uintmax_t s_record::get_value( std::size_t base, std::size_t size, bool little_endian ) const
|
---|
| 139 | {
|
---|
| 140 | boost::uintmax_t value = 0;
|
---|
| 141 | if ( little_endian )
|
---|
| 142 | {
|
---|
| 143 | for ( long j = static_cast< long >( size-1 ); j >= 0; j-- )
|
---|
| 144 | {
|
---|
| 145 | int t = ( *this )[ base + j ];
|
---|
| 146 | if ( t < 0 )
|
---|
| 147 | {
|
---|
| 148 | throw data_error();
|
---|
| 149 | }
|
---|
| 150 | value = ( value << 8 ) | ( t & 0xff );
|
---|
| 151 | }
|
---|
| 152 | }
|
---|
| 153 | else
|
---|
| 154 | {
|
---|
| 155 | for ( std::size_t j = 0; j < size; j++ )
|
---|
| 156 | {
|
---|
| 157 | int t = ( *this )[ base + j ];
|
---|
| 158 | if ( t < 0 )
|
---|
| 159 | {
|
---|
| 160 | throw data_error();
|
---|
| 161 | }
|
---|
| 162 | value = ( value << 8 ) | ( t & 0xff );
|
---|
| 163 | }
|
---|
| 164 | }
|
---|
| 165 | return value;
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | unsigned long s_record::lower_bound() const
|
---|
| 169 | {
|
---|
| 170 | return data_.front().first;
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | unsigned long s_record::upper_bound() const
|
---|
| 174 | {
|
---|
| 175 | return data_.back().first + data_.back().second.size();
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 | /*!
|
---|
| 179 | * \brief SR[hÌPsÇÝÝ
|
---|
| 180 | * \param rec_buf Psobt@
|
---|
| 181 | * \return ÇÝÝÊðÔ·
|
---|
| 182 | */
|
---|
| 183 | s_record::record const s_record::read_record( std::string const& rec_buf )
|
---|
| 184 | {
|
---|
| 185 | std::string buf( rec_buf );
|
---|
| 186 |
|
---|
| 187 | // sÉ'\r'ܽÍ'\n'ªc¯µÄ¢éêÌÎô
|
---|
| 188 | while ( std::isspace( static_cast< unsigned char >( *buf.rbegin() ) ) )
|
---|
| 189 | {
|
---|
| 190 | buf = buf.substr( 0, buf.size()-1 );
|
---|
| 191 | }
|
---|
| 192 |
|
---|
| 193 | if ( buf.size() < 10 || buf[0] != 'S' )
|
---|
| 194 | {
|
---|
| 195 | throw format_error();
|
---|
| 196 | }
|
---|
| 197 | int ch = static_cast< unsigned char >( buf[1] );
|
---|
| 198 | int address_length = 4;
|
---|
| 199 | std::string::size_type size = buf.size();
|
---|
| 200 |
|
---|
| 201 | switch ( ch )
|
---|
| 202 | {
|
---|
| 203 | case '1':
|
---|
| 204 | case '9':
|
---|
| 205 | address_length = 4;
|
---|
| 206 | break;
|
---|
| 207 | case '2':
|
---|
| 208 | case '8':
|
---|
| 209 | address_length = 6;
|
---|
| 210 | break;
|
---|
| 211 | case '3':
|
---|
| 212 | case '7':
|
---|
| 213 | address_length = 8;
|
---|
| 214 | break;
|
---|
| 215 | default:
|
---|
| 216 | if ( !std::isdigit( static_cast< unsigned char >( ch ) ) )
|
---|
| 217 | {
|
---|
| 218 | throw format_error();
|
---|
| 219 | }
|
---|
| 220 | break;
|
---|
| 221 | }
|
---|
| 222 |
|
---|
| 223 | record rec;
|
---|
| 224 | rec.type = ch;
|
---|
| 225 | rec.length = xdigit_to_int( buf[2] ) << 4 | xdigit_to_int( buf[3] );
|
---|
| 226 | if ( rec.length * 2u + 4 != buf.size() )
|
---|
| 227 | {
|
---|
| 228 | throw format_error();
|
---|
| 229 | }
|
---|
| 230 | rec.length -= address_length/2 + 1; // AhXÆ`FbNTÌ·³ðø¢ÄAf[^·É¼·
|
---|
| 231 |
|
---|
| 232 | rec.address = 0;
|
---|
| 233 | int base = 4;
|
---|
| 234 | for ( int i = 0; i < address_length; i++ )
|
---|
| 235 | {
|
---|
| 236 | rec.address = rec.address << 4 | xdigit_to_int( buf[base+i] );
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | base += address_length;
|
---|
| 240 | rec.data.reserve( rec.length );
|
---|
| 241 | for ( int i = 0; i < rec.length; i++ )
|
---|
| 242 | {
|
---|
| 243 | rec.data.push_back( static_cast< unsigned char >( xdigit_to_int( buf[base+i*2] ) << 4 | xdigit_to_int( buf[base+i*2+1] ) ) );
|
---|
| 244 | }
|
---|
| 245 |
|
---|
| 246 | rec.checksum = xdigit_to_int( buf[size-2] ) << 4 | xdigit_to_int( buf[size-1] );
|
---|
| 247 |
|
---|
| 248 | // `FbNT»èÍȪ
|
---|
| 249 |
|
---|
| 250 | return rec;
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 | /*!
|
---|
| 254 | * \brief \Zi©çlÖÌÏ·
|
---|
| 255 | * \param ch \Zii¶j
|
---|
| 256 | * \return ch Éηél
|
---|
| 257 | */
|
---|
| 258 | int s_record::xdigit_to_int( int ch )
|
---|
| 259 | {
|
---|
| 260 | static char const xdigits[] = "0123456789abcdef";
|
---|
| 261 |
|
---|
| 262 | ch = std::tolower( static_cast< unsigned char >( ch ) );
|
---|
| 263 | char const* s = std::strchr( xdigits, ch );
|
---|
| 264 | if ( s == 0 )
|
---|
| 265 | {
|
---|
| 266 | return -1;
|
---|
| 267 | }
|
---|
| 268 | return s - xdigits;
|
---|
| 269 | }
|
---|
| 270 |
|
---|
| 271 | }
|
---|