+type Headers = Map NCBS Strict.ByteString
+newtype NCBS = NCBS Strict.ByteString
+
+toNCBS :: Strict.ByteString -> NCBS
+toNCBS = NCBS
+{-# INLINE toNCBS #-}
+
+fromNCBS :: NCBS -> Strict.ByteString
+fromNCBS (NCBS x) = x
+{-# INLINE fromNCBS #-}
+
+instance Eq NCBS where
+ (NCBS a) == (NCBS b) = a == b
+
+instance Ord NCBS where
+ (NCBS a) `compare` (NCBS b) = a `noCaseCmp` b
+
+instance Show NCBS where
+ show (NCBS x) = show x
+
+noCaseCmp :: Strict.ByteString -> Strict.ByteString -> Ordering
+noCaseCmp a b = a `seq` b `seq`
+ toForeignPtr a `cmp` toForeignPtr b
+ where
+ cmp :: (ForeignPtr Word8, Int, Int) -> (ForeignPtr Word8, Int, Int) -> Ordering
+ cmp (x1, s1, l1) (x2, s2, l2)
+ | x1 `seq` s1 `seq` l1 `seq` x2 `seq` s2 `seq` l2 `seq` False = undefined
+ | l1 == 0 && l2 == 0 = EQ
+ | x1 == x2 && s1 == s2 && l1 == l2 = EQ
+ | otherwise
+ = inlinePerformIO $
+ withForeignPtr x1 $ \ p1 ->
+ withForeignPtr x2 $ \ p2 ->
+ noCaseCmp' (p1 `plusPtr` s1) l1 (p2 `plusPtr` s2) l2
+
+
+-- もし先頭の文字列が等しければ、短い方が小さい。
+noCaseCmp' :: Ptr Word8 -> Int -> Ptr Word8 -> Int -> IO Ordering
+noCaseCmp' p1 l1 p2 l2
+ | p1 `seq` l1 `seq` p2 `seq` l2 `seq` False = undefined
+ | l1 == 0 && l2 == 0 = return EQ
+ | l1 == 0 = return LT
+ | l2 == 0 = return GT
+ | otherwise
+ = do c1 <- peek p1
+ c2 <- peek p2
+ case comparing (toLower . w2c) c1 c2 of
+ EQ -> noCaseCmp' (p1 `plusPtr` 1) (l1 - 1) (p2 `plusPtr` 1) (l2 - 1)
+ x -> return x
+
+
+noCaseEq :: Strict.ByteString -> Strict.ByteString -> Bool
+noCaseEq a b = a `seq` b `seq`
+ toForeignPtr a `cmp` toForeignPtr b
+ where
+ cmp :: (ForeignPtr Word8, Int, Int) -> (ForeignPtr Word8, Int, Int) -> Bool
+ cmp (x1, s1, l1) (x2, s2, l2)
+ | x1 `seq` s1 `seq` l1 `seq` x2 `seq` s2 `seq` l2 `seq` False = undefined
+ | l1 /= l2 = False
+ | l1 == 0 && l2 == 0 = True
+ | x1 == x2 && s1 == s2 && l1 == l2 = True
+ | otherwise
+ = inlinePerformIO $
+ withForeignPtr x1 $ \ p1 ->
+ withForeignPtr x2 $ \ p2 ->
+ noCaseEq' (p1 `plusPtr` s1) (p2 `plusPtr` s2) l1
+
+
+noCaseEq' :: Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
+noCaseEq' p1 p2 l
+ | p1 `seq` p2 `seq` l `seq` False = undefined
+ | l == 0 = return True
+ | otherwise
+ = do c1 <- peek p1
+ c2 <- peek p2
+ if toLower (w2c c1) == toLower (w2c c2) then
+ noCaseEq' (p1 `plusPtr` 1) (p2 `plusPtr` 1) (l - 1)
+ else
+ return False
+