stream.bmx 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. SuperStrict
  2. Rem
  3. bbdoc: Streams/Streams
  4. End Rem
  5. Module BRL.Stream
  6. ModuleInfo "Version: 1.11"
  7. ModuleInfo "Author: Mark Sibly"
  8. ModuleInfo "License: zlib/libpng"
  9. ModuleInfo "Copyright: Blitz Research Ltd"
  10. ModuleInfo "Modserver: BRL"
  11. ModuleInfo "History: 1.11"
  12. ModuleInfo "History: Streams can now be opened for appending with the new WRITE_MODE_APPEND write mode."
  13. ModuleInfo "History: 1.10"
  14. ModuleInfo "History: Module is now SuperStrict"
  15. ModuleInfo "History: 1.09 Release"
  16. ModuleInfo "History: Fixed 'excpetion' typos"
  17. ModuleInfo "History: 1.08 Release"
  18. ModuleInfo "History: Fixed resource leak in CasedFileName"
  19. ModuleInfo "History: 1.07 Release"
  20. ModuleInfo "History: OpenStream protocol:: now case insensitive"
  21. ModuleInfo "History: Fixed ReadString with 0 length strings"
  22. ModuleInfo "History: Removed LoadStream - use LoadByteArray instead"
  23. ModuleInfo "History: Removed AddStreamFactory function"
  24. ModuleInfo "History: Added url parameter to TStreamFactory CreateStream method"
  25. ModuleInfo "History: 1.06 Release"
  26. ModuleInfo "History: Added checks to CStream for reading from write only stream and vice versa"
  27. ModuleInfo "History: 1.05 Release"
  28. ModuleInfo "History: Fixed Eof bug"
  29. ModuleInfo "History: 1.04 Release"
  30. ModuleInfo "History: Added LoadString"
  31. ModuleInfo "History: Added LoadByteArray"
  32. ModuleInfo "History: Cleaned up docs a bit"
  33. Import BRL.IO
  34. Import Pub.StdC
  35. Rem
  36. bbdoc: Base exception type thrown by streams
  37. End Rem
  38. Type TStreamException
  39. End Type
  40. Rem
  41. bbdoc: Exception type thrown by streams in the event of read errors
  42. about:
  43. #TStreamReadException is usually thrown when a stream operation failed to read enough
  44. bytes. For example, if the stream ReadInt method fails to read 4 bytes, it will throw
  45. a #TStreamReadException.
  46. End Rem
  47. Type TStreamReadException Extends TStreamException
  48. Method ToString:String() Override
  49. Return "Error reading from stream"
  50. End Method
  51. End Type
  52. Rem
  53. bbdoc: Exception type thrown by streams in the event of write errors
  54. about:
  55. #TStreamWriteException is usually thrown when a stream operation failed to write enough
  56. bytes. For example, if the stream WriteInt method fails to write 4 bytes, it will throw
  57. a #TStreamWriteException.
  58. End Rem
  59. Type TStreamWriteException Extends TStreamException
  60. Method ToString:String() Override
  61. Return "Error writing to stream"
  62. End Method
  63. End Type
  64. Rem
  65. bbdoc: Base input/output type
  66. about:
  67. To create your own stream types, you should extend TStream and implement
  68. at least these methods.
  69. You should also make sure your stream can handle multiple calls to the Close method.
  70. End Rem
  71. Type TIO
  72. Rem
  73. bbdoc: Get stream end of file status
  74. returns: True for end of file reached, otherwise False
  75. about:
  76. For seekable streams such as file streams, Eof generally returns True if the file
  77. position equals the file size. This means that no more bytes can be read from the
  78. stream. However, it may still be possible to write bytes, in which case the file will
  79. 'grow'.
  80. For communication type streams such as socket streams, Eof returns True if the stream
  81. has been shut down for some reason - either locally or by the remote host. In this case,
  82. no more bytes can be read from or written to the stream.
  83. End Rem
  84. Method Eof:Int()
  85. Return Pos()=Size()
  86. End Method
  87. Rem
  88. bbdoc: Get position of seekable stream
  89. returns: Stream position as a byte offset, or -1 if stream is not seekable
  90. End Rem
  91. Method Pos:Long()
  92. Return -1
  93. End Method
  94. Rem
  95. bbdoc: Get size of seekable stream
  96. returns: Size, in bytes, of seekable stream, or 0 if stream is not seekable
  97. End Rem
  98. Method Size:Long()
  99. Return 0
  100. End Method
  101. Rem
  102. bbdoc: Seek to position in seekable stream
  103. returns: New stream position, or -1 if stream is not seekable
  104. End Rem
  105. Method Seek:Long( pos:Long, whence:Int = SEEK_SET_ )
  106. Return -1
  107. End Method
  108. Rem
  109. bbdoc: Flush stream
  110. about:
  111. Flushes any internal stream buffers.
  112. End Rem
  113. Method Flush()
  114. End Method
  115. Rem
  116. bbdoc: Close stream
  117. about:
  118. Closes the stream after flushing any internal stream buffers.
  119. End Rem
  120. Method Close()
  121. End Method
  122. Rem
  123. bbdoc: Read at least 1 byte from a stream
  124. returns: Number of bytes successfully read
  125. about:
  126. This method may 'block' if it is not possible to read at least one byte due to IO
  127. buffering.
  128. If this method returns 0, the stream has reached end of file.
  129. End Rem
  130. Method Read:Long( buf:Byte Ptr,count:Long )
  131. RuntimeError "Stream is not readable"
  132. Return 0
  133. End Method
  134. Rem
  135. bbdoc: Write at least 1 byte to a stream
  136. returns: Number of bytes successfully written
  137. about:
  138. This method may 'block' if it is not possible to write at least one byte due to IO
  139. buffering.
  140. If this method returns 0, the stream has reached end of file.
  141. End Rem
  142. Method Write:Long( buf:Byte Ptr,count:Long )
  143. RuntimeError "Stream is not writeable"
  144. Return 0
  145. End Method
  146. Rem
  147. bbdoc: Sets the size of the stream to @size bytes.
  148. returns: #True if the stream was able to be resized, #False otherwise.
  149. about: Only a few stream types support resizing.
  150. End Rem
  151. Method SetSize:Int(size:Long)
  152. RuntimeError "Stream does not support resizing"
  153. Return 0
  154. End Method
  155. Method Delete()
  156. Close
  157. End Method
  158. End Type
  159. Rem
  160. bbdoc: Data stream type
  161. about:
  162. #TStream extends #TIO to provide methods for reading and writing various types of values
  163. to and from a stream.
  164. Note that methods dealing with strings - ReadLine, WriteLine, ReadString and WriteString -
  165. assume that strings are represented by bytes in the stream. In future, a more powerful
  166. TextStream type will be added capable of decoding text streams in multiple formats.
  167. End Rem
  168. Type TStream Extends TIO
  169. Rem
  170. bbdoc: Reads bytes from a stream
  171. about:
  172. #ReadBytes reads @count bytes from the stream into the memory block specified by @buf.
  173. If @count bytes were not successfully read, a #TStreamReadException is thrown. This typically
  174. occurs due to end of file.
  175. End Rem
  176. Method ReadBytes:Long( buf:Byte Ptr,count:Long )
  177. Local t:Long=count
  178. While count>0
  179. Local n:Long=Read( buf,count )
  180. If Not n Throw New TStreamReadException
  181. count:-n
  182. buf:+n
  183. Wend
  184. Return t
  185. End Method
  186. Rem
  187. bbdoc: Writes bytes to a stream
  188. about:
  189. #WriteBytes writes @count bytes from the memory block specified by @buf to the stream.
  190. If @count bytes were not successfully written, a #TStreamWriteException is thrown. This typically
  191. occurs due to end of file.
  192. End Rem
  193. Method WriteBytes:Long( buf:Byte Ptr,count:Long )
  194. Local t:Long=count
  195. While count>0
  196. Local n:Long=Write( buf,count )
  197. If Not n Throw New TStreamWriteException
  198. count:-n
  199. buf:+n
  200. Wend
  201. Return t
  202. End Method
  203. Rem
  204. bbdoc: Skip bytes in a stream
  205. about:
  206. #SkipBytes read @count bytes from the stream and throws them away.
  207. If @count bytes were not successfully read, a #TStreamReadException is thrown. This typically
  208. occurs due to end of file.
  209. End Rem
  210. Method SkipBytes:Long( count:Long )
  211. Local t:Long=count
  212. Local buf:Byte[1024]
  213. While count>0
  214. Local n:Long=Read( buf,Min(count,buf.length) )
  215. If Not n Throw New TStreamReadException
  216. count:-n
  217. Wend
  218. Return t
  219. End Method
  220. Rem
  221. bbdoc: Read a byte from the stream
  222. returns: The read value
  223. about:
  224. If a value could not be read (possibly due to end of file), a #TStreamReadException is thrown.
  225. End Rem
  226. Method ReadByte:Int()
  227. Local n:Byte
  228. ReadBytes Varptr n,1
  229. Return n
  230. End Method
  231. Rem
  232. bbdoc: Write a byte to the stream
  233. about:
  234. If the value could not be written (possibly due to end of file), a #TStreamWriteException is thrown.
  235. End Rem
  236. Method WriteByte( n:Int )
  237. Local q:Byte=n
  238. WriteBytes Varptr q,1
  239. End Method
  240. Rem
  241. bbdoc: Read a short (two bytes) from the stream
  242. returns: The read value
  243. about:
  244. If a value could not be read (possibly due to end of file), a #TStreamReadException is thrown.
  245. End Rem
  246. Method ReadShort:Int()
  247. Local n:Short
  248. ReadBytes Varptr n,2
  249. Return n
  250. End Method
  251. Method ReadShort:Int(buf:Byte Ptr)
  252. Return ReadBytes(buf,2)
  253. End Method
  254. Rem
  255. bbdoc: Write a short (two bytes) to the stream
  256. about:
  257. If the value could not be written (possibly due to end of file), a #TStreamWriteException is thrown.
  258. End Rem
  259. Method WriteShort( n:Int )
  260. Local q:Short=n
  261. WriteBytes Varptr q,2
  262. End Method
  263. Rem
  264. bbdoc: Read an int (four bytes) from the stream
  265. returns: The read value
  266. about:
  267. If a value could not be read (possibly due to end of file), a #TStreamReadException is thrown.
  268. End Rem
  269. Method ReadInt:Int()
  270. Local n:Int
  271. ReadBytes Varptr n,4
  272. Return n
  273. End Method
  274. Rem
  275. bbdoc: Write an int (four bytes) to the stream
  276. about:
  277. If the value could not be written (possibly due to end of file), a #TStreamWriteException is thrown.
  278. End Rem
  279. Method WriteInt( n:Int )
  280. Local q:Int=n
  281. WriteBytes Varptr q,4
  282. End Method
  283. Rem
  284. bbdoc: Read a long (eight bytes) from the stream
  285. returns: The read value
  286. about:
  287. If a value could not be read (possibly due to end of file), a #TStreamReadException is thrown.
  288. End Rem
  289. Method ReadLong:Long()
  290. Local n:Long
  291. ReadBytes Varptr n,8
  292. Return n
  293. End Method
  294. Rem
  295. bbdoc: Write a long (eight bytes) to the stream
  296. about:
  297. If the value could not be written (possibly due to end of file), a #TStreamWriteException is thrown.
  298. End Rem
  299. Method WriteLong( n:Long )
  300. Local q:Long=n
  301. WriteBytes Varptr q,8
  302. End Method
  303. Rem
  304. bbdoc: Read a float (four bytes) from the stream
  305. returns: The read value
  306. about:
  307. If a value could not be read (possibly due to end of file), a #TStreamReadException is thrown.
  308. End Rem
  309. Method ReadFloat:Float()
  310. Local n:Float
  311. ReadBytes Varptr n,4
  312. Return n
  313. End Method
  314. Rem
  315. bbdoc: Write a float (four bytes) to the stream
  316. about:
  317. If the value could not be written (possibly due to end of file), a #TStreamWriteException is thrown.
  318. End Rem
  319. Method WriteFloat( n:Float )
  320. Local q:Float=n
  321. WriteBytes Varptr q,4
  322. End Method
  323. Rem
  324. bbdoc: Read a double (eight bytes) from the stream
  325. returns: The read value
  326. about:
  327. If a value could not be read (possibly due to end of file), a #TStreamReadException is thrown.
  328. End Rem
  329. Method ReadDouble:Double()
  330. Local n:Double
  331. ReadBytes Varptr n,8
  332. Return n
  333. End Method
  334. Rem
  335. bbdoc: Write a double (eight bytes) to the stream
  336. about:
  337. If the value could not be written (possibly due to end of file), a #TStreamWriteException is thrown.
  338. End Rem
  339. Method WriteDouble( n:Double )
  340. Local q:Double=n
  341. WriteBytes Varptr q,8
  342. End Method
  343. Rem
  344. bbdoc: Read a line of text from the stream
  345. about:
  346. Bytes are read from the stream until a newline character (ascii code 10) or null
  347. character (ascii code 0) is read, or end of file is detected.
  348. Carriage return characters (ascii code 13) are silently ignored.
  349. The bytes read are returned in the form of a string, excluding any terminating newline
  350. or null character.
  351. End Rem
  352. Method ReadLine:String()
  353. return ReadLine(False)
  354. End Method
  355. Method ReadLine:String(asUTF8:Int)
  356. Local buf:Byte[1024],sz:Int
  357. Repeat
  358. Local ch:Byte
  359. If Read( Varptr ch,1 )<>1 Or ch=0 Or ch=10 Exit
  360. If ch=13 Continue
  361. If sz=buf.length buf=buf[..sz*2]
  362. buf[sz]=ch
  363. sz:+1
  364. Forever
  365. If asUTF8 Then
  366. Return String.FromUTF8Bytes( buf,sz )
  367. Else
  368. Return String.FromBytes( buf,sz )
  369. End If
  370. End Method
  371. Rem
  372. bbdoc: Write a line of text to the stream
  373. returns: True if line successfully written, else False
  374. about: A sequence of bytes is written to the stream (one for each character in @str)
  375. followed by the line terminating sequence "~r~n".
  376. End Rem
  377. Method WriteLine:Int( str:String )
  378. Return WriteLine(str, False)
  379. End Method
  380. Method WriteLine:Int( str:String, asUTF8:Int )
  381. Local buf:Byte Ptr
  382. Local length:Int
  383. If asUTF8 Then
  384. buf=str.ToUTF8String()
  385. length = strlen_(buf)
  386. Else
  387. buf=str.ToCString()
  388. length = str.length
  389. End If
  390. Local ok:Int=Write( buf,length )=length And Write( [13:Byte,10:Byte],2 )=2
  391. MemFree buf
  392. Return ok
  393. End Method
  394. Rem
  395. bbdoc: Read characters from the stream
  396. returns: A string composed of @length bytes read from the stream
  397. about:
  398. A #TStreamReadException is thrown if not all bytes could be read.
  399. End Rem
  400. Method ReadString:String( length:Int )
  401. Return ReadString(length, False)
  402. End Method
  403. Method ReadString:String( length:Int, asUTF8:Int )
  404. Assert length>=0 Else "Illegal String length"
  405. Local buf:Byte[length]
  406. Readbytes buf,length
  407. If asUTF8 Then
  408. Return String.FromUTF8Bytes( buf,length )
  409. Else
  410. Return String.FromBytes( buf,length )
  411. End If
  412. End Method
  413. Rem
  414. bbdoc: Write characters to the stream
  415. about:
  416. A #TStreamWriteException is thrown if not all bytes could be written.
  417. End Rem
  418. Method WriteString( str:String )
  419. WriteString(str, False)
  420. End Method
  421. Method WriteString( str:String, asUTF8:Int )
  422. Local buf:Byte Ptr
  423. Local length:Int
  424. If asUTF8 Then
  425. buf=str.ToUTF8String()
  426. length = strlen_(buf)
  427. Else
  428. buf=str.ToCString()
  429. length = str.length
  430. End If
  431. WriteBytes buf,length
  432. MemFree buf
  433. End Method
  434. Method ReadObject:Object()
  435. Throw "Unable to read object"
  436. End Method
  437. Method WriteObject( obj:Object )
  438. Throw "Unable to write object"
  439. End Method
  440. End Type
  441. Rem
  442. bbdoc: Utility stream wrapper type
  443. about:
  444. #TStreamWrapper 'wraps' an existing stream, redirecting all TIO method calls to the wrapped
  445. stream.
  446. This can be useful for writing stream 'filters' that modify the behaviour of existing
  447. streams.
  448. Note that the Close method causes the underlying stream to be closed, which may not always
  449. be desirable. If necessary, you should override Close with a NOP version.
  450. End Rem
  451. Type TStreamWrapper Extends TStream
  452. Field _stream:TStream
  453. Rem
  454. bbdoc: Set underlying stream
  455. about:
  456. Sets the stream to be 'wrapped'. All calls to TIO methods of this stream will be
  457. redirected to @stream.
  458. end rem
  459. Method SetStream( stream:TStream )
  460. _stream=stream
  461. End Method
  462. Method Eof:Int() Override
  463. Return _stream.Eof()
  464. End Method
  465. Method Pos:Long() Override
  466. Return _stream.Pos()
  467. End Method
  468. Method Size:Long() Override
  469. Return _stream.Size()
  470. End Method
  471. Method Seek:Long( pos:Long, whence:Int = SEEK_SET_ ) Override
  472. Return _stream.Seek( pos, whence )
  473. End Method
  474. Method Flush() Override
  475. _stream.Flush
  476. End Method
  477. Method Close() Override
  478. If _stream Then
  479. _stream.Close
  480. _stream = Null
  481. End If
  482. End Method
  483. Method Read:Long( buf:Byte Ptr,count:Long ) Override
  484. Return _stream.Read( buf,count )
  485. End Method
  486. Method Write:Long( buf:Byte Ptr,count:Long ) Override
  487. Return _stream.Write( buf,count )
  488. End Method
  489. Method ReadByte:Int() Override
  490. Return _stream.ReadByte()
  491. End Method
  492. Method WriteByte( n:Int ) Override
  493. _stream.WriteByte n
  494. End Method
  495. Method ReadShort:Int() Override
  496. Return _stream.ReadShort()
  497. End Method
  498. Method WriteShort( n:Int ) Override
  499. _stream.WriteShort n
  500. End Method
  501. Method ReadInt:Int() Override
  502. Return _stream.ReadInt()
  503. End Method
  504. Method WriteInt( n:Int ) Override
  505. _stream.WriteInt n
  506. End Method
  507. Method ReadFloat:Float() Override
  508. Return _stream.ReadFloat()
  509. End Method
  510. Method WriteFloat( n:Float ) Override
  511. _stream.WriteFloat n
  512. End Method
  513. Method ReadDouble:Double() Override
  514. Return _stream.ReadDouble()
  515. End Method
  516. Method WriteDouble( n:Double ) Override
  517. _stream.WriteDouble n
  518. End Method
  519. Method ReadLine:String() Override
  520. Return _stream.ReadLine()
  521. End Method
  522. Method ReadLine:String(asUTF8:Int) Override
  523. Return _stream.ReadLine(asUTF8)
  524. End Method
  525. Method WriteLine:Int( t:String ) Override
  526. Return _stream.WriteLine( t )
  527. End Method
  528. Method WriteLine:Int( t:String, asUTF8:Int ) Override
  529. Return _stream.WriteLine( t, asUTF8 )
  530. End Method
  531. Method ReadString:String( n:Int ) Override
  532. Return _stream.ReadString( n )
  533. End Method
  534. Method ReadString:String( n:Int, asUTF8:Int ) Override
  535. Return _stream.ReadString( n, asUTF8 )
  536. End Method
  537. Method WriteString( t:String ) Override
  538. _stream.WriteString(t)
  539. End Method
  540. Method WriteString( t:String, asUTF8:Int ) Override
  541. _stream.WriteString(t, asUTF8)
  542. End Method
  543. Method ReadObject:Object() Override
  544. Return _stream.ReadObject()
  545. End Method
  546. Method WriteObject( obj:Object ) Override
  547. _stream.WriteObject obj
  548. End Method
  549. Method SetSize:Int(size:Long) Override
  550. Return _stream.SetSize(size)
  551. End Method
  552. End Type
  553. Type TStreamStream Extends TStreamWrapper
  554. Method Close() Override
  555. SetStream Null
  556. End Method
  557. Function Create:TStreamStream( stream:TStream )
  558. Local t:TStreamStream=New TStreamStream
  559. t.SetStream stream
  560. Return t
  561. End Function
  562. End Type
  563. Type TFileStream Extends TStream
  564. Const MODE_READ:Int=1
  565. Const MODE_WRITE:Int=2
  566. Const MODE_APPEND:Int = 4
  567. Field _pos:Long,_size:Long,_mode:Int
  568. Field _stream:Byte Ptr
  569. Method Pos:Long() Override
  570. Return _pos
  571. End Method
  572. Method Size:Long() Override
  573. Return _size
  574. End Method
  575. Method Delete()
  576. Close
  577. End Method
  578. Function GetMode:String(readable:Int,writeMode:Int, _mode:Int Var)
  579. Local Mode:String
  580. If readable And writeMode = WRITE_MODE_OVERWRITE
  581. Mode="r+b"
  582. _mode=MODE_READ|MODE_WRITE
  583. Else If readable And writeMode = WRITE_MODE_APPEND
  584. Mode="a+b"
  585. _mode=MODE_READ|MODE_APPEND
  586. Else If writeMode = WRITE_MODE_OVERWRITE
  587. Mode="wb"
  588. _mode=MODE_WRITE
  589. Else If writeMode = WRITE_MODE_APPEND
  590. Mode="ab"
  591. _mode=MODE_APPEND
  592. Else
  593. Mode="rb"
  594. _mode=MODE_READ
  595. EndIf
  596. Return Mode
  597. End Function
  598. End Type
  599. Rem
  600. bbdoc: Standard C file stream type
  601. about:
  602. End Rem
  603. Type TCStream Extends TFileStream
  604. Method Seek:Long( pos:Long, whence:Int = SEEK_SET_ ) Override
  605. Assert _stream Else "Attempt to seek closed stream"
  606. fseek_ _stream,pos,whence
  607. _pos=ftell_( _stream )
  608. Return _pos
  609. End Method
  610. Method Read:Long( buf:Byte Ptr,count:Long ) Override
  611. Assert _stream Else "Attempt to read from closed stream"
  612. Assert _mode & MODE_READ Else "Attempt to read from write-only stream"
  613. count=fread_( buf,1,count,_stream )
  614. _pos:+count
  615. Return count
  616. End Method
  617. Method Write:Long( buf:Byte Ptr,count:Long ) Override
  618. Assert _stream Else "Attempt to write to closed stream"
  619. Assert _mode & (MODE_WRITE | MODE_APPEND) Else "Attempt to write to read-only stream"
  620. count=fwrite_( buf,1,count,_stream )
  621. _pos:+count
  622. If _pos>_size _size=_pos
  623. Return count
  624. End Method
  625. Method Flush() Override
  626. If _stream fflush_ _stream
  627. End Method
  628. Method Close() Override
  629. If Not _stream Return
  630. Flush
  631. fclose_ _stream
  632. _pos=0
  633. _size=0
  634. _stream=Null
  635. End Method
  636. Method SetSize:Int(size:Long) Override
  637. If Not _stream Return 0
  638. Flush()
  639. If _size > size Then
  640. Seek(size)
  641. End If
  642. Local res:Int = ftruncate_(_stream, size)
  643. Flush()
  644. If Not res Then
  645. _size = size
  646. End If
  647. Return res = 0
  648. End Method
  649. Rem
  650. bbdoc: Create a TCStream from a 'C' filename
  651. End Rem
  652. Function OpenFile:TCStream( path:String,readable:Int,writeMode:Int )
  653. Local Mode:String,_mode:Int
  654. Mode = GetMode(readable, writeMode, _mode)
  655. path=path.Replace( "\","/" )
  656. Local cstream:Byte Ptr=fopen_( path,Mode )
  657. ?Linux
  658. If (Not cstream) And (Not writeMode)
  659. path=CasedFileName(path)
  660. If path cstream=fopen_( path,Mode )
  661. EndIf
  662. ?
  663. If cstream Return CreateWithCStream( cstream,_mode )
  664. End Function
  665. Rem
  666. bbdoc: Create a TCStream from a 'C' stream handle
  667. end rem
  668. Function CreateWithCStream:TCStream( cstream:Byte Ptr,Mode:Int )
  669. Local stream:TCStream=New TCStream
  670. stream._stream=cstream
  671. stream._pos=ftell_( cstream )
  672. fseek_ cstream,0,SEEK_END_
  673. stream._size=ftell_( cstream )
  674. fseek_ cstream,stream._pos,SEEK_SET_
  675. stream._mode=Mode
  676. Return stream
  677. End Function
  678. End Type
  679. Private
  680. Global stream_factories:TStreamFactory
  681. Public
  682. Rem
  683. bbdoc: Base stream factory type
  684. about:
  685. Stream factories are used by the #OpenStream, #ReadStream and #WriteStream functions
  686. to create streams based on a 'url object'.
  687. Url objects are usually strings, in which case the url is divided into 2 parts - a
  688. protocol and a path. These are separated by a double colon string - "::".
  689. To create your own stream factories, you should extend the TStreamFactory type and
  690. implement the CreateStream method.
  691. To install your stream factory, simply create an instance of it using 'New'.
  692. End Rem
  693. Type TStreamFactory
  694. Field _succ:TStreamFactory
  695. Method New()
  696. _succ=stream_factories
  697. stream_factories=Self
  698. End Method
  699. Rem
  700. bbdoc: Create a stream based on a url object
  701. about:
  702. Types which extends TStreamFactory must implement this method.
  703. @url contains the original url object as supplied to #OpenStream, #ReadStream or
  704. #WriteStream.
  705. If @url is a string, @proto contains the url protocol - for example, the "incbin" part
  706. of "incbin::myfile".
  707. If @url is a string, @path contains the remainder of the url - for example, the "myfile"
  708. part of "incbin::myfile".
  709. If @url is not a string, both @proto and @path will be Null.
  710. End Rem
  711. Method CreateStream:TStream( url:Object,proto:String,path:String,readable:Int,writeMode:Int ) Abstract
  712. End Type
  713. Rem
  714. bbdoc: Open a stream for reading/writing/appending
  715. returns: A stream object
  716. about: All streams created by #OpenStream, #ReadStream, #WriteStream or #AppendStream should eventually be
  717. closed using #CloseStream.
  718. End Rem
  719. Function OpenStream:TStream( url:Object,readable:Int=True,writeMode:Int=WRITE_MODE_OVERWRITE )
  720. Local stream:TStream=TStream( url )
  721. If stream
  722. Return TStreamStream.Create( stream )
  723. EndIf
  724. Local str:String=String( url ),proto:String,path:String
  725. If str
  726. Local i:Int=str.Find( "::",0 )
  727. If i=-1 Then
  728. If MaxIO.ioInitialized Then
  729. Return TIOStream.OpenFile(str, readable, writemode)
  730. Else
  731. Return TCStream.OpenFile( str,readable,writeMode )
  732. End If
  733. End If
  734. proto=str[..i].ToLower()
  735. path=str[i+2..]
  736. EndIf
  737. Local factory:TStreamFactory=stream_factories
  738. While factory
  739. Local stream:TStream=factory.CreateStream( url,proto,path,readable,writeMode )
  740. If stream Return stream
  741. factory=factory._succ
  742. Wend
  743. End Function
  744. Rem
  745. bbdoc: Open a stream for reading
  746. returns: A stream object
  747. about: All streams created by #OpenStream, #ReadStream or #WriteStream should eventually
  748. be closed using #CloseStream.
  749. End Rem
  750. Function ReadStream:TStream( url:Object )
  751. Return OpenStream( url,True,False )
  752. End Function
  753. Rem
  754. bbdoc: Open a stream for writing
  755. returns: A stream object
  756. about: All streams created by #OpenStream, #ReadStream, #WriteStream or #AppendStream should eventually
  757. be closed using #CloseStream.
  758. End Rem
  759. Function WriteStream:TStream( url:Object )
  760. Return OpenStream( url,False,WRITE_MODE_OVERWRITE )
  761. End Function
  762. Rem
  763. bbdoc: Open a stream for appending
  764. returns: A stream object
  765. about: All streams created by #OpenStream, #ReadStream, #WriteStream or #AppendStream should eventually
  766. be closed using #CloseStream.
  767. End Rem
  768. Function AppendStream:TStream( url:Object )
  769. Return OpenStream( url,False,WRITE_MODE_APPEND )
  770. End Function
  771. Rem
  772. bbdoc: Get stream end of file status
  773. returns: True If stream is at end of file
  774. End Rem
  775. Function Eof:Int( stream:TStream )
  776. Return stream.Eof()
  777. End Function
  778. Rem
  779. bbdoc: Get current position of seekable stream
  780. returns: Current stream position, or -1 If stream is not seekable
  781. End Rem
  782. Function StreamPos:Long( stream:TStream )
  783. Return stream.Pos()
  784. End Function
  785. Rem
  786. bbdoc: Get current size of seekable stream
  787. returns: Current stream size in bytes, or -1 If stream is not seekable
  788. End Rem
  789. Function StreamSize:Long( stream:TStream )
  790. Return stream.Size()
  791. End Function
  792. Rem
  793. bbdoc: Set stream position of seekable stream
  794. returns: New stream position, or -1 If stream is not seekable
  795. End Rem
  796. Function SeekStream:Long( stream:TStream, pos:Long, whence:Int = SEEK_SET_ )
  797. Return stream.Seek( pos, whence )
  798. End Function
  799. Rem
  800. bbdoc: Flush a stream
  801. about: #FlushStream writes any outstanding buffered data to @stream.
  802. End Rem
  803. Function FlushStream( stream:TStream )
  804. stream.Flush
  805. End Function
  806. Rem
  807. bbdoc: Close a stream
  808. about:
  809. All streams should be closed when they are no longer required.
  810. Closing a stream also flushes the stream before it closes.
  811. End Rem
  812. Function CloseStream( stream:TStream )
  813. stream.Close
  814. End Function
  815. Rem
  816. bbdoc: Read a Byte from a stream
  817. returns: A Byte value
  818. about: #ReadByte reads a single Byte from @stream.
  819. A TStreamReadException is thrown If there is not enough data available.
  820. End Rem
  821. Function ReadByte:Int( stream:TStream )
  822. Return stream.ReadByte()
  823. End Function
  824. Rem
  825. bbdoc: Read a Short from a stream
  826. returns: A Short value
  827. about: #ReadShort reads 2 bytes from @stream.
  828. A TStreamReadException is thrown If there is not enough data available.
  829. End Rem
  830. Function ReadShort:Int( stream:TStream )
  831. Return stream.ReadShort()
  832. End Function
  833. Rem
  834. bbdoc: Read an Int from a stream
  835. returns: An Int value
  836. about: #ReadInt reads 4 bytes from @stream.
  837. A TStreamReadException is thrown If there is not enough data available.
  838. End Rem
  839. Function ReadInt:Int( stream:TStream )
  840. Return stream.ReadInt()
  841. End Function
  842. Rem
  843. bbdoc: Read a Long from a stream
  844. returns: A Long value
  845. about: #ReadLong reads 8 bytes from @stream.
  846. A TStreamReadException is thrown If there is not enough data available.
  847. End Rem
  848. Function ReadLong:Long( stream:TStream )
  849. Return stream.ReadLong()
  850. End Function
  851. Rem
  852. bbdoc: Read a Float from a stream
  853. returns: A Float value
  854. about: #ReadFloat reads 4 bytes from @stream.
  855. A TStreamReadException is thrown If there is not enough data available.
  856. End Rem
  857. Function ReadFloat:Float( stream:TStream )
  858. Return stream.ReadFloat()
  859. End Function
  860. Rem
  861. bbdoc: Read a Double from a stream
  862. returns: A Double value
  863. about: #ReadDouble reads 8 bytes from @stream.
  864. A TStreamWriteException is thrown If there is not enough data available.
  865. End Rem
  866. Function ReadDouble:Double( stream:TStream )
  867. Return stream.ReadDouble()
  868. End Function
  869. Rem
  870. bbdoc: Write a Byte to a stream
  871. about: #WriteByte writes a single Byte to @stream.
  872. A TStreamWriteException is thrown If the Byte could Not be written
  873. End Rem
  874. Function WriteByte( stream:TStream,n:Int )
  875. stream.WriteByte n
  876. End Function
  877. Rem
  878. bbdoc: Write a Short to a stream
  879. about: #WriteShort writes 2 bytes to @stream.
  880. A TStreamWriteException is thrown if not all bytes could be written
  881. End Rem
  882. Function WriteShort( stream:TStream,n:Int )
  883. stream.WriteShort n
  884. End Function
  885. Rem
  886. bbdoc: Write an Int to a stream
  887. about: #WriteInt writes 4 bytes to @stream.
  888. A TStreamWriteException is thrown if not all bytes could be written
  889. End Rem
  890. Function WriteInt( stream:TStream,n:Int )
  891. stream.WriteInt n
  892. End Function
  893. Rem
  894. bbdoc: Write a Long to a stream
  895. about: #WriteLong writes 8 bytes to @stream.
  896. A TStreamWriteException is thrown if not all bytes could be written
  897. End Rem
  898. Function WriteLong( stream:TStream,n:Long )
  899. stream.WriteLong n
  900. End Function
  901. Rem
  902. bbdoc: Write a Float to a stream
  903. about: #WriteFloat writes 4 bytes to @stream.
  904. A TStreamWriteException is thrown if not all bytes could be written
  905. End Rem
  906. Function WriteFloat( stream:TStream,n:Float )
  907. stream.WriteFloat n
  908. End Function
  909. Rem
  910. bbdoc: Write a Double to a stream
  911. about: #WriteDouble writes 8 bytes to @stream.
  912. A TStreamWriteException is thrown if not all bytes could be written
  913. End Rem
  914. Function WriteDouble( stream:TStream,n:Double )
  915. stream.WriteDouble n
  916. End Function
  917. Rem
  918. bbdoc: Read a String from a stream
  919. returns: A String of length @length
  920. about:
  921. A #TStreamReadException is thrown if not all bytes could be read.
  922. end rem
  923. Function ReadString:String( stream:TStream,length:Int )
  924. Return stream.ReadString( length )
  925. End Function
  926. Function ReadString:String( stream:TStream,length:Int, asUTF8:Int )
  927. Return stream.ReadString( length, asUTF8 )
  928. End Function
  929. Rem
  930. bbdoc: Write a String to a stream
  931. about:
  932. Each character in @str is written to @stream.
  933. A #TStreamWriteException is thrown if not all bytes could be written.
  934. End Rem
  935. Function WriteString( stream:TStream,str:String )
  936. stream.WriteString(str)
  937. End Function
  938. Function WriteString( stream:TStream,str:String, asUTF8:Int )
  939. stream.WriteString(str, asUTF8)
  940. End Function
  941. Rem
  942. bbdoc: Read a line of text from a stream
  943. returns: A string
  944. about:
  945. Bytes are read from @stream until a newline character (ascii code 10) or null
  946. character (ascii code 0) is read, or end of file is detected.
  947. Carriage Return characters (ascii code 13) are silently ignored.
  948. The bytes read are returned in the form of a string, excluding any terminating newline
  949. or null character.
  950. End Rem
  951. Function ReadLine:String( stream:TStream )
  952. Return stream.ReadLine()
  953. End Function
  954. Function ReadLine:String( stream:TStream, asUTF8:Int )
  955. Return stream.ReadLine(asUTF8)
  956. End Function
  957. Rem
  958. bbdoc: Write a line of text to a stream
  959. returns: True if line successfully written, else False
  960. about:
  961. A sequence of bytes is written to the stream (one for each character in @str)
  962. followed by the line terminating sequence "~r~n".
  963. End Rem
  964. Function WriteLine:Int( stream:TStream,str:String )
  965. Return stream.WriteLine( str )
  966. End Function
  967. Function WriteLine:Int( stream:TStream,str:String, asUTF8:Int )
  968. Return stream.WriteLine( str, asUTF8 )
  969. End Function
  970. Rem
  971. bbdoc: Load a String from a stream
  972. returns: A String
  973. about:
  974. The specified @url is opened for reading, and each byte in the resultant stream
  975. (until eof of file is reached) is read into a string.
  976. A #TStreamReadException is thrown if the stream could not be read.
  977. End Rem
  978. Function LoadString:String( url:Object )
  979. Local t:Byte[]=LoadByteArray(url)
  980. Return String.FromBytes( t,t.length )
  981. End Function
  982. Function LoadString:String( url:Object, asUTF8:Int )
  983. Local t:Byte[]=LoadByteArray(url)
  984. If asUTF8 Then
  985. Return String.FromUTF8Bytes( t,t.length )
  986. Else
  987. Return String.FromBytes( t,t.length )
  988. End If
  989. End Function
  990. Rem
  991. bbdoc: Save a String to a stream
  992. about:
  993. The specified @url is opened For writing, and each character of @str is written to the
  994. resultant stream.
  995. A #TStreamWriteException is thrown if not all bytes could be written.
  996. End Rem
  997. Function SaveString( str:String,url:Object )
  998. Local stream:TStream=WriteStream( url )
  999. If Not stream Throw New TStreamWriteException
  1000. Local t:Byte Ptr=str.ToCString()
  1001. stream.WriteBytes t,str.length 'Should be in a try block...or t is leaked!
  1002. MemFree t
  1003. stream.Close
  1004. End Function
  1005. Function SaveString( str:String,url:Object, asUTF8:Int )
  1006. Local stream:TStream=WriteStream( url )
  1007. If Not stream Throw New TStreamWriteException
  1008. Local t:Byte Ptr
  1009. If asUTF8 Then
  1010. t=str.ToUTF8String()
  1011. Else
  1012. t=str.ToCString()
  1013. End If
  1014. stream.WriteBytes t,str.length 'Should be in a try block...or t is leaked!
  1015. MemFree t
  1016. stream.Close
  1017. End Function
  1018. Function LoadObject:Object( url:Object )
  1019. Local stream:TStream=ReadStream( url )
  1020. If Not stream Throw New TStreamReadException
  1021. Local obj:Object=stream.ReadObject()
  1022. stream.Close
  1023. Return obj
  1024. End Function
  1025. Function SaveObject( obj:Object,url:Object )
  1026. Local stream:TStream=WriteStream( url )
  1027. If Not stream Throw New TStreamWriteException
  1028. stream.WriteObject obj
  1029. stream.Close
  1030. End Function
  1031. Rem
  1032. bbdoc: Load a Byte array from a stream
  1033. returns: A Byte array
  1034. about:
  1035. The specified @url is opened for reading, and each byte in the resultant stream
  1036. (until eof of reached) is read into a byte array.
  1037. If @url is a TStream, @closeStream can be set to False to prevent the stream from being closed after reading.
  1038. End Rem
  1039. Function LoadByteArray:Byte[]( url:Object, closeStream:Int=True )
  1040. Local ownStream:Int = True
  1041. If TStream(url) Then
  1042. ownStream = False
  1043. End If
  1044. Local stream:TStream=ReadStream( url )
  1045. If Not stream Throw New TStreamReadException
  1046. Local data:Byte[1024],size:Int
  1047. While Not stream.Eof()
  1048. If size=data.length data=data[..size*3/2]
  1049. size:+stream.Read( (Byte Ptr data)+size,data.length-size )
  1050. Wend
  1051. ' If the stream was not owned, we may not want to close it
  1052. If ownStream Or closeStream Then
  1053. stream.Close()
  1054. End If
  1055. Return data[..size]
  1056. End Function
  1057. Rem
  1058. bbdoc: Save a Byte array to a stream
  1059. about:
  1060. The specified @url is opened For writing, and each element of @byteArray is written to the
  1061. resultant stream.
  1062. A #TStreamWriteException is thrown if not all bytes could be written.
  1063. End Rem
  1064. Function SaveByteArray( byteArray:Byte[],url:Object )
  1065. Local stream:TStream=WriteStream( url )
  1066. If Not stream Throw New TStreamWriteException
  1067. stream.WriteBytes byteArray,byteArray.length
  1068. stream.Close
  1069. End Function
  1070. Rem
  1071. bbdoc: Copy stream contents to another stream
  1072. about:
  1073. #CopyStream copies bytes from @fromStream to @toStream Until @fromStream reaches end
  1074. of file.
  1075. A #TStreamWriteException is thrown if not all bytes could be written.
  1076. End Rem
  1077. Function CopyStream( fromStream:TStream,toStream:TStream,bufSize:Int=4096 )
  1078. Assert bufSize>0
  1079. Local buf:Byte[bufSize]
  1080. While Not fromStream.Eof()
  1081. toStream.WriteBytes buf,fromStream.Read( buf,bufSize )
  1082. Wend
  1083. End Function
  1084. Rem
  1085. bbdoc: Copy bytes from one stream to another
  1086. about:
  1087. #CopyBytes copies @count bytes from @fromStream to @toStream.
  1088. A #TStreamReadException is thrown if not all bytes could be read, and a
  1089. #TStreamWriteException is thrown if not all bytes could be written.
  1090. End Rem
  1091. Function CopyBytes( fromStream:TStream,toStream:TStream,count:Int,bufSize:Int=4096 )
  1092. Assert count>=0 And bufSize>0
  1093. Local buf:Byte[bufSize]
  1094. While count
  1095. Local n:Int=Min(count,bufSize)
  1096. fromStream.ReadBytes buf,n
  1097. toStream.WriteBytes buf,n
  1098. count:-n
  1099. Wend
  1100. End Function
  1101. Rem
  1102. bbdoc: Returns a case sensitive filename if it exists from a case insensitive file path.
  1103. End Rem
  1104. Function CasedFileName:String(path:String)
  1105. Local dir:Byte Ptr
  1106. Local sub:String,s:String,f:String,folder:String,p:Int
  1107. Local Mode:Int,size:Long,mtime:Int,ctime:Int,atime:Int
  1108. If stat_( path,Mode,size,mtime,ctime,atime )=0
  1109. Mode:&S_IFMT_
  1110. If Mode=S_IFREG_ Or Mode=S_IFDIR_ Return path
  1111. EndIf
  1112. folder="."
  1113. For p=Len(path)-2 To 0 Step -1
  1114. If path[p]=47 Exit
  1115. Next
  1116. If p>0
  1117. sub=path[0..p]
  1118. sub=CasedFileName(sub)
  1119. If Not sub Then
  1120. Return Null
  1121. End If
  1122. path=path[Len(sub)+1..]
  1123. folder=sub
  1124. EndIf
  1125. s=path.ToLower()
  1126. dir=opendir_(folder)
  1127. If dir
  1128. While True
  1129. f=readdir_(dir)
  1130. If Not f Exit
  1131. If s=f.ToLower()
  1132. If sub f=sub+"/"+f
  1133. closedir_(dir)
  1134. Return f
  1135. EndIf
  1136. Wend
  1137. closedir_(dir)
  1138. EndIf
  1139. End Function
  1140. Rem
  1141. bbdoc: Opens a file for output operations.
  1142. End Rem
  1143. Const WRITE_MODE_OVERWRITE:Int = 1
  1144. Rem
  1145. bbdoc: Opens a file for appending with all output operations writing data at the end of the file.
  1146. about: Repositioning operations such as #Seek affects the next input operations, but output operations move the position back to the end of file.
  1147. End Rem
  1148. Const WRITE_MODE_APPEND:Int = 2
  1149. Type TIOStream Extends TFileStream
  1150. Method Pos:Long() Override
  1151. Return _pos
  1152. End Method
  1153. Method Size:Long() Override
  1154. Return _size
  1155. End Method
  1156. Method Seek:Long( pos:Long, whence:Int = SEEK_SET_ ) Override
  1157. Assert _stream Else "Attempt to seek closed stream"
  1158. 'fseek_ _cstream,pos,whence
  1159. Local newPos:Long = pos
  1160. If whence = SEEK_END_ Then
  1161. newPos = _size
  1162. Else If whence = SEEK_CUR_ Then
  1163. newPos = _pos + pos
  1164. End If
  1165. PHYSFS_seek(_stream, newPos)
  1166. _pos = PHYSFS_tell(_stream)
  1167. Return _pos
  1168. End Method
  1169. Method Read:Long( buf:Byte Ptr,count:Long ) Override
  1170. Assert _stream Else "Attempt to read from closed stream"
  1171. Assert _mode & MODE_READ Else "Attempt to read from write-only stream"
  1172. count=PHYSFS_readBytes(_stream, buf,ULong(count))
  1173. _pos:+count
  1174. Return count
  1175. End Method
  1176. Method Write:Long( buf:Byte Ptr,count:Long ) Override
  1177. Assert _stream Else "Attempt to write to closed stream"
  1178. Assert _mode & (MODE_WRITE | MODE_APPEND) Else "Attempt to write to read-only stream"
  1179. count=PHYSFS_writeBytes(_stream, buf, ULong(count))
  1180. _pos:+count
  1181. If _pos>_size _size=_pos
  1182. Return count
  1183. End Method
  1184. Method Flush() Override
  1185. If _stream PHYSFS_flush(_stream)
  1186. End Method
  1187. Method Close() Override
  1188. If Not _stream Return
  1189. Flush
  1190. PHYSFS_close(_stream)
  1191. _pos=0
  1192. _size=0
  1193. _stream=Null
  1194. End Method
  1195. Method SetSize:Int(size:Long) Override
  1196. Return 0
  1197. End Method
  1198. Function OpenFile:TIOStream( path:String,readable:Int,writeMode:Int )
  1199. Local Mode:String,_mode:Int
  1200. Mode = GetMode(readable, writeMode, _mode)
  1201. path=path.Replace( "\","/" )
  1202. Local stream:Byte Ptr
  1203. If _mode & MODE_APPEND Then
  1204. stream = bmx_PHYSFS_openAppend(path)
  1205. Else If _mode & MODE_WRITE Then
  1206. stream = bmx_PHYSFS_openWrite(path)
  1207. Else
  1208. stream = bmx_PHYSFS_openRead(path)
  1209. If stream
  1210. PHYSFS_setBuffer(stream, 4096)
  1211. End If
  1212. End If
  1213. '?Linux
  1214. ' If (Not cstream) And (Not writeMode)
  1215. ' path=CasedFileName(path)
  1216. ' If path cstream=fopen_( path,Mode )
  1217. ' EndIf
  1218. '?
  1219. If stream Return CreateWithIOStream( stream,_mode )
  1220. End Function
  1221. Function CreateWithIOStream:TIOStream( _stream:Byte Ptr,Mode:Int )
  1222. Local stream:TIOStream=New TIOStream
  1223. stream._stream=_stream
  1224. stream._pos=PHYSFS_tell( _stream )
  1225. stream._size=PHYSFS_fileLength(_stream)
  1226. stream._mode=Mode
  1227. Return stream
  1228. End Function
  1229. End Type