Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ee8e9fa

Browse files
Use StringError exception and errors
1 parent 4cb98a3 commit ee8e9fa

File tree

2 files changed

+52
-25
lines changed

2 files changed

+52
-25
lines changed

‎src/iconv.jl‎

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,47 @@
11
# This file is a part of Julia. License is MIT: http://julialang.org/license
22

33
module iconv
4-
import Base: close, eof, flush, read, readall, write
4+
import Base: close, eof, flush, read, readall, write, show
55
import 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

836
depsjl = joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")
937
isfile(depsjl) ? include(depsjl) : error("libiconv not properly installed. Please run\nPkg.build(\"iconv\")")
1038

11-
1239
## iconv wrappers
1340

1441
function 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
1946
end
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
3057
end
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))
175202
end
176203

177204
function 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))
240267
end
241268

242269
function read(s::StringDecoder, ::Type{UInt8})

‎test/runtests.jl‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ end
2929
let s = "a string チャネルパートナーの選択"
3030
p = StringEncoder(IOBuffer(), "UTF-16LE")
3131
write(p, s.data[1:10])
32-
@test_throws ErrorException close(p)
32+
@test_throws StringEncodingError close(p)
3333

3434
p = StringDecoder(IOBuffer(encode(s, "UTF-16LE")[1:19]), "UTF-16LE")
3535
@test readall(p) == s[1:9]
36-
@test_throws ErrorException close(p)
36+
@test_throws StringEncodingError close(p)
3737

3838
# Test stateful encoding, which output some bytes on final reset
3939
# with strings containing different scripts
@@ -48,39 +48,39 @@ let s = "a string チャネルパートナーの選択"
4848
close(p)
4949
end
5050

51-
@test_throws ErrorException encode("qwertyé€", "ASCII")
51+
@test_throws StringEncodingError encode("qwertyé€", "ASCII")
5252
try
5353
encode("qwertyé€", "ASCII")
5454
catch err
5555
io = IOBuffer()
5656
showerror(io, err)
5757
@test takebuf_string(io) ==
58-
"iconv error: byte sequence 0xc3a9e282ac is invalid in source encoding or cannot be represented in target encoding"
58+
"StringEncodingError: iconv: byte sequence 0xc3a9e282ac is invalid in source encoding or cannot be represented in target encoding"
5959
end
6060

6161
# win_iconv currently does not throw an error on bytes >= 0x80 in ASCII sources
6262
# https://github.com/win-iconv/win-iconv/pull/26
6363
if OS_NAME != :Windows
64-
@test_throws ErrorException decode(b"qwertyé€", "ASCII")
64+
@test_throws StringEncodingError decode(b"qwertyé€", "ASCII")
6565
try
6666
decode(b"qwertyé€", "ASCII")
6767
catch err
6868
io = IOBuffer()
6969
showerror(io, err)
7070
@test takebuf_string(io) ==
71-
"iconv error: byte sequence 0xc3a9e282ac is invalid in source encoding or cannot be represented in target encoding"
71+
"StringEncodingError: iconv: byte sequence 0xc3a9e282ac is invalid in source encoding or cannot be represented in target encoding"
7272
end
7373
end
7474

7575
let x = encode("ÄÆä", "ISO-8859-1")
76-
@test_throws ErrorException decode(x, "UTF-8")
76+
@test_throws StringEncodingError decode(x, "UTF-8")
7777
try
7878
decode(x, "UTF-8")
7979
catch err
8080
io = IOBuffer()
8181
showerror(io, err)
8282
@test takebuf_string(io) ==
83-
"iconv error: byte sequence 0xc4c6e4 is invalid in source encoding or cannot be represented in target encoding"
83+
"StringEncodingError: iconv: byte sequence 0xc4c6e4 is invalid in source encoding or cannot be represented in target encoding"
8484
end
8585
end
8686

@@ -91,7 +91,7 @@ mktemp() do p, io
9191
@test readall(p, "CP1252") == s
9292
end
9393

94-
@test_throws ErrorException p = StringEncoder(IOBuffer(), "nonexistent_encoding")
95-
@test_throws ErrorException p = StringDecoder(IOBuffer(), "nonexistent_encoding")
94+
@test_throws StringEncodingError p = StringEncoder(IOBuffer(), "nonexistent_encoding")
95+
@test_throws StringEncodingError p = StringDecoder(IOBuffer(), "nonexistent_encoding")
9696

9797
nothing

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /