FreeBSD Bugzilla – Attachment 96890 Details for
Bug 135593
net-im/ejabberd: ram_file_io_server makes ejabberdevel to not run with R13B_logl
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ejabberd.diff
ejabberd.diff (text/x-diff; charset=us-ascii), 41.20 KB, created by
Ulrich Spoerlein
on 2009-07-22 13:35:20 UTC
(
hide
)
Description:
ejabberd.diff
Filename:
MIME Type:
Creator:
Ulrich Spoerlein
Created:
2009-07-22 13:35:20 UTC
Size:
41.20 KB
patch
obsolete
>? work >Index: Makefile >=================================================================== >RCS file: /tank/ncvs/ports/net-im/ejabberd/Makefile,v >retrieving revision 1.30 >diff -u -p -r1.30 Makefile >--- Makefile 19 Jul 2009 18:59:39 -0000 1.30 >+++ Makefile 22 Jul 2009 12:31:59 -0000 >@@ -7,6 +7,7 @@ > > PORTNAME= ejabberd > PORTVERSION= 2.0.5 >+PORTREVISION= 1 > CATEGORIES= net-im > MASTER_SITES= http://www.process-one.net/downloads/ejabberd/${PORTVERSION}/ > >Index: files/patch-919-fileioserver >=================================================================== >RCS file: files/patch-919-fileioserver >diff -N files/patch-919-fileioserver >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ files/patch-919-fileioserver 22 Jul 2009 12:31:59 -0000 >@@ -0,0 +1,1219 @@ >+--- Makefile.in >++++ Makefile.in >+@@ -131,6 +131,14 @@ $(BEAMS): $(ERLBEHAVBEAMS) >+ >+ all-recursive: $(ERLBEHAVBEAMS) >+ >++# Workaround for R11, that is not capable of compiling the new file: >++ram_file_io_server.beam: >++ -@ERLC@ -W $(EFLAGS) ram_file_io_server.erl >++ram_file_io_server_old.beam: >++ @ERLC@ -W $(EFLAGS) ram_file_io_server_old.erl >++ [ -f ram_file_io_server.beam ] \ >++ || cp ram_file_io_server_old.beam ram_file_io_server.beam >++ >+ %.beam: %.erl >+ @ERLC@ -W $(EFLAGS) $< >+ >+--- ejabberd_loglevel.erl >++++ ejabberd_loglevel.erl >+@@ -68,7 +68,8 @@ compile_string(Mod, Str) -> >+ end. >+ >+ open_ram_file(Fname) -> >+- ram_file_io_server:start(self(), Fname, [read,write]). >++ RamModule = get_ram_module(), >++ RamModule:start(self(), Fname, [read,write]). >+ >+ close_ram_file(Fd) -> >+ file:close(Fd). >+@@ -85,6 +86,14 @@ load_logger(Forms, Mod, Loglevel) -> >+ ?CRITICAL_MSG("Error ~p~n", [Error]) >+ end. >+ >++%% Workaround for R11 and R12, that don't support the new module >++get_ram_module() -> >++ [AS, BS, _] = string:tokens(erlang:system_info(version), "."), >++ case (list_to_integer(AS) >= 5) and (list_to_integer(BS) >= 7) of >++ true -> ram_file_io_server; >++ false -> ram_file_io_server_old >++ end. >++ >+ %% -------------------------------------------------------------- >+ %% Code of the ejabberd logger, dynamically compiled and loaded >+ %% This allows to dynamically change log level while keeping a >+--- ram_file_io_server.erl >++++ ram_file_io_server.erl >+@@ -25,7 +26,9 @@ >+ -export([format_error/1]). >+ -export([start/3, start_link/3]). >+ >+--record(state, {handle,owner,mref,buf,read_mode}). >++-export([count_and_find/3]). >++ >++-record(state, {handle,owner,mref,buf,read_mode,unic}). >+ >+ -define(PRIM_FILE, ram_file). >+ -define(READ_SIZE_LIST, 128). >+@@ -44,11 +47,11 @@ format_error(ErrorId) -> >+ erl_posix_msg:message(ErrorId). >+ >+ start(Owner, FileName, ModeList) >+- when pid(Owner), list(FileName), list(ModeList) -> >++ when is_pid(Owner), is_list(FileName), is_list(ModeList) -> >+ do_start(spawn, Owner, FileName, ModeList). >+ >+ start_link(Owner, FileName, ModeList) >+- when pid(Owner), list(FileName), list(ModeList) -> >++ when is_pid(Owner), is_list(FileName), is_list(ModeList) -> >+ do_start(spawn_link, Owner, FileName, ModeList). >+ >+ %%%----------------------------------------------------------------- >+@@ -61,27 +64,27 @@ do_start(Spawn, Owner, FileName, ModeList) -> >+ erlang:Spawn( >+ fun() -> >+ %% process_flag(trap_exit, true), >+- {ReadMode,Opts} = >+- case lists:member(binary, ModeList) of >+- true -> >+- {binary,ModeList}; >+- false -> >+- {list,[binary|ModeList]} >+- end, >+- case ?PRIM_FILE:open(FileName, Opts) of >+- {error, Reason} = Error -> >+- Self ! {Ref, Error}, >+- exit(Reason); >+- {ok, Handle} -> >+- %% XXX must I handle R6 nodes here? >+- M = erlang:monitor(process, Owner), >+- Self ! {Ref, ok}, >+- server_loop( >+- #state{handle = Handle, >+- owner = Owner, >+- mref = M, >+- buf = <<>>, >+- read_mode = ReadMode}) >++ case parse_options(ModeList) of >++ {ReadMode, UnicodeMode, Opts} -> >++ case ?PRIM_FILE:open(FileName, Opts) of >++ {error, Reason} = Error -> >++ Self ! {Ref, Error}, >++ exit(Reason); >++ {ok, Handle} -> >++ %% XXX must I handle R6 nodes here? >++ M = erlang:monitor(process, Owner), >++ Self ! {Ref, ok}, >++ server_loop( >++ #state{handle = Handle, >++ owner = Owner, >++ mref = M, >++ buf = <<>>, >++ read_mode = ReadMode, >++ unic = UnicodeMode}) >++ end; >++ {error,Reason1} = Error1 -> >++ Self ! {Ref, Error1}, >++ exit(Reason1) >+ end >+ end), >+ Mref = erlang:monitor(process, Pid), >+@@ -102,9 +105,61 @@ do_start(Spawn, Owner, FileName, ModeList) -> >+ {error, Reason} >+ end. >+ >++%%% Returns {ReadMode, UnicodeMode, RealOpts} >++parse_options(List) -> >++ parse_options(expand_encoding(List), list, latin1, []). >++ >++parse_options([],list,Uni,Acc) -> >++ {list,Uni,[binary|lists:reverse(Acc)]}; >++parse_options([],binary,Uni,Acc) -> >++ {binary,Uni,lists:reverse(Acc)}; >++parse_options([{encoding, Encoding}|T],RMode,_,Acc) -> >++ case valid_enc(Encoding) of >++ {ok, ExpandedEnc} -> >++ parse_options(T,RMode,ExpandedEnc,Acc); >++ {error,Reason} -> >++ {error,Reason} >++ end; >++parse_options([binary|T],_,Uni,Acc) -> >++ parse_options(T,binary,Uni,[binary|Acc]); >++parse_options([H|T],R,U,Acc) -> >++ parse_options(T,R,U,[H|Acc]). >++ >++expand_encoding([]) -> >++ []; >++expand_encoding([latin1 | T]) -> >++ [{encoding,latin1} | expand_encoding(T)]; >++expand_encoding([unicode | T]) -> >++ [{encoding,unicode} | expand_encoding(T)]; >++expand_encoding([H|T]) -> >++ [H|expand_encoding(T)]. >++ >++valid_enc(latin1) -> >++ {ok,latin1}; >++valid_enc(utf8) -> >++ {ok,unicode}; >++valid_enc(unicode) -> >++ {ok,unicode}; >++valid_enc(utf16) -> >++ {ok,{utf16,big}}; >++valid_enc({utf16,big}) -> >++ {ok,{utf16,big}}; >++valid_enc({utf16,little}) -> >++ {ok,{utf16,little}}; >++valid_enc(utf32) -> >++ {ok,{utf32,big}}; >++valid_enc({utf32,big}) -> >++ {ok,{utf32,big}}; >++valid_enc({utf32,little}) -> >++ {ok,{utf32,little}}; >++valid_enc(_Other) -> >++ {error,badarg}. >++ >++ >++ >+ server_loop(#state{mref = Mref} = State) -> >+ receive >+- {file_request, From, ReplyAs, Request} when pid(From) -> >++ {file_request, From, ReplyAs, Request} when is_pid(From) -> >+ case file_request(Request, State) of >+ {reply, Reply, NewState} -> >+ file_reply(From, ReplyAs, Reply), >+@@ -118,7 +173,7 @@ server_loop(#state{mref = Mref} = State) -> >+ file_reply(From, ReplyAs, Reply), >+ exit(Reason) >+ end; >+- {io_request, From, ReplyAs, Request} when pid(From) -> >++ {io_request, From, ReplyAs, Request} when is_pid(From) -> >+ case io_request(Request, State) of >+ {reply, Reply, NewState} -> >+ io_reply(From, ReplyAs, Reply), >+@@ -152,7 +207,7 @@ file_request({pread,At,Sz}, >+ case position(Handle, At, Buf) of >+ {ok,_Offs} -> >+ case ?PRIM_FILE:read(Handle, Sz) of >+- {ok,Bin} when ReadMode==list -> >++ {ok,Bin} when ReadMode =:= list -> >+ std_reply({ok,binary_to_list(Bin)}, State); >+ Reply -> >+ std_reply(Reply, State) >+@@ -203,42 +258,61 @@ std_reply(Reply, State) -> >+ %%%----------------------------------------------------------------- >+ %%% I/O request >+ >+-io_request({put_chars,Chars}, % binary(Chars) new in R9C >++%% New protocol with encoding tags (R13) >++io_request({put_chars, Enc, Chars}, >+ #state{buf= <<>>}=State) -> >+- put_chars(Chars, State); >+-io_request({put_chars,Chars}, % binary(Chars) new in R9C >++ put_chars(Chars, Enc, State); >++io_request({put_chars, Enc, Chars}, >+ #state{handle=Handle,buf=Buf}=State) -> >+ case position(Handle, cur, Buf) of >+ {error,_}=Reply -> >+ {stop,normal,Reply,State#state{buf= <<>>}}; >+ _ -> >+- put_chars(Chars, State#state{buf= <<>>}) >++ put_chars(Chars, Enc, State#state{buf= <<>>}) >+ end; >+-io_request({put_chars,Mod,Func,Args}, >++io_request({put_chars,Enc,Mod,Func,Args}, >+ #state{}=State) -> >+ case catch apply(Mod, Func, Args) of >+- Chars when list(Chars); binary(Chars) -> >+- io_request({put_chars,Chars}, State); >++ Chars when is_list(Chars); is_binary(Chars) -> >++ io_request({put_chars,Enc,Chars}, State); >+ _ -> >+ {error,{error,Func},State} >+ end; >+-io_request({get_until,_Prompt,Mod,Func,XtraArgs}, >+- #state{}=State) -> >+- get_chars(io_lib, get_until, {Mod, Func, XtraArgs}, State); >+-io_request({get_chars,_Prompt,N}, % New in R9C >++ >++ >++io_request({get_until,Enc,_Prompt,Mod,Func,XtraArgs}, >+ #state{}=State) -> >+- get_chars(N, State); >+-io_request({get_chars,_Prompt,Mod,Func,XtraArg}, % New in R9C >++ get_chars(io_lib, get_until, {Mod, Func, XtraArgs}, Enc, State); >++io_request({get_chars,Enc,_Prompt,N}, >+ #state{}=State) -> >+- get_chars(Mod, Func, XtraArg, State); >+-io_request({get_line,_Prompt}, % New in R9C >++ get_chars(N, Enc, State); >++io_request({get_line,Enc,_Prompt}, >+ #state{}=State) -> >+- get_chars(io_lib, collect_line, [], State); >+-io_request({setopts, Opts}, % New in R9C >+- #state{}=State) when list(Opts) -> >++ get_chars(io_lib, collect_line, [], Enc, State); >++ >++ >++io_request({setopts, Opts}, >++ #state{}=State) when is_list(Opts) -> >+ setopts(Opts, State); >++ >++io_request(getopts, >++ #state{}=State) -> >++ getopts(State); >++ >++%% BC with pre-R13 nodes >++io_request({put_chars, Chars},#state{}=State) -> >++ io_request({put_chars, latin1, Chars},State); >++io_request({put_chars,Mod,Func,Args}, #state{}=State) -> >++ io_request({put_chars,latin1,Mod,Func,Args}, State); >++io_request({get_until,_Prompt,Mod,Func,XtraArgs}, #state{}=State) -> >++ io_request({get_until,latin1,_Prompt,Mod,Func,XtraArgs}, State); >++io_request({get_chars,_Prompt,N}, #state{}=State) -> >++ io_request({get_chars,latin1,_Prompt,N}, State); >++io_request({get_line,_Prompt}, #state{}=State) -> >++ io_request({get_line,latin1,_Prompt}, State); >++ >+ io_request({requests,Requests}, >+- #state{}=State) when list(Requests) -> >++ #state{}=State) when is_list(Requests) -> >+ io_request_loop(Requests, {reply,ok,State}); >+ io_request(Unknown, >+ #state{}=State) -> >+@@ -265,76 +339,213 @@ io_request_loop([Request|Tail], >+ >+ %% I/O request put_chars >+ %% >+-put_chars(Chars, #state{handle=Handle}=State) -> >++put_chars(Chars, latin1, #state{handle=Handle, unic=latin1}=State) -> >+ case ?PRIM_FILE:write(Handle, Chars) of >+ {error,_}=Reply -> >+ {stop,normal,Reply,State}; >+ Reply -> >+ {reply,Reply,State} >++ end; >++put_chars(Chars, InEncoding, #state{handle=Handle, unic=OutEncoding}=State) -> >++ case unicode:characters_to_binary(Chars,InEncoding,OutEncoding) of >++ Bin when is_binary(Bin) -> >++ case ?PRIM_FILE:write(Handle, Bin) of >++ {error,_}=Reply -> >++ {stop,normal,Reply,State}; >++ Reply -> >++ {reply,Reply,State} >++ end; >++ {error,_,_} -> >++ {stop,normal,{error,{no_translation, InEncoding, OutEncoding}},State} >+ end. >+ >+ >+ %% Process the I/O request get_chars >+ %% >+-get_chars(0, #state{read_mode=ReadMode}=State) -> >+- {reply,cast(<<>>, ReadMode),State}; >+-get_chars(N, #state{buf=Buf,read_mode=ReadMode}=State) >+- when integer(N), N > 0, N =< size(Buf) -> >++get_chars(0, Enc, #state{read_mode=ReadMode,unic=InEncoding}=State) -> >++ {reply,cast(<<>>, ReadMode,InEncoding, Enc),State}; >++get_chars(N, Enc, #state{buf=Buf,read_mode=ReadMode,unic=latin1}=State) >++ when is_integer(N), N > 0, N =< byte_size(Buf) -> >++ {B1,B2} = split_binary(Buf, N), >++ {reply,cast(B1, ReadMode,latin1,Enc),State#state{buf=B2}}; >++get_chars(N, Enc, #state{buf=Buf,read_mode=ReadMode,unic=latin1}=State) >++ when is_integer(N), N > 0, N =< byte_size(Buf) -> >+ {B1,B2} = split_binary(Buf, N), >+- {reply,cast(B1, ReadMode),State#state{buf=B2}}; >+-get_chars(N, #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) >+- when integer(N), N > 0 -> >+- BufSize = size(Buf), >++ {reply,cast(B1, ReadMode,latin1,Enc),State#state{buf=B2}}; >++get_chars(N, OutEnc,#state{handle=Handle,buf=Buf,read_mode=ReadMode,unic=latin1}=State) >++ when is_integer(N), N > 0 -> >++ BufSize = byte_size(Buf), >+ NeedSize = N-BufSize, >+- Size = max(NeedSize, ?READ_SIZE_BINARY), >++ Size = erlang:max(NeedSize, ?READ_SIZE_BINARY), >+ case ?PRIM_FILE:read(Handle, Size) of >+ {ok, B} -> >+- if BufSize+size(B) < N -> >+- std_reply(cat(Buf, B, ReadMode), State); >++ if BufSize+byte_size(B) < N -> >++ std_reply(cat(Buf, B, ReadMode,latin1,OutEnc), State); >+ true -> >+ {B1,B2} = split_binary(B, NeedSize), >+- {reply,cat(Buf, B1, ReadMode),State#state{buf=B2}} >++ {reply,cat(Buf, B1, ReadMode, latin1,OutEnc),State#state{buf=B2}} >+ end; >+- eof when BufSize==0 -> >++ eof when BufSize =:= 0 -> >+ {reply,eof,State}; >+ eof -> >+- std_reply(cast(Buf, ReadMode), State); >++ std_reply(cast(Buf, ReadMode,latin1,OutEnc), State); >+ {error,Reason}=Error -> >+ {stop,Reason,Error,State#state{buf= <<>>}} >+ end; >+-get_chars(_N, #state{}=State) -> >++get_chars(N, OutEnc,#state{handle=Handle,buf=Buf,read_mode=ReadMode,unic=InEncoding}=State) >++ when is_integer(N), N > 0 -> >++ try >++ %% This is rather tricky, we need to count the actual number of characters >++ %% in the buffer first as unicode characters are not constant in length >++ {BufCount, SplitPos} = count_and_find(Buf,N,InEncoding), >++ case BufCount >= N of >++ true -> >++ {B1,B2} = case SplitPos of >++ none -> {Buf,<<>>}; >++ _ ->split_binary(Buf,SplitPos) >++ end, >++ {reply,cast(B1, ReadMode,InEncoding,OutEnc),State#state{buf=B2}}; >++ false -> >++ %% Need more, Try to read 4*needed in bytes... >++ NeedSize = (N - BufCount) * 4, >++ Size = erlang:max(NeedSize, ?READ_SIZE_BINARY), >++ case ?PRIM_FILE:read(Handle, Size) of >++ {ok, B} -> >++ NewBuf = list_to_binary([Buf,B]), >++ {NewCount,NewSplit} = count_and_find(NewBuf,N,InEncoding), >++ case NewCount >= N of >++ true -> >++ {B01,B02} = case NewSplit of >++ none -> {NewBuf,<<>>}; >++ _ ->split_binary(NewBuf, NewSplit) >++ end, >++ {reply,cast(B01, ReadMode,InEncoding,OutEnc), >++ State#state{buf=B02}}; >++ false -> >++ %% Reached end of file >++ std_reply(cast(NewBuf, ReadMode,InEncoding,OutEnc), >++ State#state{buf = <<>>}) >++ end; >++ eof when BufCount =:= 0 -> >++ {reply,eof,State}; >++ eof -> >++ std_reply(cast(Buf, ReadMode,InEncoding,OutEnc), State#state{buf = <<>>}); >++ {error,Reason}=Error -> >++ {stop,Reason,Error,State#state{buf = <<>>}} >++ end >++ end >++ catch >++ exit:ExError -> >++ {stop,ExError,{error,ExError},State#state{buf= <<>>}} >++ end; >++ >++get_chars(_N, _, #state{}=State) -> >+ {error,{error,get_chars},State}. >+ >+-get_chars(Mod, Func, XtraArg, #state{buf= <<>>}=State) -> >+- get_chars_empty(Mod, Func, XtraArg, start, State); >+-get_chars(Mod, Func, XtraArg, #state{buf=Buf}=State) -> >+- get_chars_apply(Mod, Func, XtraArg, start, State#state{buf= <<>>}, Buf). >++get_chars(Mod, Func, XtraArg, OutEnc, #state{buf= <<>>}=State) -> >++ get_chars_empty(Mod, Func, XtraArg, start, OutEnc, State); >++get_chars(Mod, Func, XtraArg, OutEnc, #state{buf=Buf}=State) -> >++ get_chars_apply(Mod, Func, XtraArg, start, OutEnc, State#state{buf= <<>>}, Buf). >+ >+-get_chars_empty(Mod, Func, XtraArg, S, >++get_chars_empty(Mod, Func, XtraArg, S, latin1, >++ #state{handle=Handle,read_mode=ReadMode, unic=latin1}=State) -> >++ case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of >++ {ok,Bin} -> >++ get_chars_apply(Mod, Func, XtraArg, S, latin1, State, Bin); >++ eof -> >++ get_chars_apply(Mod, Func, XtraArg, S, latin1, State, eof); >++ {error,Reason}=Error -> >++ {stop,Reason,Error,State} >++ end; >++get_chars_empty(Mod, Func, XtraArg, S, OutEnc, >+ #state{handle=Handle,read_mode=ReadMode}=State) -> >+ case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of >+ {ok,Bin} -> >+- get_chars_apply(Mod, Func, XtraArg, S, State, Bin); >++ get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, Bin); >++ eof -> >++ get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, eof); >++ {error,Reason}=Error -> >++ {stop,Reason,Error,State} >++ end. >++get_chars_notempty(Mod, Func, XtraArg, S, OutEnc, >++ #state{handle=Handle,read_mode=ReadMode,buf = B}=State) -> >++ case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of >++ {ok,Bin} -> >++ get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, list_to_binary([Bin,B])); >+ eof -> >+- get_chars_apply(Mod, Func, XtraArg, S, State, eof); >++ case B of >++ <<>> -> >++ get_chars_apply(Mod, Func, XtraArg, S, OutEnc, State, eof); >++ _ -> >++ {stop,invalid_unicode,{error,invalid_unicode},State} >++ end; >+ {error,Reason}=Error -> >+ {stop,Reason,Error,State} >+ end. >+ >+-get_chars_apply(Mod, Func, XtraArg, S0, >+- #state{read_mode=ReadMode}=State, Data0) -> >++ >++get_chars_apply(Mod, Func, XtraArg, S0, latin1, >++ #state{read_mode=ReadMode,unic=latin1}=State, Data0) -> >+ Data1 = case ReadMode of >+- list when binary(Data0) -> binary_to_list(Data0); >++ list when is_binary(Data0) -> binary_to_list(Data0); >+ _ -> Data0 >+ end, >+- case catch Mod:Func(S0, Data1, XtraArg) of >++ case catch Mod:Func(S0, Data1, latin1, XtraArg) of >+ {stop,Result,Buf} -> >+ {reply,Result,State#state{buf=cast_binary(Buf)}}; >+ {'EXIT',Reason} -> >+ {stop,Reason,{error,err_func(Mod, Func, XtraArg)},State}; >+ S1 -> >+- get_chars_empty(Mod, Func, XtraArg, S1, State) >++ get_chars_empty(Mod, Func, XtraArg, S1, latin1, State) >++ end; >++get_chars_apply(Mod, Func, XtraArg, S0, OutEnc, >++ #state{read_mode=ReadMode,unic=InEnc}=State, Data0) -> >++ try >++ {Data1,NewBuff} = case ReadMode of >++ list when is_binary(Data0) -> >++ case unicode:characters_to_list(Data0,InEnc) of >++ {Tag,Decoded,Rest} when Decoded =/= [], Tag =:= error; Decoded =/= [], Tag =:= incomplete -> >++ {Decoded,erlang:iolist_to_binary(Rest)}; >++ {Tag, [], _} when Tag =:= error; Tag =:= incomplete -> >++ exit(invalid_unicode); >++ List when is_list(List) -> >++ {List,<<>>} >++ end; >++ binary when is_binary(Data0) -> >++ case unicode:characters_to_binary(Data0,InEnc,OutEnc) of >++ {Tag2,Decoded2,Rest2} when Decoded2 =/= <<>>, Tag2 =:= error; Decoded2 =/= <<>>, Tag2 =:= incomplete -> >++ {Decoded2,erlang:iolist_to_binary(Rest2)}; >++ {Tag2, <<>>, _} when Tag2 =:= error; Tag2 =:= incomplete -> >++ exit(invalid_unicode); >++ Binary when is_binary(Binary) -> >++ {Binary,<<>>} >++ end; >++ _ -> %i.e. eof >++ {Data0,<<>>} >++ end, >++ case catch Mod:Func(S0, Data1, OutEnc, XtraArg) of >++ {stop,Result,Buf} -> >++ {reply,Result,State#state{buf = (if >++ is_binary(Buf) -> >++ unicode:characters_to_binary(Buf,OutEnc,InEnc); >++ is_list(Buf) -> >++ unicode:characters_to_binary(Buf,unicode,InEnc); >++ true -> >++ <<>> >++ end)}}; >++ {'EXIT',Reason} -> >++ {stop,Reason,{error,err_func(Mod, Func, XtraArg)},State}; >++ S1 -> >++ get_chars_notempty(Mod, Func, XtraArg, S1, OutEnc, State#state{buf=NewBuff}) >++ end >++ catch >++ exit:ExReason -> >++ {stop,ExReason,{error,err_func(Mod, Func, XtraArg)},State}; >++ error:ErrReason -> >++ {stop,ErrReason,{error,err_func(Mod, Func, XtraArg)},State} >+ end. >++ >++ >+ >+ %% Convert error code to make it look as before >+ err_func(io_lib, get_until, {_,F,_}) -> >+@@ -347,35 +558,100 @@ err_func(_, F, _) -> >+ %% Process the I/O request setopts >+ %% >+ %% setopts >+-setopts(Opts0, State) -> >+- Opts = proplists:substitute_negations([{list,binary}], Opts0), >+- case proplists:get_value(binary, Opts) of >++setopts(Opts0,State) -> >++ Opts = proplists:unfold( >++ proplists:substitute_negations( >++ [{list,binary}], >++ expand_encoding(Opts0))), >++ case check_valid_opts(Opts) of >+ true -> >+- {ok,ok,State#state{read_mode=binary}}; >++ do_setopts(Opts,State); >+ false -> >+- {ok,ok,State#state{read_mode=list}}; >++ {error,{error,enotsup},State} >++ end. >++check_valid_opts([]) -> >++ true; >++check_valid_opts([{binary,_}|T]) -> >++ check_valid_opts(T); >++check_valid_opts([{encoding,_Enc}|T]) -> >++ check_valid_opts(T); >++check_valid_opts(_) -> >++ false. >++do_setopts(Opts, State) -> >++ case valid_enc(proplists:get_value(encoding, Opts, State#state.unic)) of >++ {ok,NewUnic} -> >++ case proplists:get_value(binary, Opts) of >++ true -> >++ {reply,ok,State#state{read_mode=binary, unic=NewUnic}}; >++ false -> >++ {reply,ok,State#state{read_mode=list, unic=NewUnic}}; >++ undefined -> >++ {reply,ok,State#state{unic=NewUnic}} >++ end; >+ _ -> >+- {error,{error,badarg},State} >++ {error,{error,badarg},State} >+ end. >+ >+- >++getopts(#state{read_mode=RM, unic=Unic} = State) -> >++ Bin = {binary, case RM of >++ binary -> >++ true; >++ _ -> >++ false >++ end}, >++ Uni = {encoding, Unic}, >++ {reply,[Bin,Uni],State}. >++ >+ >+ %% Concatenate two binaries and convert the result to list or binary >+-cat(B1, B2, binary) -> >++cat(B1, B2, binary,latin1,latin1) -> >+ list_to_binary([B1,B2]); >+-cat(B1, B2, list) -> >++cat(B1, B2, binary,InEncoding,OutEncoding) -> >++ case unicode:characters_to_binary([B1,B2],InEncoding,OutEncoding) of >++ Good when is_binary(Good) -> >++ Good; >++ _ -> >++ exit({no_translation,InEncoding,OutEncoding}) >++ end; >++%% Dialyzer finds this is never used... >++%% cat(B1, B2, list, InEncoding, OutEncoding) when InEncoding =/= latin1 -> >++%% % Catch i.e. unicode -> latin1 errors by using the outencoding although otherwise >++%% % irrelevant for lists... >++%% try >++%% unicode:characters_to_list(unicode:characters_to_binary([B1,B2],InEncoding,OutEncoding), >++%% OutEncoding) >++%% catch >++%% error:_ -> >++%% exit({no_translation,InEncoding,OutEncoding}) >++%% end. >++cat(B1, B2, list, latin1,_) -> >+ binary_to_list(B1)++binary_to_list(B2). >+ >+ %% Cast binary to list or binary >+-cast(B, binary) -> >++cast(B, binary, latin1, latin1) -> >+ B; >+-cast(B, list) -> >+- binary_to_list(B). >++cast(B, binary, InEncoding, OutEncoding) -> >++ case unicode:characters_to_binary(B,InEncoding,OutEncoding) of >++ Good when is_binary(Good) -> >++ Good; >++ _ -> >++ exit({no_translation,InEncoding,OutEncoding}) >++ end; >++cast(B, list, latin1, _) -> >++ binary_to_list(B); >++cast(B, list, InEncoding, OutEncoding) -> >++ try >++ unicode:characters_to_list(unicode:characters_to_binary(B,InEncoding,OutEncoding), >++ OutEncoding) >++ catch >++ error:_ -> >++ exit({no_translation,InEncoding,OutEncoding}) >++ end. >+ >+ %% Convert buffer to binary >+-cast_binary(Binary) when binary(Binary) -> >++cast_binary(Binary) when is_binary(Binary) -> >+ Binary; >+-cast_binary(List) when list(List) -> >++cast_binary(List) when is_list(List) -> >+ list_to_binary(List); >+ cast_binary(_EOF) -> >+ <<>>. >+@@ -386,10 +662,150 @@ read_size(binary) -> >+ read_size(list) -> >+ ?READ_SIZE_LIST. >+ >+-max(A, B) when A >= B -> >+- A; >+-max(_, B) -> >+- B. >++%% Utf utility >++count_and_find(Bin,N,Encoding) -> >++ cafu(Bin,N,0,0,none,case Encoding of >++ unicode -> utf8; >++ Oth -> Oth >++ end). >++ >++cafu(<<>>,0,Count,ByteCount,_SavePos,_) -> >++ {Count,ByteCount}; >++cafu(<<>>,_N,Count,_ByteCount,SavePos,_) -> >++ {Count,SavePos}; >++cafu(<<_/utf8,Rest/binary>>, 0, Count, ByteCount, _SavePos, utf8) -> >++ cafu(Rest,-1,Count+1,0,ByteCount,utf8); >++cafu(<<_/utf8,Rest/binary>>, N, Count, _ByteCount, SavePos, utf8) when N < 0 -> >++ cafu(Rest,-1,Count+1,0,SavePos,utf8); >++cafu(<<_/utf8,Rest/binary>> = Whole, N, Count, ByteCount, SavePos, utf8) -> >++ Delta = byte_size(Whole) - byte_size(Rest), >++ cafu(Rest,N-1,Count+1,ByteCount+Delta,SavePos,utf8); >++cafu(<<_/utf16-big,Rest/binary>>, 0, Count, ByteCount, _SavePos, {utf16,big}) -> >++ cafu(Rest,-1,Count+1,0,ByteCount,{utf16,big}); >++cafu(<<_/utf16-big,Rest/binary>>, N, Count, _ByteCount, SavePos, {utf16,big}) when N < 0 -> >++ cafu(Rest,-1,Count+1,0,SavePos,{utf16,big}); >++cafu(<<_/utf16-big,Rest/binary>> = Whole, N, Count, ByteCount, SavePos, {utf16,big}) -> >++ Delta = byte_size(Whole) - byte_size(Rest), >++ cafu(Rest,N-1,Count+1,ByteCount+Delta,SavePos,{utf16,big}); >++cafu(<<_/utf16-little,Rest/binary>>, 0, Count, ByteCount, _SavePos, {utf16,little}) -> >++ cafu(Rest,-1,Count+1,0,ByteCount,{utf16,little}); >++cafu(<<_/utf16-little,Rest/binary>>, N, Count, _ByteCount, SavePos, {utf16,little}) when N < 0 -> >++ cafu(Rest,-1,Count+1,0,SavePos,{utf16,little}); >++cafu(<<_/utf16-little,Rest/binary>> = Whole, N, Count, ByteCount, SavePos, {utf16,little}) -> >++ Delta = byte_size(Whole) - byte_size(Rest), >++ cafu(Rest,N-1,Count+1,ByteCount+Delta,SavePos,{utf16,little}); >++cafu(<<_/utf32-big,Rest/binary>>, 0, Count, ByteCount, _SavePos, {utf32,big}) -> >++ cafu(Rest,-1,Count+1,0,ByteCount,{utf32,big}); >++cafu(<<_/utf32-big,Rest/binary>>, N, Count, _ByteCount, SavePos, {utf32,big}) when N < 0 -> >++ cafu(Rest,-1,Count+1,0,SavePos,{utf32,big}); >++cafu(<<_/utf32-big,Rest/binary>> = Whole, N, Count, ByteCount, SavePos, {utf32,big}) -> >++ Delta = byte_size(Whole) - byte_size(Rest), >++ cafu(Rest,N-1,Count+1,ByteCount+Delta,SavePos,{utf32,big}); >++cafu(<<_/utf32-little,Rest/binary>>, 0, Count, ByteCount, _SavePos, {utf32,little}) -> >++ cafu(Rest,-1,Count+1,0,ByteCount,{utf32,little}); >++cafu(<<_/utf32-little,Rest/binary>>, N, Count, _ByteCount, SavePos, {utf32,little}) when N < 0 -> >++ cafu(Rest,-1,Count+1,0,SavePos,{utf32,little}); >++cafu(<<_/utf32-little,Rest/binary>> = Whole, N, Count, ByteCount, SavePos, {utf32,little}) -> >++ Delta = byte_size(Whole) - byte_size(Rest), >++ cafu(Rest,N-1,Count+1,ByteCount+Delta,SavePos,{utf32,little}); >++cafu(_Other,0,Count,ByteCount,_,_) -> % Non Unicode character, >++ % but found our point, OK this time >++ {Count,ByteCount}; >++cafu(Other,_N,Count,0,_SavePos,Enc) -> % Not enough, but valid chomped unicode >++ % at end. >++ case cbv(Enc,Other) of >++ false -> >++ exit(invalid_unicode); >++ _ -> >++ {Count,none} >++ end; >++cafu(Other,_N,Count,ByteCount,none,Enc) -> % Return what we'we got this far >++ % although not complete, >++ % it's not (yet) in error >++ case cbv(Enc,Other) of >++ false -> >++ exit(invalid_unicode); >++ _ -> >++ {Count,ByteCount} >++ end; >++cafu(Other,_N,Count,_ByteCount,SavePos,Enc) -> % As above but we have >++ % found a position >++ case cbv(Enc,Other) of >++ false -> >++ exit(invalid_unicode); >++ _ -> >++ {Count,SavePos} >++ end. >++ >++%% >++%% Bluntly stolen from stdlib/unicode.erl (cbv means can be valid?) >++%% >++cbv(utf8,<<1:1,1:1,0:1,_:5>>) -> >++ 1; >++cbv(utf8,<<1:1,1:1,1:1,0:1,_:4,R/binary>>) -> >++ case R of >++ <<>> -> >++ 2; >++ <<1:1,0:1,_:6>> -> >++ 1; >++ _ -> >++ false >++ end; >++cbv(utf8,<<1:1,1:1,1:1,1:1,0:1,_:3,R/binary>>) -> >++ case R of >++ <<>> -> >++ 3; >++ <<1:1,0:1,_:6>> -> >++ 2; >++ <<1:1,0:1,_:6,1:1,0:1,_:6>> -> >++ 1; >++ _ -> >++ false >++ end; >++cbv(utf8,_) -> >++ false; >++ >++cbv({utf16,big},<<A:8>>) when A =< 215; A >= 224 -> >++ 1; >++cbv({utf16,big},<<54:6,_:2>>) -> >++ 3; >++cbv({utf16,big},<<54:6,_:10>>) -> >++ 2; >++cbv({utf16,big},<<54:6,_:10,55:6,_:2>>) -> >++ 1; >++cbv({utf16,big},_) -> >++ false; >++cbv({utf16,little},<<_:8>>) -> >++ 1; % or 3, we'll see >++cbv({utf16,little},<<_:8,54:6,_:2>>) -> >++ 2; >++cbv({utf16,little},<<_:8,54:6,_:2,_:8>>) -> >++ 1; >++cbv({utf16,little},_) -> >++ false; >++ >++ >++cbv({utf32,big}, <<0:8>>) -> >++ 3; >++cbv({utf32,big}, <<0:8,X:8>>) when X =< 16 -> >++ 2; >++cbv({utf32,big}, <<0:8,X:8,Y:8>>) >++ when X =< 16, ((X > 0) or ((Y =< 215) or (Y >= 224))) -> >++ 1; >++cbv({utf32,big},_) -> >++ false; >++cbv({utf32,little},<<_:8>>) -> >++ 3; >++cbv({utf32,little},<<_:8,_:8>>) -> >++ 2; >++cbv({utf32,little},<<X:8,255:8,0:8>>) when X =:= 254; X =:= 255 -> >++ false; >++cbv({utf32,little},<<_:8,Y:8,X:8>>) >++ when X =< 16, ((X > 0) or ((Y =< 215) or (Y >= 224))) -> >++ 1; >++cbv({utf32,little},_) -> >++ false. >++ >+ >+ %%%----------------------------------------------------------------- >+ %%% ?PRIM_FILE helpers >+@@ -399,10 +815,10 @@ max(_, B) -> >+ >+ position(Handle, cur, Buf) -> >+ position(Handle, {cur, 0}, Buf); >+-position(Handle, {cur, Offs}, Buf) when list(Buf) -> >++position(Handle, {cur, Offs}, Buf) when is_list(Buf) -> >+ ?PRIM_FILE:position(Handle, {cur, Offs-length(Buf)}); >+-position(Handle, {cur, Offs}, Buf) when binary(Buf) -> >+- ?PRIM_FILE:position(Handle, {cur, Offs-size(Buf)}); >++position(Handle, {cur, Offs}, Buf) when is_binary(Buf) -> >++ ?PRIM_FILE:position(Handle, {cur, Offs-byte_size(Buf)}); >+ position(Handle, At, _Buf) -> >+ ?PRIM_FILE:position(Handle, At). >+ >+--- /dev/null >++++ ram_file_io_server_old.erl >+@@ -0,0 +1,408 @@ >++%% ``The contents of this file are subject to the Erlang Public License, >++%% Version 1.1, (the "License"); you may not use this file except in >++%% compliance with the License. You should have received a copy of the >++%% Erlang Public License along with this software. If not, it can be >++%% retrieved via the world wide web at http://www.erlang.org/. >++%% >++%% Software distributed under the License is distributed on an "AS IS" >++%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See >++%% the License for the specific language governing rights and limitations >++%% under the License. >++%% >++%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. >++%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings >++%% AB. All Rights Reserved.'' >++%% >++%% $Id$ >++%% >++%% This file is mostly copied from Erlang file_io_server.erl >++%% See: http://www.erlang.org/ml-archive/erlang-questions/200607/msg00080.html >++%% for details on ram_file_io_server.erl (Erlang OTP R11B-2) >++-module(ram_file_io_server_old). >++ >++%% A simple file server for io to one file instance per server instance. >++ >++-export([format_error/1]). >++-export([start/3, start_link/3]). >++ >++-record(state, {handle,owner,mref,buf,read_mode}). >++ >++-define(PRIM_FILE, ram_file). >++-define(READ_SIZE_LIST, 128). >++-define(READ_SIZE_BINARY, (8*1024)). >++ >++-define(eat_message(M, T), receive M -> M after T -> timeout end). >++ >++%%%----------------------------------------------------------------- >++%%% Exported functions >++ >++format_error({_Line, ?MODULE, Reason}) -> >++ io_lib:format("~w", [Reason]); >++format_error({_Line, Mod, Reason}) -> >++ Mod:format_error(Reason); >++format_error(ErrorId) -> >++ erl_posix_msg:message(ErrorId). >++ >++start(Owner, FileName, ModeList) >++ when pid(Owner), list(FileName), list(ModeList) -> >++ do_start(spawn, Owner, FileName, ModeList). >++ >++start_link(Owner, FileName, ModeList) >++ when pid(Owner), list(FileName), list(ModeList) -> >++ do_start(spawn_link, Owner, FileName, ModeList). >++ >++%%%----------------------------------------------------------------- >++%%% Server starter, dispatcher and helpers >++ >++do_start(Spawn, Owner, FileName, ModeList) -> >++ Self = self(), >++ Ref = make_ref(), >++ Pid = >++ erlang:Spawn( >++ fun() -> >++ %% process_flag(trap_exit, true), >++ {ReadMode,Opts} = >++ case lists:member(binary, ModeList) of >++ true -> >++ {binary,ModeList}; >++ false -> >++ {list,[binary|ModeList]} >++ end, >++ case ?PRIM_FILE:open(FileName, Opts) of >++ {error, Reason} = Error -> >++ Self ! {Ref, Error}, >++ exit(Reason); >++ {ok, Handle} -> >++ %% XXX must I handle R6 nodes here? >++ M = erlang:monitor(process, Owner), >++ Self ! {Ref, ok}, >++ server_loop( >++ #state{handle = Handle, >++ owner = Owner, >++ mref = M, >++ buf = <<>>, >++ read_mode = ReadMode}) >++ end >++ end), >++ Mref = erlang:monitor(process, Pid), >++ receive >++ {Ref, {error, _Reason} = Error} -> >++ erlang:demonitor(Mref), >++ receive {'DOWN', Mref, _, _, _} -> ok after 0 -> ok end, >++ Error; >++ {Ref, ok} -> >++ erlang:demonitor(Mref), >++ receive >++ {'DOWN', Mref, _, _, Reason} -> >++ {error, Reason} >++ after 0 -> >++ {ok, Pid} >++ end; >++ {'DOWN', Mref, _, _, Reason} -> >++ {error, Reason} >++ end. >++ >++server_loop(#state{mref = Mref} = State) -> >++ receive >++ {file_request, From, ReplyAs, Request} when pid(From) -> >++ case file_request(Request, State) of >++ {reply, Reply, NewState} -> >++ file_reply(From, ReplyAs, Reply), >++ server_loop(NewState); >++ {error, Reply, NewState} -> >++ %% error is the same as reply, except that >++ %% it breaks the io_request_loop further down >++ file_reply(From, ReplyAs, Reply), >++ server_loop(NewState); >++ {stop, Reason, Reply, _NewState} -> >++ file_reply(From, ReplyAs, Reply), >++ exit(Reason) >++ end; >++ {io_request, From, ReplyAs, Request} when pid(From) -> >++ case io_request(Request, State) of >++ {reply, Reply, NewState} -> >++ io_reply(From, ReplyAs, Reply), >++ server_loop(NewState); >++ {error, Reply, NewState} -> >++ %% error is the same as reply, except that >++ %% it breaks the io_request_loop further down >++ io_reply(From, ReplyAs, Reply), >++ server_loop(NewState); >++ {stop, Reason, Reply, _NewState} -> >++ io_reply(From, ReplyAs, Reply), >++ exit(Reason) >++ end; >++ {'DOWN', Mref, _, _, Reason} -> >++ exit(Reason); >++ _ -> >++ server_loop(State) >++ end. >++ >++file_reply(From, ReplyAs, Reply) -> >++ From ! {file_reply, ReplyAs, Reply}. >++ >++io_reply(From, ReplyAs, Reply) -> >++ From ! {io_reply, ReplyAs, Reply}. >++ >++%%%----------------------------------------------------------------- >++%%% file requests >++ >++file_request({pread,At,Sz}, >++ #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) -> >++ case position(Handle, At, Buf) of >++ {ok,_Offs} -> >++ case ?PRIM_FILE:read(Handle, Sz) of >++ {ok,Bin} when ReadMode==list -> >++ std_reply({ok,binary_to_list(Bin)}, State); >++ Reply -> >++ std_reply(Reply, State) >++ end; >++ Reply -> >++ std_reply(Reply, State) >++ end; >++file_request({pwrite,At,Data}, >++ #state{handle=Handle,buf=Buf}=State) -> >++ case position(Handle, At, Buf) of >++ {ok,_Offs} -> >++ std_reply(?PRIM_FILE:write(Handle, Data), State); >++ Reply -> >++ std_reply(Reply, State) >++ end; >++file_request(sync, >++ #state{handle=Handle}=State) -> >++ case ?PRIM_FILE:sync(Handle) of >++ {error,_}=Reply -> >++ {stop,normal,Reply,State}; >++ Reply -> >++ {reply,Reply,State} >++ end; >++file_request(close, >++ #state{handle=Handle}=State) -> >++ {stop,normal,?PRIM_FILE:close(Handle),State#state{buf= <<>>}}; >++file_request({position,At}, >++ #state{handle=Handle,buf=Buf}=State) -> >++ std_reply(position(Handle, At, Buf), State); >++file_request(truncate, >++ #state{handle=Handle}=State) -> >++ case ?PRIM_FILE:truncate(Handle) of >++ {error,_Reason}=Reply -> >++ {stop,normal,Reply,State#state{buf= <<>>}}; >++ Reply -> >++ {reply,Reply,State} >++ end; >++file_request(Unknown, >++ #state{}=State) -> >++ Reason = {request, Unknown}, >++ {error,{error,Reason},State}. >++ >++std_reply({error,_}=Reply, State) -> >++ {error,Reply,State#state{buf= <<>>}}; >++std_reply(Reply, State) -> >++ {reply,Reply,State#state{buf= <<>>}}. >++ >++%%%----------------------------------------------------------------- >++%%% I/O request >++ >++io_request({put_chars,Chars}, % binary(Chars) new in R9C >++ #state{buf= <<>>}=State) -> >++ put_chars(Chars, State); >++io_request({put_chars,Chars}, % binary(Chars) new in R9C >++ #state{handle=Handle,buf=Buf}=State) -> >++ case position(Handle, cur, Buf) of >++ {error,_}=Reply -> >++ {stop,normal,Reply,State#state{buf= <<>>}}; >++ _ -> >++ put_chars(Chars, State#state{buf= <<>>}) >++ end; >++io_request({put_chars,Mod,Func,Args}, >++ #state{}=State) -> >++ case catch apply(Mod, Func, Args) of >++ Chars when list(Chars); binary(Chars) -> >++ io_request({put_chars,Chars}, State); >++ _ -> >++ {error,{error,Func},State} >++ end; >++io_request({get_until,_Prompt,Mod,Func,XtraArgs}, >++ #state{}=State) -> >++ get_chars(io_lib, get_until, {Mod, Func, XtraArgs}, State); >++io_request({get_chars,_Prompt,N}, % New in R9C >++ #state{}=State) -> >++ get_chars(N, State); >++io_request({get_chars,_Prompt,Mod,Func,XtraArg}, % New in R9C >++ #state{}=State) -> >++ get_chars(Mod, Func, XtraArg, State); >++io_request({get_line,_Prompt}, % New in R9C >++ #state{}=State) -> >++ get_chars(io_lib, collect_line, [], State); >++io_request({setopts, Opts}, % New in R9C >++ #state{}=State) when list(Opts) -> >++ setopts(Opts, State); >++io_request({requests,Requests}, >++ #state{}=State) when list(Requests) -> >++ io_request_loop(Requests, {reply,ok,State}); >++io_request(Unknown, >++ #state{}=State) -> >++ Reason = {request,Unknown}, >++ {error,{error,Reason},State}. >++ >++ >++ >++%% Process a list of requests as long as the results are ok. >++ >++io_request_loop([], Result) -> >++ Result; >++io_request_loop([_Request|_Tail], >++ {stop,_Reason,_Reply,_State}=Result) -> >++ Result; >++io_request_loop([_Request|_Tail], >++ {error,_Reply,_State}=Result) -> >++ Result; >++io_request_loop([Request|Tail], >++ {reply,_Reply,State}) -> >++ io_request_loop(Tail, io_request(Request, State)). >++ >++ >++ >++%% I/O request put_chars >++%% >++put_chars(Chars, #state{handle=Handle}=State) -> >++ case ?PRIM_FILE:write(Handle, Chars) of >++ {error,_}=Reply -> >++ {stop,normal,Reply,State}; >++ Reply -> >++ {reply,Reply,State} >++ end. >++ >++ >++%% Process the I/O request get_chars >++%% >++get_chars(0, #state{read_mode=ReadMode}=State) -> >++ {reply,cast(<<>>, ReadMode),State}; >++get_chars(N, #state{buf=Buf,read_mode=ReadMode}=State) >++ when integer(N), N > 0, N =< size(Buf) -> >++ {B1,B2} = split_binary(Buf, N), >++ {reply,cast(B1, ReadMode),State#state{buf=B2}}; >++get_chars(N, #state{handle=Handle,buf=Buf,read_mode=ReadMode}=State) >++ when integer(N), N > 0 -> >++ BufSize = size(Buf), >++ NeedSize = N-BufSize, >++ Size = max(NeedSize, ?READ_SIZE_BINARY), >++ case ?PRIM_FILE:read(Handle, Size) of >++ {ok, B} -> >++ if BufSize+size(B) < N -> >++ std_reply(cat(Buf, B, ReadMode), State); >++ true -> >++ {B1,B2} = split_binary(B, NeedSize), >++ {reply,cat(Buf, B1, ReadMode),State#state{buf=B2}} >++ end; >++ eof when BufSize==0 -> >++ {reply,eof,State}; >++ eof -> >++ std_reply(cast(Buf, ReadMode), State); >++ {error,Reason}=Error -> >++ {stop,Reason,Error,State#state{buf= <<>>}} >++ end; >++get_chars(_N, #state{}=State) -> >++ {error,{error,get_chars},State}. >++ >++get_chars(Mod, Func, XtraArg, #state{buf= <<>>}=State) -> >++ get_chars_empty(Mod, Func, XtraArg, start, State); >++get_chars(Mod, Func, XtraArg, #state{buf=Buf}=State) -> >++ get_chars_apply(Mod, Func, XtraArg, start, State#state{buf= <<>>}, Buf). >++ >++get_chars_empty(Mod, Func, XtraArg, S, >++ #state{handle=Handle,read_mode=ReadMode}=State) -> >++ case ?PRIM_FILE:read(Handle, read_size(ReadMode)) of >++ {ok,Bin} -> >++ get_chars_apply(Mod, Func, XtraArg, S, State, Bin); >++ eof -> >++ get_chars_apply(Mod, Func, XtraArg, S, State, eof); >++ {error,Reason}=Error -> >++ {stop,Reason,Error,State} >++ end. >++ >++get_chars_apply(Mod, Func, XtraArg, S0, >++ #state{read_mode=ReadMode}=State, Data0) -> >++ Data1 = case ReadMode of >++ list when binary(Data0) -> binary_to_list(Data0); >++ _ -> Data0 >++ end, >++ case catch Mod:Func(S0, Data1, XtraArg) of >++ {stop,Result,Buf} -> >++ {reply,Result,State#state{buf=cast_binary(Buf)}}; >++ {'EXIT',Reason} -> >++ {stop,Reason,{error,err_func(Mod, Func, XtraArg)},State}; >++ S1 -> >++ get_chars_empty(Mod, Func, XtraArg, S1, State) >++ end. >++ >++%% Convert error code to make it look as before >++err_func(io_lib, get_until, {_,F,_}) -> >++ F; >++err_func(_, F, _) -> >++ F. >++ >++ >++ >++%% Process the I/O request setopts >++%% >++%% setopts >++setopts(Opts0, State) -> >++ Opts = proplists:substitute_negations([{list,binary}], Opts0), >++ case proplists:get_value(binary, Opts) of >++ true -> >++ {ok,ok,State#state{read_mode=binary}}; >++ false -> >++ {ok,ok,State#state{read_mode=list}}; >++ _ -> >++ {error,{error,badarg},State} >++ end. >++ >++ >++ >++%% Concatenate two binaries and convert the result to list or binary >++cat(B1, B2, binary) -> >++ list_to_binary([B1,B2]); >++cat(B1, B2, list) -> >++ binary_to_list(B1)++binary_to_list(B2). >++ >++%% Cast binary to list or binary >++cast(B, binary) -> >++ B; >++cast(B, list) -> >++ binary_to_list(B). >++ >++%% Convert buffer to binary >++cast_binary(Binary) when binary(Binary) -> >++ Binary; >++cast_binary(List) when list(List) -> >++ list_to_binary(List); >++cast_binary(_EOF) -> >++ <<>>. >++ >++%% Read size for different read modes >++read_size(binary) -> >++ ?READ_SIZE_BINARY; >++read_size(list) -> >++ ?READ_SIZE_LIST. >++ >++max(A, B) when A >= B -> >++ A; >++max(_, B) -> >++ B. >++ >++%%%----------------------------------------------------------------- >++%%% ?PRIM_FILE helpers >++ >++%% Compensates ?PRIM_FILE:position/2 for the number of bytes >++%% we have buffered >++ >++position(Handle, cur, Buf) -> >++ position(Handle, {cur, 0}, Buf); >++position(Handle, {cur, Offs}, Buf) when list(Buf) -> >++ ?PRIM_FILE:position(Handle, {cur, Offs-length(Buf)}); >++position(Handle, {cur, Offs}, Buf) when binary(Buf) -> >++ ?PRIM_FILE:position(Handle, {cur, Offs-size(Buf)}); >++position(Handle, At, _Buf) -> >++ ?PRIM_FILE:position(Handle, At). >++
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 135593
:
96886
|
96887
|
96888
|
96889
| 96890