s_record.cpp

00001 /*
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 によって生成されました。