Here is new solution which use only one sequential machine to parse total chunk of file. But this solution 2 times slover than previous :( Interesting thing, execution of SM took 10% of total time, and about 90% took postprocessing :(

Can somebody help me with improving this solution?

#!/bin/j

require 'socket strings'

IFNAME =: 'headers'
OFNAME =: 'records'

HCNT =: 0
LHN =: , 1{::sdgethostname_jsocket_''

NB. ================== parse ====================

SFs =: 154$0
SFs =: (1)(8 12 13)}SFs
SFs =: (2)(22 24 25 26 27 50 52 53 54 55)}SFs
SFs =: (3)(29 32 33 34)}SFs
SFs =: (4)(35 36 39 40 41)}SFs
SFs =: (5)(38)}SFs
SFs =: (6)(64 67 68 69)}SFs
SFs =: (7)(78 82 83)}SFs
SFs =: (8)(92 96 97)}SFs
SFs =: (9)(114)}SFs
SFs =: (10)(133 139)}SFs
SFs =: (11)(146)}SFs

cm =: 256$0
cm =: (1)(a.i.' ')}cm
cm =: (2)(a.i.':')}cm
cm =: (3)(a.i.'/')}cm
cm =: (4)(a.i.'?')}cm
cm =: (5)(a.i.TAB)}cm
cm =: (6)(a.i. LF)}cm

NB.       other   SP    :     /     ?    TAB    LF
NB.         0     1     2     3     4     5     6
NB.
sm =:      1 1   0 6   0 6   0 6   0 6   0 6  20 1 NB.  0: wait for METHOD
sm =: sm,  1 0   2 3   0 6   0 6   0 6   2 3  21 3 NB.  1: read METHOD
sm =: sm,  3 1  12 0   7 1   8 0  10 0  12 0  15 0 NB.  2: wait for 
[protocol://][host[:[port]]][/[path]][?[query]]
sm =: sm,  3 0  12 3   4 0   8 3  10 3  12 3  15 3 NB.  3: read PROTOCOL or HOST
sm =: sm,  7 0  12 3   0 6   5 0  10 3  12 3  15 3 NB.  4: current is PROTOCOL: 
or HOST:
sm =: sm,  9 2  12 3   0 6   6 3  10 3  12 3  15 3 NB.  5: current PROTOCOL:/ 
or HOST:/
sm =: sm,  7 1  12 0   7 1   8 0  10 0  12 0  15 0 NB.  6: wait for 
[HOST[:[PORT]]][/[PATH]][?[QUERY]]
sm =: sm,  7 0  12 3   7 0   8 3  10 3  12 3  15 3 NB.  7: read HOST
sm =: sm,  9 1  12 0   0 6   9 1  10 0  12 0  15 0 NB.  8: wait for 
[PATH][?[QUERY]]
sm =: sm,  9 0  12 3   0 6   9 0  10 3  12 3  15 3 NB.  9: read PATH
sm =: sm, 11 1  12 0  11 1  11 1  11 1  12 0  15 0 NB. 10: wait for QUERY
sm =: sm, 11 0  12 3  11 0  11 0  11 0  12 3  15 3 NB. 11: read QUERY
sm =: sm, 13 1  12 0   0 6   0 6   0 6  12 0  15 0 NB. 12: wait for VERSION or 
LF
sm =: sm, 13 0  14 3  13 0  13 0  13 0  14 3  15 3 NB. 13: read VERSION
sm =: sm, 14 0  14 0  14 0  14 0  14 0  14 0  15 0 NB. 14: wait for end of 
'method url version' line
sm =: sm, 16 1   0 6   0 6   0 6   0 6   0 6  20 1 NB. 15: wait for ATTRNAME
sm =: sm, 16 0   0 6  17 3   0 6   0 6   0 6   0 6 NB. 16: read ATTRNAME
sm =: sm, 18 1  18 1  18 1  18 1  18 1  18 1  19 1 NB. 17: wait for ATTRVALUE
sm =: sm, 18 0  18 0  18 0  18 0  18 0  18 0  19 0 NB. 18: read ATTRVALUE
sm =: sm, 16 2  18 0  18 0  18 0  18 0  18 0  20 2 NB. 19: continue read 
ATTRVALUE or start read ATTRNAME?
sm =: sm,  0 6   0 6   0 6   0 6   0 6   0 6   0 3 NB. 20: wait for end of 
header (second LF from LF,LF)
sm =: sm,  0 6   0 6   0 6   0 6   0 6   0 6  20 1 NB. 21: wait for first LF 
from LF,LF

sm =: 22 7 2 $ sm
process =: monad define
    ANs =: 
'METHOD:';'HTTP-PROTOCOL-VERSION:';'PROTOCOL:';'HOST:';'PORT:';'RESOURCE:';'QUERY:'
    AVs =: 'GET';'HTTP/0.9';'http';LHN;'80';'';''

    t =. (4;sm;cm);:y.

    for_j. t do.
        'i l f' =. j
        s =. (i+i.l){y.
        select. f{SFs
            case. 1 do. AVs =: (<s)(0)}AVs
            case. 2 do. AVs =: (<s)(3)}AVs
            case. 3 do. AVs =: (<_1}.s)(3)}AVs
            case. 4 do. AVs =: (<_2}.s)(3)}AVs
            case. 5 do. AVs =: (<_2}.s)(2)}AVs
            case. 6 do. AVs =: (<s)(5)}AVs
            case. 7 do. AVs =: (<s)(6)}AVs
            case. 8 do. AVs =: (<s)(1)}AVs
            case. 9 do. n =. <toupper s,':'
            case. 10 do.
                s =. }.}:s
                if. #s do.
                    i =. ANs i.n
                    if. i<#ANs do.
                        AVs =: (<s)(i)}AVs
                    else.
                        ANs =: ANs,n
                        AVs =: AVs,<s
                    end.
                end.
            case. 11 do.
                v =. 3{::AVs
                i =. v i.':'
                if. i<#v do.
                    h =. deb i{.v
                    if. 0=#h do. h =. LHN end.
                    p =. ((>:i)}.v)-.LF
                    if. 0=#p do. p =. '80' end.
                    AVs =: (h;p)(3 4)}AVs
                end.
                AVs =: (' '&,@:,&LF)each AVs
                TEXT =: TEXT,(;ANs,.AVs),LF
                ANs =: 
'METHOD:';'HTTP-PROTOCOL-VERSION:';'PROTOCOL:';'HOST:';'PORT:';'RESOURCE:';'QUERY:'
                AVs =: 'GET';'HTTP/0.9';'http';LHN;'80';'';''
                HCNT =: >:HCNT
        end.
    end.
    
    i =. (2{|:t)i:146
    i =. i{0{|:t
    i =. i+2
    
    i return.
)

NB. ================== read =====================

main =: monad define
    TEXT =: ''

    fn =. IFNAME
    fs =. 1!:4<fn
    fp =. 0
    fss =. 1e7
    buf =. ''
    '' 1!:2 <OFNAME
    while. 1 do.
        if. fp<fs do.
            NB. read chunk
            n =. fss<.fs-fp
            t =. (buf, 1!:11 fn;fp,n)-.CR
            fp =. fp+n
            i =. process t
            buf =. i}.t
        else.
            if. #buf do. process buf end.
            break.
        end.
    end.

    TEXT 1!:3<OFNAME
    
    ''return.
)

main''

echo HCNT

exit''
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to