Removed inefficient builder-to-lbs calls

This commit is contained in:
Michael Snoyman 2010-08-09 17:48:59 +03:00
parent 02fd6bfffd
commit 2f3a0effff
3 changed files with 29 additions and 37 deletions

View File

@ -266,8 +266,8 @@ $maybe creds c
|] |]
json creds = json creds =
jsonMap jsonMap
[ ("ident", jsonScalar $ maybe (string "") (string . credsIdent) creds) [ ("ident", jsonScalar $ maybe "" credsIdent creds)
, ("displayName", jsonScalar $ string $ fromMaybe "" , ("displayName", jsonScalar $ fromMaybe ""
$ creds >>= credsDisplayName) $ creds >>= credsDisplayName)
] ]

View File

@ -1,4 +1,4 @@
-- | Efficient generation of JSON documents, with HTML-entity encoding handled via types. -- | Efficient generation of JSON documents.
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP #-} {-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@ -19,13 +19,12 @@ module Yesod.Json
where where
import qualified Data.ByteString.Char8 as S import qualified Data.ByteString.Char8 as S
import qualified Data.ByteString.Lazy.Char8 as L
import Data.Char (isControl) import Data.Char (isControl)
import Yesod.Handler import Yesod.Handler
import Numeric (showHex) import Numeric (showHex)
import Data.Monoid (Monoid (..)) import Data.Monoid (Monoid (..))
import Text.Blaze.Builder.Core import Text.Blaze.Builder.Core
import Text.Hamlet (Html, renderHtml, string) import Text.Blaze.Builder.Utf8 (writeChar)
#if TEST #if TEST
import Test.Framework (testGroup, Test) import Test.Framework (testGroup, Test)
@ -58,35 +57,31 @@ jsonToRepJson = fmap RepJson . jsonToContent
-- | Outputs a single scalar. This function essentially: -- | Outputs a single scalar. This function essentially:
-- --
-- * Performs HTML entity escaping as necesary.
--
-- * Performs JSON encoding. -- * Performs JSON encoding.
-- --
-- * Wraps the resulting string in quotes. -- * Wraps the resulting string in quotes.
jsonScalar :: Html -> Json jsonScalar :: String -> Json
jsonScalar s = Json $ mconcat jsonScalar s = Json $ mconcat
[ fromByteString "\"" [ fromByteString "\""
-- FIXME the following line can be optimized after blaze-html 0.2 , writeList writeJsonChar s
, fromByteString $ S.concat $ L.toChunks $ encodeJson $ renderHtml s
, fromByteString "\"" , fromByteString "\""
] ]
where where
encodeJson = L.concatMap (L.pack . encodeJsonChar) writeJsonChar '\b' = writeByteString "\\b"
writeJsonChar '\f' = writeByteString "\\f"
encodeJsonChar '\b' = "\\b" writeJsonChar '\n' = writeByteString "\\n"
encodeJsonChar '\f' = "\\f" writeJsonChar '\r' = writeByteString "\\r"
encodeJsonChar '\n' = "\\n" writeJsonChar '\t' = writeByteString "\\t"
encodeJsonChar '\r' = "\\r" writeJsonChar '"' = writeByteString "\\\""
encodeJsonChar '\t' = "\\t" writeJsonChar '\\' = writeByteString "\\\\"
encodeJsonChar '"' = "\\\"" writeJsonChar c
encodeJsonChar '\\' = "\\\\" | not $ isControl c = writeChar c
encodeJsonChar c | c < '\x10' = writeString $ '\\' : 'u' : '0' : '0' : '0' : hexxs
| not $ isControl c = [c] | c < '\x100' = writeString $ '\\' : 'u' : '0' : '0' : hexxs
| c < '\x10' = '\\' : 'u' : '0' : '0' : '0' : hexxs | c < '\x1000' = writeString $ '\\' : 'u' : '0' : hexxs
| c < '\x100' = '\\' : 'u' : '0' : '0' : hexxs
| c < '\x1000' = '\\' : 'u' : '0' : hexxs
where hexxs = showHex (fromEnum c) "" where hexxs = showHex (fromEnum c) ""
encodeJsonChar c = [c] writeJsonChar c = writeChar c
writeString = writeByteString . S.pack
-- | Outputs a JSON list, eg [\"foo\",\"bar\",\"baz\"]. -- | Outputs a JSON list, eg [\"foo\",\"bar\",\"baz\"].
jsonList :: [Json] -> Json jsonList :: [Json] -> Json
@ -112,7 +107,7 @@ jsonMap (x:xs) = mconcat
where where
go' y = mappend (Json $ fromByteString ",") $ go y go' y = mappend (Json $ fromByteString ",") $ go y
go (k, v) = mconcat go (k, v) = mconcat
[ jsonScalar $ string k [ jsonScalar k
, Json $ fromByteString ":" , Json $ fromByteString ":"
, v , v
] ]

View File

@ -35,7 +35,8 @@ import Data.List (nub)
import Data.Monoid import Data.Monoid
import Control.Monad.Trans.Writer import Control.Monad.Trans.Writer
import Control.Monad.Trans.State import Control.Monad.Trans.State
import Yesod.Hamlet (Hamlet, hamlet, PageContent (..), Html) import Yesod.Hamlet (PageContent (..))
import Text.Hamlet
import Text.Camlet import Text.Camlet
import Text.Jamlet import Text.Jamlet
import Yesod.Handler (Route, GHandler, getUrlRenderParams) import Yesod.Handler (Route, GHandler, getUrlRenderParams)
@ -45,9 +46,6 @@ import Control.Applicative (Applicative)
import Control.Monad.IO.Class (MonadIO) import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Class (lift)
import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO) import "MonadCatchIO-transformers" Control.Monad.CatchIO (MonadCatchIO)
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as S
import Text.Hamlet (unsafeByteString)
data Location url = Local url | Remote String data Location url = Local url | Remote String
deriving (Show, Eq) deriving (Show, Eq)
@ -178,13 +176,12 @@ widgetToPageContent (GWidget w) = do
let scripts = map (locationToHamlet . unScript) $ runUniqueList scripts' let scripts = map (locationToHamlet . unScript) $ runUniqueList scripts'
let stylesheets = map (locationToHamlet . unStylesheet) let stylesheets = map (locationToHamlet . unStylesheet)
$ runUniqueList stylesheets' $ runUniqueList stylesheets'
-- FIXME the next functions can be optimized once blaze-html switches to let cssToHtml (Css b) = Html b
-- blaze-builder celper :: Camlet url -> Hamlet url
let lbsToHtml = unsafeByteString . S.concat . L.toChunks celper = fmap cssToHtml
let celper :: Camlet url -> Hamlet url jsToHtml (Javascript b) = Html b
celper c render = lbsToHtml $ renderCamlet render c jelper :: Jamlet url -> Hamlet url
let jelper :: Jamlet url -> Hamlet url jelper = fmap jsToHtml
jelper j render = lbsToHtml $ renderJamlet render j
render <- getUrlRenderParams render <- getUrlRenderParams
let renderLoc x = let renderLoc x =