/* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġcom . so y wiz . kor au . format . org . gr agr av arr . ogg Ċ Ċ import Ġcom . so y wiz . kor io . lang .* Ċ import Ġcom . so y wiz . kor io . stream .* Ċ import Ġkotlin . random . Random Ċ Ċ /** Ċ Ġ* ĠThis Ġclass Ġtakes Ġcare Ġof Ġreading Ġand Ġwriting Ċ Ġ* Ġfiles Ġusing Ġthe ĠO gg Ġcontainer Ġformat . Ċ Ġ*/ Ċ class ĠO gg File ( val Ġwarning Processor : Ġ(( String ) Ġ-> ĠUnit )? ) Ġ: ĠClose able Ġ{ Ċ ĉ private Ġvar Ġinp : ĠSync InputStream ? Ġ= Ġnull Ċ ĉ private Ġvar Ġout : ĠSync OutputStream ? Ġ= Ġnull Ċ ĉ private Ġvar Ġwriting Ġ= Ġtrue ĊĊ ĉ private Ġval Ġseen S IDs Ġ= ĠHashSet < Int >() ĊĊ ĉ /** Ċĉ Ġ* ĠReturns Ġa Ġreader Ġthat Ġwill Ġallow Ġyou Ġto Ġread Ġpackets Ċĉ Ġ* Ġfrom Ġthe Ġfile , Ġacross Ġall ĠLogical ĠBit ĠStreams , Ċĉ Ġ* Ġin Ġthe Ġorder Ġthat Ġthey Ġoccur . Ċĉ Ġ*/ Ċ ĉ val Ġpacket Reader : ĠO gg Packet Reader Ċĉ ĉ get () Ġ{ Ċĉĉ ĉ if Ġ( writing Ġ|| Ġinp Ġ== Ġnull ) Ġ{ Ċĉĉĉ ĉ throw ĠIllegalStateException (" Can Ġonly Ġread Ġfrom Ġa Ġfile Ġopened Ġwith Ġan ĠInputStream ") Ċĉĉ ĉ } Ċĉĉ ĉ return ĠO gg Packet Reader ( inp !! , Ġwarning Processor ) Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCreates Ġa Ġnew ĠLogical ĠBit ĠStream Ġin Ġthe Ġfile , Ċĉ Ġ* Ġand Ġreturns Ġa ĠWriter Ġfor Ġputting Ġdata Ċĉ Ġ* Ġinto Ġit . Ċĉ Ġ*/ Ċ ĉ val Ġpacket Writer : ĠO gg Packet Writer Ċĉ ĉ get () Ġ= Ġget Packet Writer ( unused SerialNumber ) ĊĊĊ ĉ /** Ċĉ Ġ* ĠReturns Ġa Ġrandom , Ġbut Ġpreviously Ġun - used Ġserial Ċĉ Ġ* Ġnumber Ġfor Ġuse Ġby Ġa Ġnew Ġstream Ċĉ Ġ*/ Ċ ĉ protected Ġval Ġunused SerialNumber : ĠInt Ċĉ ĉ get () Ġ{ Ċĉĉ ĉ while Ġ( true ) Ġ{ Ċĉĉĉ ĉ val Ġsid Ġ= Ġ( Random . next Double () Ġ* ĠShort . MAX _ VALUE ). toInt () Ċĉĉĉ ĉ if Ġ(! seen S IDs . contains ( sid )) Ġ{ Ċĉĉĉĉ ĉ return Ġsid Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠOpen s Ġa Ġfile Ġfor Ġwriting . Ċĉ Ġ* ĠCall Ġ[. get Packet Writer ] Ġto Ċĉ Ġ* Ġbegin Ġwriting Ġyour Ġdata . Ċĉ Ġ*/ Ċ ĉ constructor ( output : ĠSync OutputStream , Ġwarning Processor : Ġ(( String ) Ġ-> ĠUnit )? ) Ġ: Ġthis ( warning Processor ) Ġ{ Ċĉ ĉ this . out Ġ= Ġoutput Ċĉ ĉ this . writing Ġ= Ġtrue Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠOpen s Ġa Ġfile Ġfor Ġreading Ġin Ċĉ Ġ* Ġblocking Ġ( non Ġevent ) Ġmode . Ċĉ Ġ* ĠCall Ġ[. get Packet Reader ] Ġto Ċĉ Ġ* Ġbegin Ġreading Ġthe Ġfile . Ċĉ Ġ*/ Ċ ĉ constructor ( input : ĠSync InputStream , Ġwarning Processor : Ġ(( String ) Ġ-> ĠUnit )? ) Ġ: Ġthis ( warning Processor ) Ġ{ Ċĉ ĉ this . inp Ġ= Ġinput Ċĉ ĉ this . writing Ġ= Ġfalse Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠOpen s Ġa Ġfile Ġfor Ġreading Ġin Ġnon - blocking Ċĉ Ġ* Ġ( event ) Ġmode . Ċĉ Ġ* ĠWill Ġbegin Ġprocessing Ġthe Ġfile Ġand Ġnotify ing Ċĉ Ġ* Ġyour Ġlistener Ġimmediately . Ċĉ Ġ*/ Ċ ĉ constructor ( input : ĠSync InputStream , Ġlistener : ĠO gg Stream Listener , Ġwarning Processor : Ġ(( String ) Ġ-> ĠUnit )? ) Ġ: Ġthis ( input , Ġwarning Processor ) Ġ{ ĊĊĉ ĉ val Ġreaders Ġ= ĠHashMap < Int , ĠArray < O gg StreamReader >>() Ċĉ ĉ val Ġreader Ġ= Ġpacket Reader Ċĉ ĉ var Ġpacket : ĠO gg Packet ? Ġ= Ġnull Ċĉ ĉ while Ġ( true ) Ġ{ Ċĉĉ ĉ packet Ġ= Ġreader . getNext Packet () Ġ?: Ġbreak Ċĉĉ ĉ if Ġ( packet !!. is Beginning Of Stream ) Ġ{ Ċĉĉĉ ĉ val Ġstreams Ġ= Ġlistener . process New Stream ( packet !!. sid , Ġpacket !!. data ) Ċĉĉĉ ĉ if Ġ( streams Ġ!= Ġnull Ġ&& Ġstreams !!. size Ġ> Ġ 0 ) Ġ{ Ċĉĉĉĉ ĉ readers [ packet !!. sid ] Ġ= Ġstreams Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉ ĉ val Ġstreams Ġ= Ġreaders [ packet !!. sid ] Ċĉĉĉ ĉ if Ġ( streams Ġ!= Ġnull ) Ġ{ Ċĉĉĉĉ ĉ for Ġ( r Ġin Ġstreams ) Ġ{ Ċĉĉĉĉĉ ĉ r . process Packet ( packet ) Ċĉĉĉĉ ĉ } Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉĉ ĉ if Ġ( packet !!. is EndOf Stream ) Ġ{ Ċĉĉĉ ĉ listener . process Stream End ( packet !!. sid ) Ċĉĉ ĉ } Ċĉ ĉ } Ċ ĉ } ĊĊĊ ĉ /** Ċĉ Ġ* ĠCloses Ġour Ġstreams . ĠIt 's Ġup Ġto Ġyou Ċĉ Ġ* Ġto Ġclose Ġany Ġ[ O gg Packet Writer ] Ġinstances Ċĉ Ġ* Ġfirst ! Ċĉ Ġ*/ Ċ ĉ override Ġfun Ġclose () Ġ{ Ċĉ ĉ if Ġ( inp Ġ!= Ġnull ) Ċĉĉ ĉ inp !!. close () Ċĉ ĉ if Ġ( out Ġ!= Ġnull ) Ċĉĉ ĉ out !!. close () Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠCreates Ġa Ġnew ĠLogical ĠBit ĠStream Ġin Ġthe Ġfile , Ċĉ Ġ* Ġand Ġreturns Ġa ĠWriter Ġfor Ġputting Ġdata Ċĉ Ġ* Ġinto Ġit . Ċĉ Ġ*/ Ċ ĉ fun Ġget Packet Writer ( sid : ĠInt ): ĠO gg Packet Writer Ġ{ Ċĉ ĉ if Ġ(! writing ) Ġ{ Ċĉĉ ĉ throw ĠIllegalStateException (" Can Ġonly Ġwrite Ġto Ġa Ġfile Ġopened Ġwith Ġan ĠOutputStream ") Ċĉ ĉ } Ċĉ ĉ seen S IDs . add ( sid ) Ċĉ ĉ return ĠO gg Packet Writer ( this , Ġsid ) Ċ ĉ } ĊĊ ĉ /** Ċĉ Ġ* ĠWrites Ġa Ġ( possibly Ġseries ) Ġof Ġpages Ġto Ġthe Ċĉ Ġ* Ġstream Ġin Ġone Ġgo . Ċĉ Ġ*/ Ċ ĉ fun Ġwrite Pages ( pages : ĠArray < O gg Page >) Ġ{ Ċĉ ĉ for Ġ( page Ġin Ġpages ) Ġ{ Ċĉĉ ĉ page . write Header ( out !! ) Ċĉĉ ĉ out !!. write ( page . getData () !! ) Ċĉ ĉ } Ċĉ ĉ out !!. flush () Ċ ĉ } Ċ } Ċ