OTWO-1213 Works around lost encoding in Ruby/C binding layer
[ohcount] / test / expected_dir / haskell1.hs
1 haskell comment {-|
2 haskell comment   This module contains some functions that are useful in several places in the
3 haskell comment   program and don't belong to one specific other module.
4 haskell comment -}
5 haskell code    module Gnutella.Misc where
6 haskell blank   
7 haskell code    import Data.ByteString(ByteString)
8 haskell code    import qualified Data.ByteString as BS
9 haskell code    import Data.Bits
10 haskell code    import Data.Word
11 haskell code    import Text.Read
12 haskell code    import Data.Char(isNumber)
13 haskell code    import Data.List(intersperse)
14 haskell code    import Network
15 haskell code    import Network.BSD(getHostByName, HostEntry(..))
16 haskell code    import Network.Socket(HostAddress(..))
17 haskell code    import Debug.Trace
18 haskell blank   
19 haskell comment {-|
20 haskell comment   Maakt van vier bytes een Word32. Gaat ervan uit dat die vier bytes little-endian achter elkaar
21 haskell comment   staan. Als de gegeven string korter is dan 4 bytes, termineert de functie. Als de string langer
22 haskell comment   is, worden alle bytes voorbij de vierde genegeerd.
23 haskell comment -}
24 haskell code    composeWord32 :: ByteString -> Word32
25 haskell code    composeWord32 s = shiftL byte4 24 + shiftL byte3 16 + shiftL byte2 8 + byte1
26 haskell code      where byte1, byte2, byte3, byte4 :: Word32
27 haskell code            [byte1, byte2, byte3, byte4] = map fromIntegral $ BS.unpack (BS.take 4 s)
28 haskell blank   
29 haskell comment {-| 
30 haskell comment   Turns a Word32 into a tuple of Word8s. The tuple is little-endian: the least
31 haskell comment   significant octet comes first.
32 haskell comment -}
33 haskell code    word32ToWord8s :: Word32 -> (Word8, Word8, Word8, Word8)
34 haskell code    word32ToWord8s w = (fromIntegral (w .&. 0x000000ff)
35 haskell code                       ,fromIntegral (shiftR w 8 .&. 0x000000ff)
36 haskell code                       ,fromIntegral (shiftR w 16 .&. 0x000000ff)
37 haskell code                       ,fromIntegral (shiftR w 24 .&. 0x000000ff)
38 haskell code                       )
39 haskell blank   
40 haskell comment {-|
41 haskell comment   Parses a host specification in the "name:12345"-style notation into a hostname
42 haskell comment   and a port number.
43 haskell blank   
44 haskell comment   As a rather special feature, it returns 6346 as the port number when there is
45 haskell comment   no port specified. When there is a port specified, but it is unparseable, it
46 haskell comment   returns Nothing.
47 haskell comment -}
48 haskell code    parseHostnameWithPort :: String -> IO (Maybe ((Word8, Word8, Word8, Word8)
49 haskell code                                                 ,PortNumber))
50 haskell code    parseHostnameWithPort str = do maybeHostName <- stringToIP hostNameStr
51 haskell code                                   return $ (do portNum <- maybePortNum
52 haskell code                                                hostName <- maybeHostName
53 haskell code                                                return (hostName, portNum)
54 haskell code                                            )
55 haskell code      where hostNameStr = takeWhile (/=':') str
56 haskell code            maybePortNum  = case tail (dropWhile (/=':') str) of
57 haskell code                              [] -> Just $ 6346
58 haskell code                              s  -> case reads s of
59 haskell code                                      []     -> Nothing
60 haskell code                                      (x:xs) -> Just $ fromIntegral $ fst x
61 haskell blank   
62 haskell comment {-|
63 haskell comment   Translates a string, representing an IP address, to a list of bytes.
64 haskell comment   Returns Nothing when the string does not represent an IP address in xxx.xxx.xxx.xxx format
65 haskell comment -}
66 haskell code    ipStringToBytes :: String -> Maybe (Word8, Word8, Word8, Word8)
67 haskell comment -- Again, hugs won't let us use regexes where they would be damn convenient
68 haskell code    ipStringToBytes s =
69 haskell code        let ipBytesStrings = splitAtDots s
70 haskell code        in if all (all isNumber) ipBytesStrings
71 haskell code             then let bytesList = map (fst . head . reads) ipBytesStrings
72 haskell code                  in Just (bytesList!!0
73 haskell code                          ,bytesList!!1
74 haskell code                          ,bytesList!!2
75 haskell code                          ,bytesList!!3
76 haskell code                          )
77 haskell code             else Nothing
78 haskell code      where splitAtDots s = foldr (\c (n:nums) -> if c == '.'
79 haskell code                                                  then [] : n : nums
80 haskell code                                                  else (c:n) : nums
81 haskell code                                  ) [[]] s
82 haskell blank   
83 haskell comment {-|
84 haskell comment   Translates a list of bytes representing an IP address (big endian) to a string
85 haskell comment   in the xxx.xxx.xxx.xxx format.
86 haskell comment -}
87 haskell code    ipBytesToString :: (Word8, Word8, Word8, Word8) -> String
88 haskell code    ipBytesToString (b1, b2, b3, b4) = 
89 haskell code        concat $ intersperse "." $ map show [b1, b2, b3, b4]
90 haskell blank   
91 haskell comment {-| 
92 haskell comment   Takes a String that's either an IP address or a hostname, and returns you the
93 haskell comment   IP address as a list of 4 bytes (in big-endian byte order). It returns Nothing
94 haskell comment   if there is no parse for the string as IP address and the hostname can't be
95 haskell comment   found.
96 haskell comment -}
97 haskell code    stringToIP :: String -> IO (Maybe (Word8, Word8, Word8, Word8))
98 haskell code    stringToIP hostName = case ipStringToBytes hostName of
99 haskell code                            Just a  -> return (Just a)
100 haskell code                            Nothing -> do hostent <- getHostByName hostName
101 haskell code                                          let ipWord32 = head (hostAddresses hostent)
102 haskell code                                              ipWord8s = word32ToWord8s ipWord32
103 haskell code                                          return (Just ipWord8s)
104 haskell blank   
105 haskell comment -- used in reading the hostcache
106 haskell code    instance Read PortNumber where
107 haskell code        readsPrec i = map (\(a, b) -> (fromIntegral a, b)) . (readsPrec i :: ReadS Word16)
108 haskell blank