/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 4 ĠSquare , ĠInc . Ċ Ġ* Ċ Ġ* Ġ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 . Ċ Ġ*/ Ċ Ċ @ file : Jvm Name ("- G zip Source Extensions ") Ċ @ file : Suppress (" NOTH ING _ TO _ INLINE ") Ġ// ĠAli ases Ġto Ġpublic ĠAPI . Ċ Ċ package Ġok io Ċ Ċ import Ġjava . io . EOF Exception Ċ import Ġjava . io . IOException Ċ import Ġjava . util . zip . CRC 3 2 Ċ import Ġjava . util . zip . Inflater Ċ Ċ /** Ċ Ġ* ĠA Ġsource Ġthat Ġuses Ġ[ GZIP ]( http :// www . ietf . org / rfc / rfc 1 9 5 2 . txt ) Ġto Ċ Ġ* Ġde compress Ġdata Ġread Ġfrom Ġanother Ġsource . Ċ Ġ*/ Ċ class ĠG zip Source ( source : ĠSource ) Ġ: ĠSource Ġ{ ĊĊĠ Ġ/** ĠThe Ġcurrent Ġsection . ĠAlways Ġprog resses Ġforward . Ġ*/ ĊĠ Ġprivate Ġvar Ġsection Ġ= ĠSECTION _ HEADER ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠOur Ġsource Ġshould Ġyield Ġa ĠG ZIP Ġheader Ġ( which Ġwe Ġconsume Ġdirectly ), Ġfollowed ĊĠĠ Ġ* Ġby Ġdef lated Ġbytes Ġ( which Ġwe Ġconsume Ġvia Ġan ĠIn flater Source ), Ġfollowed Ġby Ġa ĊĠĠ Ġ* ĠG ZIP Ġtr ailer Ġ( which Ġwe Ġalso Ġconsume Ġdirectly ). ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġval Ġsource Ġ= ĠReal Buffered Source ( source ) ĊĊĠ Ġ/** ĠThe Ġinflater Ġused Ġto Ġde compress Ġthe Ġdef lated Ġbody . Ġ*/ ĊĠ Ġprivate Ġval Ġinflater Ġ= ĠIn flater ( true ) ĊĊĠ Ġ/** ĊĠĠ Ġ* ĠThe Ġinflater Ġsource Ġtakes Ġcare Ġof Ġmoving Ġdata Ġbetween Ġcompressed Ġsource Ġand ĊĠĠ Ġ* Ġde compressed Ġsink Ġbuffers . ĊĠĠ Ġ*/ ĊĠ Ġprivate Ġval Ġinflater Source Ġ= ĠIn flater Source ( this . source , Ġinflater ) ĊĊĠ Ġ/** ĠCheck sum Ġused Ġto Ġcheck Ġboth Ġthe ĠG ZIP Ġheader Ġand Ġde compressed Ġbody . Ġ*/ ĊĠ Ġprivate Ġval Ġcrc Ġ= ĠCRC 3 2 () ĊĊĠ Ġ@ Throws ( IOException :: class ) ĊĠ Ġoverride Ġfun Ġread ( sink : ĠBuffer , Ġbyte Count : ĠLong ): ĠLong Ġ{ ĊĠĠĠ Ġrequire ( byte Count Ġ>= Ġ 0 L ) Ġ{ Ġ" byte Count Ġ< Ġ 0 : Ġ$ byte Count " Ġ} ĊĠĠĠ Ġif Ġ( byte Count Ġ== Ġ 0 L ) Ġreturn Ġ 0 L ĊĊĠĠĠ Ġ// ĠIf Ġwe Ġhaven 't Ġconsumed Ġthe Ġheader , Ġwe Ġmust Ġconsume Ġit Ġbefore Ġanything Ġelse . ĊĠĠĠ Ġif Ġ( section Ġ== ĠSECTION _ HEADER ) Ġ{ ĊĠĠĠĠĠ Ġconsume Header () ĊĠĠĠĠĠ Ġsection Ġ= ĠSECTION _ BODY ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠAttempt Ġto Ġread Ġat Ġleast Ġa Ġbyte Ġof Ġthe Ġbody . ĠIf Ġwe Ġdo , Ġwe 're Ġdone . ĊĠĠĠ Ġif Ġ( section Ġ== ĠSECTION _ BODY ) Ġ{ ĊĠĠĠĠĠ Ġval Ġoffset Ġ= Ġsink . size ĊĠĠĠĠĠ Ġval Ġresult Ġ= Ġinflater Source . read ( sink , Ġbyte Count ) ĊĠĠĠĠĠ Ġif Ġ( result Ġ!= Ġ- 1 L ) Ġ{ ĊĠĠĠĠĠĠĠ Ġupdate Crc ( sink , Ġoffset , Ġresult ) ĊĠĠĠĠĠĠĠ Ġreturn Ġresult ĊĠĠĠĠĠ Ġ} ĊĠĠĠĠĠ Ġsection Ġ= ĠSECTION _ TR AIL ER ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠThe Ġbody Ġis Ġex hausted ; Ġtime Ġto Ġread Ġthe Ġtr ailer . ĠWe Ġalways Ġconsume Ġthe ĊĠĠĠ Ġ// Ġtr ailer Ġbefore Ġreturning Ġa Ġ- 1 Ġex hausted Ġresult ; Ġthat Ġway Ġif Ġyou Ġread Ġto ĊĠĠĠ Ġ// Ġthe Ġend Ġof Ġa ĠG zip Source Ġyou Ġguarantee Ġthat Ġthe ĠCRC Ġhas Ġbeen Ġchecked . ĊĠĠĠ Ġif Ġ( section Ġ== ĠSECTION _ TR AIL ER ) Ġ{ ĊĠĠĠĠĠ Ġconsume Tr ailer () ĊĠĠĠĠĠ Ġsection Ġ= ĠSECTION _ DONE ĊĊĠĠĠĠĠ Ġ// ĠG zip Ġstreams Ġself - terminate : Ġthey Ġreturn Ġ- 1 Ġbefore Ġtheir Ġunderlying ĊĠĠĠĠĠ Ġ// Ġsource Ġreturns Ġ- 1 . ĠHere Ġwe Ġattempt Ġto Ġforce Ġthe Ġunderlying Ġstream Ġto ĊĠĠĠĠĠ Ġ// Ġreturn Ġ- 1 Ġwhich Ġmay Ġtrigger Ġit Ġto Ġrelease Ġits Ġresources . ĠIf Ġit Ġdoesn 't ĊĠĠĠĠĠ Ġ// Ġreturn Ġ- 1 , Ġthen Ġour ĠG zip Ġdata Ġfinished Ġprem ature ly ! ĊĠĠĠĠĠ Ġif Ġ(! source . ex hausted ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠIOException (" gzip Ġfinished Ġwithout Ġex haust ing Ġsource ") ĊĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġ- 1 ĊĠ Ġ} ĊĊĠ Ġ@ Throws ( IOException :: class ) ĊĠ Ġprivate Ġfun Ġconsume Header () Ġ{ ĊĠĠĠ Ġ// ĠRead Ġthe Ġ 1 0 - byte Ġheader . ĠWe Ġpeek Ġat Ġthe Ġflags Ġbyte Ġfirst Ġso Ġwe Ġknow Ġif Ġwe ĊĠĠĠ Ġ// Ġneed Ġto ĠCRC Ġthe Ġentire Ġheader . ĠThen Ġwe Ġread Ġthe Ġmagic ĠID 1 ID 2 Ġsequence . ĊĠĠĠ Ġ// ĠWe Ġcan Ġskip Ġeverything Ġelse Ġin Ġthe Ġfirst Ġ 1 0 Ġbytes . ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ĊĠĠĠ Ġ// Ġ| ID 1 | ID 2 | CM Ġ| FL G | ĠĠĠĠ ĠM TIME ĠĠĠĠ Ġ| X FL | OS Ġ| Ġ( more --> ) ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ĊĠĠĠ Ġsource . require ( 1 0 ) ĊĠĠĠ Ġval Ġflags Ġ= Ġsource . buffer ()[ 3 ]. toInt () ĊĠĠĠ Ġval Ġf hc rc Ġ= Ġflags . get Bit ( FH CRC ) ĊĠĠĠ Ġif Ġ( f hc rc ) Ġupdate Crc ( source . buffer (), Ġ 0 , Ġ 1 0 ) ĊĊĠĠĠ Ġval Ġid 1 id 2 Ġ= Ġsource . read Short () ĊĠĠĠ Ġcheck Equal (" ID 1 ID 2 ", Ġ 0 x 1 f 8 b , Ġid 1 id 2 . toInt ()) ĊĠĠĠ Ġsource . skip ( 8 ) ĊĊĠĠĠ Ġ// ĠSkip Ġoptional Ġextra Ġfields . ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ================================ = + ĊĠĠĠ Ġ// Ġ| ĠX LEN Ġ Ġ| ... X LEN Ġbytes Ġof Ġ" extra Ġfield " ... | Ġ( more --> ) ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ================================ = + ĊĠĠĠ Ġif Ġ( flags . get Bit ( F EXTRA )) Ġ{ ĊĠĠĠĠĠ Ġsource . require ( 2 ) ĊĠĠĠĠĠ Ġif Ġ( f hc rc ) Ġupdate Crc ( source . buffer (), Ġ 0 , Ġ 2 ) ĊĠĠĠĠĠ Ġval Ġx len Ġ= Ġsource . buffer (). read Short Le (). to Long () ĊĠĠĠĠĠ Ġsource . require ( x len ) ĊĠĠĠĠĠ Ġif Ġ( f hc rc ) Ġupdate Crc ( source . buffer (), Ġ 0 , Ġx len ) ĊĠĠĠĠĠ Ġsource . skip ( x len ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠSkip Ġan Ġoptional Ġ 0 - terminated Ġname . ĊĠĠĠ Ġ// Ġ+ ================================ ========= + ĊĠĠĠ Ġ// Ġ| ... original Ġfile Ġname , Ġzero - terminated ... | Ġ( more --> ) ĊĠĠĠ Ġ// Ġ+ ================================ ========= + ĊĠĠĠ Ġif Ġ( flags . get Bit ( F NAME )) Ġ{ ĊĠĠĠĠĠ Ġval Ġindex Ġ= Ġsource . indexOf ( 0 ) ĊĠĠĠĠĠ Ġif Ġ( index Ġ== Ġ- 1 L ) Ġthrow ĠEOF Exception () ĊĠĠĠĠĠ Ġif Ġ( f hc rc ) Ġupdate Crc ( source . buffer (), Ġ 0 , Ġindex Ġ+ Ġ 1 ) ĊĠĠĠĠĠ Ġsource . skip ( index Ġ+ Ġ 1 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠSkip Ġan Ġoptional Ġ 0 - terminated Ġcomment . ĊĠĠĠ Ġ// Ġ+ ================================ === + ĊĠĠĠ Ġ// Ġ| ... file Ġcomment , Ġzero - terminated ... | Ġ( more --> ) ĊĠĠĠ Ġ// Ġ+ ================================ === + ĊĠĠĠ Ġif Ġ( flags . get Bit ( F COMMENT )) Ġ{ ĊĠĠĠĠĠ Ġval Ġindex Ġ= Ġsource . indexOf ( 0 ) ĊĠĠĠĠĠ Ġif Ġ( index Ġ== Ġ- 1 L ) Ġthrow ĠEOF Exception () ĊĠĠĠĠĠ Ġif Ġ( f hc rc ) Ġupdate Crc ( source . buffer (), Ġ 0 , Ġindex Ġ+ Ġ 1 ) ĊĠĠĠĠĠ Ġsource . skip ( index Ġ+ Ġ 1 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠConfirm Ġthe Ġoptional Ġheader ĠCRC . ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ĊĠĠĠ Ġ// Ġ| ĠCRC 1 6 Ġ| ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ĊĠĠĠ Ġif Ġ( f hc rc ) Ġ{ ĊĠĠĠĠĠ Ġcheck Equal (" FH CRC ", Ġsource . read Short Le (). toInt (), Ġcrc . value . to Short (). toInt ()) ĊĠĠĠĠĠ Ġcrc . reset () ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġ@ Throws ( IOException :: class ) ĊĠ Ġprivate Ġfun Ġconsume Tr ailer () Ġ{ ĊĠĠĠ Ġ// ĠRead Ġthe Ġeight - byte Ġtr ailer . ĠConfirm Ġthe Ġbody 's ĠCRC Ġand Ġsize . ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ĊĠĠĠ Ġ// Ġ| ĠĠĠĠ ĠCRC 3 2 ĠĠĠĠ Ġ| ĠĠĠĠ ĠI SIZE ĠĠĠĠ Ġ| ĊĠĠĠ Ġ// Ġ+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ---+ ĊĠĠĠ Ġcheck Equal (" CRC ", Ġsource . readInt Le (), Ġcrc . value . toInt ()) ĊĠĠĠ Ġcheck Equal (" IS IZE ", Ġsource . readInt Le (), Ġinflater . bytes Written . toInt ()) ĊĠ Ġ} ĊĊĠ Ġoverride Ġfun Ġtimeout (): ĠTimeout Ġ= Ġsource . timeout () ĊĊĠ Ġ@ Throws ( IOException :: class ) ĊĠ Ġoverride Ġfun Ġclose () Ġ= Ġinflater Source . close () ĊĊĠ Ġ/** ĠUpdates Ġthe ĠCRC Ġwith Ġthe Ġgiven Ġbytes . Ġ Ġ*/ ĊĠ Ġprivate Ġfun Ġupdate Crc ( buffer : ĠBuffer , Ġoffset : ĠLong , Ġbyte Count : ĠLong ) Ġ{ ĊĠĠĠ Ġvar Ġoffset Ġ= Ġoffset ĊĠĠĠ Ġvar Ġbyte Count Ġ= Ġbyte Count ĊĠĠĠ Ġ// ĠSkip Ġsegments Ġthat Ġwe Ġaren 't Ġchecksum ming . ĊĠĠĠ Ġvar Ġs Ġ= Ġbuffer . head !! ĊĠĠĠ Ġwhile Ġ( offset Ġ>= Ġs . limit Ġ- Ġs . pos ) Ġ{ ĊĠĠĠĠĠ Ġoffset Ġ-= Ġs . limit Ġ- Ġs . pos ĊĠĠĠĠĠ Ġs Ġ= Ġs . next !! ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠCheck sum Ġone Ġsegment Ġat Ġa Ġtime . ĊĠĠĠ Ġwhile Ġ( byte Count Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠ Ġval Ġpos Ġ= Ġ( s . pos Ġ+ Ġoffset ). toInt () ĊĠĠĠĠĠ Ġval Ġto Update Ġ= Ġmin Of ( s . limit Ġ- Ġpos , Ġbyte Count ). toInt () ĊĠĠĠĠĠ Ġcrc . update ( s . data , Ġpos , Ġto Update ) ĊĠĠĠĠĠ Ġbyte Count Ġ-= Ġto Update ĊĠĠĠĠĠ Ġoffset Ġ= Ġ 0 ĊĠĠĠĠĠ Ġs Ġ= Ġs . next !! ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġcheck Equal ( name : ĠString , Ġexpected : ĠInt , Ġactual : ĠInt ) Ġ{ ĊĠĠĠ Ġif Ġ( actual Ġ!= Ġexpected ) Ġ{ ĊĠĠĠĠĠ Ġthrow ĠIOException ("% s : Ġactual Ġ 0 x % 0 8 x Ġ!= Ġexpected Ġ 0 x % 0 8 x ". format ( name , Ġactual , Ġexpected )) ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ private Ġinline Ġfun ĠInt . get Bit ( bit : ĠInt ) Ġ= Ġthis Ġshr Ġbit Ġand Ġ 1 Ġ== Ġ 1 Ċ Ċ private Ġconst Ġval ĠF H CRC Ġ= Ġ 1 Ċ private Ġconst Ġval ĠF EXTRA Ġ= Ġ 2 Ċ private Ġconst Ġval ĠF NAME Ġ= Ġ 3 Ċ private Ġconst Ġval ĠF COMMENT Ġ= Ġ 4 Ċ Ċ private Ġconst Ġval ĠSECTION _ HEADER : ĠByte Ġ= Ġ 0 Ċ private Ġconst Ġval ĠSECTION _ BODY : ĠByte Ġ= Ġ 1 Ċ private Ġconst Ġval ĠSECTION _ TR AIL ER : ĠByte Ġ= Ġ 2 Ċ private Ġconst Ġval ĠSECTION _ DONE : ĠByte Ġ= Ġ 3 Ċ Ċ /** Ċ Ġ* ĠReturns Ġa Ġ[ G zip Source ] Ġthat Ġgzip - de comp resses Ġthis Ġ[ Source ] Ġwhile Ġreading . Ċ Ġ* Ċ Ġ* Ġ@ see ĠG zip Source Ċ Ġ*/ Ċ inline Ġfun ĠSource . gzip () Ġ= ĠG zip Source ( this ) Ċ