hw-json-simple-cursor (empty) → 0.1.0.0
raw patch · 25 files changed
+764/−0 lines, 25 filesdep +attoparsecdep +basedep +bytestringsetup-changed
Dependencies added: attoparsec, base, bytestring, criterion, directory, dlist, generic-lens, hedgehog, hspec, hw-balancedparens, hw-bits, hw-hspec-hedgehog, hw-json-simd, hw-json-simple-cursor, hw-mquery, hw-prim, hw-rankselect, hw-rankselect-base, lens, mmap, optparse-applicative, semigroups, text, transformers, vector, word8
Files
- LICENSE +30/−0
- README.md +18/−0
- Setup.hs +2/−0
- app/App/Commands.hs +13/−0
- app/App/Commands/CreateIndex.hs +70/−0
- app/App/Commands/Types.hs +15/−0
- app/Main.hs +11/−0
- bench/Main.hs +10/−0
- corpus/5000B.json +1/−0
- corpus/5000B.json.bp.idx +1/−0
- corpus/5000B.json.ib.idx +1/−0
- corpus/issue-0001.json +1/−0
- corpus/issue-0001.json.bp.idx +1/−0
- corpus/issue-0001.json.ib.idx +1/−0
- corpus/issue-0001.md +9/−0
- hw-json-simple-cursor.cabal +164/−0
- src/HaskellWorks/Data/Json/Simple/Cursor.hs +90/−0
- src/HaskellWorks/Data/Json/Simple/Cursor/Fast.hs +35/−0
- src/HaskellWorks/Data/Json/Simple/Cursor/Internal/IbBp.hs +10/−0
- src/HaskellWorks/Data/Json/Simple/Cursor/Internal/ToIbBp.hs +12/−0
- src/HaskellWorks/Data/Json/Simple/Cursor/Internal/Word8.hs +72/−0
- src/HaskellWorks/Data/Json/Simple/Cursor/SemiIndex.hs +80/−0
- src/HaskellWorks/Data/Json/Simple/Cursor/Snippet.hs +32/−0
- test/HaskellWorks/Data/Json/Simple/CursorSpec.hs +84/−0
- test/Spec.hs +1/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright John Ky (c) 2016++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Author name here nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,18 @@+# hw-json-simple-cursor+[](https://circleci.com/gh/haskell-works/hw-json-simple-cursor/tree/master)++`hw-json-simple-cursor` is support library for `hw-json`, a succinct JSON parsing library.++It uses succinct data-structures to allow traversal of large JSON strings with minimal memory overhead.++For more information see [`hw-json`](https://github.com/haskell-works/hw-json).++## References++* [Semi-Indexing Semi-Structured Data in Tiny Space](http://www.di.unipi.it/~ottavian/files/semi_index_cikm.pdf)+* [Succinct Data Structures talk by Edward Kmett](https://www.youtube.com/watch?v=uA0Z7_4J7u8)+* [Typed Tagless Final Interpreters](http://okmij.org/ftp/tagless-final/course/lecture.pdf)++## Special mentions++* [Sydney Paper Club](http://www.meetup.com/Sydney-Paper-Club/)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/App/Commands.hs view
@@ -0,0 +1,13 @@+module App.Commands where++import App.Commands.CreateIndex+import Data.Semigroup ((<>))+import Options.Applicative++commands :: Parser (IO ())+commands = commandsGeneral++commandsGeneral :: Parser (IO ())+commandsGeneral = subparser $ mempty+ <> commandGroup "Commands:"+ <> cmdCreateIndex
+ app/App/Commands/CreateIndex.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++module App.Commands.CreateIndex+ ( cmdCreateIndex+ ) where++import Control.Lens+import Data.Generics.Product.Any+import Data.Maybe+import Data.Semigroup ((<>))+import Data.Word+import Foreign+import Options.Applicative hiding (columns)++import qualified App.Commands.Types as Z+import qualified Data.ByteString.Internal as BSI+import qualified Data.ByteString.Lazy as LBS+import qualified HaskellWorks.Data.ByteString.Lazy as LBS+import qualified HaskellWorks.Data.Json.Simple.Cursor.SemiIndex as SISI+import qualified System.IO.MMap as IO++{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}+{-# ANN module ("HLint: ignore Redundant do" :: String) #-}++runCreateIndex :: Z.CreateIndexOptions -> IO ()+runCreateIndex opts = do+ let filePath = opts ^. the @"filePath"+ let outputIbFile = opts ^. the @"outputIbFile" & fromMaybe (filePath <> ".ib.idx")+ let outputBpFile = opts ^. the @"outputBpFile" & fromMaybe (filePath <> ".bp.idx")+ (fptr :: ForeignPtr Word8, offset, size) <- IO.mmapFileForeignPtr filePath IO.ReadOnly Nothing+ let !bs = BSI.fromForeignPtr (castForeignPtr fptr) offset size+ let SISI.SemiIndex _ ibs bps = SISI.buildSemiIndex bs+ LBS.writeFile outputIbFile (LBS.toLazyByteString ibs)+ LBS.writeFile outputBpFile (LBS.toLazyByteString bps)++optsCreateIndex :: Parser Z.CreateIndexOptions+optsCreateIndex = Z.CreateIndexOptions+ <$> strOption+ ( long "input"+ <> short 'i'+ <> help "Input JSON file"+ <> metavar "STRING"+ )+ <*> strOption+ ( long "backend"+ <> short 'b'+ <> value "standard"+ <> help "Backend for creating index"+ <> metavar "STRING"+ )+ <*> optional+ ( strOption+ ( long "output-ib-file"+ <> help "Filename for output ib index"+ <> metavar "STRING"+ )+ )+ <*> optional+ ( strOption+ ( long "output-bp-file"+ <> help "Filename for output bp index"+ <> metavar "STRING"+ )+ )++cmdCreateIndex :: Mod CommandFields (IO ())+cmdCreateIndex = command "create-index" $ flip info idm $ runCreateIndex <$> optsCreateIndex
+ app/App/Commands/Types.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DuplicateRecordFields #-}++module App.Commands.Types+ ( CreateIndexOptions(..)+ ) where++import GHC.Generics++data CreateIndexOptions = CreateIndexOptions+ { filePath :: FilePath+ , backend :: String+ , outputIbFile :: Maybe FilePath+ , outputBpFile :: Maybe FilePath+ } deriving (Eq, Show, Generic)
+ app/Main.hs view
@@ -0,0 +1,11 @@+module Main where++import App.Commands+import Control.Monad+import Data.Semigroup ((<>))+import Options.Applicative++main :: IO ()+main = join $ customExecParser+ (prefs $ showHelpOnEmpty <> showHelpOnError)+ (info (commands <**> helper) idm)
+ bench/Main.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE ScopedTypeVariables #-}++module Main where++import Criterion.Main++main :: IO ()+main = do+ benchmarks <- fmap mconcat $ sequence $ mempty+ defaultMain benchmarks
+ corpus/5000B.json view
@@ -0,0 +1,1 @@+[ { "_id" : { "$oid" : "52cdef7c4bab8bd675297d8a" }, "name" : "Wetpaint", "permalink" : "abc2", "crunchbase_url" : "http://www.crunchbase.com/company/wetpaint", "homepage_url" : "http://wetpaint-inc.com", "blog_url" : "http://digitalquarters.net/", "blog_feed_url" : "http://digitalquarters.net/feed/", "twitter_username" : "BachelrWetpaint", "category_code" : "web", "number_of_employees" : 47, "founded_year" : 2005, "founded_month" : 10, "founded_day" : 17, "deadpooled_year" : 1, "tag_list" : "wiki, seattle, elowitz, media-industry, media-platform, social-distribution-system", "alias_list" : "", "email_address" : "info@wetpaint.com", "phone_number" : "206.859.6300", "description" : "Technology Platform Company", "created_at" : { "$date" : 1180075887000 }, "updated_at" : "Sun Dec 08 07:15:44 UTC 2013", "overview" : "<p>Wetpaint is a technology platform company that uses its proprietary state-of-the-art technology and expertise in social media to build and monetize audiences for digital publishers. Wetpaint's own online property, Wetpaint Entertainment, an entertainment news site that attracts more than 12 million unique visitors monthly and has over 2 million Facebook fans, is a proof point to the company's success in building and engaging audiences. Media companies can license Wetpaint's platform which includes a dynamic playbook tailored to their individual needs and comprehensive training. Founded by Internet pioneer Ben Elowitz, and with offices in New York and Seattle, Wetpaint is backed by Accel Partners, the investors behind Facebook.</p>", "image" : { "available_sizes" : [ [ [ 150, 75 ], "assets/images/resized/0000/3604/3604v14-max-150x150.jpg" ], [ [ 250, 125 ], "assets/images/resized/0000/3604/3604v14-max-250x250.jpg" ], [ [ 450, 225 ], "assets/images/resized/0000/3604/3604v14-max-450x450.jpg" ] ] }, "products" : [ { "name" : "Wikison Wetpaint", "permalink" : "wetpaint-wiki" }, { "name" : "Wetpaint Social Distribution System", "permalink" : "wetpaint-social-distribution-system" } ], "relationships" : [ { "is_past" : false, "title" : "Co-Founder and VP, Social and Audience Development", "person" : { "first_name" : "Michael", "last_name" : "Howell", "permalink" : "michael-howell" } }, { "is_past" : false, "title" : "Co-Founder/CEO/Board of Directors", "person" : { "first_name" : "Ben", "last_name" : "Elowitz", "permalink" : "ben-elowitz" } }, { "is_past" : false, "title" : "COO/Board of Directors", "person" : { "first_name" : "Rob", "last_name" : "Grady", "permalink" : "rob-grady" } }, { "is_past" : false, "title" : "SVP, Strategy and Business Development", "person" : { "first_name" : "Chris", "last_name" : "Kollas", "permalink" : "chris-kollas" } }, { "is_past" : false, "title" : "Board", "person" : { "first_name" : "Theresia", "last_name" : "Ranzetta", "permalink" : "theresia-ranzetta" } }, { "is_past" : false, "title" : "Board Member", "person" : { "first_name" : "Gus", "last_name" : "Tai", "permalink" : "gus-tai" } }, { "is_past" : false, "title" : "Board", "person" : { "first_name" : "Len", "last_name" : "Jordan", "permalink" : "len-jordan" } }, { "is_past" : false, "title" : "Head of Technology and Product", "person" : { "first_name" : "Alex", "last_name" : "Weinstein", "permalink" : "alex-weinstein" } }, { "is_past" : true, "title" : "CFO", "person" : { "first_name" : "Bert", "last_name" : "Hogue", "permalink" : "bert-hogue" } }, { "is_past" : true, "title" : "CFO/ CRO", "person" : { "first_name" : "Brian", "last_name" : "Watkins", "permalink" : "brian-watkins" } }, { "is_past" : true, "title" : "Senior Vice President, Marketing", "person" : { "first_name" : "Rob", "last_name" : "Grady", "permalink" : "rob-grady" } }, { "is_past" : true, "title" : "VP, Technology and Product", "person" : { "first_name" : "Werner", "last_name" : "Koepf", "permalink" : "werner-koepf" } }, { "is_past" : true, "title" : "VP Marketing", "person" : { "first_name" : "Kevin", "last_name" : "Flaherty", "permalink" : "kevin-flaherty" } }, { "is_past" : true, "title" : "VP User Experience", "person" : { "first_name" : "Alex", "last_name" : "Berg", "permalink" : "alex-berg" } }, { "is_past" : true, "title" : "VP Engineering", "person" : { "first_name" : "Steve", "last_name" : "McQuade", "permalink" : "steve-mcquade" } }, { "is_past" : true, "title" : "Executive Editor", "person" : { "first_name" : "Susan", "last_name" : "Mulcahy", "permalink" : "susan-mulcahy" } }, { "is_past" : true, "title" : "VP Business Development", "person" : { "first_name" : "Chris", "last_name" : "Kollas", "permalink" : "chris-kollas" } } ], "competitions" : [ { "competitor" : { "name" : "Wikia", "permalink" : "wikia" } }, { "competitor" : { "name" : "JotSpot", "permalink" : "jotspot" } }, { "competitor" : { "name" : "Socialtext", "permalink" : "socialtext" } }, { "competitor" : { "name" : "Ning by Glam Media", "permalink" : "ning" } }, { "competitor" : { "name" : "Soceeo", "permalink" : "soceeo" } }, { "competitor" : { "n" : "Y", "" : 1234567}}]}]
+ corpus/5000B.json.bp.idx view
@@ -0,0 +1,1 @@+111011010010101010101010101010101010101010101010101010101010101010101010101010101010110100101010101011011110100100111010010011101001000010111010101001101010100010111010101010110101010101000110101010101101010101010001101010101011010101010100011010101010110101010101000110101010101101010101010001101010101011010101010100011010101010110101010101000110101010101101010101010001101010101011010101010100011010101010110101010101000110101010101101010101010001101010101011010101010100011010101010110101010101000110101010101101010101010001101010101011010101010100011010101010110101010101000110101010101101010101010000101110110101010001101101010100011011010101000110110101010001101101010100011011010101000000
+ corpus/5000B.json.ib.idx view
@@ -0,0 +1,1 @@+10101000000010100000000100000000000000000000000000000100000000100000000000100000000000001000000010000000000000000001000000000000000000000000000000000000000000000100000000000000001000000000000000000000000001000000000000100000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000010000000000000000001000000000000000001000000100000000000000000000000100010000000000000000100000100000000000000000100010000000000000001000100000000000000000001001000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000001000100000000000000000100000000000000000000100000000000000001000000000000000100000000000000010000000000000000000000000000001000000000000001010000000001000000000000000010000000000000010000000000000000000000000000000100000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001010000000000000000000101010100001000001000000000000000000000000000000000000000000000000000000000000101010000100000010000000000000000000000000000000000000000000000000000000000001010100001000000100000000000000000000000000000000000000000000000000000000000000001000000000000101010000000010000000000000000000100000000000001000000000000000000101000000001000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000001000000000000000001010100000000000100000010000000001000000000000000000000000000000000000000000000000000001000000000010100000000000000100000000001000000000000010000000001000000000000010000000000000000000001010000000000010000001000000000100000000000000000000000000000000000010000000000101000000000000001000000100000000000001000000000010000000000000100000000000000000010100000000000100000010000000001000000000000000000000000010000000000101000000000000001000000100000000000001000000001000000000000010000000000000000101000000000001000000100000000010000000000000000000000000000000000000000010000000000101000000000000001000000001000000000000010000000001000000000000010000000000000000000101000000000001000000100000000010000000010000000000101000000000000001000000000001000000000000010000000000010000000000000100000000000000000000000010100000000000100000010000000001000000000000000100000000001010000000000000010000001000000000000010000001000000000000010000000000000010100000000000100000010000000001000000001000000000010100000000000000100000010000000000000100000000010000000000000100000000000000000101000000000001000000100000000010000000000000000000000000000000001000000000010100000000000000100000001000000000000010000000000001000000000000010000000000000000000001010000000000010000010000000001000000100000000001010000000000000010000000100000000000001000000001000000000000010000000000000000010100000000000100000100000000010000000000010000000000101000000000000001000000001000000000000010000000000100000000000001000000000000000000001010000000000010000010000000001000000000000000000000000000000000001000000000010100000000000000100000010000000000000100000000100000000000001000000000000000010100000000000100000100000000010000000000000000000000000000010000000000101000000000000001000000000100000000000001000000001000000000000010000000000000000000101000000000001000001000000000100000000000000010000000000101000000000000001000000001000000000000010000000000010000000000000100000000000000000000010100000000000100000100000000010000000000000000000001000000000010100000000000000100000001000000000000010000000100000000000001000000000000000010100000000000100000100000000010000000000000000010000000000101000000000000001000000001000000000000010000000000100000000000001000000000000000000001010000000000010000010000000001000000000000000000010000000000101000000000000001000000001000000000000010000000000100000000000001000000000000000000001010000000000010000010000000001000000000000000000000000001000000000010100000000000000100000000100000000000001000000000100000000000001000000000000000000000100000000000000001010100000000000000101000000001000000001000000000000010000000000001010000000000000010100000000100000000001000000000000010000000000000010100000000000000101000000001000000000000010000000000000100000000000000000101000000000000001010000000010000000000000000000001000000000000010000000000010100000000000000101000000001000000000100000000000001000000000000010100000000000000101000001000010000100000
+ corpus/issue-0001.json view
@@ -0,0 +1,1 @@+[ { "total_money_raised" : "$39.8M", "funding_rounds" : [], "investments" : [], "acquisition" : { "price_amount" : 30000000, "price_currency_code" : "USD", "term_code" : "cash_and_stock", "source_url" : "http://allthingsd.com/20131216/viggle-tries-to-bulk-up-its-social-tv-business-by-buying-wetpaint/?mod=atdtweet", "source_description" : " Viggle Tries to Bulk Up Its Social TV Business by Buying Wetpaint", "acquired_year" : 2013, "acquired_month" : 12, "acquired_day" : 16, "acquiring_company" : { "name" : "Viggle", "permalink" : "viggle" } }, "acquisitions" : [], "offices" : [ { "description" : "", "address1" : "710 - 2nd Avenue", "address2" : "Suite 1100", "zip_code" : "98104", "city" : "Seattle", "state_code" : "WA", "country_code" : "USA", "latitude" : 47.603122, "longitude" : -122.333253 }, { "description" : "", "address1" : "270 Lafayette Street", "address2" : "Suite 505", "zip_code" : "10012", "city" : "New York", "state_code" : "NY", "country_code" : "USA", "latitude" : 40.7237306, "longitude" : -73.9964312 } ], "milestones" : [ { "id" : 5869, "description" : "Wetpaint named in Lead411's Hottest Seattle Companies list", "stoned_year" : 2010, "stoned_month" : 6, "stoned_day" : 8, "source_url" : "http://www.lead411.com/seattle-companies.html", "source_text" : null, "source_description" : "LEAD411 LAUNCHES \"HOTTEST SEATTLE COMPANIES\" AWARDS", "stoneable_type" : "Company", "stoned_value" : null, "stoned_value_type" : null, "stoned_acquirer" : null, "stoneable" : { "name" : "Wetpaint", "permalink" : "wetpaint" } }, { "id" : 8702, "description" : "Site-Builder Wetpaint Makes One For Itself, Using the Demand Media Playbook", "stoned_year" : 2010, "stoned_month" : 9, "stoned_day" : 6, "source_url" : "http://mediamemo.allthingsd.com/20100906/site-builder-wetpaint-makes-one-for-itself-using-the-demand-media-playbook/", "source_text" : null, "source_description" : "All Things D", "stoneable_type" : "Company", "stoned_value" : null, "stoned_value_type" : null, "stoned_acquirer" : null, "stoneable" : { "name" : "Wetpaint", "permalink" : "wetpaint" } } ], "video_embeds" : [], "screenshots" : [ { "available_sizes" : [ [ [ 150, 86 ], "assets/images/resized/0016/0929/160929v2-max-150x150.png" ], [ [ 250, 143 ], "assets/images/resized/0016/0929/160929v2-max-250x250.png" ], [ [ 450, 258 ], "assets/images/resized/0016/0929/160929v2-max-450x450.png" ] ], "attribution" : null } ], "external_links" : [ { "external_url" : "http://www.geekwire.com/2011/rewind-ben-elowitz-wetpaint-ceo-building-type-media-company", "title" : "GeekWire interview: Rewind - Ben Elowitz, Wetpaint CEO, on building a new type of media company" }, { "external_url" : "http://techcrunch.com/2012/06/17/search-and-social-how-two-will-soon-become-one/", "title" : "Guest post by CEO Ben Elowitz in TechCrunch" }, { "external_url" : "http://allthingsd.com/20120516/what-to-expect-when-facebook-is-expecting-five-predictions-for-facebooks-first-public-year/", "title" : "Guest post by CEO Ben Elowitz in AllThingsD" }, { "external_url" : "http://adage.com/article/digitalnext/facebook-biggest-player-advertising-s-540-billion-world/235708/", "title" : "Guest post by CEO Ben Elowitz in AdAge" }, { "external_url" : "http://www.businessinsider.com/facebook-captures-14-percent-of-our-online-attention-but-only-4-percent-of-ad-spending-online-2012-6", "title" : "Guest post by CEO Ben Elowitz in Business Insider" }, { "external_url" : "http://allfacebook.com/wetpaint-media-data_b75963", "title" : "AllFacebook coverage of Wetpaint" }, { "external_url" : "http://adage.com/article/digital/celeb-site-wetpaint-shows-media-profit-facebook/237828/", "title" : "Profile of Wetpaint in Ad Age" }, { "external_url" : "http://allthingsd.com/20121018/how-to-boost-your-facebook-traffic-tips-and-tricks-from-wetpaint/", "title" : "Interview with Wetpaint CEO Ben Elowitz in All Things D" }, { "external_url" : "http://www.xconomy.com/seattle/2012/10/19/wetpaint-starts-licensing-its-facebook-based-media-distribution-tech/", "title" : "Profile of Wetpaint in Xconomy" } ]}, {}]
+ corpus/issue-0001.json.bp.idx view
@@ -0,0 +1,1 @@+111010101010101011010101010101010101010101010101010110101010001010101110101010101010101010101010101010101001101010101010101010101010101010101010001011101010101010101010101010101010101010101010101010101101010100011010101010101010101010101010101010101010101010101011010101000010101011101111010010011101001001110100100010100010111010101001101010100110101010011010101001101010100110101010011010101001101010100110101010000100
+ corpus/issue-0001.json.ib.idx view
@@ -0,0 +1,1 @@+1010100000000000000000000001000000000100000000000000000010001000000000000000100010000000000000001010000000000000000100000000010000000000000000000000010000001000000000000010000000000000000010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000010000000000000000001000100000000000000001000100000000000000000000010100000000100000000010000000000000100000000000001000000000000000010001000000000001010100000000000000010001000000000000100000000000000000001000000000000100000000000001000000000000100000000100000000100000000001000000000000001000001000000000000000010000001000000000000100000000001000000000000010000000000000010100000000000000010001000000000000100000000000000000000000100000000000010000000000001000000000000100000000100000000100000000000100000000000000100000100000000000000001000000100000000000010000000000010000000000000100000000000000001000000000000001010100000010000010000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000001000001000000000000000010010000000000000010010000000000000010000000000000000000000000000000000000000000000001000000000000000100000100000000000000000000001000000000000000000000000000000000000000000000000000000001000000000000000000100000000001000000000000000010000010000000000000000000001000001000000000000000000010000010000000000000101000000001000000000001000000000000010000000000000001010000001000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000001000000000000000010010000000000000010010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000001000000000000000000000010000000000000001000000000000000000100000000001000000000000000010000010000000000000000000001000001000000000000000000010000010000000000000101000000001000000000001000000000000010000000000000000010000000000000000100010000000000000001010100000000000000000001010101000010000010000000000000000000000000000000000000000000000000000000000000101010000100000010000000000000000000000000000000000000000000000000000000000000101010000100000010000000000000000000000000000000000000000000000000000000000000001000000000000000100000000010000000000000000001010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000010100000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000001010000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000000001000000000000000000000000000000
+ corpus/issue-0001.md view
@@ -0,0 +1,9 @@+In this issue, there is a missing open close at the end of the JSON document.++Erroneous balance parens calculated:++ |<---------------------- last 64-bits ------------------------>|+ 011010101001101010100110101010000100+ 0110101010011010101001101010100000000000000000000000000000000000+ ^+ +---- missing bit
+ hw-json-simple-cursor.cabal view
@@ -0,0 +1,164 @@+cabal-version: 2.2++name: hw-json-simple-cursor+version: 0.1.0.0+synopsis: Memory efficient JSON parser+description: Memory efficient JSON parser. Please see README.md+category: Data+homepage: http://github.com/haskell-works/hw-json-simple-cursor#readme+bug-reports: https://github.com/haskell-works/hw-json-simple-cursor/issues+author: John Ky+maintainer: newhoggy@gmail.com+copyright: 2016 - 2019 John Ky+license: BSD-3-Clause+license-file: LICENSE+build-type: Simple+extra-source-files:+ README.md+ corpus/5000B.json+ corpus/5000B.json.bp.idx+ corpus/5000B.json.ib.idx+ corpus/issue-0001.json+ corpus/issue-0001.json.bp.idx+ corpus/issue-0001.json.ib.idx+ corpus/issue-0001.md++source-repository head+ type: git+ location: https://github.com/haskell-works/hw-json-simple-cursor++flag bmi2+ description: Enable bmi2 instruction set+ manual: False+ default: False++flag sse42+ description: Enable sse4.2 instruction set+ manual: False+ default: False++common base { build-depends: base >= 4 && < 5 }++common ansi-wl-pprint { build-depends: ansi-wl-pprint >= 0.6.8.2 && < 0.7 }+common array { build-depends: array >= 0.5 && < 0.6 }+common attoparsec { build-depends: attoparsec >= 0.13 && < 0.14 }+common bits-extra { build-depends: bits-extra >= 0.0.1.3 && < 0.1 }+common bytestring { build-depends: bytestring >= 0.10.6 && < 0.11 }+common criterion { build-depends: criterion >= 1.4 && < 1.6 }+common directory { build-depends: directory >= 1.3 && < 1.4 }+common dlist { build-depends: dlist >= 0.8 && < 0.9 }+common generic-lens { build-depends: generic-lens >= 1.1.0.0 && < 1.2 }+common hedgehog { build-depends: hedgehog >= 0.6 && < 1.1 }+common hspec { build-depends: hspec >= 2.4 && < 3 }+common hw-balancedparens { build-depends: hw-balancedparens >= 0.3.0.0 && < 0.4 }+common hw-bits { build-depends: hw-bits >= 0.7.0.5 && < 0.8 }+common hw-hspec-hedgehog { build-depends: hw-hspec-hedgehog >= 0.1.0.4 && < 0.2 }+common hw-json-simd { build-depends: hw-json-simd >= 0.1.0.2 && < 0.2 }+common hw-mquery { build-depends: hw-mquery >= 0.2.0.0 && < 0.3 }+common hw-parser { build-depends: hw-parser >= 0.1 && < 0.2 }+common hw-prim { build-depends: hw-prim >= 0.6.2.28 && < 0.7 }+common hw-rankselect { build-depends: hw-rankselect >= 0.13 && < 0.14 }+common hw-rankselect-base { build-depends: hw-rankselect-base >= 0.3.2.1 && < 0.4 }+common hw-simd { build-depends: hw-simd >= 0.1.1.2 && < 0.2 }+common lens { build-depends: lens >= 4 && < 5 }+common mmap { build-depends: mmap >= 0.5 && < 0.6 }+common optparse-applicative { build-depends: optparse-applicative >= 0.14 && < 0.15 }+common text { build-depends: text >= 1.2 && < 1.3 }+common transformers { build-depends: transformers >= 0.4 && < 0.6 }+common vector { build-depends: vector >= 0.12 && < 0.13 }+common word8 { build-depends: word8 >= 0.1 && < 0.2 }++common semigroups { if impl(ghc < 8 ) { build-depends: semigroups >= 0.16 && < 0.19 } }++common config+ default-language: Haskell2010+ ghc-options: -Wall -O2 -msse4.2+ if flag(sse42)+ ghc-options: -msse4.2+ if flag(bmi2) && impl(ghc >= 8.4.1)+ ghc-options: -mbmi2 -msse4.2+ cpp-options: -DBMI2_ENABLED++library+ import: base, config+ , bytestring+ , hw-balancedparens+ , hw-bits+ , hw-prim+ , hw-rankselect+ , hw-rankselect-base+ , vector+ , word8+ hs-source-dirs: src+ other-modules: Paths_hw_json_simple_cursor+ autogen-modules: Paths_hw_json_simple_cursor+ exposed-modules: HaskellWorks.Data.Json.Simple.Cursor+ HaskellWorks.Data.Json.Simple.Cursor.Fast+ HaskellWorks.Data.Json.Simple.Cursor.Internal.IbBp+ HaskellWorks.Data.Json.Simple.Cursor.Internal.ToIbBp+ HaskellWorks.Data.Json.Simple.Cursor.Internal.Word8+ HaskellWorks.Data.Json.Simple.Cursor.SemiIndex+ HaskellWorks.Data.Json.Simple.Cursor.Snippet++executable hw-json+ import: base, config+ , bytestring+ , dlist+ , generic-lens+ , hw-balancedparens+ , hw-json-simd+ , hw-mquery+ , hw-prim+ , hw-rankselect+ , hw-rankselect-base+ , lens+ , mmap+ , optparse-applicative+ , semigroups+ , text+ , vector+ main-is: Main.hs+ hs-source-dirs: app+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-depends: hw-json-simple-cursor+ other-modules:+ App.Commands+ App.Commands.CreateIndex+ App.Commands.Types++test-suite hw-json-test+ import: base, config+ , attoparsec+ , bytestring+ , hedgehog+ , hspec+ , hw-balancedparens+ , hw-bits+ , hw-hspec-hedgehog+ , hw-prim+ , hw-rankselect+ , hw-rankselect-base+ , transformers+ , vector+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ build-depends: hw-json-simple-cursor+ hs-source-dirs: test+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ build-tools: hspec-discover+ other-modules:+ HaskellWorks.Data.Json.Simple.CursorSpec+ Paths_hw_json_simple_cursor++benchmark bench+ import: base, config+ , bytestring+ , criterion+ , directory+ , mmap+ , semigroups+ type: exitcode-stdio-1.0+ main-is: Main.hs+ hs-source-dirs: bench+ build-depends: hw-json-simple-cursor+ other-modules: Paths_hw_json_simple_cursor
+ src/HaskellWorks/Data/Json/Simple/Cursor.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}++module HaskellWorks.Data.Json.Simple.Cursor+ ( JsonCursor(..)+ , jsonCursorPos+ ) where++import Data.String+import Data.Word+import HaskellWorks.Data.FromByteString+import HaskellWorks.Data.FromForeignRegion+import HaskellWorks.Data.Positioning+import HaskellWorks.Data.RankSelect.Base.Rank0+import HaskellWorks.Data.RankSelect.Base.Rank1+import HaskellWorks.Data.RankSelect.Base.Select1+import HaskellWorks.Data.RankSelect.CsPoppy+import HaskellWorks.Data.TreeCursor+import Prelude hiding (drop)++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString.Internal as BSI+import qualified Data.Vector.Storable as DVS+import qualified Foreign.ForeignPtr as F+import qualified HaskellWorks.Data.BalancedParens as BP+import qualified HaskellWorks.Data.BalancedParens.RangeMin as RM+import qualified HaskellWorks.Data.Json.Simple.Cursor.SemiIndex as SI++data JsonCursor t v w = JsonCursor+ { cursorText :: !t+ , interests :: !v+ , balancedParens :: !w+ , cursorRank :: !Count+ }+ deriving (Eq, Show)++instance FromByteString (JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))) where+ fromByteString bs = JsonCursor+ { cursorText = bs+ , interests = ib+ , balancedParens = BP.SimpleBalancedParens bp+ , cursorRank = 1+ }+ where SI.SemiIndex _ ib bp = SI.buildSemiIndex bs++instance FromByteString (JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy)) where+ fromByteString bs = JsonCursor+ { cursorText = bs+ , interests = makeCsPoppy ib+ , balancedParens = RM.mkRangeMin (makeCsPoppy bp)+ , cursorRank = 1+ }+ where SI.SemiIndex _ ib bp = SI.buildSemiIndex bs++instance FromForeignRegion (JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))) where+ fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (F.castForeignPtr fptr) offset size)++instance FromForeignRegion (JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy)) where+ fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (F.castForeignPtr fptr) offset size)++instance IsString (JsonCursor BS.ByteString (DVS.Vector Word64) (BP.SimpleBalancedParens (DVS.Vector Word64))) where+ fromString = fromByteString . BSC.pack++instance IsString (JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy)) where+ fromString = fromByteString . BSC.pack++instance (BP.BalancedParens u, Rank1 u, Rank0 u) => TreeCursor (JsonCursor t v u) where+ firstChild :: JsonCursor t v u -> Maybe (JsonCursor t v u)+ firstChild k = let mq = BP.firstChild (balancedParens k) (cursorRank k) in (\q -> k { cursorRank = q }) <$> mq++ nextSibling :: JsonCursor t v u -> Maybe (JsonCursor t v u)+ nextSibling k = (\q -> k { cursorRank = q }) <$> BP.nextSibling (balancedParens k) (cursorRank k)++ parent :: JsonCursor t v u -> Maybe (JsonCursor t v u)+ parent k = let mq = BP.parent (balancedParens k) (cursorRank k) in (\q -> k { cursorRank = q }) <$> mq++ depth :: JsonCursor t v u -> Maybe Count+ depth k = BP.depth (balancedParens k) (cursorRank k)++ subtreeSize :: JsonCursor t v u -> Maybe Count+ subtreeSize k = BP.subtreeSize (balancedParens k) (cursorRank k)++jsonCursorPos :: (Rank1 w, Select1 v) => JsonCursor s v w -> Position+jsonCursorPos k = toPosition (select1 ik (rank1 bpk (cursorRank k)) - 1)+ where ik = interests k+ bpk = balancedParens k
+ src/HaskellWorks/Data/Json/Simple/Cursor/Fast.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}++module HaskellWorks.Data.Json.Simple.Cursor.Fast+ ( fromByteString+ , fromForeignRegion+ , fromString+ ) where++import Foreign.ForeignPtr+import HaskellWorks.Data.Json.Simple.Cursor+import HaskellWorks.Data.RankSelect.CsPoppy++import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString.Internal as BSI+import qualified HaskellWorks.Data.BalancedParens.RangeMin as RM+import qualified HaskellWorks.Data.FromForeignRegion as F+import qualified HaskellWorks.Data.Json.Simple.Cursor.Internal.IbBp as J+import qualified HaskellWorks.Data.Json.Simple.Cursor.Internal.ToIbBp as J++fromByteString :: BS.ByteString -> JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy)+fromByteString bs = JsonCursor+ { cursorText = bs+ , interests = makeCsPoppy ib+ , balancedParens = RM.mkRangeMin (makeCsPoppy bp)+ , cursorRank = 1+ }+ where J.IbBp ib bp = J.toIbBp bs++fromForeignRegion :: F.ForeignRegion -> JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy)+fromForeignRegion (fptr, offset, size) = fromByteString (BSI.fromForeignPtr (castForeignPtr fptr) offset size)++fromString :: String -> JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy)+fromString = fromByteString . BSC.pack
+ src/HaskellWorks/Data/Json/Simple/Cursor/Internal/IbBp.hs view
@@ -0,0 +1,10 @@+module HaskellWorks.Data.Json.Simple.Cursor.Internal.IbBp where++import Data.Word++import qualified Data.Vector.Storable as DVS++data IbBp = IbBp+ { ib :: DVS.Vector Word64+ , bp :: DVS.Vector Word64+ }
+ src/HaskellWorks/Data/Json/Simple/Cursor/Internal/ToIbBp.hs view
@@ -0,0 +1,12 @@+module HaskellWorks.Data.Json.Simple.Cursor.Internal.ToIbBp where++import qualified Data.ByteString as BS+import qualified HaskellWorks.Data.Json.Simple.Cursor.Internal.IbBp as Z+import qualified HaskellWorks.Data.Json.Simple.Cursor.SemiIndex as J++class ToIbBp a where+ toIbBp :: a -> Z.IbBp++instance ToIbBp BS.ByteString where+ toIbBp bs = Z.IbBp ib bp+ where J.SemiIndex _ ib bp = J.buildSemiIndex bs
+ src/HaskellWorks/Data/Json/Simple/Cursor/Internal/Word8.hs view
@@ -0,0 +1,72 @@+module HaskellWorks.Data.Json.Simple.Cursor.Internal.Word8 where++import Data.Word+import Data.Word8 hiding (isDigit)++import qualified Data.Char as C++isLeadingDigit :: Word8 -> Bool+isLeadingDigit w = w == _hyphen || (w >= _0 && w <= _9)++isTrailingDigit :: Word8 -> Bool+isTrailingDigit w = w == _plus || w == _hyphen || (w >= _0 && w <= _9) || w == _period || w == _E || w == _e++isAlphabetic :: Word8 -> Bool+isAlphabetic w = (w >= _A && w <= _Z) || (w >= _a && w <= _z)++isDigit :: Word8 -> Bool+isDigit w = w >= _0 && w <= _9++wIsJsonNumberDigit :: Word8 -> Bool+wIsJsonNumberDigit w = (w >= _0 && w <= _9) || w == _hyphen++doubleQuote :: Word8+doubleQuote = fromIntegral (C.ord '"')++backSlash :: Word8+backSlash = fromIntegral (C.ord '\\')++openBrace :: Word8+openBrace = fromIntegral (C.ord '{')++closeBrace :: Word8+closeBrace = fromIntegral (C.ord '}')++openBracket :: Word8+openBracket = fromIntegral (C.ord '[')++closeBracket :: Word8+closeBracket = fromIntegral (C.ord ']')++comma :: Word8+comma = fromIntegral (C.ord ',')++colon :: Word8+colon = fromIntegral (C.ord ':')++isPeriod :: Word8 -> Bool+isPeriod w = w == 46++isMinus :: Word8 -> Bool+isMinus w = w == 45++isPlus :: Word8 -> Bool+isPlus w = w == 43++isValueChar :: Word8 -> Bool+isValueChar c = isAlphabetic c || isDigit c || isPeriod c || isMinus c || isPlus c++isOpen :: Word8 -> Bool+isOpen c = c == openBracket || c == openBrace++isClose :: Word8 -> Bool+isClose c = c == closeBracket || c == closeBrace++isDelim :: Word8 -> Bool+isDelim c = c == comma || c == colon++isDoubleQuote :: Word8 -> Bool+isDoubleQuote c = c == doubleQuote++isBackSlash :: Word8 -> Bool+isBackSlash c = c == backSlash
+ src/HaskellWorks/Data/Json/Simple/Cursor/SemiIndex.hs view
@@ -0,0 +1,80 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiWayIf #-}++module HaskellWorks.Data.Json.Simple.Cursor.SemiIndex+ ( buildSemiIndex+ , SemiIndex(..)+ ) where++import Control.Monad.ST+import Data.Word++import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BSU+import qualified Data.Vector.Storable as DVS+import qualified HaskellWorks.Data.Bits.Writer.Storable as W+import qualified HaskellWorks.Data.Json.Simple.Cursor.Internal.Word8 as W8++{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}+{-# ANN module ("HLint: ignore Redundant do" :: String) #-}++data Context = InJson | InString | InEscape deriving (Eq, Show)++data SemiIndex v = SemiIndex+ { semiIndexContext :: !Context+ , semiIndexIb :: !v+ , semiIndexBp :: !v+ } deriving (Functor, Traversable, Foldable)++buildSemiIndex :: BS.ByteString -> SemiIndex (DVS.Vector Word64)+buildSemiIndex bs = DVS.createT $ do+ let len = (BS.length bs + 7) `div` 8+ mib <- W.newWriter len+ mbp <- W.newWriter (len * 2)+ buildFromByteString mib mbp bs 0 InJson+{-# INLINE buildSemiIndex #-}++buildFromByteString :: W.Writer s -> W.Writer s -> BS.ByteString -> Int -> Context -> ST s (SemiIndex (DVS.MVector s Word64))+buildFromByteString ib bp bs i context = if i < BS.length bs+ then do+ let c = BSU.unsafeIndex bs i+ case context of+ InJson -> if+ | c == W8.openBracket || c == W8.openBrace -> do+ W.unsafeWriteBit bp 1+ W.unsafeWriteBit bp 1+ W.unsafeWriteBit ib 1+ buildFromByteString ib bp bs (i + 1) InJson+ | c == W8.closeBracket || c == W8.closeBrace -> do+ W.unsafeWriteBit bp 0+ W.unsafeWriteBit bp 0+ W.unsafeWriteBit ib 1+ buildFromByteString ib bp bs (i + 1) InJson+ | c == W8.comma || c == W8.colon -> do+ W.unsafeWriteBit bp 0+ W.unsafeWriteBit bp 1+ W.unsafeWriteBit ib 1+ buildFromByteString ib bp bs (i + 1) InJson+ | c == W8.doubleQuote -> do+ W.unsafeWriteBit ib 0+ buildFromByteString ib bp bs (i + 1) InString+ | otherwise -> do+ W.unsafeWriteBit ib 0+ buildFromByteString ib bp bs (i + 1) InJson+ InString -> do+ W.unsafeWriteBit ib 0+ let newContext = if+ | c == W8.doubleQuote -> InJson+ | c == W8.backSlash -> InEscape+ | otherwise -> InString+ buildFromByteString ib bp bs (i + 1) newContext+ InEscape -> do+ W.unsafeWriteBit ib 0+ buildFromByteString ib bp bs (i + 1) InString+ else do+ ibv <- W.written ib+ bpv <- W.written bp+ return (SemiIndex context ibv bpv)+{-# INLINE buildFromByteString #-}
+ src/HaskellWorks/Data/Json/Simple/Cursor/Snippet.hs view
@@ -0,0 +1,32 @@+module HaskellWorks.Data.Json.Simple.Cursor.Snippet+ ( snippetPos+ , snippet+ ) where++import Data.Maybe+import HaskellWorks.Data.Json.Simple.Cursor+import HaskellWorks.Data.Positioning+import HaskellWorks.Data.RankSelect.Base.Select1+import HaskellWorks.Data.RankSelect.CsPoppy++import qualified Data.ByteString as BS+import qualified HaskellWorks.Data.BalancedParens as BP+import qualified HaskellWorks.Data.BalancedParens.RangeMin as RM++snippetPos :: JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy) -> (Count, Count)+snippetPos k = (kpa, kpz)+ where kpa = select1 kib kta + km+ kpz = select1 kib ktz - km+ kib = interests k+ kbp = balancedParens k+ kra = cursorRank k+ krz = fromMaybe maxBound (BP.findClose kbp kra)+ ksa = kra + 1+ ksz = krz + 1+ kta = ksa `div` 2+ ktz = ksz `div` 2+ km = ksa `mod` 2++snippet :: JsonCursor BS.ByteString CsPoppy (RM.RangeMin CsPoppy) -> BS.ByteString+snippet k = let (a, z) = snippetPos k in BS.take (fromIntegral (z - a + 1)) (BS.drop (fromIntegral (a - 1)) kt)+ where kt = cursorText k
+ test/HaskellWorks/Data/Json/Simple/CursorSpec.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-# OPTIONS_GHC -fno-warn-missing-signatures #-}++module HaskellWorks.Data.Json.Simple.CursorSpec+ ( spec+ ) where++import Control.Monad+import HaskellWorks.Hspec.Hedgehog+import Hedgehog+import Test.Hspec++import qualified HaskellWorks.Data.Json.Simple.Cursor as Z+import qualified HaskellWorks.Data.Json.Simple.Cursor.Fast as FAST+import qualified HaskellWorks.Data.Json.Simple.Cursor.Snippet as S+import qualified HaskellWorks.Data.TreeCursor as TC++{-# ANN module ("HLint: ignore Redundant do" :: String) #-}+{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}+{-# ANN module ("HLint: ignore Redundant bracket" :: String) #-}++fc = TC.firstChild+ns = TC.nextSibling++spec :: Spec+spec = describe "HaskellWorks.Data.Json.Backend.Simple.CursorSpec" $ do+ describe "Json cursor" $ do+ describe "For sample Json" $ do+ let k = FAST.fromByteString "[[11],[22]]"+ -- [ [ 1 1 ] , [ 2 2 ] ]+ -- (( (( )) )( (( )) ))+ it "can navigate" $ requireTest $ do+ (Z.cursorRank <$> Just k) === Just 1+ (Z.cursorRank <$> ns k) === Nothing+ (Z.cursorRank <$> fc k) === Just 2+ (Z.cursorRank <$> (fc >=> ns ) k) === Just 8+ (Z.cursorRank <$> (fc >=> ns >=> fc ) k) === Just 9+ (Z.cursorRank <$> (fc >=> ns >=> fc >=> ns ) k) === Nothing+ (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc ) k) === Just 10+ (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing+ (Z.cursorRank <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing+ (Z.cursorRank <$> (fc >=> fc ) k) === Just 3+ (Z.cursorRank <$> (fc >=> fc >=> ns ) k) === Nothing+ (Z.cursorRank <$> (fc >=> fc >=> fc ) k) === Just 4+ (Z.cursorRank <$> (fc >=> fc >=> fc >=> ns ) k) === Nothing+ (Z.cursorRank <$> (fc >=> fc >=> fc >=> fc ) k) === Nothing+ it "can snippet pos" $ requireTest $ do+ (S.snippetPos <$> Just k) === Just (1, 11)+ (S.snippetPos <$> ns k) === Nothing+ (S.snippetPos <$> fc k) === Just (2, 5)+ (S.snippetPos <$> (fc >=> ns ) k) === Just (7, 10)+ (S.snippetPos <$> (fc >=> ns >=> fc ) k) === Just (7, 10)+ (S.snippetPos <$> (fc >=> ns >=> fc >=> ns ) k) === Nothing+ (S.snippetPos <$> (fc >=> ns >=> fc >=> fc ) k) === Just (8, 9)+ (S.snippetPos <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing+ (S.snippetPos <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing+ (S.snippetPos <$> (fc >=> fc ) k) === Just (2, 5)+ (S.snippetPos <$> (fc >=> fc >=> ns ) k) === Nothing+ (S.snippetPos <$> (fc >=> fc >=> fc ) k) === Just (3, 4)+ (S.snippetPos <$> (fc >=> fc >=> fc >=> ns ) k) === Nothing+ (S.snippetPos <$> (fc >=> fc >=> fc >=> fc ) k) === Nothing+ it "can snippet" $ requireTest $ do+ (S.snippet <$> Just k) === Just "[[11],[22]]"+ (S.snippet <$> ns k) === Nothing+ (S.snippet <$> fc k) === Just "[11]"+ (S.snippet <$> (fc >=> ns ) k) === Just "[22]"+ (S.snippet <$> (fc >=> ns >=> fc ) k) === Just "[22]"+ (S.snippet <$> (fc >=> ns >=> fc >=> ns ) k) === Nothing+ (S.snippet <$> (fc >=> ns >=> fc >=> fc ) k) === Just "22"+ (S.snippet <$> (fc >=> ns >=> fc >=> fc >=> ns) k) === Nothing+ (S.snippet <$> (fc >=> ns >=> fc >=> fc >=> fc) k) === Nothing+ (S.snippet <$> (fc >=> fc ) k) === Just "[11]"+ (S.snippet <$> (fc >=> fc >=> ns ) k) === Nothing+ (S.snippet <$> (fc >=> fc >=> fc ) k) === Just "11"+ (S.snippet <$> (fc >=> fc >=> fc >=> ns ) k) === Nothing+ (S.snippet <$> (fc >=> fc >=> fc >=> fc ) k) === Nothing
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}