00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "CeylanInputStream.h"
00028
00029 #include "CeylanThread.h"
00030 #include "CeylanOperators.h"
00031 #include "CeylanLogPlug.h"
00032 #include "CeylanTypes.h"
00033 #include "CeylanStringUtils.h"
00034 #include "CeylanEndianness.h"
00035 #include "CeylanNetwork.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #ifdef CEYLAN_USES_CONFIG_H
00059 #include "CeylanConfig.h"
00060 #endif // CEYLAN_USES_CONFIG_H
00061
00062
00063
00064 extern "C"
00065 {
00066
00067 #ifdef CEYLAN_USES_SYS_TYPES_H
00068 #include <sys/types.h>
00069 #endif // CEYLAN_USES_SYS_TYPES_H
00070
00071 #ifdef CEYLAN_USES_UNISTD_H
00072 #include <unistd.h>
00073 #endif // CEYLAN_USES_UNISTD_H
00074
00075 #ifdef CEYLAN_USES_STRINGS_H
00076 #include <strings.h>
00077 #endif // CEYLAN_USES_STRINGS_H
00078
00079 #ifdef CEYLAN_USES_SYS_SELECT_H
00080 #include <sys/select.h>
00081 #endif // CEYLAN_USES_SYS_SELECT_H
00082
00083 #ifdef CEYLAN_USES_WINSOCK2_H
00084 #include <winsock2.h>
00085 #endif // CEYLAN_USES_WINSOCK2_H
00086
00087 }
00088
00089
00090 #include <ctime>
00091 #include <cerrno>
00092
00093
00094
00095 using std::string ;
00096 using std::list ;
00097
00098
00099 using namespace Ceylan::System ;
00100 using namespace Ceylan::Log ;
00101 using namespace Ceylan ;
00102
00103
00104
00105 InputStream::InputStream( bool blocking ) :
00106 Stream( blocking ),
00107 _isSelected( false ),
00108 _isFaulty( false )
00109 {
00110
00111 }
00112
00113
00114
00115 InputStream::~InputStream() throw()
00116 {
00117
00118 }
00119
00120
00121
00122 bool InputStream::isSelected() const
00123 {
00124
00125 return _isSelected ;
00126
00127 }
00128
00129
00130
00131 bool InputStream::isFaulty() const
00132 {
00133
00134 return _isFaulty ;
00135
00136 }
00137
00138
00139
00140 const std::string InputStream::toString( Ceylan::VerbosityLevels level ) const
00141 {
00142
00143 string res = "InputStream whose ID is "
00144 + Ceylan::toString( getInputStreamID() ) + ", which is " ;
00145
00146 if ( ! isSelected() )
00147 res += "not " ;
00148
00149 res += "selected, and which is " ;
00150
00151 if ( ! isFaulty() )
00152 res += "not " ;
00153
00154 res += "faulty" ;
00155
00156 res += ". This is a " + Stream::toString( level ) ;
00157
00158 return res ;
00159
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169 Size InputStream::read( Ceylan::Byte * buffer, Size length )
00170 {
00171
00172 throw ReadFailedException( "InputStream::read failed: "
00173 "this method should have been subclassed." ) ;
00174
00175 }
00176
00177
00178
00179 void InputStream::clearInput()
00180 {
00181
00182 Ceylan::Byte b ;
00183
00184 while ( hasAvailableData() )
00185 read( &b, 1 ) ;
00186
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 Ceylan::Sint8 InputStream::readSint8()
00204 {
00205
00206 const Ceylan::Uint8 TypeSize = 1 ;
00207
00208 Ceylan::Byte tempBuffer[ TypeSize ] ;
00209
00210 Size readCount = read( tempBuffer, TypeSize ) ;
00211
00212 if ( readCount < TypeSize )
00213 throw EOFException( "InputStream::readSint8" ) ;
00214
00215 return * reinterpret_cast<Ceylan::Sint8 *>( tempBuffer ) ;
00216
00217 }
00218
00219
00220
00221 Ceylan::Uint8 InputStream::readUint8()
00222 {
00223
00224 const Ceylan::Uint8 TypeSize = 1 ;
00225
00226 Ceylan::Byte tempBuffer[ TypeSize ] ;
00227
00228 Size readCount = read( tempBuffer, TypeSize ) ;
00229
00230 if ( readCount < TypeSize )
00231 throw EOFException( "InputStream::readUint8" ) ;
00232
00233 return * reinterpret_cast<Ceylan::Uint8 *>( tempBuffer ) ;
00234
00235 }
00236
00237
00238
00239 Ceylan::Sint16 InputStream::readSint16()
00240 {
00241
00242 const Ceylan::Uint8 TypeSize = 2 ;
00243
00244 Ceylan::Byte tempBuffer[ TypeSize ] ;
00245
00246 Size readCount = read( tempBuffer, TypeSize ) ;
00247
00248 if ( readCount < TypeSize )
00249 throw EOFException( "InputStream::readSint16" ) ;
00250
00251 Ceylan::Sint16 * ret = reinterpret_cast<Ceylan::Sint16 *>( tempBuffer ) ;
00252
00253
00254 #if CEYLAN_RUNS_ON_LITTLE_ENDIAN
00255
00256 return *ret ;
00257
00258 #else // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00259
00260 return ceylan_bswap_16( *ret ) ;
00261
00262 #endif // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00263
00264 }
00265
00266
00267
00268 Ceylan::Uint16 InputStream::readUint16()
00269 {
00270
00271 const Ceylan::Uint8 TypeSize = 2 ;
00272
00273 Ceylan::Byte tempBuffer[ TypeSize ] ;
00274
00275 Size readCount = read( tempBuffer, TypeSize ) ;
00276
00277 if ( readCount < TypeSize )
00278 throw EOFException( "InputStream::readUint16" ) ;
00279
00280 Ceylan::Uint16 * ret = reinterpret_cast<Ceylan::Uint16 *>( tempBuffer ) ;
00281
00282
00283 #if CEYLAN_RUNS_ON_LITTLE_ENDIAN
00284
00285 return *ret ;
00286
00287 #else // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00288
00289 return ceylan_bswap_16( *ret ) ;
00290
00291
00292 #endif // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00293
00294 }
00295
00296
00297
00298 Ceylan::Sint32 InputStream::readSint32()
00299 {
00300
00301 const Ceylan::Uint8 TypeSize = 4 ;
00302
00303 Ceylan::Byte tempBuffer[ TypeSize ] ;
00304
00305 Size readCount = read( tempBuffer, TypeSize ) ;
00306
00307 if ( readCount < TypeSize )
00308 throw EOFException( "InputStream::readSint32" ) ;
00309
00310 Ceylan::Sint32 * ret = reinterpret_cast<Ceylan::Sint32 *>( tempBuffer ) ;
00311
00312
00313 #if CEYLAN_RUNS_ON_LITTLE_ENDIAN
00314
00315 return *ret ;
00316
00317 #else // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00318
00319 return ceylan_bswap_32( *ret ) ;
00320
00321 #endif // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00322
00323 }
00324
00325
00326
00327 Ceylan::Uint32 InputStream::readUint32()
00328 {
00329
00330 const Ceylan::Uint8 TypeSize = 4 ;
00331
00332 Ceylan::Byte tempBuffer[ TypeSize ] ;
00333
00334 Size readCount = read( tempBuffer, TypeSize ) ;
00335
00336 if ( readCount < TypeSize )
00337 throw EOFException( "InputStream::readUint32" ) ;
00338
00339 Ceylan::Uint32 * ret = reinterpret_cast<Ceylan::Uint32 *>( tempBuffer ) ;
00340
00341
00342 #if CEYLAN_RUNS_ON_LITTLE_ENDIAN
00343
00344 return *ret ;
00345
00346 #else // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00347
00348 return ceylan_bswap_32( *ret ) ;
00349
00350 #endif // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00351
00352 }
00353
00354
00355
00356 Ceylan::Float32 InputStream::readFloat32()
00357 {
00358
00359 const Ceylan::Uint8 TypeSize = 4 ;
00360
00361 Ceylan::Byte tempBuffer[ TypeSize ] ;
00362
00363 Size readCount = read( tempBuffer, TypeSize ) ;
00364
00365 if ( readCount < TypeSize )
00366 throw EOFException( "InputStream::readFloat32" ) ;
00367
00368
00369 #if CEYLAN_RUNS_ON_LITTLE_ENDIAN
00370
00371 Ceylan::Float32 * ret = reinterpret_cast<Ceylan::Float32 *>( tempBuffer ) ;
00372 return *ret ;
00373
00374 #else // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00375
00376 Ceylan::Uint32 * tmp = reinterpret_cast<Ceylan::Uint32 *>( tempBuffer ) ;
00377
00378
00379 *tmp = ceylan_bswap_32( *tmp ) ;
00380
00381 Ceylan::Float32 * ret = reinterpret_cast<Ceylan::Float32 *>( tmp ) ;
00382
00383 return *ret ;
00384
00385
00386 #endif // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00387
00388 }
00389
00390
00391
00392 Ceylan::Float64 InputStream::readFloat64()
00393 {
00394
00395 const Ceylan::Uint8 TypeSize = 8 ;
00396
00397 Ceylan::Byte tempBuffer[ TypeSize ] ;
00398
00399 Size readCount = read( tempBuffer, TypeSize ) ;
00400
00401 if ( readCount < TypeSize )
00402 throw EOFException( "InputStream::readFloat64" ) ;
00403
00404
00405 #if CEYLAN_RUNS_ON_LITTLE_ENDIAN
00406
00407 Ceylan::Float64 * ret = reinterpret_cast<Ceylan::Float64 *>( tempBuffer ) ;
00408 return *ret ;
00409
00410 #else // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00411
00412 Ceylan::Uint64 * tmp = reinterpret_cast<Ceylan::Uint64 *>( tempBuffer ) ;
00413
00414
00415
00416 #ifdef CEYLAN_FAKES_64_BIT_TYPE
00417
00418 Ceylan::byteswap( *tmp ) ;
00419
00420 #else // CEYLAN_FAKES_64_BIT_TYPE
00421
00422 *tmp = ceylan_bswap_64( *tmp ) ;
00423
00424 #endif // CEYLAN_FAKES_64_BIT_TYPE
00425
00426
00427 Ceylan::Float64 * ret = reinterpret_cast<Ceylan::Float64 *>( tmp ) ;
00428
00429 return *ret ;
00430
00431 #endif // CEYLAN_RUNS_ON_LITTLE_ENDIAN
00432
00433 }
00434
00435
00436
00437 void InputStream::readString( std::string & result )
00438 {
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 Uint16 stringSize = readUint16() ;
00449
00450 #if CEYLAN_DEBUG_LOW_LEVEL_STREAMS
00451 LogPlug::debug( "InputStream::readString: string size is "
00452 + Ceylan::toString( stringSize ) + " characters." ) ;
00453 #endif // CEYLAN_DEBUG_LOW_LEVEL_STREAMS
00454
00455
00456
00457 result.erase() ;
00458
00459 if ( stringSize == 0 )
00460 return ;
00461
00462
00463 const Sint16 thresholdSize = 255 ;
00464
00465 if ( stringSize < thresholdSize )
00466 {
00467
00468
00469
00470 Ceylan::Byte tempBuffer[thresholdSize] ;
00471
00472 Size readSize = read( tempBuffer, stringSize ) ;
00473
00474 if ( readSize < stringSize )
00475 throw EOFException( "In InputStream::readString." ) ;
00476
00477
00478 tempBuffer[stringSize] = 0 ;
00479
00480 result = tempBuffer ;
00481
00482 }
00483 else
00484 {
00485
00486
00487
00488
00489
00490
00491
00492
00493 Ceylan::Byte * tempBuffer = new Ceylan::Byte[ stringSize + 1 ] ;
00494
00495 Size readSize = read( tempBuffer, stringSize ) ;
00496
00497 if ( readSize < stringSize )
00498 {
00499 delete tempBuffer ;
00500 throw EOFException( "In InputStream::readString." ) ;
00501 }
00502
00503
00504 tempBuffer[stringSize] = 0 ;
00505
00506 result = tempBuffer ;
00507 delete tempBuffer ;
00508
00509
00510 }
00511
00512 }
00513
00514
00515
00516 void InputStream::skipWhitespaces( Ceylan::Uint8 & firstNonSpace )
00517 {
00518
00519 Ceylan::Uint8 readChar ;
00520
00521 do
00522 {
00523
00524 readChar = readUint8() ;
00525
00526 } while ( Ceylan::isWhitespace( static_cast<char>( readChar ) ) ) ;
00527
00528 firstNonSpace = readChar ;
00529
00530 }
00531
00532
00533
00534 Ceylan::Uint16 InputStream::Select( list<InputStream*> & is )
00535 {
00536
00537 #if CEYLAN_ARCH_NINTENDO_DS
00538
00539 throw InputStream::SelectFailedException( "InputStream::Select: "
00540 "not available on the Nintendo DS." ) ;
00541
00542 #else // CEYLAN_ARCH_NINTENDO_DS
00543
00544
00545 #if CEYLAN_ARCH_WINDOWS
00546
00547 #if CEYLAN_USES_NETWORK
00548
00549
00550 if ( is.empty() )
00551 return 0 ;
00552
00553
00554 fd_set waitFDSet ;
00555 FD_ZERO( & waitFDSet ) ;
00556
00557
00558 FileDescriptor maxFD = 0 ;
00559
00560 for ( list<InputStream*>::iterator it = is.begin(); it != is.end(); it++ )
00561 {
00562 if ( *it )
00563 {
00564 FileDescriptor fd = (*it)->getInputStreamID() ;
00565 FD_SET( fd, & waitFDSet ) ;
00566 (*it)->setSelected( false ) ;
00567 if ( fd > maxFD )
00568 maxFD = fd ;
00569 }
00570 }
00571
00573 const int selectAttemptCount = 5 ;
00574
00575
00577
00583 const Ceylan::Uint8 selectWaitingTime = 2 ;
00584
00585 Ceylan::Uint8 attemptCount = selectAttemptCount ;
00586
00587 int selectedCount ;
00588
00589 for ( ; attemptCount; attemptCount-- )
00590 {
00591
00592
00593
00594 selectedCount = ::select(
00595 maxFD + 1,
00596 & waitFDSet,
00597 0,
00598 0,
00599 0 ) ;
00600
00601 if ( selectedCount == SOCKET_ERROR )
00602 {
00603
00604
00605 Network::SocketError error = Network::getSocketError() ;
00606 if ( error == WSAEBADF || error == WSAENOTSOCK )
00607 {
00608
00609 LogPlug::error( "InputStream::Select: there seems to be "
00610 "at least one bad file descriptor in the list, "
00611 "checking them to flag them as faulty ("
00612 + ( ( error == WSAEBADF ) ?
00613 string( "WSAEBADF" ) : string( "WSAENOTSOCK" ) )
00614 + ")." ) ;
00615
00616 for ( list<InputStream*>::iterator it = is.begin();
00617 it != is.end(); it++ )
00618 {
00619
00620 fd_set testFDSet ;
00621 FD_ZERO( & testFDSet ) ;
00622
00623 FileDescriptor testedFD = (*it)->getInputStreamID() ;
00624 FD_SET( testedFD, & testFDSet ) ;
00625
00626
00627 struct timeval timeout ;
00628 timeout.tv_sec = 0 ;
00629 timeout.tv_usec = 0 ;
00630
00631 if ( ::select(
00632 testedFD + 1,
00633 &testFDSet,
00634 0,
00635 0,
00636 &timeout ) == SOCKET_ERROR )
00637 {
00638
00639 error = Network::getSocketError() ;
00640 if ( error == WSAEBADF || error == WSAENOTSOCK )
00641 {
00642
00643 LogPlug::error( "InputStream::Select: "
00644 "following stream is faulty: "
00645 + (*it)->toString()
00646 + ", flagging it as such ("
00647 + ( ( error == WSAEBADF ) ?
00648 string( "WSAEBADF" ) :
00649 string( "WSAENOTSOCK" ) )
00650 + ")." ) ;
00651 (*it)->setFaulty( true ) ;
00652
00653 }
00654
00655 }
00656
00657 }
00658 }
00659 else
00660 {
00661
00662 LogPlug::error( "InputStream::Select: "
00663 "no InputStream selected (" + Network::explainSocketError()
00664 + "), retrying in " + Ceylan::toString( selectWaitingTime )
00665 + " second(s) ..." ) ;
00666
00667 Thread::Sleep( selectWaitingTime ) ;
00668
00669 }
00670
00671
00672 }
00673 else
00674 {
00675 if ( selectedCount > 0 )
00676 break ;
00677 }
00678
00679 }
00680
00681 if ( attemptCount == 0 )
00682 throw SelectFailedException( string( "After " )
00683 + selectAttemptCount
00684 + " attempts, still no InputStream selected." ) ;
00685
00686
00687 selectedCount = 0 ;
00688 for ( list<InputStream*>::iterator it = is.begin(); it != is.end(); it++ )
00689 {
00690 if ( *it && ( FD_ISSET( (*it)->getInputStreamID(), & waitFDSet ) ) )
00691 {
00692 selectedCount++ ;
00693 (*it)->setSelected( true ) ;
00694 }
00695 }
00696
00697 return selectedCount ;
00698
00699
00700 #else // CEYLAN_USES_NETWORK
00701
00702 throw InputStream::SelectFailedException(
00703 "InputStream::Select operation not supported on Windows "
00704 "when the network feature is disabled." ) ;
00705
00706 #endif // CEYLAN_USES_NETWORK
00707
00708 #else // CEYLAN_ARCH_WINDOWS
00709
00710 #if CEYLAN_USES_FILE_DESCRIPTORS
00711
00712
00713 if ( is.empty() )
00714 return 0 ;
00715
00716
00717 fd_set waitFDSet ;
00718 FD_ZERO( & waitFDSet ) ;
00719
00720
00721 FileDescriptor maxFD = -1 ;
00722
00723 for ( list<InputStream*>::iterator it = is.begin(); it != is.end(); it++ )
00724 {
00725 if ( *it )
00726 {
00727 FileDescriptor fd = (*it)->getInputStreamID() ;
00728 FD_SET( fd, & waitFDSet ) ;
00729 (*it)->setSelected( false ) ;
00730 if ( fd > maxFD )
00731 maxFD = fd ;
00732 }
00733 }
00734
00736 const int selectAttemptCount = 5 ;
00737
00738
00740
00746 const Ceylan::Uint8 selectWaitingTime = 2 ;
00747
00748 Ceylan::Uint8 attemptCount = selectAttemptCount ;
00749
00750 int selectedCount ;
00751
00752 for ( ; attemptCount; attemptCount-- )
00753 {
00754
00755
00756
00757 selectedCount = ::select(
00758 maxFD + 1,
00759 & waitFDSet,
00760 0,
00761 0,
00762 0 ) ;
00763
00764 if ( selectedCount < 0 )
00765 {
00766
00767
00768
00769 if ( System::getError() == EBADF )
00770 {
00771
00772 LogPlug::error( "InputStream::Select: there seems to be "
00773 "at least one bad file descriptor in the list, "
00774 "checking them to flag them as faulty." ) ;
00775
00776 for ( list<InputStream*>::iterator it = is.begin();
00777 it != is.end(); it++ )
00778 {
00779
00780 fd_set testFDSet ;
00781 FD_ZERO( & testFDSet ) ;
00782
00783 FileDescriptor testedFD = (*it)->getInputStreamID() ;
00784 FD_SET( testedFD, & testFDSet ) ;
00785
00786
00787 struct timeval timeout ;
00788 timeout.tv_sec = 0 ;
00789 timeout.tv_usec = 0 ;
00790
00791 if ( ( ::select( testedFD + 1,
00792 &testFDSet, 0, 0, &timeout ) < 0 )
00793 && ( System::getError() == EBADF ) )
00794 {
00795
00796 LogPlug::error( "InputStream::Select: "
00797 "following stream is faulty: "
00798 + (*it)->toString()
00799 + ", flagging it as such." ) ;
00800 (*it)->setFaulty( true ) ;
00801
00802 }
00803
00804 }
00805 }
00806 else
00807 {
00808
00809 LogPlug::error( "InputStream::Select: "
00810 "no InputStream selected (" + explainError()
00811 + "), retrying in " + Ceylan::toString( selectWaitingTime )
00812 + " second(s) ..." ) ;
00813
00814 Thread::Sleep( selectWaitingTime ) ;
00815
00816 }
00817
00818
00819 }
00820 else
00821 {
00822 if ( selectedCount > 0 )
00823 break ;
00824 }
00825
00826 }
00827
00828 if ( attemptCount == 0 )
00829 throw SelectFailedException( string( "After " )
00830 + selectAttemptCount
00831 + " attempts, still no InputStream selected." ) ;
00832
00833
00834 selectedCount = 0 ;
00835 for ( list<InputStream*>::iterator it = is.begin(); it != is.end(); it++ )
00836 {
00837 if ( *it && ( FD_ISSET( (*it)->getInputStreamID(), & waitFDSet ) ) )
00838 {
00839 selectedCount++ ;
00840 (*it)->setSelected( true ) ;
00841 }
00842 }
00843
00844 return selectedCount ;
00845
00846
00847 #else // CEYLAN_USES_FILE_DESCRIPTORS
00848
00849
00850 throw SelectFailedException( "InputStream::Select: "
00851 "File descriptor feature not available on this platform." ) ;
00852
00853 #endif // CEYLAN_USES_FILE_DESCRIPTORS
00854
00855 #endif // CEYLAN_ARCH_WINDOWS
00856
00857 #endif // CEYLAN_ARCH_NINTENDO_DS
00858
00859 }
00860
00861
00862
00863 Ceylan::Uint16 InputStream::Test( list<InputStream*> & is )
00864 {
00865
00866 #if CEYLAN_ARCH_NINTENDO_DS
00867
00868 throw InputStream::SelectFailedException( "InputStream::Test: "
00869 "not available on the Nintendo DS." ) ;
00870
00871 #else // CEYLAN_ARCH_NINTENDO_DS
00872
00873 #if CEYLAN_USES_FILE_DESCRIPTORS
00874
00875 if ( is.empty() )
00876 return 0 ;
00877
00878
00879 struct timeval tv ;
00880 tv.tv_sec = 0 ;
00881 tv.tv_usec = 0 ;
00882
00883
00884 fd_set waitFDSet ;
00885 FD_ZERO( & waitFDSet ) ;
00886
00887 FileDescriptor maxFD = -1 ;
00888
00889
00890 for ( list<InputStream*>::iterator it = is.begin(); it != is.end(); it++ )
00891 {
00892 if ( *it )
00893 {
00894 FileDescriptor fd = (*it)->getInputStreamID() ;
00895 FD_SET( fd, & waitFDSet ) ;
00896 (*it)->setSelected( false ) ;
00897 if ( fd > maxFD )
00898 maxFD = fd ;
00899 }
00900 }
00901
00902 if ( ::select( maxFD + 1, & waitFDSet, 0, 0, & tv ) < 0 )
00903 {
00904
00905
00906
00907 if ( System::getError() == EBADF )
00908 {
00909
00910 LogPlug::error( "InputStream::Test: there seems to be "
00911 "at least one bad file descriptor in the list, "
00912 "checking them to flag them as faulty." ) ;
00913
00914 for ( list<InputStream*>::iterator it = is.begin();
00915 it != is.end(); it++ )
00916 {
00917
00918 fd_set testFDSet ;
00919 FD_ZERO( & testFDSet ) ;
00920
00921 FileDescriptor testedFD = (*it)->getInputStreamID() ;
00922 FD_SET( testedFD, & testFDSet ) ;
00923
00924
00925 struct timeval timeout ;
00926 timeout.tv_sec = 0 ;
00927 timeout.tv_usec = 0 ;
00928
00929 if ( ( ::select( testedFD + 1,
00930 &testFDSet, 0, 0, &timeout ) < 0 )
00931 && ( System::getError() == EBADF ) )
00932 {
00933
00934 LogPlug::error( "InputStream::Select: "
00935 "following stream is faulty: " + (*it)->toString()
00936 + ", flagging it as such." ) ;
00937
00938 (*it)->setFaulty( true ) ;
00939
00940 }
00941
00942 }
00943
00944 }
00945 else
00946 {
00947
00948 throw SelectFailedException(
00949 "InputStream select failed in non-blocking test method: "
00950 + explainError( getError() ) ) ;
00951 }
00952
00953
00954 }
00955
00956
00957 Ceylan::Uint16 selectedCount = 0 ;
00958 for ( list<InputStream*>::iterator it = is.begin(); it != is.end(); it++ )
00959 {
00960 if ( *it && ( FD_ISSET( (*it)->getInputStreamID(), & waitFDSet ) ) )
00961 {
00962 selectedCount++ ;
00963 (*it)->setSelected( true ) ;
00964 }
00965 }
00966
00967 return selectedCount ;
00968
00969 #else // if CEYLAN_USES_FILE_DESCRIPTORS
00970
00971
00972 throw SelectFailedException( "InputStream::Test: "
00973 "File descriptor feature not available on this platform." ) ;
00974
00975 #endif // if CEYLAN_USES_FILE_DESCRIPTORS
00976
00977 #endif // CEYLAN_ARCH_NINTENDO_DS
00978
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 void InputStream::setSelected( bool newStatus )
00990 {
00991
00992 #if CEYLAN_DEBUG_LOW_LEVEL_STREAMS
00993 if ( ( _isSelected == false ) && ( newStatus == true ) )
00994 LogPlug::debug( "InputStream::setSelected: selecting descriptor #"
00995 + Ceylan::toString( getInputStreamID() ) ) ;
00996 #endif // CEYLAN_DEBUG_LOW_LEVEL_STREAMS
00997
00998 _isSelected = newStatus ;
00999
01000 }
01001
01002
01003
01004 void InputStream::setFaulty( bool newFaultyState )
01005 {
01006
01007 _isFaulty = newFaultyState ;
01008
01009 }
01010
01011
01012
01013 void InputStream::setStreamID( StreamID newInputStreamID )
01014 {
01015 throw InputStreamException( "InputStream::setStreamID: "
01016 "operation not supportedby this class." ) ;
01017 }
01018