11#  This file is a part of Julia. License is MIT: http://julialang.org/license
22
33module  iconv
4- import  Base:  close, eof, flush, read, readall, write
4+ import  Base:  close, eof, flush, read, readall, write, show 
55import  Base. Libc:  errno, strerror, E2BIG, EINVAL, EILSEQ
6- export  StringEncoder, StringDecoder, encode, decode
6+ export  StringEncoder, StringDecoder, encode, decode, StringErr, StringEncodingError
7+ 8+ module  StringErr
9+ const  global  UNKNOWN_ERR =  " <<1>>: <<2>> (<<3>>)" 
10+ const  global  OUTPUT_BUFFER =  " iconv: ran out of space in the output buffer" 
11+ const  global  UNSUPPORTED_CONV = 
12+  " conversion from <<1>> to <<2>> not supported by iconv implementation, check that specified encodings are correct" 
13+ const  global  INVALID_SEQUENCE =  " iconv: byte sequence 0x<<1>> is invalid in source encoding or cannot be represented in target encoding" 
14+ const  global  INPUT_END_INVALID =  " iconv: incomplete byte sequence at end of input" 
15+ const  global  INVALID_BYTES =  " iconv: invalid byte sequence in input" 
16+ end 
17+ 18+ type StringEncodingError <:  Exception 
19+  errmsg:: AbstractString  #  A StringErr. message
20+  args
21+  StringEncodingError (msg) =  new (msg, ())
22+  StringEncodingError (msg, args... ) =  new (msg, args)
23+ end 
24+ 25+ generalerror (msg) = 
26+  throw (StringEncodingError (StringErr. UNKNOWN_ERR, msg, errno (), strerror (errno ())))
27+ 28+ function  show (io:: IO , exc:: StringEncodingError )
29+  str =  string (" StringEncodingError: "  , exc. errmsg)
30+  for  i =  1 : length (exc. args)
31+  str =  replace (str, " <<$i >>"  , exc. args[i])
32+  end 
33+  print (io, str)
34+ end 
735
836depsjl =  joinpath (dirname (@__FILE__ ), " .."  , " deps"  , " deps.jl"  )
937isfile (depsjl) ?  include (depsjl) :  error (" libiconv not properly installed. Please run\n Pkg.build(\" iconv\" )"  )
1038
11- 1239# # iconv wrappers
1340
1441function  iconv_close (cd:: Ptr{Void} )
1542 if  cd !=  C_NULL 
1643 ccall ((:iconv_close , libiconv), Cint, (Ptr{Void},), cd) ==  0  || 
17-  error ( " failed to call  iconv_close: error  $( errno ())  ( $( strerror ( errno ())) ) "  )
44+  generalerror ( " iconv_close"  )
1845 end 
1946end 
2047
@@ -23,9 +50,9 @@ function iconv_open(tocode, fromcode)
2350 if  p !=  Ptr {Void} (- 1 )
2451 return  p
2552 elseif  errno () ==  EINVAL
26-  error ( " conversion from  $ fromcode to  $tocode  not supported by iconv implementation, check that specified encodings are correct "  )
53+  throw ( StringEncodingError (StringErr . UNSUPPORTED_CONV,  fromcode, tocode) )
2754 else 
28-  error (" iconv_open error  $( errno ()) :  $( strerror ( errno ())) "  )
55+  generalerror (" iconv_open"  )
2956 end 
3057end 
3158
@@ -84,16 +111,16 @@ function iconv!(cd::Ptr{Void}, inbuf::Vector{UInt8}, outbuf::Vector{UInt8},
84111
85112 #  Should never happen unless a very small buffer is used
86113 if  err ==  E2BIG &&  outbytesleft[] ==  BUFSIZE
87-  error ( " iconv error: ran out of space in the output buffer "  )
114+  throw ( StringEncodingError (StringErr . OUTPUT_BUFFER) )
88115 #  Output buffer is full, or sequence is incomplete:
89116 #  copy remaining bytes to the start of the input buffer for next time
90117 elseif  err ==  E2BIG ||  err ==  EINVAL
91118 copy! (inbuf, 1 , inbuf, inbytesleft_orig- inbytesleft[]+ 1 , inbytesleft[])
92119 elseif  err ==  EILSEQ
93120 b =  inbuf[(inbytesleft_orig- inbytesleft[]+ 1 ): inbytesleft_orig]
94-  error ( " iconv error: byte sequence 0x $( bytes2hex (b)) is invalid in source encoding or cannot be represented in target encoding "  )
121+  throw ( StringEncodingError (StringErr . INVALID_SEQUENCE,  bytes2hex (b)))
95122 else 
96-  error (" iconv error  $( errno ()) :  $( strerror ( errno ())) "  )
123+  generalerror (" iconv! "  )
97124 end 
98125 end 
99126
@@ -114,13 +141,13 @@ function iconv_reset!(s::Union{StringEncoder, StringDecoder})
114141 if  ret ==  - 1  %  Csize_t
115142 err =  errno ()
116143 if  err ==  EINVAL
117-  error ( " iconv error: incomplete byte sequence at end of input "  )
144+  throw ( StringEncodingError (StringErr . INPUT_END_INVALID) )
118145 elseif  err ==  E2BIG
119-  error ( " iconv error: ran out of space in the output buffer "  )
146+  throw ( StringEncodingError (StringErr . OUTPUT_BUFFER) )
120147 elseif  err ==  EILSEQ
121-  error ( " iconv error: invalid byte sequence in input "  )
148+  throw ( StringEncodingError (StringErr . INVALID_BYTES) )
122149 else 
123-  error ( " iconv error  $( errno ()) :  $( strerror ( errno ())) "  )
150+  generalerror ( " iconv_reset! "  )
124151 end 
125152 end 
126153
@@ -171,7 +198,7 @@ function close(s::StringEncoder)
171198 #  Make sure C memory/resources are returned
172199 finalize (s)
173200 #  flush() wasn't able to empty input buffer, which cannot happen with correct data
174-  s. inbytesleft[] ==  0  ||  error ( " iconv error: incomplete byte sequence at end of input "  )
201+  s. inbytesleft[] ==  0  ||  throw ( StringEncodingError (StringErr . INPUT_END_INVALID) )
175202end 
176203
177204function  write (s:: StringEncoder , x:: UInt8 )
@@ -236,7 +263,7 @@ function close(s::StringDecoder)
236263 #  Make sure C memory/resources are returned
237264 finalize (s)
238265 #  iconv_reset!() wasn't able to empty input buffer, which cannot happen with correct data
239-  s. inbytesleft[] ==  0  ||  error ( " iconv error: incomplete byte sequence at end of input "  )
266+  s. inbytesleft[] ==  0  ||  throw ( StringEncodingError (StringErr . INPUT_END_INVALID) )
240267end 
241268
242269function  read (s:: StringDecoder , :: Type{UInt8} )
0 commit comments