diff options
Diffstat (limited to 'base64')
| -rw-r--r-- | base64/Makefile | 45 | ||||
| -rw-r--r-- | base64/base64.hs | 80 | ||||
| -rw-r--r-- | base64/base64_1.hs | 59 | ||||
| -rw-r--r-- | base64/base64_2.hs | 47 |
4 files changed, 192 insertions, 39 deletions
diff --git a/base64/Makefile b/base64/Makefile new file mode 100644 index 0000000..611abcf --- /dev/null +++ b/base64/Makefile @@ -0,0 +1,45 @@ +# +# Some GHC flags explained +# +# -v verbose mode +# -O2 level 2 optimizations +# -rtsopts allow +RTS flags +# -prof enable basic time and allocation profiling +# -auto-all cost centers on all top level functions +# (you can also add them via the SCC pragma) +# -caf-all generate data for CAFs (constant applicative forms) +# t +# -fforce-recomp force recompilation +# +# Notes: you will obtain the profiling versions of dependancies via: +# stack install --profile [libraryname] +# +# -fprof-auto replaced -auto-all +# -fprof-cafs replaced -caf-all +# + +build-prof: + stack ghc --profile -- -rtsopts -prof -fprof-auto -fprof-cafs -O2 base64.hs + +# +# Some +RTS flags +# +# -p profiling +# -K set stack limit +# -hc extract heap profile +# -hy allocation by type +# -hd allocation by constructor +# -iN sampling frequency in seconds. e.g. -i0.01 +# -ddump-simpl generate core version +# +# Note: render the heap profile as graph with: hp2ps -e8in -c file.hp +# + +run-prof: + cat random.bin | ./base64 +RTS -p -K100M > /dev/null + + +test-mini-hask: + stack ghc -- -O mini.hs +test-mini-c: + gcc -O3 mini.c -o mini.out diff --git a/base64/base64.hs b/base64/base64.hs index 13f12bb..2443d07 100644 --- a/base64/base64.hs +++ b/base64/base64.hs @@ -1,45 +1,47 @@ --- --- Miguel's Naive --- Base64 Encoder -- Coded on a winter afterfnoon on 19th Feb 2018 A.D. --- to fully understand base64 encoding and play with --- haskell, which is always an indisputable pleasure. --- --- The following lines were written in full awareness --- that 'libraries' for this purpose, which perform way --- better, are in existence. --- --- Coded in big anger due to nick's stories about saving his binary --- format, encrypted passwords in an ascii config file, featuring --- strange letters and characters. --- --- Example Usage: echo "just testing" | stack runghc base64.hs | stack runghc base64 -- -d --- (You can cross check with base64 / base64 -d) - -import System.Environment -import qualified Data.List.Split as T -import qualified Data.List as L -import qualified Data.Map.Strict as M +import Data.Maybe (fromJust,isJust) +import Data.List.Split (chunksOf) +import Data.Tuple (swap) +import Data.Tuple.Extra (first,second,dupe) +import System.Environment (getArgs) import qualified Data.ByteString.Lazy as B -import Text.Printf -import Data.Maybe -import Data.Char -import Control.Monad +import qualified Data.ByteString.Lazy.Char8 as C +import qualified Data.Map as M -main = do args<-getArgs - if length args == 0 then go encode64 - else when (args!!0 == "-d") $ go decode64 - where go f = getContents >>= putStr.(++"\n").f +-- Example Usage: echo "hello world" | ./base64 | ./base64 -d -fromBase64 x = (['A'..'Z']++['a'..'z']++['0'..'9']++['+','/']) !! x -mapBase64 = M.fromList $ map (\x-> (fromBase64 x,x)) [0..63] -binToDec = sum . map (2^) . L.findIndices (=='1') . reverse +-- TODO +-- cleanup/simplify +-- unit testing (cross check with cli base64, different lengths) +-- flag for line widht / check flags / filename on command-line +-- (see man base64) +-- compare performance . named map? array? -encode64 x = pad64 (length x) . map (fromBase64 . binToDec) . T.chunksOf 6 . - concat . map (printf "%08b" ) $ x ++ cycle "\000" +main = do arg<-getArgs + dat<-B.getContents + B.putStr.B.pack.encode.B.unpack $ dat +{- + if length arg == 0 + then putStr . (++"\n") . encode64 . map fromIntegral . B.unpack $ dat + else B.putStr. B.pack . map fromIntegral . decode64 . C.unpack $ dat +-} -decode64 x = map (chr . binToDec) . T.chunksOf 8 . - concat . map ( printf "%06b" . fromJust) . filter isJust . - map (flip M.lookup mapBase64) $ x +encode = map ((+65).(`mod` 24)) -pad64 l = (++(take m ((cycle "=")))) . take ((l+m)*3 `div` 2 -3-m) - where m = mod (3 - mod l 3) 3 +table64 = zip [0..] (['A'..'Z']++['a'..'z']++['0'..'9']++['+','/']) + +enc64 k = M.lookup k mp where mp = M.fromList table64 +dec64 k = M.lookup k mp where mp = M.fromList $ map swap table64 + +encode64 :: [Int] -> [Char] +encode64 = map (fromJust.enc64.flip mod 64) -- concat . map (pad . first enc . second length . dupe) . chunksOf 3 + where enc = map (fromJust . enc64) . sumC + pad (v,l) =take 4 $ take (1+l) v ++ "===" + sumC = map fst . reverse . take 4 . drop 1 .iterate to64 . (,) 0 . sum . map (uncurry (*)) . zip mult + mult = map (256^) [2,1,0] + to64 (r,v) = let r' = v `mod` 64 in (r',(v-r')`div`64) + +decode64 :: [Char]->[Int] +decode64 = map fst . concat . map (rem . first (reverse . take 3 . drop 1 . iterate to256 . (,) 0 . dec. map (fromJust) . filter (isJust) . map dec64).second (length.filter(=='=')). dupe) . chunksOf 4 . filter (/='\n') + where dec = sum . map (uncurry (*)) . zip (map (64^) [3,2..]) + to256 (r,v) = let r' = v `mod` 256 in (r',(v-r')`div`256) + rem (v,l) = take (3-l) v diff --git a/base64/base64_1.hs b/base64/base64_1.hs new file mode 100644 index 0000000..28655c1 --- /dev/null +++ b/base64/base64_1.hs @@ -0,0 +1,59 @@ +-- +-- Miguel's Naive Base64 Encoder +-- +-- Coded on a winter afterfnoon on 19th Feb 2018 A.D. +-- to fully understand base64 encoding and play with +-- haskell, which is always an indisputable pleasure. +-- +-- The following lines were written in full awareness +-- that 'libraries' for this purpose, which perform way +-- better, are in existence. +-- +-- Coded in big anger due to nick's stories about saving his binary +-- format, encrypted passwords in an ascii config file, featuring +-- strange letters and characters. +-- +-- Example Usage: echo "just testing" | stack runghc base64.hs | stack runghc base64 -- -d +-- (You can cross check with base64 / base64 -d) + +import System.Environment +import qualified Data.List.Split as T +import qualified Data.List as L +import qualified Data.Map.Strict as M +import qualified Data.ByteString.Lazy as B +--import Data.ByteString.Char8 as C +import Text.Printf +import Data.Maybe +import Data.Char +import Control.Monad + +main = do args<-getArgs + -- if Prelude.length args == 0 then go encode64 +-- else when (args!!0 == "-d") $ go decode64 + go encode64 + where go f = B.getContents >>= B.putStr.B.pack.f.B.unpack + +fromBase64 x = (['A'..'Z']++['a'..'z']++['0'..'9']++['+','/']) !! x +--mapBase64 = M.fromList $ C.map (\x-> (fromBase64 x,x)) [0..63] +--binToDec = sum . C.map (2^) . L.findIndices (=='1') . C.reverse + +encode64 x = L.map (printf "%08b") xi + where xi=map fromIntegral x :: [Int] + +--x++repeat (fromIntegral $ ord '=') + +{- +encode64 x = pad64 (C.length x) . C.map (fromBase64 . binToDec) . T.chunksOf 6 . + C.concat . C.map (printf "%08b" ) $ x ++ cycle 0 +-} + +{- +decode64 x = C.map (chr . binToDec) . T.chunksOf 8 . + C.concat . C.map ( printf "%06b" . fromJust) . C.filter isJust . + C.map (flip M.lookup mapBase64) $ x +-} + +{- +pad64 l = (++(C.take m ((cycle "=")))) . C.take ((l+m)*3 `div` 2 -3-m) + where m = mod (3 - mod l 3) 3 +-} diff --git a/base64/base64_2.hs b/base64/base64_2.hs new file mode 100644 index 0000000..2443d07 --- /dev/null +++ b/base64/base64_2.hs @@ -0,0 +1,47 @@ +import Data.Maybe (fromJust,isJust) +import Data.List.Split (chunksOf) +import Data.Tuple (swap) +import Data.Tuple.Extra (first,second,dupe) +import System.Environment (getArgs) +import qualified Data.ByteString.Lazy as B +import qualified Data.ByteString.Lazy.Char8 as C +import qualified Data.Map as M + +-- Example Usage: echo "hello world" | ./base64 | ./base64 -d + +-- TODO +-- cleanup/simplify +-- unit testing (cross check with cli base64, different lengths) +-- flag for line widht / check flags / filename on command-line +-- (see man base64) +-- compare performance . named map? array? + +main = do arg<-getArgs + dat<-B.getContents + B.putStr.B.pack.encode.B.unpack $ dat +{- + if length arg == 0 + then putStr . (++"\n") . encode64 . map fromIntegral . B.unpack $ dat + else B.putStr. B.pack . map fromIntegral . decode64 . C.unpack $ dat +-} + +encode = map ((+65).(`mod` 24)) + +table64 = zip [0..] (['A'..'Z']++['a'..'z']++['0'..'9']++['+','/']) + +enc64 k = M.lookup k mp where mp = M.fromList table64 +dec64 k = M.lookup k mp where mp = M.fromList $ map swap table64 + +encode64 :: [Int] -> [Char] +encode64 = map (fromJust.enc64.flip mod 64) -- concat . map (pad . first enc . second length . dupe) . chunksOf 3 + where enc = map (fromJust . enc64) . sumC + pad (v,l) =take 4 $ take (1+l) v ++ "===" + sumC = map fst . reverse . take 4 . drop 1 .iterate to64 . (,) 0 . sum . map (uncurry (*)) . zip mult + mult = map (256^) [2,1,0] + to64 (r,v) = let r' = v `mod` 64 in (r',(v-r')`div`64) + +decode64 :: [Char]->[Int] +decode64 = map fst . concat . map (rem . first (reverse . take 3 . drop 1 . iterate to256 . (,) 0 . dec. map (fromJust) . filter (isJust) . map dec64).second (length.filter(=='=')). dupe) . chunksOf 4 . filter (/='\n') + where dec = sum . map (uncurry (*)) . zip (map (64^) [3,2..]) + to256 (r,v) = let r' = v `mod` 256 in (r',(v-r')`div`256) + rem (v,l) = take (3-l) v |
