1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-29 00:34:26 +03:00

Merge branch 'fuzzy' into develop

This commit is contained in:
Tae Won Ha 2020-01-18 20:52:35 +01:00
commit ab68de2dce
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
115 changed files with 10828 additions and 1122 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9cfd2a5d30525406eb4326171a7d43641105bea0d11eebea2bd161186c459929
oid sha256:d26911f127c071ad3614ffe5506cb48eb018ebf4f203e528e5ca3be5648eebad
size 71680

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:14bcee7757d7dfa751eb33c554a1c3b6230ae9fe4e9dd5a22d5a238aaa1036bd
size 100832
oid sha256:da69917872f71d621ac0083cb03b7bd585ef7d8c7ac8e8c709569e3eaa049aae
size 100824

View File

@ -19,14 +19,12 @@
1929B29B95AD176D57942E08 /* UiRootReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */; };
1929B2D56C4652E251C23AD4 /* DefaultShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B93256AF7F9137223E36 /* DefaultShortcuts.swift */; };
1929B3217A7A3D79E28C80DB /* PrefWindowReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B49E6924847AD085C8C9 /* PrefWindowReducer.swift */; };
1929B333855A5406C400DA92 /* OpenQuicklyFilterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEDE7F92BC7B49E802AF /* OpenQuicklyFilterOperation.swift */; };
1929B3557317755A43513B17 /* OpenQuicklyWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B71A92C24FEFE79A851E /* OpenQuicklyWindow.swift */; };
1929B370A275F8C70AD5AA08 /* UrlCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B11D672134E52A256A7F /* UrlCommonsTest.swift */; };
1929B376DB09AB5FDBF42BA1 /* MainWindow+Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B41F704A4D67621197ED /* MainWindow+Types.swift */; };
1929B3A6C332FFAAEC7FD219 /* MainWindow+CustomTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B71B4BB6550F5BC6D4CF /* MainWindow+CustomTitle.swift */; };
1929B3AC66EFE35D68C020E3 /* PreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFB0F294F3714D5E095F /* PreviewToolReducer.swift */; };
1929B3F5743967125F357C9F /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7CB4863F80230C32D3C /* FileItem.swift */; };
1929B443B7AB2176A7818CA1 /* fuzzy_match.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1B01340283D6AAD6B06 /* fuzzy_match.cc */; };
1929B4B00D7BB191A9A6532D /* HtmlPreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.swift */; };
1929B4B70926DE113E6BF990 /* PreviewReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE37AA2843779CAFA76F /* PreviewReducer.swift */; };
1929B4E54E2F13A7F5F2B682 /* BufferListReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B67A10E6BB2986B2416E /* BufferListReducer.swift */; };
@ -35,8 +33,8 @@
1929B4FEE6EB56EF3F56B805 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B34FC23D805A8B29E8F7 /* Context.swift */; };
1929B50D933A369A86A165DE /* AdvencedPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */; };
1929B5257DB27F03C6663482 /* MainWindow+Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B067B3247675BCD09218 /* MainWindow+Actions.swift */; };
1929B53876E6952D378C2B30 /* ScoredFileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */; };
1929B542A071BD03C846F6EF /* PrefUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8241CDE58F7AAF89AE4 /* PrefUtils.swift */; };
1929B543D5C82485F053CF17 /* FuzzySearch.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = 1929B656C04BA6F950BFA2F5 /* FuzzySearch.xcdatamodel */; };
1929B5543B1E31A26096E656 /* FileMonitorReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B04EC69F616EEFAF5F96 /* FileMonitorReducer.swift */; };
1929B560C6CE264FD1E1F5A3 /* com.qvacua.VimR.vim in Resources */ = {isa = PBXBuildFile; fileRef = 1929BC6D45B7E14D4D75D4E6 /* com.qvacua.VimR.vim */; };
1929B59FA5C286E010F70BEE /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFC0A5A9C6DB09BE1368 /* Types.swift */; };
@ -44,7 +42,6 @@
1929B5A2EE366F79ED32744C /* KeysPrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B88B5FA08E897A3C2168 /* KeysPrefReducer.swift */; };
1929B5C1BABBC0D09D97C3EF /* PreviewMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B617C229B19DB3E987B8 /* PreviewMiddleware.swift */; };
1929B5F016431A76292D1E84 /* FileMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B365A6434354B568B04F /* FileMonitor.swift */; };
1929B6388EAF16C190B82955 /* FileItemIgnorePattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */; };
1929B6460862447A31B5B082 /* ImageAndTextTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDC3F82CB4CB4FE56D1B /* ImageAndTextTableCell.swift */; };
1929B66F795867B8C07FAAD4 /* DictionaryCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9355C892BEBA7496C71 /* DictionaryCommonsTest.swift */; };
1929B67DA3EB21A631EF1DBB /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
@ -58,14 +55,13 @@
1929B8F498D1E7C53F572CE2 /* KeysPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B14A5949FB64C4B2646F /* KeysPref.swift */; };
1929B8FB248D71BF88A35761 /* PreviewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6C6C7792B05164B0216 /* PreviewTool.swift */; };
1929B9318D32146D58BB38EC /* AppKitCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70931D60E04200E12030 /* AppKitCommons.swift */; };
1929B94083273D4B321AD848 /* FileItemUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B56C8ED31834BA9D8543 /* FileItemUtils.swift */; };
1929B98F94536E3912AD9F3B /* ArrayCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BAF13FAD5DA8D3762367 /* ArrayCommonsTest.swift */; };
1929B990A143763A56CFCED0 /* PrefMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B364460D86F17E80943C /* PrefMiddleware.swift */; };
1929BA269EBD68251410A08E /* ShortcutsTableSubviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B07F0085B7AE10413346 /* ShortcutsTableSubviews.swift */; };
1929BA715337FE26155B2071 /* BufferList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA43449BA41666CD55ED /* BufferList.swift */; };
1929BA76A1D97D8226F7CFB1 /* Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6AD3396160AA2C46919 /* Debouncer.swift */; };
1929BAAD7336FDFF1F78E749 /* ScorerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF69B01107F358CF7EAD /* ScorerTest.swift */; };
1929BAE4900D72A7877741B1 /* PrefWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE168F31344B69E61B62 /* PrefWindow.swift */; };
1929BAEE911EC7620EE51911 /* fuzzy_match.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1B01340283D6AAD6B06 /* fuzzy_match.cc */; };
1929BAFF1E011321D3186EE6 /* UiRoot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD4149D5A25C82064DD8 /* UiRoot.swift */; };
1929BB4A9B2FA42A64CCCC76 /* MainWindowReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD83A13BF133741766CC /* MainWindowReducer.swift */; };
1929BB67CAAD4F6CBD38DF0A /* RxRedux.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B66A5E2D00EA143AFD86 /* RxRedux.swift */; };
@ -76,7 +72,6 @@
1929BCF7F7B9CC5499A3F506 /* AdvancedPrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7039C5689CE45F53888 /* AdvancedPrefReducer.swift */; };
1929BD2F41D93ADFF43C1C98 /* NetUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B02440BC99C42F9EBD45 /* NetUtils.m */; };
1929BD3878A3A47B8D685CD2 /* AppDelegateReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7A68B7109CEFAF105E8 /* AppDelegateReducer.swift */; };
1929BD3F9E609BFADB27584B /* Scorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D510177918080BE39B /* Scorer.swift */; };
1929BDFDBDA7180D02ACB37E /* RxSwiftCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6C215ACCBE12672A8D7 /* RxSwiftCommonsTest.swift */; };
1929BE0DAEE9664C5BCFA211 /* States.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB6608B4F0E037CA0F4C /* States.swift */; };
1929BE0F64A6CE5BCE2A5092 /* MainWindow+Delegates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B714EB137AE448CE8ABD /* MainWindow+Delegates.swift */; };
@ -84,11 +79,10 @@
1929BE601267D52FA2E0D6D2 /* Defs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7F7A4B3FD52263D211D /* Defs.swift */; };
1929BEAE0592096BC1191B67 /* PrefPane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B07A4A9209C88380E015 /* PrefPane.swift */; };
1929BEDE1BE950EDA9497363 /* GeneralPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB55946DAEBF55D24048 /* GeneralPref.swift */; };
1929BEFEABA0448306CDB6D4 /* FileItemIgnorePatternTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBC84557C8351EC6183E /* FileItemIgnorePatternTest.swift */; };
1929BF03FD6465F289AA80B2 /* ToolsPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB2AD21A10A0ECA66A5E /* ToolsPref.swift */; };
1929BF3253594E5B1908C6CE /* RpcAppearanceEpic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B230EE8F1428980988F0 /* RpcAppearanceEpic.swift */; };
1929BF4FF30D9A9DE82C3052 /* FileUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8042AC566CDF6C998A3 /* FileUtilsTest.swift */; };
1929BFC70581084B5CE04A5B /* MatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BFE179BCA3C75A13D71B /* MatcherTests.swift */; };
1929BF5D0EFCC56A733BB4B7 /* FuzzySearch.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = 1929B656C04BA6F950BFA2F5 /* FuzzySearch.xcdatamodel */; };
1929BFDE22D155F7C4B19E96 /* HtmlPreviewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B85023B042C485409CE1 /* HtmlPreviewTool.swift */; };
4B004BCF21063B600043A396 /* DictionaryDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B004BCB21063B600043A396 /* DictionaryDecoder.swift */; };
4B004BD021063B600043A396 /* DictionaryDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B004BCB21063B600043A396 /* DictionaryDecoder.swift */; };
@ -111,13 +105,8 @@
4B2636B1223A487B00021586 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70951D6100E300E12030 /* SwiftCommons.swift */; };
4B2636B2223A487B00021586 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBA5081CFF374B00673FDF /* AppDelegate.swift */; };
4B2636B3223A487B00021586 /* WorkspaceTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6423991D8EFE3000FC78C8 /* WorkspaceTool.swift */; };
4B2636B4223A487B00021586 /* FileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7CB4863F80230C32D3C /* FileItem.swift */; };
4B2636B5223A487B00021586 /* FileItemIgnorePattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */; };
4B2636B6223A487B00021586 /* DictionaryErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B004BCE21063B600043A396 /* DictionaryErrors.swift */; };
4B2636B7223A487B00021586 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
4B2636B8223A487B00021586 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
4B2636B9223A487B00021586 /* ScoredFileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */; };
4B2636BA223A487B00021586 /* Scorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D510177918080BE39B /* Scorer.swift */; };
4B2636BB223A487B00021586 /* ProxyWorkspaceBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB409ED1DDA77E9005F39A2 /* ProxyWorkspaceBar.swift */; };
4B2636BC223A487B00021586 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
4B2636BD223A487B00021586 /* NetUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B02440BC99C42F9EBD45 /* NetUtils.m */; };
@ -151,12 +140,10 @@
4B2636D9223A487B00021586 /* AdvencedPref.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */; };
4B2636DA223A487B00021586 /* AppearancePrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BED01F5D94BFCA4CF80F /* AppearancePrefReducer.swift */; };
4B2636DB223A487B00021586 /* OpenQuicklyWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B71A92C24FEFE79A851E /* OpenQuicklyWindow.swift */; };
4B2636DC223A487B00021586 /* OpenQuicklyFilterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEDE7F92BC7B49E802AF /* OpenQuicklyFilterOperation.swift */; };
4B2636DD223A487B00021586 /* OpenQuicklyFileViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */; };
4B2636DE223A487B00021586 /* PrefMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B364460D86F17E80943C /* PrefMiddleware.swift */; };
4B2636DF223A487B00021586 /* Debouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B6AD3396160AA2C46919 /* Debouncer.swift */; };
4B2636E0223A487B00021586 /* PreviewUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8EF9A9F5ACC175452BD /* PreviewUtils.swift */; };
4B2636E1223A487B00021586 /* FileItemUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B56C8ED31834BA9D8543 /* FileItemUtils.swift */; };
4B2636E2223A487B00021586 /* HtmlPreviewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B85023B042C485409CE1 /* HtmlPreviewTool.swift */; };
4B2636E3223A487B00021586 /* HtmlPreviewToolReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.swift */; };
4B2636E4223A487B00021586 /* AdvancedPrefReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7039C5689CE45F53888 /* AdvancedPrefReducer.swift */; };
@ -373,10 +360,7 @@
4B94341420B95EC7005807BA /* MacVim-sch.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4B9433D920B95EC6005807BA /* MacVim-sch.icns */; };
4B94341520B95EC7005807BA /* MacVim-ps.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4B9433DA20B95EC6005807BA /* MacVim-ps.icns */; };
4B94341620B95EC7005807BA /* MacVim-css.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4B9433DB20B95EC6005807BA /* MacVim-css.icns */; };
4B96FB3B1EBBC56F00E4E164 /* FileItemIgnorePattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */; };
4B96FB3C1EBBC56F00E4E164 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
4B96FB3D1EBBC56F00E4E164 /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
4B96FB3E1EBBC56F00E4E164 /* Scorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D510177918080BE39B /* Scorer.swift */; };
4B96FB3F1EBBC56F00E4E164 /* PrefUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B8241CDE58F7AAF89AE4 /* PrefUtils.swift */; };
4B96FB401EBBC56F00E4E164 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
4B96FB421EBBC56F00E4E164 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70951D6100E300E12030 /* SwiftCommons.swift */; };
@ -429,6 +413,24 @@
4BF18C571FD2E52300DF95D1 /* NvimView.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BC1642B1FD2DEE1001903BE /* NvimView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4BF18C581FD2E53400DF95D1 /* CocoaMarkdown.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BF18C331FD2E2AA00DF95D1 /* CocoaMarkdown.framework */; };
4BF18C591FD2E53B00DF95D1 /* CocoaMarkdown.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BF18C331FD2E2AA00DF95D1 /* CocoaMarkdown.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
4BF70EC423D1B3F9009E51E9 /* FuzzyMatcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EBF23D1B3F9009E51E9 /* FuzzyMatcher.mm */; };
4BF70EC523D1B3F9009E51E9 /* FuzzyMatcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EBF23D1B3F9009E51E9 /* FuzzyMatcher.mm */; };
4BF70EC823D1B3F9009E51E9 /* FuzzyMatcherPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EC323D1B3F9009E51E9 /* FuzzyMatcherPool.swift */; };
4BF70EC923D1B3F9009E51E9 /* FuzzyMatcherPool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EC323D1B3F9009E51E9 /* FuzzyMatcherPool.swift */; };
4BF70ED223D1B4AF009E51E9 /* FoundationCommons.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70ED123D1B4AF009E51E9 /* FoundationCommons.m */; };
4BF70ED323D1B4AF009E51E9 /* FoundationCommons.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70ED123D1B4AF009E51E9 /* FoundationCommons.m */; };
4BF70ED623D1B54F009E51E9 /* ScoredUrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70ED523D1B54F009E51E9 /* ScoredUrl.m */; };
4BF70ED723D1B54F009E51E9 /* ScoredUrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70ED523D1B54F009E51E9 /* ScoredUrl.m */; };
4BF70EE123D1B5B3009E51E9 /* FileScanBaton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EDF23D1B5B3009E51E9 /* FileScanBaton.m */; };
4BF70EE223D1B5B3009E51E9 /* FileScanBaton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EDF23D1B5B3009E51E9 /* FileScanBaton.m */; };
4BF70EE523D1B5EC009E51E9 /* FuzzySearchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EE323D1B5EC009E51E9 /* FuzzySearchService.swift */; };
4BF70EE623D1B5EC009E51E9 /* FuzzySearchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EE323D1B5EC009E51E9 /* FuzzySearchService.swift */; };
4BF70EE723D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EE423D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift */; };
4BF70EE823D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EE423D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift */; };
4BF70EEA23D1B5FF009E51E9 /* CoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EE923D1B5FF009E51E9 /* CoreDataStack.swift */; };
4BF70EEB23D1B5FF009E51E9 /* CoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EE923D1B5FF009E51E9 /* CoreDataStack.swift */; };
4BF70EED23D1B618009E51E9 /* ConditionVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EEC23D1B618009E51E9 /* ConditionVariable.swift */; };
4BF70EEE23D1B619009E51E9 /* ConditionVariable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF70EEC23D1B618009E51E9 /* ConditionVariable.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -510,13 +512,22 @@
1929B067B3247675BCD09218 /* MainWindow+Actions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MainWindow+Actions.swift"; sourceTree = "<group>"; };
1929B07A4A9209C88380E015 /* PrefPane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefPane.swift; sourceTree = "<group>"; };
1929B07F0085B7AE10413346 /* ShortcutsTableSubviews.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsTableSubviews.swift; sourceTree = "<group>"; };
1929B0A888EA54E5C8FD04C7 /* search.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = search.h; path = "../../third-party/libag/include/search.h"; sourceTree = "<group>"; };
1929B0E63986F95E2F8DFF21 /* FileItem+CoreDataClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileItem+CoreDataClass.h"; sourceTree = "<group>"; };
1929B0E9B2F018D3E31D4B0B /* ShortcutsPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutsPref.swift; sourceTree = "<group>"; };
1929B0EA67C53B49B98182CA /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = log.h; path = "../../third-party/libag/include/log.h"; sourceTree = "<group>"; };
1929B0EB3F49C42A57D083AF /* GeneralPrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneralPrefReducer.swift; sourceTree = "<group>"; };
1929B0FBFB766042CF06E463 /* AppearancePref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearancePref.swift; sourceTree = "<group>"; };
1929B11D672134E52A256A7F /* UrlCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UrlCommonsTest.swift; sourceTree = "<group>"; };
1929B12CE56A9B36980288A4 /* OpenQuicklyReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyReducer.swift; sourceTree = "<group>"; };
1929B13E47E7D20EA99EDF92 /* print.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = print.h; path = "../../third-party/libag/include/print.h"; sourceTree = "<group>"; };
1929B13F14CABB7BDCD16B5D /* options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = options.h; path = "../../third-party/libag/include/options.h"; sourceTree = "<group>"; };
1929B14A5949FB64C4B2646F /* KeysPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeysPref.swift; sourceTree = "<group>"; };
1929B14F9B30D4A3FA1871A9 /* uthash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uthash.h; path = "../../third-party/libag/include/uthash.h"; sourceTree = "<group>"; };
1929B1534B8857C519D7C0FB /* FileItem+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FileItem+CoreDataProperties.h"; sourceTree = "<group>"; };
1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyFileViewRow.swift; sourceTree = "<group>"; };
1929B17B1BC7CA08DC76495C /* FileItem+CoreDataProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FileItem+CoreDataProperties.m"; sourceTree = "<group>"; };
1929B1B01340283D6AAD6B06 /* fuzzy_match.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fuzzy_match.cc; path = FuzzyMatcher/fuzzy_match.cc; sourceTree = "<group>"; };
1929B1DC584C89C477E83FA2 /* HttpServerMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpServerMiddleware.swift; sourceTree = "<group>"; };
1929B230EE8F1428980988F0 /* RpcAppearanceEpic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RpcAppearanceEpic.swift; sourceTree = "<group>"; };
1929B34FC23D805A8B29E8F7 /* Context.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Context.swift; sourceTree = "<group>"; };
@ -525,13 +536,13 @@
1929B41F704A4D67621197ED /* MainWindow+Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MainWindow+Types.swift"; sourceTree = "<group>"; };
1929B457B9D0FA4D21F3751E /* UiRootReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiRootReducer.swift; sourceTree = "<group>"; };
1929B49E6924847AD085C8C9 /* PrefWindowReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefWindowReducer.swift; sourceTree = "<group>"; };
1929B56C8ED31834BA9D8543 /* FileItemUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItemUtils.swift; sourceTree = "<group>"; };
1929B5D45C9792BBE76B8AFF /* StringCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringCommonsTest.swift; sourceTree = "<group>"; };
1929B617C229B19DB3E987B8 /* PreviewMiddleware.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewMiddleware.swift; sourceTree = "<group>"; };
1929B656C04BA6F950BFA2F5 /* FuzzySearch.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = FuzzySearch.xcdatamodel; sourceTree = "<group>"; };
1929B66A5E2D00EA143AFD86 /* RxRedux.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxRedux.swift; sourceTree = "<group>"; };
1929B672CE187B4D3EA1D3EE /* fuzzy_match.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = fuzzy_match.hh; path = FuzzyMatcher/fuzzy_match.hh; sourceTree = "<group>"; };
1929B67A10E6BB2986B2416E /* BufferListReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferListReducer.swift; sourceTree = "<group>"; };
1929B694508FB5FDE607513A /* ToolsPrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolsPrefReducer.swift; sourceTree = "<group>"; };
1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItemIgnorePattern.swift; sourceTree = "<group>"; };
1929B6AD3396160AA2C46919 /* Debouncer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Debouncer.swift; sourceTree = "<group>"; };
1929B6C215ACCBE12672A8D7 /* RxSwiftCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSwiftCommonsTest.swift; sourceTree = "<group>"; };
1929B6C6C7792B05164B0216 /* PreviewTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewTool.swift; sourceTree = "<group>"; };
@ -540,20 +551,23 @@
1929B714EB137AE448CE8ABD /* MainWindow+Delegates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MainWindow+Delegates.swift"; sourceTree = "<group>"; };
1929B71A92C24FEFE79A851E /* OpenQuicklyWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyWindow.swift; sourceTree = "<group>"; };
1929B71B4BB6550F5BC6D4CF /* MainWindow+CustomTitle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "MainWindow+CustomTitle.swift"; sourceTree = "<group>"; };
1929B77CD37F201AEDD6E703 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = "../../third-party/libag/include/config.h"; sourceTree = "<group>"; };
1929B7A68B7109CEFAF105E8 /* AppDelegateReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegateReducer.swift; sourceTree = "<group>"; };
1929B7BB3E4B3DC96284B686 /* PrefUtilsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefUtilsTest.swift; sourceTree = "<group>"; };
1929B7CB4863F80230C32D3C /* FileItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItem.swift; sourceTree = "<group>"; };
1929B7F7A4B3FD52263D211D /* Defs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Defs.swift; sourceTree = "<group>"; };
1929B8042AC566CDF6C998A3 /* FileUtilsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtilsTest.swift; sourceTree = "<group>"; };
1929B8241CDE58F7AAF89AE4 /* PrefUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefUtils.swift; sourceTree = "<group>"; };
1929B84E4B53B05F5434E464 /* lang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lang.h; path = "../../third-party/libag/include/lang.h"; sourceTree = "<group>"; };
1929B85023B042C485409CE1 /* HtmlPreviewTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlPreviewTool.swift; sourceTree = "<group>"; };
1929B88B5FA08E897A3C2168 /* KeysPrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeysPrefReducer.swift; sourceTree = "<group>"; };
1929B8EF9A9F5ACC175452BD /* PreviewUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewUtils.swift; sourceTree = "<group>"; };
1929B93256AF7F9137223E36 /* DefaultShortcuts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultShortcuts.swift; sourceTree = "<group>"; };
1929B9355C892BEBA7496C71 /* DictionaryCommonsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DictionaryCommonsTest.swift; sourceTree = "<group>"; };
1929B9695325580C7100B44C /* ignore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ignore.h; path = "../../third-party/libag/include/ignore.h"; sourceTree = "<group>"; };
1929B98192F6873508F8D76A /* FileItem+CoreDataClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FileItem+CoreDataClass.m"; sourceTree = "<group>"; };
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationCommons.swift; sourceTree = "<group>"; };
1929B9D510177918080BE39B /* Scorer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scorer.swift; sourceTree = "<group>"; };
1929BA43449BA41666CD55ED /* BufferList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BufferList.swift; sourceTree = "<group>"; };
1929BA5854064776A5C38257 /* decompress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = decompress.h; path = "../../third-party/libag/include/decompress.h"; sourceTree = "<group>"; };
1929BA5C7099CDEB04B76BA4 /* FileBrowser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileBrowser.swift; sourceTree = "<group>"; };
1929BA8AC40B901B20F20B71 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
1929BADEB143008EFA6F3318 /* NetUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetUtils.h; sourceTree = "<group>"; };
@ -561,7 +575,7 @@
1929BB2AD21A10A0ECA66A5E /* ToolsPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToolsPref.swift; sourceTree = "<group>"; };
1929BB55946DAEBF55D24048 /* GeneralPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneralPref.swift; sourceTree = "<group>"; };
1929BB6608B4F0E037CA0F4C /* States.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = States.swift; sourceTree = "<group>"; };
1929BBC84557C8351EC6183E /* FileItemIgnorePatternTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItemIgnorePatternTest.swift; sourceTree = "<group>"; };
1929BB75BEF0ADFD00619A45 /* scandir.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scandir.h; path = "../../third-party/libag/include/scandir.h"; sourceTree = "<group>"; };
1929BBE0A534F2F6009D31BE /* AdvencedPref.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvencedPref.swift; sourceTree = "<group>"; };
1929BBF0944940845485A512 /* RpcEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RpcEvents.swift; sourceTree = "<group>"; };
1929BC2F05E9A5C0DB039739 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
@ -572,19 +586,15 @@
1929BD83A13BF133741766CC /* MainWindowReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowReducer.swift; sourceTree = "<group>"; };
1929BDC3F82CB4CB4FE56D1B /* ImageAndTextTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageAndTextTableCell.swift; sourceTree = "<group>"; };
1929BDC8F5D48578A90236E9 /* FileBrowserReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileBrowserReducer.swift; sourceTree = "<group>"; };
1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScoredFileItem.swift; sourceTree = "<group>"; };
1929BE168F31344B69E61B62 /* PrefWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefWindow.swift; sourceTree = "<group>"; };
1929BE37AA2843779CAFA76F /* PreviewReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewReducer.swift; sourceTree = "<group>"; };
1929BE5AEA3D0980860EED50 /* HtmlPreviewToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HtmlPreviewToolReducer.swift; sourceTree = "<group>"; };
1929BE6AB18FA655A8A9DA73 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = "../../third-party/libag/include/util.h"; sourceTree = "<group>"; };
1929BE867BD8F0ED0246CC94 /* OSLogCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLogCommons.swift; sourceTree = "<group>"; };
1929BED01F5D94BFCA4CF80F /* AppearancePrefReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearancePrefReducer.swift; sourceTree = "<group>"; };
1929BEDE7F92BC7B49E802AF /* OpenQuicklyFilterOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenQuicklyFilterOperation.swift; sourceTree = "<group>"; };
1929BEEB33113B0E33C3830F /* Matcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matcher.swift; sourceTree = "<group>"; };
1929BF230875DED6CD7AB3EB /* ShortcutItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShortcutItem.swift; sourceTree = "<group>"; };
1929BF69B01107F358CF7EAD /* ScorerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScorerTest.swift; sourceTree = "<group>"; };
1929BFB0F294F3714D5E095F /* PreviewToolReducer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewToolReducer.swift; sourceTree = "<group>"; };
1929BFC0A5A9C6DB09BE1368 /* Types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
1929BFE179BCA3C75A13D71B /* MatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherTests.swift; sourceTree = "<group>"; };
4B004BCB21063B600043A396 /* DictionaryDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DictionaryDecoder.swift; path = ../../Carthage/Checkouts/DictionaryCoding/Sources/DictionaryCoding/DictionaryDecoder.swift; sourceTree = "<group>"; };
4B004BCC21063B600043A396 /* DictionaryCodingKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DictionaryCodingKey.swift; path = ../../Carthage/Checkouts/DictionaryCoding/Sources/DictionaryCoding/DictionaryCodingKey.swift; sourceTree = "<group>"; };
4B004BCD21063B600043A396 /* DictionaryEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DictionaryEncoder.swift; path = ../../Carthage/Checkouts/DictionaryCoding/Sources/DictionaryCoding/DictionaryEncoder.swift; sourceTree = "<group>"; };
@ -701,6 +711,19 @@
4BF18C381FD2E2AB00DF95D1 /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxCocoa.framework; path = ../Carthage/Build/Mac/RxCocoa.framework; sourceTree = "<group>"; };
4BF18C491FD2E2DE00DF95D1 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = ../Carthage/Build/Mac/Nimble.framework; sourceTree = "<group>"; };
4BF18C501FD2E4F200DF95D1 /* RxTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxTest.framework; path = ../Carthage/Build/Mac/RxTest.framework; sourceTree = "<group>"; };
4BF70EBF23D1B3F9009E51E9 /* FuzzyMatcher.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = FuzzyMatcher.mm; path = FuzzyMatcher/FuzzyMatcher.mm; sourceTree = "<group>"; };
4BF70EC123D1B3F9009E51E9 /* FuzzyMatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FuzzyMatcher.h; path = FuzzyMatcher/FuzzyMatcher.h; sourceTree = "<group>"; };
4BF70EC323D1B3F9009E51E9 /* FuzzyMatcherPool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FuzzyMatcherPool.swift; path = FuzzyMatcher/FuzzyMatcherPool.swift; sourceTree = "<group>"; };
4BF70ED023D1B4AF009E51E9 /* FoundationCommons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FoundationCommons.h; sourceTree = "<group>"; };
4BF70ED123D1B4AF009E51E9 /* FoundationCommons.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FoundationCommons.m; sourceTree = "<group>"; };
4BF70ED423D1B54F009E51E9 /* ScoredUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScoredUrl.h; sourceTree = "<group>"; };
4BF70ED523D1B54F009E51E9 /* ScoredUrl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScoredUrl.m; sourceTree = "<group>"; };
4BF70EDF23D1B5B3009E51E9 /* FileScanBaton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileScanBaton.m; sourceTree = "<group>"; };
4BF70EE023D1B5B3009E51E9 /* FileScanBaton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileScanBaton.h; sourceTree = "<group>"; };
4BF70EE323D1B5EC009E51E9 /* FuzzySearchService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FuzzySearchService.swift; sourceTree = "<group>"; };
4BF70EE423D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FuzzySearchFileMonitor.swift; sourceTree = "<group>"; };
4BF70EE923D1B5FF009E51E9 /* CoreDataStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStack.swift; sourceTree = "<group>"; };
4BF70EEC23D1B618009E51E9 /* ConditionVariable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConditionVariable.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -769,12 +792,28 @@
name = "File Browser";
sourceTree = "<group>";
};
1929B180CD479C16EE70BE41 /* the_silver_searcher */ = {
isa = PBXGroup;
children = (
1929B77CD37F201AEDD6E703 /* config.h */,
1929BA5854064776A5C38257 /* decompress.h */,
1929B9695325580C7100B44C /* ignore.h */,
1929B84E4B53B05F5434E464 /* lang.h */,
1929B0EA67C53B49B98182CA /* log.h */,
1929B13F14CABB7BDCD16B5D /* options.h */,
1929B13E47E7D20EA99EDF92 /* print.h */,
1929BB75BEF0ADFD00619A45 /* scandir.h */,
1929B0A888EA54E5C8FD04C7 /* search.h */,
1929B14F9B30D4A3FA1871A9 /* uthash.h */,
1929BE6AB18FA655A8A9DA73 /* util.h */,
);
name = the_silver_searcher;
sourceTree = "<group>";
};
1929B275B9921DA7503A1932 /* Utils */ = {
isa = PBXGroup;
children = (
1929B8042AC566CDF6C998A3 /* FileUtilsTest.swift */,
1929BFE179BCA3C75A13D71B /* MatcherTests.swift */,
1929BF69B01107F358CF7EAD /* ScorerTest.swift */,
1929B7BB3E4B3DC96284B686 /* PrefUtilsTest.swift */,
);
name = Utils;
@ -847,6 +886,18 @@
name = Commons;
sourceTree = "<group>";
};
1929BA1E1547FE22A342BFD4 /* Core Data */ = {
isa = PBXGroup;
children = (
1929B17B1BC7CA08DC76495C /* FileItem+CoreDataProperties.m */,
1929B1534B8857C519D7C0FB /* FileItem+CoreDataProperties.h */,
1929B98192F6873508F8D76A /* FileItem+CoreDataClass.m */,
1929B0E63986F95E2F8DFF21 /* FileItem+CoreDataClass.h */,
1929B656C04BA6F950BFA2F5 /* FuzzySearch.xcdatamodel */,
);
name = "Core Data";
sourceTree = "<group>";
};
1929BA652D3B88FC071531EC /* UI */ = {
isa = PBXGroup;
children = (
@ -861,6 +912,15 @@
name = UI;
sourceTree = "<group>";
};
1929BAD7FC1CCB6E95D6C098 /* ccls */ = {
isa = PBXGroup;
children = (
1929B1B01340283D6AAD6B06 /* fuzzy_match.cc */,
1929B672CE187B4D3EA1D3EE /* fuzzy_match.hh */,
);
name = ccls;
sourceTree = "<group>";
};
1929BB4CF1C1FFEE6CCDD6FD /* Preferences */ = {
isa = PBXGroup;
children = (
@ -905,7 +965,6 @@
isa = PBXGroup;
children = (
1929B71A92C24FEFE79A851E /* OpenQuicklyWindow.swift */,
1929BEDE7F92BC7B49E802AF /* OpenQuicklyFilterOperation.swift */,
1929B1558455B3A74D93EF2A /* OpenQuicklyFileViewRow.swift */,
1929BDC3F82CB4CB4FE56D1B /* ImageAndTextTableCell.swift */,
);
@ -1080,6 +1139,8 @@
4BDF50101D760AB700D8FBC3 /* Commons */ = {
isa = PBXGroup;
children = (
4BF70ED023D1B4AF009E51E9 /* FoundationCommons.h */,
4BF70ED123D1B4AF009E51E9 /* FoundationCommons.m */,
4B3CF02F224B7EAC00FA9833 /* RxSwiftCommons.swift */,
4B6A70931D60E04200E12030 /* AppKitCommons.swift */,
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */,
@ -1089,16 +1150,6 @@
name = Commons;
sourceTree = "<group>";
};
4BDF50111D760B1100D8FBC3 /* File Items */ = {
isa = PBXGroup;
children = (
1929B7CB4863F80230C32D3C /* FileItem.swift */,
1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */,
1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */,
);
name = "File Items";
sourceTree = "<group>";
};
4BEBA4FC1CFF374B00673FDF = {
isa = PBXGroup;
children = (
@ -1125,12 +1176,12 @@
4BEBA5071CFF374B00673FDF /* VimR */ = {
isa = PBXGroup;
children = (
4BF70ECB23D1B40A009E51E9 /* Fuzzy Search */,
4BB4CCEE224A7E6D00474C79 /* FSEvents */,
4B004BCA21063B4D0043A396 /* DictionaryCoding */,
4B2A2C0D1D0353750074CE9A /* Bridge.h */,
4B238BE01D3BF24200CBDD98 /* Application.swift */,
4BEBA5081CFF374B00673FDF /* AppDelegate.swift */,
4BDF50111D760B1100D8FBC3 /* File Items */,
4BF8EED91D858C4400CAC08A /* Utils */,
4BDF50101D760AB700D8FBC3 /* Commons */,
4B6423941D8EFD6100FC78C8 /* Workspace */,
@ -1147,7 +1198,6 @@
isa = PBXGroup;
children = (
4BEBA51A1CFF374B00673FDF /* Info.plist */,
1929BBC84557C8351EC6183E /* FileItemIgnorePatternTest.swift */,
1929B41F745CDCDFE09ACDCF /* resources */,
1929B79B3F03D2E050438074 /* Commons */,
1929B275B9921DA7503A1932 /* Utils */,
@ -1155,17 +1205,35 @@
path = VimRTests;
sourceTree = "<group>";
};
4BF70ECB23D1B40A009E51E9 /* Fuzzy Search */ = {
isa = PBXGroup;
children = (
4BF70EE923D1B5FF009E51E9 /* CoreDataStack.swift */,
4BF70EE423D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift */,
4BF70EE323D1B5EC009E51E9 /* FuzzySearchService.swift */,
4BF70ED423D1B54F009E51E9 /* ScoredUrl.h */,
4BF70ED523D1B54F009E51E9 /* ScoredUrl.m */,
4BF70EC123D1B3F9009E51E9 /* FuzzyMatcher.h */,
4BF70EBF23D1B3F9009E51E9 /* FuzzyMatcher.mm */,
4BF70EC323D1B3F9009E51E9 /* FuzzyMatcherPool.swift */,
4BF70EE023D1B5B3009E51E9 /* FileScanBaton.h */,
4BF70EDF23D1B5B3009E51E9 /* FileScanBaton.m */,
1929B180CD479C16EE70BE41 /* the_silver_searcher */,
1929BAD7FC1CCB6E95D6C098 /* ccls */,
1929BA1E1547FE22A342BFD4 /* Core Data */,
);
name = "Fuzzy Search";
sourceTree = "<group>";
};
4BF8EED91D858C4400CAC08A /* Utils */ = {
isa = PBXGroup;
children = (
4BF70EEC23D1B618009E51E9 /* ConditionVariable.swift */,
1929BA8AC40B901B20F20B71 /* FileUtils.swift */,
1929BEEB33113B0E33C3830F /* Matcher.swift */,
1929B9D510177918080BE39B /* Scorer.swift */,
1929B02440BC99C42F9EBD45 /* NetUtils.m */,
1929BADEB143008EFA6F3318 /* NetUtils.h */,
1929B6AD3396160AA2C46919 /* Debouncer.swift */,
1929B8EF9A9F5ACC175452BD /* PreviewUtils.swift */,
1929B56C8ED31834BA9D8543 /* FileItemUtils.swift */,
1929B8241CDE58F7AAF89AE4 /* PrefUtils.swift */,
);
name = Utils;
@ -1487,13 +1555,8 @@
4B2636B1223A487B00021586 /* SwiftCommons.swift in Sources */,
4B2636B2223A487B00021586 /* AppDelegate.swift in Sources */,
4B2636B3223A487B00021586 /* WorkspaceTool.swift in Sources */,
4B2636B4223A487B00021586 /* FileItem.swift in Sources */,
4B2636B5223A487B00021586 /* FileItemIgnorePattern.swift in Sources */,
4B2636B6223A487B00021586 /* DictionaryErrors.swift in Sources */,
4B2636B7223A487B00021586 /* FileUtils.swift in Sources */,
4B2636B8223A487B00021586 /* Matcher.swift in Sources */,
4B2636B9223A487B00021586 /* ScoredFileItem.swift in Sources */,
4B2636BA223A487B00021586 /* Scorer.swift in Sources */,
4B2636BB223A487B00021586 /* ProxyWorkspaceBar.swift in Sources */,
4B2636BC223A487B00021586 /* FoundationCommons.swift in Sources */,
4B2636BD223A487B00021586 /* NetUtils.m in Sources */,
@ -1503,6 +1566,8 @@
4B2636C1223A487B00021586 /* UiRoot.swift in Sources */,
4B2636C2223A487B00021586 /* UiRootReducer.swift in Sources */,
4B2636C3223A487B00021586 /* MainWindowReducer.swift in Sources */,
4BF70ED723D1B54F009E51E9 /* ScoredUrl.m in Sources */,
4BF70EC923D1B3F9009E51E9 /* FuzzyMatcherPool.swift in Sources */,
4B2636C4223A487B00021586 /* PreviewTool.swift in Sources */,
4B917E612334D52D00752149 /* EonilFSEvents.swift in Sources */,
4B2636C5223A487B00021586 /* PreviewReducer.swift in Sources */,
@ -1512,6 +1577,7 @@
4B2636C9223A487B00021586 /* PreviewToolReducer.swift in Sources */,
4B2636CA223A487B00021586 /* Types.swift in Sources */,
4B2636CB223A487B00021586 /* OpenQuicklyReducer.swift in Sources */,
4BF70EE223D1B5B3009E51E9 /* FileScanBaton.m in Sources */,
4B917E582334D52D00752149 /* EonilFSEventStreamCreateFlags.swift in Sources */,
4B2636CC223A487B00021586 /* FileMonitorReducer.swift in Sources */,
4B2636CD223A487B00021586 /* FileMonitor.swift in Sources */,
@ -1520,6 +1586,7 @@
4B2636D0223A487B00021586 /* BufferListReducer.swift in Sources */,
4B2636D1223A487B00021586 /* PrefWindow.swift in Sources */,
4B917E552334D52D00752149 /* EonilFSEventStream.swift in Sources */,
4BF70EE823D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift in Sources */,
4B2636D2223A487B00021586 /* PrefPane.swift in Sources */,
4B2636D3223A487B00021586 /* GeneralPref.swift in Sources */,
4B917E522334D52D00752149 /* EonilFSEventStreamEventFlags.swift in Sources */,
@ -1532,18 +1599,19 @@
4B2636D9223A487B00021586 /* AdvencedPref.swift in Sources */,
4B2636DA223A487B00021586 /* AppearancePrefReducer.swift in Sources */,
4B2636DB223A487B00021586 /* OpenQuicklyWindow.swift in Sources */,
4B2636DC223A487B00021586 /* OpenQuicklyFilterOperation.swift in Sources */,
4B2636DD223A487B00021586 /* OpenQuicklyFileViewRow.swift in Sources */,
4BF70EEB23D1B5FF009E51E9 /* CoreDataStack.swift in Sources */,
4B2636DE223A487B00021586 /* PrefMiddleware.swift in Sources */,
4B2636DF223A487B00021586 /* Debouncer.swift in Sources */,
4B2636E0223A487B00021586 /* PreviewUtils.swift in Sources */,
4B2636E1223A487B00021586 /* FileItemUtils.swift in Sources */,
4B2636E2223A487B00021586 /* HtmlPreviewTool.swift in Sources */,
4B2636E3223A487B00021586 /* HtmlPreviewToolReducer.swift in Sources */,
4BF70ED323D1B4AF009E51E9 /* FoundationCommons.m in Sources */,
4B2636E4223A487B00021586 /* AdvancedPrefReducer.swift in Sources */,
4B2636E5223A487B00021586 /* ToolsPref.swift in Sources */,
4B2636E6223A487B00021586 /* ToolsPrefReducer.swift in Sources */,
4B2636E7223A487B00021586 /* PrefUtils.swift in Sources */,
4BF70EC523D1B3F9009E51E9 /* FuzzyMatcher.mm in Sources */,
4B917E642334D52D00752149 /* EonilFSEventStreamEventID.swift in Sources */,
4B2636E8223A487B00021586 /* ThemedTableSubviews.swift in Sources */,
4B2636E9223A487B00021586 /* ImageAndTextTableCell.swift in Sources */,
@ -1562,12 +1630,16 @@
4B2636F4223A487B00021586 /* ShortcutsPref.swift in Sources */,
4B2636F5223A487B00021586 /* ShortcutsTableSubviews.swift in Sources */,
4B2636F6223A487B00021586 /* DefaultShortcuts.swift in Sources */,
4BF70EE623D1B5EC009E51E9 /* FuzzySearchService.swift in Sources */,
4B2636F7223A487B00021586 /* ShortcutItem.swift in Sources */,
4B2636F8223A487B00021586 /* RpcEvents.swift in Sources */,
4B2636F9223A487B00021586 /* RpcAppearanceEpic.swift in Sources */,
4BF70EEE23D1B619009E51E9 /* ConditionVariable.swift in Sources */,
4B2636FA223A487B00021586 /* OSLogCommons.swift in Sources */,
4B2636FB223A487B00021586 /* Defs.swift in Sources */,
1929B179DBDE58A9D9BCA819 /* MainWindow+Types.swift in Sources */,
1929BAEE911EC7620EE51911 /* fuzzy_match.cc in Sources */,
1929B543D5C82485F053CF17 /* FuzzySearch.xcdatamodel in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1585,13 +1657,8 @@
4B6A70961D6100E300E12030 /* SwiftCommons.swift in Sources */,
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */,
4B64239A1D8EFE3000FC78C8 /* WorkspaceTool.swift in Sources */,
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */,
1929B6388EAF16C190B82955 /* FileItemIgnorePattern.swift in Sources */,
4B004BD521063B600043A396 /* DictionaryErrors.swift in Sources */,
1929B67DA3EB21A631EF1DBB /* FileUtils.swift in Sources */,
1929B3F5743967125F357C9F /* Matcher.swift in Sources */,
1929B53876E6952D378C2B30 /* ScoredFileItem.swift in Sources */,
1929BD3F9E609BFADB27584B /* Scorer.swift in Sources */,
4BB409EE1DDA77E9005F39A2 /* ProxyWorkspaceBar.swift in Sources */,
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */,
1929BD2F41D93ADFF43C1C98 /* NetUtils.m in Sources */,
@ -1601,6 +1668,8 @@
1929BAFF1E011321D3186EE6 /* UiRoot.swift in Sources */,
1929B29B95AD176D57942E08 /* UiRootReducer.swift in Sources */,
1929BB4A9B2FA42A64CCCC76 /* MainWindowReducer.swift in Sources */,
4BF70ED623D1B54F009E51E9 /* ScoredUrl.m in Sources */,
4BF70EC823D1B3F9009E51E9 /* FuzzyMatcherPool.swift in Sources */,
1929B8FB248D71BF88A35761 /* PreviewTool.swift in Sources */,
4B917E5F2334D52D00752149 /* EonilFSEvents.swift in Sources */,
1929B4B70926DE113E6BF990 /* PreviewReducer.swift in Sources */,
@ -1610,6 +1679,7 @@
1929B3AC66EFE35D68C020E3 /* PreviewToolReducer.swift in Sources */,
1929B59FA5C286E010F70BEE /* Types.swift in Sources */,
1929B6D8F5FC723B7109031F /* OpenQuicklyReducer.swift in Sources */,
4BF70EE123D1B5B3009E51E9 /* FileScanBaton.m in Sources */,
4B917E562334D52D00752149 /* EonilFSEventStreamCreateFlags.swift in Sources */,
1929B5543B1E31A26096E656 /* FileMonitorReducer.swift in Sources */,
1929B5F016431A76292D1E84 /* FileMonitor.swift in Sources */,
@ -1618,6 +1688,7 @@
1929B4E54E2F13A7F5F2B682 /* BufferListReducer.swift in Sources */,
1929BAE4900D72A7877741B1 /* PrefWindow.swift in Sources */,
4B917E532334D52D00752149 /* EonilFSEventStream.swift in Sources */,
4BF70EE723D1B5EC009E51E9 /* FuzzySearchFileMonitor.swift in Sources */,
1929BEAE0592096BC1191B67 /* PrefPane.swift in Sources */,
1929BEDE1BE950EDA9497363 /* GeneralPref.swift in Sources */,
4B917E502334D52D00752149 /* EonilFSEventStreamEventFlags.swift in Sources */,
@ -1630,18 +1701,19 @@
1929B50D933A369A86A165DE /* AdvencedPref.swift in Sources */,
1929BCC7908DD899999B70BE /* AppearancePrefReducer.swift in Sources */,
1929B3557317755A43513B17 /* OpenQuicklyWindow.swift in Sources */,
1929B333855A5406C400DA92 /* OpenQuicklyFilterOperation.swift in Sources */,
1929B1837C750CADB3A5BCB9 /* OpenQuicklyFileViewRow.swift in Sources */,
4BF70EEA23D1B5FF009E51E9 /* CoreDataStack.swift in Sources */,
1929B990A143763A56CFCED0 /* PrefMiddleware.swift in Sources */,
1929BA76A1D97D8226F7CFB1 /* Debouncer.swift in Sources */,
1929B71610FF1DC6E459BA49 /* PreviewUtils.swift in Sources */,
1929B94083273D4B321AD848 /* FileItemUtils.swift in Sources */,
1929BFDE22D155F7C4B19E96 /* HtmlPreviewTool.swift in Sources */,
1929B4B00D7BB191A9A6532D /* HtmlPreviewToolReducer.swift in Sources */,
4BF70ED223D1B4AF009E51E9 /* FoundationCommons.m in Sources */,
1929BCF7F7B9CC5499A3F506 /* AdvancedPrefReducer.swift in Sources */,
1929BF03FD6465F289AA80B2 /* ToolsPref.swift in Sources */,
1929B6C0393DE40E34F4A49A /* ToolsPrefReducer.swift in Sources */,
1929B542A071BD03C846F6EF /* PrefUtils.swift in Sources */,
4BF70EC423D1B3F9009E51E9 /* FuzzyMatcher.mm in Sources */,
4B917E622334D52D00752149 /* EonilFSEventStreamEventID.swift in Sources */,
1929BE2F3E0182CC51F2763A /* ThemedTableSubviews.swift in Sources */,
1929B6460862447A31B5B082 /* ImageAndTextTableCell.swift in Sources */,
@ -1660,12 +1732,16 @@
1929BB85B2D30E548A32663D /* ShortcutsPref.swift in Sources */,
1929BA269EBD68251410A08E /* ShortcutsTableSubviews.swift in Sources */,
1929B2D56C4652E251C23AD4 /* DefaultShortcuts.swift in Sources */,
4BF70EE523D1B5EC009E51E9 /* FuzzySearchService.swift in Sources */,
1929B0C7150100A84FBDB8BF /* ShortcutItem.swift in Sources */,
1929B250DB3FB395A700FE8C /* RpcEvents.swift in Sources */,
1929BF3253594E5B1908C6CE /* RpcAppearanceEpic.swift in Sources */,
4BF70EED23D1B618009E51E9 /* ConditionVariable.swift in Sources */,
1929B4E8B916008399CD5D3A /* OSLogCommons.swift in Sources */,
1929B5A0EDD1119CFF7BB84C /* Defs.swift in Sources */,
1929B376DB09AB5FDBF42BA1 /* MainWindow+Types.swift in Sources */,
1929B443B7AB2176A7818CA1 /* fuzzy_match.cc in Sources */,
1929BF5D0EFCC56A733BB4B7 /* FuzzySearch.xcdatamodel in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1674,18 +1750,14 @@
buildActionMask = 2147483647;
files = (
4B6DFB3A22366D140066BB43 /* OSLogCommons.swift in Sources */,
4B96FB3B1EBBC56F00E4E164 /* FileItemIgnorePattern.swift in Sources */,
4B96FB3C1EBBC56F00E4E164 /* FileUtils.swift in Sources */,
4B917E572334D52D00752149 /* EonilFSEventStreamCreateFlags.swift in Sources */,
4B96FB3D1EBBC56F00E4E164 /* Matcher.swift in Sources */,
4B96FB3E1EBBC56F00E4E164 /* Scorer.swift in Sources */,
4B004BD621063B600043A396 /* DictionaryErrors.swift in Sources */,
4B96FB3F1EBBC56F00E4E164 /* PrefUtils.swift in Sources */,
4B96FB401EBBC56F00E4E164 /* FoundationCommons.swift in Sources */,
4B004BD021063B600043A396 /* DictionaryDecoder.swift in Sources */,
4B96FB421EBBC56F00E4E164 /* SwiftCommons.swift in Sources */,
4B3CF031224B7EAC00FA9833 /* RxSwiftCommons.swift in Sources */,
1929BEFEABA0448306CDB6D4 /* FileItemIgnorePatternTest.swift in Sources */,
1929B66F795867B8C07FAAD4 /* DictionaryCommonsTest.swift in Sources */,
4B004BD221063B600043A396 /* DictionaryCodingKey.swift in Sources */,
4B917E542334D52D00752149 /* EonilFSEventStream.swift in Sources */,
@ -1697,9 +1769,7 @@
1929BF4FF30D9A9DE82C3052 /* FileUtilsTest.swift in Sources */,
4B917E4E2334D52D00752149 /* EonilFSEventStreamError.swift in Sources */,
4B917E632334D52D00752149 /* EonilFSEventStreamEventID.swift in Sources */,
1929BFC70581084B5CE04A5B /* MatcherTests.swift in Sources */,
4B917E602334D52D00752149 /* EonilFSEvents.swift in Sources */,
1929BAAD7336FDFF1F78E749 /* ScorerTest.swift in Sources */,
4B917E512334D52D00752149 /* EonilFSEventStreamEventFlags.swift in Sources */,
4B004BD421063B600043A396 /* DictionaryEncoder.swift in Sources */,
1929B8E90A1378E494D481E7 /* PrefUtilsTest.swift in Sources */,
@ -1783,8 +1853,18 @@
"$(inherited)",
"$(PROJECT_DIR)/../Carthage/Build/Mac",
);
HEADER_SEARCH_PATHS = (
"$(PROJECT_DIR)/../third-party/libxz/include",
"$(PROJECT_DIR)/../third-party/libpcre/include",
);
INFOPLIST_FILE = "$(SRCROOT)/VimR.dev.Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
OTHER_LDFLAGS = (
"$(PROJECT_DIR)/../third-party/libxz/lib/liblzma.a",
"$(PROJECT_DIR)/../third-party/libpcre/lib/libpcre.a",
"$(PROJECT_DIR)/../third-party/libag/lib/libag.a",
"-pthread",
);
PRODUCT_BUNDLE_IDENTIFIER = com.qvacua.VimR.dev;
PRODUCT_MODULE_NAME = VimR;
PRODUCT_NAME = "VimR-dev";
@ -1803,8 +1883,18 @@
"$(inherited)",
"$(PROJECT_DIR)/../Carthage/Build/Mac",
);
HEADER_SEARCH_PATHS = (
"$(PROJECT_DIR)/../third-party/libxz/include",
"$(PROJECT_DIR)/../third-party/libpcre/include",
);
INFOPLIST_FILE = "$(SRCROOT)/VimR.dev.Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
OTHER_LDFLAGS = (
"$(PROJECT_DIR)/../third-party/libxz/lib/liblzma.a",
"$(PROJECT_DIR)/../third-party/libpcre/lib/libpcre.a",
"$(PROJECT_DIR)/../third-party/libag/lib/libag.a",
"-pthread",
);
PRODUCT_BUNDLE_IDENTIFIER = com.qvacua.VimR.dev;
PRODUCT_MODULE_NAME = VimR;
PRODUCT_NAME = "VimR-dev";
@ -1937,8 +2027,18 @@
"$(inherited)",
"$(PROJECT_DIR)/../Carthage/Build/Mac",
);
HEADER_SEARCH_PATHS = (
"$(PROJECT_DIR)/../third-party/libxz/include",
"$(PROJECT_DIR)/../third-party/libpcre/include",
);
INFOPLIST_FILE = VimR/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
OTHER_LDFLAGS = (
"$(PROJECT_DIR)/../third-party/libxz/lib/liblzma.a",
"$(PROJECT_DIR)/../third-party/libpcre/lib/libpcre.a",
"$(PROJECT_DIR)/../third-party/libag/lib/libag.a",
"-pthread",
);
PRODUCT_BUNDLE_IDENTIFIER = com.qvacua.VimR;
PRODUCT_NAME = VimR;
SWIFT_OBJC_BRIDGING_HEADER = VimR/Bridge.h;
@ -1955,8 +2055,18 @@
"$(inherited)",
"$(PROJECT_DIR)/../Carthage/Build/Mac",
);
HEADER_SEARCH_PATHS = (
"$(PROJECT_DIR)/../third-party/libxz/include",
"$(PROJECT_DIR)/../third-party/libpcre/include",
);
INFOPLIST_FILE = VimR/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
OTHER_LDFLAGS = (
"$(PROJECT_DIR)/../third-party/libxz/lib/liblzma.a",
"$(PROJECT_DIR)/../third-party/libpcre/lib/libpcre.a",
"$(PROJECT_DIR)/../third-party/libag/lib/libag.a",
"-pthread",
);
PRODUCT_BUNDLE_IDENTIFIER = com.qvacua.VimR;
PRODUCT_NAME = VimR;
SWIFT_OBJC_BRIDGING_HEADER = VimR/Bridge.h;

View File

@ -90,9 +90,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
self.setSparkleUrl(self.useSnapshot)
}
if appState.quit {
NSApp.terminate(self)
}
if appState.quit { NSApp.terminate(self) }
})
.disposed(by: self.disposeBag)
}
@ -209,8 +207,7 @@ extension AppDelegate {
}
private func updateMainWindowTemplateBeforeQuitting() {
guard let uuid = self.context.state.currentMainWindowUuid,
let curMainWindow = self.context.state.mainWindows[uuid] else { return }
guard let curMainWindow = self.context.state.currentMainWindow else { return }
self.context.state.mainWindowTemplate = curMainWindow
self.context.savePrefs()

View File

@ -60,6 +60,7 @@ class AppDelegateReducer: ReducerType {
)
mainWindow.preview.server = self.baseServerUrl.appendingPathComponent(MarkdownReducer.nonePath)
mainWindow.usesVcsIgnores = state.openQuickly.defaultUsesVcsIgnores
mainWindow.nvimArgs = config.nvimArgs
mainWindow.cliPipePath = config.cliPipePath
mainWindow.envDict = config.envDict

View File

@ -231,6 +231,17 @@ extension NSOutlineView {
}
}
extension NSTextField {
static func defaultTitleTextField() -> NSTextField {
let field = NSTextField(forAutoLayout: ())
field.backgroundColor = NSColor.clear;
field.isEditable = false;
field.isBordered = false;
return field
}
}
extension NSScrollView {
static func standardScrollView() -> NSScrollView {

View File

@ -1,5 +1,5 @@
{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf200
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;}
{\rtf1\ansi\ansicpg1252\cocoartf2511
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\paperw11900\paperh16840\vieww10960\viewh15520\viewkind0
@ -105,6 +105,18 @@ By:
{\field{\*\fldinst{HYPERLINK "https://github.com/Kentzo/ShortcutRecorder"}}{\fldrslt https://github.com/Kentzo/ShortcutRecorder}}\
\
\f1\b ccls\
{\field{\*\fldinst{HYPERLINK "https://github.com/MaskRay/ccls"}}{\fldrslt
\f0\b0 https://github.com/MaskRay/ccls}}
\f0\b0 \
\
\f1\b The Silver Searcher\
{\field{\*\fldinst{HYPERLINK "https://github.com/ggreer/the_silver_searcher"}}{\fldrslt
\f0\b0 https://github.com/ggreer/the_silver_searcher}}
\f0\b0 \
\
\f1\b Nimble
\f0\b0 \
{\field{\*\fldinst{HYPERLINK "https://github.com/Quick/Nimble"}}{\fldrslt https://github.com/Quick/Nimble}}\

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSWindowController">
@ -12,12 +13,12 @@
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Open Quickly" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" frameAutosaveName="38.open-quickly-window.frame" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" texturedBackground="YES"/>
<window title="Open Quickly" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="38.open-quickly-window.frame" animationBehavior="default" titlebarAppearsTransparent="YES" titleVisibility="hidden" id="QvC-M9-y7g" customClass="TitlelessKeyWindow" customModule="VimR" customModuleProvider="target">
<windowStyleMask key="styleMask" titled="YES" closable="YES" resizable="YES" fullSizeContentView="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenAuxiliary="YES"/>
<windowPositionMask key="initialPositionMask" topStrut="YES"/>
<rect key="contentRect" x="196" y="420" width="365" height="255"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<value key="minFullScreenContentSize" type="size" width="200" height="255"/>
<view key="contentView" id="EiT-Mj-1SZ">
<rect key="frame" x="0.0" y="0.0" width="365" height="255"/>

View File

@ -5,3 +5,8 @@
#import <NvimView/SharedTypes.h>
#import "NetUtils.h"
#import "FuzzyMatcher.h"
#import "FoundationCommons.h"
#import "ScoredUrl.h"
#import "FileScanBaton.h"
#import "FileItem+CoreDataProperties.h"

View File

@ -0,0 +1,38 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class ConditionVariable {
private(set) var posted: Bool
init(posted: Bool = false) {
self.posted = posted
}
func wait(`for` seconds: TimeInterval, then fn: (() -> Void)? = nil) {
self.condition.lock()
defer { self.condition.unlock() }
while !self.posted {
self.condition.wait(until: Date(timeIntervalSinceNow: seconds))
}
fn?()
}
func broadcast(then fn: (() -> Void)? = nil) {
self.condition.lock()
defer { self.condition.unlock() }
self.posted = true
self.condition.broadcast()
fn?()
}
private let condition = NSCondition()
}

View File

@ -0,0 +1,118 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import CoreData
import os
class CoreDataStack {
enum Error: Swift.Error {
case noCacheFolder
case pathDoesNotExit
case pathNotFolder
case unableToComplete(Swift.Error)
}
enum StoreLocation {
case temp(String)
case cache(String)
case path(String)
}
let container: NSPersistentContainer
let storeFile: URL
var storeLocation: URL { self.storeFile.parent }
var deleteOnDeinit: Bool
func newBackgroundContext() -> NSManagedObjectContext {
let context = self.container.newBackgroundContext()
context.undoManager = nil
return context
}
init(modelName: String, storeLocation: StoreLocation, deleteOnDeinit: Bool = false) throws {
self.deleteOnDeinit = deleteOnDeinit
self.container = NSPersistentContainer(name: modelName)
let fileManager = FileManager.default
let url: URL
switch storeLocation {
case .temp(let folderName):
let parentUrl = fileManager
.temporaryDirectory
.appendingPathComponent(folderName)
try fileManager.createDirectory(at: parentUrl, withIntermediateDirectories: true)
url = parentUrl.appendingPathComponent(modelName)
case .cache(let folderName):
guard let cacheUrl = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first else {
throw Error.noCacheFolder
}
let parentUrl = cacheUrl.appendingPathComponent(folderName)
try fileManager.createDirectory(at: parentUrl, withIntermediateDirectories: true)
url = parentUrl.appendingPathComponent(modelName)
case .path(let path):
guard fileManager.fileExists(atPath: path) else { throw Error.pathDoesNotExit }
let parentFolder = URL(fileURLWithPath: path)
guard parentFolder.isDir else { throw Error.pathNotFolder }
url = parentFolder.appendingPathComponent(modelName)
}
self.container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: url)]
self.storeFile = url
self.log.info("Created Core Data store in \(self.storeLocation)")
let condition = ConditionVariable()
var error: Swift.Error?
self.container.loadPersistentStores { _, err in
error = err
condition.broadcast()
}
condition.wait(for: 5)
if let err = error { throw Error.unableToComplete(err) }
self.container.viewContext.undoManager = nil
}
func deleteStore() throws {
guard self.deleteOnDeinit else { return }
guard let store = self.container.persistentStoreCoordinator.persistentStore(
for: self.storeFile
) else { return }
try self.container.persistentStoreCoordinator.remove(store)
let parentFolder = self.storeLocation
let fileManager = FileManager.default
guard fileManager.fileExists(atPath: parentFolder.path) else { return }
try fileManager.removeItem(at: parentFolder)
self.log.info("Deleted store at \(self.storeLocation)")
}
deinit {
guard self.deleteOnDeinit else { return }
do {
try self.deleteStore()
} catch {
self.log.error("Could not delete store at \(self.storeLocation): \(error)")
}
}
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.service)
}

View File

@ -16,6 +16,7 @@ struct Defs {
static let uiComponents = "ui-components"
static let middleware = "middleware"
static let service = "service"
}
static let webViewProcessPool = WKProcessPool()

View File

@ -0,0 +1,21 @@
//
// FileItem+CoreDataClass.h
// VimR
//
// Created by Tae Won Ha on 18.01.20.
// Copyright © 2020 Tae Won Ha. All rights reserved.
//
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
NS_ASSUME_NONNULL_BEGIN
@interface FileItem : NSManagedObject
@end
NS_ASSUME_NONNULL_END
#import "FileItem+CoreDataProperties.h"

View File

@ -0,0 +1,14 @@
//
// FileItem+CoreDataClass.m
// VimR
//
// Created by Tae Won Ha on 18.01.20.
// Copyright © 2020 Tae Won Ha. All rights reserved.
//
//
#import "FileItem+CoreDataClass.h"
@implementation FileItem
@end

View File

@ -0,0 +1,39 @@
//
// FileItem+CoreDataProperties.h
// VimR
//
// Created by Tae Won Ha on 18.01.20.
// Copyright © 2020 Tae Won Ha. All rights reserved.
//
//
#import "FileItem+CoreDataClass.h"
NS_ASSUME_NONNULL_BEGIN
@interface FileItem (CoreDataProperties)
+ (NSFetchRequest<FileItem *> *)fetchRequest;
@property (nonatomic) int16_t direntType;
@property (nonatomic) BOOL isHidden;
@property (nonatomic) BOOL isPackage;
@property (nonatomic) BOOL needsScanChildren;
@property (nullable, nonatomic, copy) NSString *pathStart;
@property (nullable, nonatomic, copy) NSURL *url;
@property (nullable, nonatomic, retain) NSSet<FileItem *> *children;
@property (nullable, nonatomic, retain) FileItem *parent;
@end
@interface FileItem (CoreDataGeneratedAccessors)
- (void)addChildrenObject:(FileItem *)value;
- (void)removeChildrenObject:(FileItem *)value;
- (void)addChildren:(NSSet<FileItem *> *)values;
- (void)removeChildren:(NSSet<FileItem *> *)values;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,27 @@
//
// FileItem+CoreDataProperties.m
// VimR
//
// Created by Tae Won Ha on 18.01.20.
// Copyright © 2020 Tae Won Ha. All rights reserved.
//
//
#import "FileItem+CoreDataProperties.h"
@implementation FileItem (CoreDataProperties)
+ (NSFetchRequest<FileItem *> *)fetchRequest {
return [NSFetchRequest fetchRequestWithEntityName:@"FileItem"];
}
@dynamic direntType;
@dynamic isHidden;
@dynamic isPackage;
@dynamic needsScanChildren;
@dynamic pathStart;
@dynamic url;
@dynamic children;
@dynamic parent;
@end

View File

@ -1,59 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class FileItem : CustomStringConvertible, Hashable, Comparable {
static func ==(left: FileItem, right: FileItem) -> Bool {
return left.url == right.url
}
static func <(left: FileItem, right: FileItem) -> Bool {
return left.url.lastPathComponent < right.url.lastPathComponent
}
let url: URL
var isDir: Bool {
return self.url.isDir
}
var isHidden: Bool {
return self.url.isHidden
}
var isPackage: Bool {
return self.url.isPackage
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.url)
}
/// When nil, then it has never been fnmatch'ed.
weak var ignoreToken: Token?
var ignore = false
var needsScanChildren = false
var childrenScanned = false
var children: [FileItem] = []
var description: String {
return "<FileItem: \(self.url), dir=\(self.isDir), hidden=\(self.isHidden), package=\(self.isPackage), "
+ "needsScan=\(self.needsScanChildren), childrenScanned=\(self.childrenScanned), "
+ "ignore=\(self.ignore), ignoreToken=\(String(describing: self.ignoreToken)), "
+ "children=\(self.children.count)>"
}
init(_ url: URL) {
self.url = url
}
func child(with url: URL) -> FileItem? {
return self.children.first { $0.url == url }
}
}

View File

@ -1,87 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
private let whitespaceCharSet = CharacterSet.whitespaces
class FileItemIgnorePattern: Hashable, CustomStringConvertible {
static func ==(lhs: FileItemIgnorePattern, rhs: FileItemIgnorePattern) -> Bool {
return lhs.pattern == rhs.pattern
}
static func from(string str: String) -> Set<FileItemIgnorePattern> {
if str.trimmingCharacters(in: whitespaceCharSet).count == 0 {
return Set()
}
let patterns: [FileItemIgnorePattern] = str
.components(separatedBy: ",")
.compactMap {
let trimmed = $0.trimmingCharacters(in: whitespaceCharSet)
if trimmed.count == 0 {
return nil
}
return FileItemIgnorePattern(pattern: trimmed)
}
return Set(patterns)
}
static func toString(_ set: Set<FileItemIgnorePattern>) -> String {
return Array(set)
.map { $0.pattern }
.sorted()
.joined(separator: ", ")
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.pattern)
}
var description: String {
return "<FileItemIgnorePattern: pattern=\(self.pattern), folderPattern=\(self.folderPattern)>"
}
let folderPattern: Bool
let pattern: String
private let patternAsFileSysRep: UnsafeMutablePointer<Int8>
init(pattern: String) {
self.pattern = pattern
self.folderPattern = pattern.hasPrefix("*/")
let fileSysRep = (pattern as NSString).fileSystemRepresentation
let len = Int(strlen(fileSysRep))
self.patternAsFileSysRep = UnsafeMutablePointer<Int8>.allocate(capacity: len + 1)
memcpy(self.patternAsFileSysRep, fileSysRep, len)
self.patternAsFileSysRep[len] = 0
}
deinit {
self.patternAsFileSysRep.deallocate()
}
func match(absolutePath path: String) -> Bool {
let matches: Int32
let absolutePath = path as NSString
if self.folderPattern {
matches = fnmatch(self.patternAsFileSysRep,
absolutePath.fileSystemRepresentation,
FNM_LEADING_DIR | FNM_NOESCAPE)
} else {
matches = fnmatch(self.patternAsFileSysRep,
(absolutePath.lastPathComponent as NSString).fileSystemRepresentation,
FNM_NOESCAPE)
}
return matches != FNM_NOMATCH
}
}

View File

@ -1,178 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
import RxSwift
class FileItemUtils {
static func flatFileItems(of url: URL,
ignorePatterns: Set<FileItemIgnorePattern>,
ignoreToken: Token,
root: FileItem) -> Observable<[FileItem]> {
guard url.isFileURL else {
return Observable.empty()
}
guard FileUtils.fileExists(at: url) else {
return Observable.empty()
}
let pathComponents = url.pathComponents
return Observable.create { observer in
let cancel = Disposables.create {
// noop
}
scanDispatchQueue.async {
guard let targetItem = fileItem(for: pathComponents, root: root) else {
observer.onCompleted()
return
}
var flatNewFileItems: [FileItem] = []
var dirStack: [FileItem] = [targetItem]
while let curItem = dirStack.popLast() {
if cancel.isDisposed {
observer.onCompleted()
return
}
if !curItem.childrenScanned || curItem.needsScanChildren {
scanChildren(curItem)
}
curItem.children
.filter { item in
if item.isHidden || item.isPackage {
return false
}
// This item already has been fnmatch'ed, thus return the cached value.
if item.ignoreToken == ignoreToken {
return !item.ignore
}
item.ignoreToken = ignoreToken
item.ignore = false
let path = item.url.path
for pattern in ignorePatterns {
// We don't use `String.FnMatchOption.leadingDir` (`FNM_LEADING_DIR`) for directories since we do not
// scan ignored directories at all when filtering. For example "*/.git" would create a `FileItem`
// for `/some/path/.git`, but not scan its children when we filter.
if pattern.match(absolutePath: path) {
item.ignore = true
return false
}
}
return true
}
.forEach { $0.isDir ? dirStack.append($0) : flatNewFileItems.append($0) }
if flatNewFileItems.count >= emitChunkSize {
observer.onNext(flatNewFileItems)
flatNewFileItems = []
}
}
if !cancel.isDisposed {
observer.onNext(flatNewFileItems)
observer.onCompleted()
}
}
return cancel
}
}
static func item(for url: URL, root: FileItem, create: Bool = true) -> FileItem? {
return fileItem(for: url.pathComponents, root: root, create: create)
}
static func sortedChildren(for url: URL, root: FileItem) -> [FileItem] {
guard let fileItem = fileItem(for: url, root: root) else {
return []
}
if !fileItem.childrenScanned || fileItem.needsScanChildren {
scanChildren(fileItem, sorted: true)
return fileItem.children
}
return fileItem.children.sorted()
}
}
/// When at least this much of non-directory and visible files are scanned, they are emitted.
private let emitChunkSize = 1000
private let scanDispatchQueue = DispatchQueue.global(qos: .userInitiated)
private let lock = NSRecursiveLock()
private func synced<T>(_ fn: () -> T) -> T {
lock.lock()
defer { lock.unlock() }
return fn()
}
private func fileItem(for pathComponents: [String], root: FileItem, create: Bool = true) -> FileItem? {
return synced {
pathComponents.dropFirst().reduce(root) { (resultItem, childName) -> FileItem? in
guard let parent = resultItem else {
return nil
}
return child(withName: childName, ofParent: parent, create: true)
}
}
}
private func fileItem(for url: URL, root: FileItem, create: Bool = true) -> FileItem? {
return fileItem(for: url.pathComponents, root: root, create: create)
}
/// Even when the result is nil it does not mean that there's no child with the given name. It could well be that
/// it's not been scanned yet. However, if `create` parameter was true and `nil` is returned, the requested
/// child does not exist.
///
/// - parameters:
/// - name: name of the child to get.
/// - parent: parent of the child.
/// - create: whether to create the child `FileItem` if it's not scanned yet.
/// - returns: child `FileItem` or nil.
private func child(withName name: String, ofParent parent: FileItem, create: Bool = false) -> FileItem? {
let filteredChildren = parent.children.filter { $0.url.lastPathComponent == name }
if filteredChildren.isEmpty && create {
let childUrl = parent.url.appendingPathComponent(name)
guard FileUtils.fileExists(at: childUrl) else {
return nil
}
let child = FileItem(childUrl)
synced { parent.children.append(child) }
return child
}
return filteredChildren.first
}
private func scanChildren(_ item: FileItem, sorted: Bool = false) {
let children = FileUtils.directDescendants(of: item.url).map(FileItem.init)
synced {
if sorted {
item.children = children.sorted()
} else {
item.children = children
}
item.childrenScanned = true
item.needsScanChildren = false
}
}

View File

@ -16,10 +16,6 @@ class FileMonitorReducer: ReducerType {
switch tuple.action {
case let .change(in: url):
if let fileItem = FileItemUtils.item(for: url, root: state.openQuickly.root, create: false) {
fileItem.needsScanChildren = true
}
state.mainWindows
.filter { (uuid, mainWindow) in url == mainWindow.cwd || url.isContained(in: mainWindow.cwd) }
.map { $0.0 }

23
VimR/VimR/FileScanBaton.h Normal file
View File

@ -0,0 +1,23 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import <Foundation/Foundation.h>
#import "ignore.h"
#import "scandir.h"
@interface FileScanBaton : NSObject
@property(readonly, nonnull) ignores *ig;
@property(readonly, nonnull) NSString *pathStart;
@property(readonly, nonnull) NSURL *url;
- (bool)test:(NSURL * _Nonnull)url;
- (instancetype _Nonnull)initWithBaseUrl:(NSURL *_Nonnull)baseUrl;
- (instancetype _Nonnull)initWithParent:(FileScanBaton *_Nonnull)parent url:(NSURL *_Nonnull)url;
@end

205
VimR/VimR/FileScanBaton.m Normal file
View File

@ -0,0 +1,205 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import "FileScanBaton.h"
#import "util.h"
#import "FoundationCommons.h"
#ifdef DEBUG
FILE *out_fd;
static dispatch_once_t debugToken;
#endif
@implementation FileScanBaton {
NSURL *_baseUrl;
scandir_baton_t *_baton;
const char *_basePathCstr;
const char *_pathStartCstr;
}
static const char *cfstr_to_cstr_copy(CFStringRef cfstr);
static void load_global_gitignores(ignores *ig);
- (bool)test:(NSURL *_Nonnull)url {
struct dirent dirent = url.fakeDirent;
return (bool) filename_filter(_baton->path_start, &dirent, _baton);
}
- (instancetype)initWithBaseUrl:(NSURL *)baseUrl {
#ifdef DEBUG
dispatch_once(&debugToken, ^{
out_fd = fopen("/Users/hat/Downloads/scan.log", "w");
set_log_level(LOG_LEVEL_DEBUG);
});
#endif
self = [super init];
if (self == nil) {return nil;}
_baseUrl = baseUrl;
_url = baseUrl;
_pathStart = @".";
_ig = init_ignore([FileScanBaton stubBatonWithGlobalGitignores].ig, "", 0);
[self initScanDirBaton];
[self loadVcsIgnores];
return self;
}
- (instancetype)initWithParent:(FileScanBaton *)parent url:(NSURL *)url {
self = [super init];
if (self == nil) {return nil;}
_baseUrl = parent.url;
_url = url;
_pathStart = [parent.pathStart stringByAppendingFormat:@"/%@", url.lastPathComponent];
const char *dirname = [url.lastPathComponent cStringUsingEncoding:NSUTF8StringEncoding];
_ig = init_ignore(parent.ig, dirname, strlen(dirname));
[self initScanDirBaton];
[self loadVcsIgnores];
return self;
}
- (void)initScanDirBaton {
_basePathCstr = (char *) cfstr_to_cstr_copy((__bridge CFStringRef) _baseUrl.path);
_pathStartCstr = (char *) cfstr_to_cstr_copy((__bridge CFStringRef) _pathStart);
_baton = malloc(sizeof(scandir_baton_t));
_baton->ig = _ig;
_baton->base_path = _basePathCstr;
_baton->base_path_len = strlen(_basePathCstr);
_baton->path_start = _pathStartCstr;
}
- (void)loadVcsIgnores {
const char *ignoreFile = NULL;
for (int i = 0; (ignore_pattern_files[i] != NULL); i++) {
ignoreFile = ignore_pattern_files[i];
char *dirFullPath = NULL;
ag_asprintf(
&dirFullPath,
"%s/%s",
[_url.path cStringUsingEncoding:NSUTF8StringEncoding],
ignoreFile
);
load_ignore_patterns(_ig, dirFullPath);
free(dirFullPath);
dirFullPath = NULL;
}
}
- (void)dealloc {
cleanup_ignore(_ig);
free(_baton);
free((void *) _basePathCstr);
free((void *) _pathStartCstr);
}
+ (instancetype)stubBatonWithGlobalGitignores {
static FileScanBaton *sharedStub = nil;
static dispatch_once_t singletonToken;
dispatch_once(&singletonToken, ^{
sharedStub = [[FileScanBaton alloc] initAsStub];
});
return sharedStub;
}
- (instancetype)initAsStub {
self = [super init];
if (self == nil) {return nil;}
_baseUrl = [NSURL fileURLWithPath:@"~"];
_url = _baseUrl;
_pathStart = @".";
_ig = init_ignore(NULL, "", 0);
[self initScanDirBaton];
load_global_gitignores(_ig);
return self;
}
static const char *cfstr_to_cstr_copy(CFStringRef cfstr) {
CFIndex out_len = 0;
CFRange whole_range = CFRangeMake(0, CFStringGetLength(cfstr));
CFIndex converted = CFStringGetBytes(
cfstr,
whole_range,
kCFStringEncodingUTF8,
0,
false,
NULL,
0,
&out_len
);
if (converted == 0 || out_len == 0) {return NULL;}
char *result = malloc((size_t) (out_len + 1));
converted = CFStringGetBytes(
cfstr,
whole_range,
kCFStringEncodingUTF8,
0,
false,
(UInt8 *) result,
out_len,
NULL
);
if (converted == 0) {
free(result);
return NULL;
}
result[out_len] = NULL;
return result;
}
// From the_silver_searcher/options.c
static void load_global_gitignores(ignores *ig) {
const char *home_dir = getenv("HOME");
FILE *gitconfig_file = NULL;
size_t buf_len = 0;
char *gitconfig_res = NULL;
gitconfig_file = popen("git config -z --path --get core.excludesfile 2>/dev/null", "r");
if (gitconfig_file != NULL) {
do {
gitconfig_res = ag_realloc(gitconfig_res, buf_len + 65);
buf_len += fread(gitconfig_res + buf_len, 1, 64, gitconfig_file);
} while (!feof(gitconfig_file) && buf_len > 0 && buf_len % 64 == 0);
gitconfig_res[buf_len] = '\0';
if (buf_len == 0) {
free(gitconfig_res);
const char *config_home = getenv("XDG_CONFIG_HOME");
if (config_home) {
ag_asprintf(&gitconfig_res, "%s/%s", config_home, "git/ignore");
} else {
ag_asprintf(&gitconfig_res, "%s/%s", home_dir, ".config/git/ignore");
}
}
log_debug("global core.excludesfile: %s", gitconfig_res);
load_ignore_patterns(ig, gitconfig_res);
free(gitconfig_res);
pclose(gitconfig_file);
}
}
@end

View File

@ -0,0 +1,13 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import <Foundation/Foundation.h>
@interface NSURL (Commons)
- (struct dirent)fakeDirent;
- (uint8_t)direntType;
@end

View File

@ -0,0 +1,40 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import "FoundationCommons.h"
#import <dirent.h>
@implementation NSURL (Commons)
- (struct dirent)fakeDirent {
const char *nameCstr = [self.lastPathComponent cStringUsingEncoding:NSUTF8StringEncoding];
struct dirent result = {
.d_type=self.direntType,
.d_namlen=(__uint16_t) strlen(nameCstr),
};
strcpy(result.d_name, nameCstr);
return result;
}
- (uint8_t)direntType {
NSString *value = nil;
if (![self getResourceValue:&value forKey:NSURLFileResourceTypeKey error:nil]) {
return DT_UNKNOWN;
}
if ([value isEqualToString:NSURLFileResourceTypeNamedPipe]) {return DT_FIFO;}
if ([value isEqualToString:NSURLFileResourceTypeCharacterSpecial]) {return DT_CHR;}
if ([value isEqualToString:NSURLFileResourceTypeDirectory]) {return DT_DIR;}
if ([value isEqualToString:NSURLFileResourceTypeBlockSpecial]) {return DT_BLK;}
if ([value isEqualToString:NSURLFileResourceTypeRegular]) {return DT_REG;}
if ([value isEqualToString:NSURLFileResourceTypeSymbolicLink]) {return DT_LNK;}
if ([value isEqualToString:NSURLFileResourceTypeSocket]) {return DT_SOCK;}
return DT_UNKNOWN;
}
@end

View File

@ -8,6 +8,8 @@ import os
extension URL {
var direntType: UInt8 { (self as NSURL).direntType() }
func isDirectParent(of url: URL) -> Bool {
guard self.isFileURL && url.isFileURL else {
return false

View File

@ -0,0 +1,18 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import <Foundation/Foundation.h>
@interface FuzzyMatcher : NSObject
+ (NSInteger)maxPatternLength;
+ (NSInteger)maxTextLength;
+ (NSInteger)minScore;
- (instancetype _Nonnull)initWithPattern:(NSString * _Nonnull)pattern;
- (NSInteger)score:(NSString * _Nonnull)text;
@end

View File

@ -0,0 +1,33 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import "FuzzyMatcher.h"
#import "fuzzy_match.hh"
@implementation FuzzyMatcher {
ccls::FuzzyMatcher *_matcher;
}
+ (NSInteger)maxPatternLength {return ccls::FuzzyMatcher::kMaxPat;}
+ (NSInteger)maxTextLength {return ccls::FuzzyMatcher::kMaxText;}
+ (NSInteger)minScore {return ccls::FuzzyMatcher::kMinScore;}
- (instancetype)initWithPattern:(NSString *)pattern {
self = [super init];
if (!self) {return nil;}
_matcher = new ccls::FuzzyMatcher([pattern cStringUsingEncoding:NSUTF8StringEncoding], 0);
return self;
}
- (NSInteger)score:(NSString *)text {
return _matcher->match([text cStringUsingEncoding:NSUTF8StringEncoding], false);
}
@end

View File

@ -0,0 +1,58 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import os
class FuzzyMatcherPool {
let pattern: String
init(pattern: String, initialPoolSize: Int = 2) {
self.pattern = pattern
self.matchers = []
for _ in 0..<initialPoolSize {
self.matchers.append(FuzzyMatcher(pattern: pattern))
}
}
func request() -> FuzzyMatcher {
return self.lock.withLock {
if self.matchers.isEmpty {
let matcher = FuzzyMatcher(pattern: self.pattern)
return matcher
}
let matcher = self.matchers.popLast()! // We know that the array is not empty!
return matcher
}
}
func giveBack(_ matcher: FuzzyMatcher) {
self.lock.withLock {
self.matchers.append(matcher)
}
}
deinit {
self.log.debug(
"DEBUG FuzzyMatcherPool with pattern '\(self.pattern)' had \(self.matchers.count) matchers."
)
}
private var matchers: [FuzzyMatcher]
private let lock = NSLock()
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.service)
}
private extension NSLocking {
func withLock<T>(_ body: () -> T) -> T {
self.lock()
defer { self.unlock() }
return body()
}
}

View File

@ -0,0 +1,191 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#include "fuzzy_match.hh"
#include <algorithm>
#include <ctype.h>
#include <stdio.h>
#include <vector>
namespace ccls {
namespace {
enum CharClass { Other, Lower, Upper };
enum CharRole { None, Tail, Head };
CharClass getCharClass(int c) {
if (islower(c))
return Lower;
if (isupper(c))
return Upper;
return Other;
}
void calculateRoles(std::string_view s, int roles[], int *class_set) {
if (s.empty()) {
*class_set = 0;
return;
}
CharClass pre = Other, cur = getCharClass(s[0]), suc;
*class_set = 1 << cur;
auto fn = [&]() {
if (cur == Other)
return None;
// U(U)L is Head while U(U)U is Tail
return pre == Other || (cur == Upper && (pre == Lower || suc == Lower))
? Head
: Tail;
};
for (size_t i = 0; i < s.size() - 1; i++) {
suc = getCharClass(s[i + 1]);
*class_set |= 1 << suc;
roles[i] = fn();
pre = cur;
cur = suc;
}
roles[s.size() - 1] = fn();
}
} // namespace
int FuzzyMatcher::missScore(int j, bool last) {
int s = -3;
if (last)
s -= 10;
if (text_role[j] == Head)
s -= 10;
return s;
}
int FuzzyMatcher::matchScore(int i, int j, bool last) {
int s = 0;
// Case matching.
if (pat[i] == text[j]) {
s++;
// pat contains uppercase letters or prefix matching.
if ((pat_set & 1 << Upper) || i == j)
s++;
}
if (pat_role[i] == Head) {
if (text_role[j] == Head)
s += 30;
else if (text_role[j] == Tail)
s -= 10;
}
// Matching a tail while previous char wasn't matched.
if (text_role[j] == Tail && i && !last)
s -= 30;
// First char of pat matches a tail.
if (i == 0 && text_role[j] == Tail)
s -= 40;
return s;
}
FuzzyMatcher::FuzzyMatcher(std::string_view pattern, int sensitivity) {
calculateRoles(pattern, pat_role, &pat_set);
if (sensitivity == 1)
sensitivity = pat_set & 1 << Upper ? 2 : 0;
case_sensitivity = sensitivity;
size_t n = 0;
for (size_t i = 0; i < pattern.size(); i++)
if (pattern[i] != ' ') {
pat += pattern[i];
low_pat[n] = (char)::tolower(pattern[i]);
pat_role[n] = pat_role[i];
n++;
}
}
int FuzzyMatcher::match(std::string_view text, bool strict) {
if (pat.empty() != text.empty())
return kMinScore;
int n = int(text.size());
if (n > kMaxText)
return kMinScore + 1;
this->text = text;
for (int i = 0; i < n; i++)
low_text[i] = (char)::tolower(text[i]);
calculateRoles(text, text_role, &text_set);
if (strict && n && !!pat_role[0] != !!text_role[0])
return kMinScore;
dp[0][0][0] = dp[0][0][1] = 0;
for (int j = 0; j < n; j++) {
dp[0][j + 1][0] = dp[0][j][0] + missScore(j, false);
dp[0][j + 1][1] = kMinScore * 2;
}
for (int i = 0; i < int(pat.size()); i++) {
int(*pre)[2] = dp[i & 1];
int(*cur)[2] = dp[(i + 1) & 1];
cur[i][0] = cur[i][1] = kMinScore;
for (int j = i; j < n; j++) {
cur[j + 1][0] = std::max(cur[j][0] + missScore(j, false),
cur[j][1] + missScore(j, true));
// For the first char of pattern, apply extra restriction to filter bad
// candidates (e.g. |int| in |PRINT|)
cur[j + 1][1] = (case_sensitivity ? pat[i] == text[j]
: low_pat[i] == low_text[j] &&
(i || text_role[j] != Tail ||
pat[i] == text[j]))
? std::max(pre[j][0] + matchScore(i, j, false),
pre[j][1] + matchScore(i, j, true))
: kMinScore * 2;
}
}
// Enumerate the end position of the match in str. Each removed trailing
// character has a penulty.
int ret = kMinScore;
for (int j = pat.size(); j <= n; j++)
ret = std::max(ret, dp[pat.size() & 1][j][1] - 2 * (n - j));
return ret;
}
} // namespace ccls
#if 0
TEST_SUITE("fuzzy_match") {
bool Ranks(std::string_view pat, std::vector<const char*> texts) {
FuzzyMatcher fuzzy(pat, 0);
std::vector<int> scores;
for (auto text : texts)
scores.push_back(fuzzy.Match(text));
bool ret = true;
for (size_t i = 0; i < texts.size() - 1; i++)
if (scores[i] < scores[i + 1]) {
ret = false;
break;
}
if (!ret) {
for (size_t i = 0; i < texts.size(); i++)
printf("%s %d ", texts[i], scores[i]);
puts("");
}
return ret;
}
TEST_CASE("test") {
FuzzyMatcher fuzzy("", 0);
CHECK(fuzzy.Match("") == 0);
CHECK(fuzzy.Match("aaa") < 0);
// case
CHECK(Ranks("monad", {"monad", "Monad", "mONAD"}));
// initials
CHECK(Ranks("ab", {"ab", "aoo_boo", "acb"}));
CHECK(Ranks("CC", {"CamelCase", "camelCase", "camelcase"}));
CHECK(Ranks("cC", {"camelCase", "CamelCase", "camelcase"}));
CHECK(Ranks("c c", {"camelCase", "camel case", "CamelCase", "camelcase",
"camel ace"}));
CHECK(Ranks("Da.Te",
{"Data.Text", "Data.Text.Lazy", "Data.Aeson.Encoding.text"}));
CHECK(Ranks("foo bar.h", {"foo/bar.h", "foobar.h"}));
// prefix
CHECK(Ranks("is", {"isIEEE", "inSuf"}));
// shorter
CHECK(Ranks("ma", {"map", "many", "maximum"}));
CHECK(Ranks("print", {"printf", "sprintf"}));
// score(PRINT) = kMinScore
CHECK(Ranks("ast", {"ast", "AST", "INT_FAST16_MAX"}));
// score(PRINT) > kMinScore
CHECK(Ranks("Int", {"int", "INT", "PRINT"}));
}
}
#endif

View File

@ -0,0 +1,34 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <limits.h>
#include <string>
#include <string_view>
namespace ccls {
class FuzzyMatcher {
public:
constexpr static int kMaxPat = 100;
constexpr static int kMaxText = 200 + 300; // TAE: originally 200
// Negative but far from INT_MIN so that intermediate results are hard to
// overflow.
constexpr static int kMinScore = INT_MIN / 4;
FuzzyMatcher(std::string_view pattern, int case_sensitivity);
int match(std::string_view text, bool strict);
private:
int case_sensitivity;
std::string pat;
std::string_view text;
int pat_set, text_set;
char low_pat[kMaxPat], low_text[kMaxText];
int pat_role[kMaxPat], text_role[kMaxText];
int dp[2][kMaxText + 1][2];
int matchScore(int i, int j, bool last);
int missScore(int j, bool last);
};
} // namespace ccls

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="19C57" minimumToolsVersion="Automatic" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="FileItem" representedClassName="FileItem" syncable="YES" codeGenerationType="class">
<attribute name="direntType" attributeType="Integer 16" usesScalarValueType="YES"/>
<attribute name="isHidden" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="isPackage" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="needsScanChildren" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="pathStart" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="children" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="FileItem" inverseName="parent" inverseEntity="FileItem"/>
<relationship name="parent" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="FileItem" inverseName="children" inverseEntity="FileItem"/>
<fetchIndex name="byIsDirAndUrlIndex">
<fetchIndexElement property="direntType" type="Binary" order="ascending"/>
<fetchIndexElement property="url" type="Binary" order="ascending"/>
</fetchIndex>
<fetchIndex name="byIsDirAndNeedsScanChildrenIndex">
<fetchIndexElement property="direntType" type="Binary" order="ascending"/>
<fetchIndexElement property="needsScanChildren" type="Binary" order="ascending"/>
</fetchIndex>
</entity>
<elements>
<element name="FileItem" positionX="-63" positionY="-18" width="128" height="163"/>
</elements>
</model>

View File

@ -0,0 +1,49 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import os
class FuzzySearchFileMonitor {
static let fileSystemEventsLatency = 1.0
func start(eventHandler: (@escaping (URL) -> Void)) throws {
self.monitor = try EonilFSEventStream(
pathsToWatch: [urlToMonitor.path],
sinceWhen: EonilFSEventsEventID.getCurrentEventId(),
latency: FuzzySearchFileMonitor.fileSystemEventsLatency,
flags: [],
handler: { [weak self] event in
if event.flag == .historyDone {
self?.log.info("Not firing first event (.historyDone): \(event)")
return
}
eventHandler(URL(fileURLWithPath: event.path))
}
)
self.monitor?.setDispatchQueue(globalFileMonitorQueue)
try self.monitor?.start()
self.log.info("Started monitoring \(self.urlToMonitor)")
}
init(urlToMonitor: URL) {
self.urlToMonitor = urlToMonitor
}
deinit {
self.monitor?.stop()
self.monitor?.invalidate()
}
private var urlToMonitor: URL
private var monitor: EonilFSEventStream?
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.service)
}
private let globalFileMonitorQueue = DispatchQueue.global(qos: .userInitiated)

View File

@ -0,0 +1,457 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import CoreData
import os
class FuzzySearchService {
typealias ScoredUrlsCallback = ([ScoredUrl]) -> Void
var root: URL {
didSet {
self.queue.sync {
self.deleteAllFiles()
self.ensureRootFileInStore()
}
}
}
var usesVcsIgnores = true {
willSet { self.stopScanScore() }
didSet {
self.queue.sync {
self.deleteAllFiles()
self.ensureRootFileInStore()
}
}
}
let coreDataStack: CoreDataStack
func cleanUp() {
do {
try self.coreDataStack.deleteStore()
} catch {
self.log.error("Could not delete core data store: \(error)")
}
}
func stopScanScore() {
self.stopLock.lock()
defer { self.stopLock.unlock() }
self.stop = true
}
func scanScore(
for pattern: String,
beginCallback: @escaping () -> Void,
endCallback: @escaping () -> Void,
callback: @escaping ScoredUrlsCallback
) {
self.queue.async {
self.log.info("Starting fuzzy search for \(pattern) in \(self.root)")
beginCallback()
defer { endCallback() }
let ctx = self.writeContext
ctx.performAndWait {
self.stopLock.lock()
self.stop = false
self.stopLock.unlock()
let matcherPool = FuzzyMatcherPool(pattern: pattern, initialPoolSize: 2)
self.scanScoreSavedFiles(matcherPool: matcherPool, context: ctx, callback: callback)
if self.shouldStop() { return }
self.scanScoreFilesNeedScanning(matcherPool: matcherPool, context: ctx, callback: callback)
}
self.log.info("Finished fuzzy search for \(pattern) in \(self.root)")
}
}
private func scanScoreSavedFiles(
matcherPool: FuzzyMatcherPool,
context: NSManagedObjectContext,
callback: ScoredUrlsCallback
) {
let predicate = NSPredicate(format: "direntType != %d", DT_DIR)
let countReq = FileItem.fetchRequest()
countReq.predicate = predicate
countReq.includesSubentities = false
guard let count = try? context.count(for: countReq) else {
self.log.error("Could not get count of Files")
return
}
self.log.info("Scoring \(count) Files for pattern \(matcherPool.pattern)")
let urlSorter = NSSortDescriptor(key: "url", ascending: true)
let fetchReq = FileItem.fetchRequest()
fetchReq.fetchLimit = coreDataBatchSize
fetchReq.sortDescriptors = [urlSorter]
fetchReq.predicate = predicate
let chunkCount = Int(ceil(Double(count) / Double(coreDataBatchSize)))
for chunkIndex in (0..<chunkCount) {
if self.shouldStop({ context.reset() }) { return }
let start = Swift.min(chunkIndex * coreDataBatchSize, count)
fetchReq.fetchOffset = start
do {
self.scoreFiles(
matcherPool: matcherPool,
files: try context.fetch(fetchReq),
callback: callback
)
} catch {
self.log.error("Could not fetch \(fetchReq): \(error)")
}
context.reset()
}
}
private func scanScoreFilesNeedScanning(
matcherPool: FuzzyMatcherPool,
context: NSManagedObjectContext,
callback: ([ScoredUrl]) -> ()
) {
let req = self.fileFetchRequest("needsScanChildren == TRUE AND direntType == %d", [DT_DIR])
do {
let foldersToScan = try context.fetch(req)
// We use the ID of objects since we reset in scanScore(), which resets all properties of
// foldersToScan after first folderToScan.
foldersToScan.forEach { folder in
self.scanScore(
matcherPool: matcherPool,
folderId: folder.objectID,
context: context,
callback: callback
)
}
} catch {
self.log.error("Could not fetch \(req): \(error)")
}
}
private func scanScore(
matcherPool: FuzzyMatcherPool,
folderId: NSManagedObjectID,
context: NSManagedObjectContext,
callback: ([ScoredUrl]) -> ()
) {
var saveCounter = 1
var counter = 1
guard let folder = context.object(with: folderId) as? FileItem else {
self.log.error("Could not convert object with ID \(folderId) to File")
return
}
let (initialBaton, initialBatons) = self.baton(for: folder.url!)
let testIgnores = self.usesVcsIgnores
var batons = initialBatons
var stack = [(initialBaton, folder)]
while let iterElement = stack.popLast() {
if self.shouldStop({ self.saveAndReset(context: context) }) { return }
autoreleasepool {
let baton = iterElement.0
let folder = iterElement.1
let urlToScan = folder.url!
let childUrls = FileUtils
.directDescendants(of: urlToScan)
.filter {
let keep = testIgnores ? baton.test($0) : true
if !keep { self.log.debug("Ignoring \($0.path)") }
return keep
}
let childFiles = childUrls
.filter { !$0.isPackage }
.map { url -> FileItem in self.file(fromUrl: url, pathStart: baton.pathStart, in: context) }
saveCounter += childFiles.count
counter += childFiles.count
folder.addChildren(Set(childFiles))
folder.needsScanChildren = false
let childFolders = childFiles.filter { $0.direntType == DT_DIR }
let childBatons = childFolders.map { FileScanBaton(parent: baton, url: $0.url!) }
batons.append(contentsOf: childBatons)
stack.append(contentsOf: zip(childBatons, childFolders))
if saveCounter > coreDataBatchSize {
self.log.debug(
"Flushing and scoring \(saveCounter) Files, stack has \(stack.count) Files"
)
self.scoreAllRegisteredFiles(
matcherPool: matcherPool,
context: context,
callback: callback
)
self.saveAndReset(context: context)
saveCounter = 0
// We have to re-fetch the Files in stack to get the parent-children relationship right.
// Since objectID survives NSManagedObjectContext.reset(), we can re-populate (re-fetch)
// stack using the objectIDs.
let ids = stack.map { $0.1.objectID }
stack = Array(zip(
stack.map { $0.0 },
ids.map { context.object(with: $0) as! FileItem }
))
}
}
}
self.log.debug("Flushing and scoring last \(saveCounter) Files")
self.scoreAllRegisteredFiles(matcherPool: matcherPool, context: context, callback: callback)
self.saveAndReset(context: context)
self.log.debug("Stored \(counter) Files")
}
private func saveAndReset(context: NSManagedObjectContext) {
do {
try context.save()
} catch {
self.log.error("There was an error saving the context: \(error)")
}
context.reset()
}
private func shouldStop(_ body: (() -> Void)? = nil) -> Bool {
self.stopLock.lock()
defer { self.stopLock.unlock() }
if self.stop {
body?()
return true
}
return false
}
private func scoreAllRegisteredFiles(
matcherPool: FuzzyMatcherPool,
context: NSManagedObjectContext,
callback: ([ScoredUrl]) -> ()
) {
let files = context.registeredObjects
.compactMap { $0 as? FileItem }
.filter { $0.direntType != DT_DIR }
self.log.debug("Scoring \(files.count) Files")
self.scoreFiles(matcherPool: matcherPool, files: files, callback: callback)
}
private func scoreFiles(
matcherPool: FuzzyMatcherPool,
files: [FileItem],
callback: ScoredUrlsCallback
) {
let matchFullPath = matcherPool.pattern.contains("/")
let count = files.count
let chunkCount = Int(ceil(Double(count) / Double(fuzzyMatchChunkSize)))
DispatchQueue.concurrentPerform(iterations: chunkCount) { chunkIndex in
let matcher = matcherPool.request()
defer { matcherPool.giveBack(matcher) }
let start = Swift.min(chunkIndex * fuzzyMatchChunkSize, count)
let end = Swift.min(start + fuzzyMatchChunkSize, count)
if self.shouldStop() { return }
let scoreThreshold = FuzzyMatcher.minScore() + 1
callback(files[start..<end].compactMap { file in
let url = file.url!
let score = matcher.score(matchFullPath ? url.path : url.lastPathComponent)
if score <= scoreThreshold { return nil }
return ScoredUrl(url: url, score: score)
})
}
}
init(root: URL) throws {
self.coreDataStack = try CoreDataStack(
modelName: "FuzzySearch",
storeLocation: .temp(UUID().uuidString),
deleteOnDeinit: true
)
self.root = root
self.writeContext = self.coreDataStack.newBackgroundContext()
self.fileMonitor = FuzzySearchFileMonitor(urlToMonitor: root)
self.queue.sync { self.ensureRootFileInStore() }
try self.fileMonitor.start { [weak self] url in self?.handleChange(in: url) }
}
private func ensureRootFileInStore() {
self.queue.async {
let ctx = self.writeContext
ctx.performAndWait {
let req = self.fileFetchRequest("url == %@", [self.root])
do {
let files = try ctx.fetch(req)
guard files.isEmpty else { return }
_ = self.file(fromUrl: self.root, pathStart: ".", in: ctx)
try ctx.save()
} catch {
self.log.error("Could not ensure root File in Core Data: \(error)")
}
}
}
}
private func handleChange(in folderUrl: URL) {
self.log.debug("File event in \(folderUrl)")
self.queue.async {
let ctx = self.writeContext
ctx.performAndWait {
let req = self.fileFetchRequest("url == %@", [folderUrl])
do {
let fetchResult = try ctx.fetch(req)
guard let folder = fetchResult.first else {
self.log.debug("File with url \(folderUrl) not found, doing nothing")
return
}
for child in folder.children ?? [] { ctx.delete(child) }
folder.needsScanChildren = true
self.log.debug("Marked \(folder.url!) for scanning")
try ctx.save()
} catch {
self.log.error(
"Could not fetch File with url \(folderUrl) "
+ "or could not save after setting needsScanChildren: \(error)"
)
}
ctx.reset()
}
}
}
private func fileFetchRequest(
_ format: String,
_ arguments: [Any]? = nil
) -> NSFetchRequest<FileItem> {
let req: NSFetchRequest<FileItem> = FileItem.fetchRequest()
req.predicate = NSPredicate(format: format, argumentArray: arguments)
return req
}
/// Call this in self.queue.(a)sync
private func deleteAllFiles() {
let delReq = NSBatchDeleteRequest(
fetchRequest: NSFetchRequest(entityName: String(describing: FileItem.self))
)
let ctx = self.writeContext
ctx.performAndWait {
do {
try ctx.execute(delReq)
} catch {
self.log.error("Could not delete all Files: \(error)")
}
}
}
private func baton(for url: URL) -> (FileScanBaton, [FileScanBaton]) {
assert(self.root.isParent(of: url) || url == self.root)
if url == self.root {
let rootBaton = FileScanBaton(baseUrl: self.root)
return (rootBaton, [rootBaton])
}
let rootBaton = FileScanBaton(baseUrl: self.root)
var batons = [rootBaton]
var pathComps = url.pathComponents.suffix(from: self.root.pathComponents.count)
var lastBaton = rootBaton
var lastUrl = self.root
while let pathComp = pathComps.popFirst() {
let childUrl = lastUrl.appendingPathComponent(pathComp)
let childBaton = FileScanBaton(
parent: lastBaton,
url: childUrl
)
batons.append(childBaton)
lastBaton = childBaton
lastUrl = childUrl
}
return (lastBaton, batons)
}
private func file(
fromUrl url: URL,
pathStart: String,
in context: NSManagedObjectContext
) -> FileItem {
let file = FileItem(context: context)
file.url = url
file.direntType = Int16(url.direntType)
file.isHidden = url.isHidden
file.isPackage = url.isPackage
file.pathStart = pathStart
if url.isDir { file.needsScanChildren = true }
return file
}
func debug() {
let req = self.fileFetchRequest("needsScanChildren == TRUE AND direntType == %d", [DT_DIR]);
self.queue.async {
let moc = self.writeContext
moc.performAndWait {
do {
let result = try moc.fetch(req)
Swift.print("Files with needsScanChildren = true:")
result.forEach {
Swift.print("\t\($0.url)")
}
Swift.print("--- \(result.count)")
} catch {
Swift.print(error)
}
}
}
}
private var stop = false
private let stopLock = NSLock()
private let queue = DispatchQueue(label: "scan-score-queue", qos: .userInitiated)
private let fileMonitor: FuzzySearchFileMonitor
private let writeContext: NSManagedObjectContext
private let log = OSLog(subsystem: Defs.loggerSubsystem, category: Defs.LoggerCategory.service)
}
private let fuzzyMatchChunkSize = 100
private let coreDataBatchSize = 10000

View File

@ -16,7 +16,7 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
case setOpenOnLaunch(Bool)
case setAfterLastWindowAction(AppState.AfterLastWindowAction)
case setOpenOnReactivation(Bool)
case setIgnorePatterns(Set<FileItemIgnorePattern>)
case setDefaultUsesVcsIgnores(Bool)
}
override var displayName: String {
@ -27,10 +27,6 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
return true
}
override func windowWillClose() {
self.ignorePatternsAction()
}
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
self.emit = emitter.typedEmit()
@ -40,13 +36,11 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
self.openWhenLaunchingCheckbox.boolState = state.openNewMainWindowOnLaunch
self.openOnReactivationCheckbox.boolState = state.openNewMainWindowOnReactivation
self.defaultUsesVcsIgnoresCheckbox.boolState = state.openQuickly.defaultUsesVcsIgnores
self.lastWindowAction = state.afterLastWindowAction
self.afterLastWindowPopup.selectItem(at: indexToAfterLastWindowAction.firstIndex(of: state.afterLastWindowAction) ?? 0)
self.ignorePatterns = state.openQuickly.ignorePatterns
self.ignoreField.stringValue = FileItemIgnorePattern.toString(state.openQuickly.ignorePatterns)
source
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
@ -75,13 +69,10 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
private let openWhenLaunchingCheckbox = NSButton(forAutoLayout: ())
private let openOnReactivationCheckbox = NSButton(forAutoLayout: ())
private let defaultUsesVcsIgnoresCheckbox = NSButton(forAutoLayout: ())
private let afterLastWindowPopup = NSPopUpButton(forAutoLayout: ())
private let ignoreField = NSTextField(forAutoLayout: ())
private var ignorePatterns = Set<FileItemIgnorePattern>()
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -92,10 +83,13 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
let openUntitledWindowTitle = self.titleTextField(title: "Open Untitled Window:")
self.configureCheckbox(button: self.openWhenLaunchingCheckbox,
title: "On launch",
action: #selector(GeneralPref.openUntitledWindowWhenLaunchingAction(_:)))
action: #selector(GeneralPref.openUntitledWindowWhenLaunchingAction))
self.configureCheckbox(button: self.openOnReactivationCheckbox,
title: "On re-activation",
action: #selector(GeneralPref.openUntitledWindowOnReactivationAction(_:)))
action: #selector(GeneralPref.openUntitledWindowOnReactivationAction))
self.configureCheckbox(button: self.defaultUsesVcsIgnoresCheckbox,
title: "Use VCS Ignores",
action: #selector(GeneralPref.defaultUsesVcsIgnoresAction))
let whenLaunching = self.openWhenLaunchingCheckbox
let onReactivation = self.openOnReactivationCheckbox
@ -110,19 +104,17 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
"Quit",
])
let ignoreListTitle = self.titleTextField(title: "Files To Ignore:")
let ignoreField = self.ignoreField
NotificationCenter.default.addObserver(forName: NSControl.textDidEndEditingNotification,
object: ignoreField,
queue: nil) { [unowned self] _ in
self.ignorePatternsAction()
}
let ignoreListTitle = self.titleTextField(title: "Open Quickly:")
let ignoreInfo =
self.infoTextField(markdown:
"Comma-separated list of ignore patterns \n"
+ "Matching files will be ignored in \"Open Quickly\" and the file browser. \n"
+ "Example: `*/.git, */node_modules` \n"
+ "For detailed information see [VimR Wiki](https://github.com/qvacua/vimr/wiki)."
self.infoTextField(
markdown:
"""
When checked, the ignore files of VCSs, e.g. `gitignore`, will we used to ignore files.
This checkbox will set the initial value for each VimR window.
You can change this setting for each VimR window in the Open Quickly window.
The behavior should be almost identical to that of
[The Silver Searcher](https://github.com/ggreer/the_silver_searcher).
"""
)
let cliToolTitle = self.titleTextField(title: "CLI Tool:")
@ -137,13 +129,15 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
markdown: "Put the executable `vimr` in your `$PATH` and execute `vimr -h` for help."
)
let vcsIg = self.defaultUsesVcsIgnoresCheckbox
self.addSubview(paneTitle)
self.addSubview(openUntitledWindowTitle)
self.addSubview(whenLaunching)
self.addSubview(onReactivation)
self.addSubview(vcsIg)
self.addSubview(ignoreListTitle)
self.addSubview(ignoreField)
self.addSubview(ignoreInfo)
self.addSubview(afterLastWindowTitle)
@ -175,17 +169,16 @@ class GeneralPref: PrefPane, UiComponent, NSTextFieldDelegate {
lastWindow.autoPinEdge(.top, to: .bottom, of: onReactivation, withOffset: 18)
lastWindow.autoPinEdge(.left, to: .right, of: afterLastWindowTitle, withOffset: 5)
ignoreListTitle.autoAlignAxis(.baseline, toSameAxisOf: ignoreField)
ignoreListTitle.autoAlignAxis(.baseline, toSameAxisOf: vcsIg)
ignoreListTitle.autoPinEdge(.right, to: .right, of: openUntitledWindowTitle)
ignoreListTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18, relation: .greaterThanOrEqual)
ignoreField.autoPinEdge(.top, to: .bottom, of: lastWindow, withOffset: 18)
ignoreField.autoPinEdge(toSuperviewEdge: .right, withInset: 18)
ignoreField.autoPinEdge(.left, to: .right, of: ignoreListTitle, withOffset: 5)
vcsIg.autoPinEdge(.top, to: .bottom, of: lastWindow, withOffset: 18)
vcsIg.autoPinEdge(.left, to: .right, of: ignoreListTitle, withOffset: 5)
ignoreInfo.autoPinEdge(.top, to: .bottom, of: ignoreField, withOffset: 5)
ignoreInfo.autoPinEdge(.top, to: .bottom, of: vcsIg, withOffset: 5)
ignoreInfo.autoPinEdge(toSuperviewEdge: .right, withInset: 18)
ignoreInfo.autoPinEdge(.left, to: .right, of: ignoreListTitle, withOffset: 5)
ignoreInfo.autoPinEdge(.left, to: .left, of: vcsIg)
cliToolTitle.autoAlignAxis(.baseline, toSameAxisOf: cliToolButton)
cliToolTitle.autoPinEdge(toSuperviewEdge: .left, withInset: 18, relation: .greaterThanOrEqual)
@ -234,6 +227,10 @@ extension GeneralPref {
}
}
@objc func defaultUsesVcsIgnoresAction(_ sender: NSButton) {
self.emit(.setDefaultUsesVcsIgnores(sender.boolState))
}
@objc func openUntitledWindowWhenLaunchingAction(_ sender: NSButton) {
self.emit(.setOpenOnLaunch(self.openWhenLaunchingCheckbox.boolState))
}
@ -253,16 +250,6 @@ extension GeneralPref {
self.emit(.setAfterLastWindowAction(self.lastWindowAction))
}
private func ignorePatternsAction() {
let patterns = FileItemIgnorePattern.from(string: self.ignoreField.stringValue)
if patterns == self.ignorePatterns {
return
}
self.ignorePatterns = patterns
self.emit(.setIgnorePatterns(ignorePatterns))
}
private func alert(title: String, info: String) {
let alert = NSAlert()
alert.alertStyle = .warning

View File

@ -24,9 +24,8 @@ class GeneralPrefReducer: ReducerType {
case let .setOpenOnReactivation(value):
state.openNewMainWindowOnReactivation = value
case let .setIgnorePatterns(patterns):
state.openQuickly.ignorePatterns = patterns
state.openQuickly.ignoreToken = Token()
case let .setDefaultUsesVcsIgnores(value):
state.openQuickly.defaultUsesVcsIgnores = value
}

View File

@ -1,125 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class Matcher {
static let uppercaseCharSet = CharacterSet.uppercaseLetters
enum ExactMatchResult {
case none
case exact
case prefix
case suffix
case contains
}
static func exactMatchIgnoringCase(_ target: String, pattern: String) -> ExactMatchResult {
let ltarget = target.lowercased()
let lpattern = pattern.lowercased()
if ltarget == lpattern {
return .exact
}
if ltarget.hasPrefix(lpattern) {
return .prefix
}
if ltarget.hasSuffix(lpattern) {
return .suffix
}
if ltarget.contains(lpattern) {
return .contains
}
return .none
}
static func numberOfUppercaseMatches(_ target: String, pattern: String) -> Int {
var tscalars = target.unicodeScalars.filter { self.uppercaseCharSet.contains($0) }
let count = tscalars.count
guard count > 0 else {
return 0
}
let pscalars = pattern.uppercased().unicodeScalars
pscalars.forEach {
if let idx = tscalars.firstIndex(of: $0) {
tscalars.remove(at: idx)
}
}
return count - tscalars.count
}
/// Matches `pattern` to `target` in a fuzzy way.
/// - returns: number of matched characters where first character match gets a bonus of 5
static func fuzzyIgnoringCase(_ target: String, pattern: String) -> Int {
let tlower = target.lowercased()
let plower = pattern.lowercased()
let tchars = tlower.unicodeScalars
let pchars = plower.unicodeScalars
var result = 0
var pidx = pchars.startIndex
for tchar in tchars {
if pchars[pidx] == tchar {
result += 1
pidx = pchars.index(after: pidx)
if pidx == pchars.endIndex {
break
}
}
}
if tchars.first == pchars.first {
result += 5
}
return result
}
/// Wagner-Fischer algorithm.
/// We use the 32 bit representation (`String.unicodeScalars`) of both parameters to compare them.
///
/// - returns: the distance of pattern from target
/// - seealso: https://en.wikipedia.org/wiki/WagnerFischer_algorithm
static func wagnerFisherDistance(_ target: String, pattern: String) -> Int {
let s = target.unicodeScalars
let t = pattern.unicodeScalars
let m = s.count
var prevRow = Array(repeating: 0, count: m &+ 1)
var curRow = Array(repeating: 0, count: m &+ 1)
for i in 0 ... m {
prevRow[i] = i
}
for (j, tchar) in t.enumerated() {
curRow[0] = j &+ 1
for (i, schar) in s.enumerated() {
if schar == tchar {
curRow[i &+ 1] = prevRow[i]
} else {
curRow[i &+ 1] = min(curRow[i] &+ 1, prevRow[i &+ 1] &+ 1, prevRow[i] &+ 1)
}
}
prevRow = curRow
}
return curRow[m]
}
}

View File

@ -1,115 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Cocoa
class OpenQuicklyFilterOperation: Operation {
init(forOpenQuickly openQuickly: OpenQuicklyWindow) {
self.openQuickly = openQuickly
self.pattern = openQuickly.pattern
self.cwd = openQuickly.cwd
self.flatFileItems = openQuickly.flatFileItems
super.init()
}
override func main() {
self.openQuickly.scanCondition.lock()
self.openQuickly.pauseScan = true
defer {
self.openQuickly.pauseScan = false
self.openQuickly.scanCondition.broadcast()
self.openQuickly.scanCondition.unlock()
}
if self.isCancelled {
return
}
if self.flatFileItems.isEmpty {
return
}
let sorted: [ScoredFileItem]
if pattern.count == 0 {
let truncatedItems = self.flatFileItems[0...min(maxResultCount, self.flatFileItems.count - 1)]
sorted = truncatedItems.map { ScoredFileItem(score: 0, url: $0.url) }
} else {
DispatchQueue.main.async { self.openQuickly.startProgress() }
defer { DispatchQueue.main.async { self.openQuickly.endProgress() } }
let count = self.flatFileItems.count
let chunksCount = Int(ceil(Float(count) / Float(chunkSize)))
let useFullPath = pattern.contains("/")
let cwdPath = self.cwd.path + "/"
var result = [ScoredFileItem]()
var spinLock = OS_SPINLOCK_INIT
let cleanedPattern = useFullPath ? self.pattern.replacingOccurrences(of: "/", with: "")
: self.pattern
DispatchQueue.concurrentPerform(iterations: chunksCount) { [unowned self] idx in
if self.isCancelled {
return
}
let startIndex = min(idx * chunkSize, count)
let endIndex = min(startIndex + chunkSize, count)
let chunkedItems = self.flatFileItems[startIndex..<endIndex]
let chunkedResult: [ScoredFileItem] = chunkedItems.compactMap {
if self.isCancelled {
return nil
}
let url = $0.url
if useFullPath {
let target = url.path.replacingOccurrences(of: cwdPath, with: "")
.replacingOccurrences(of: "/", with: "")
return ScoredFileItem(score: Scorer.score(target, pattern: cleanedPattern), url: url)
}
return ScoredFileItem(score: Scorer.score(url.lastPathComponent, pattern: cleanedPattern), url: url)
}
if self.isCancelled {
return
}
OSSpinLockLock(&spinLock)
result.append(contentsOf: chunkedResult)
OSSpinLockUnlock(&spinLock)
}
if self.isCancelled {
return
}
sorted = result.sorted(by: >)
}
if self.isCancelled {
return
}
DispatchQueue.main.async {
let result = Array(sorted[0...min(maxResultCount, sorted.count - 1)])
self.openQuickly.reloadFileView(withScoredItems: result)
}
}
private let pattern: String
private let flatFileItems: [FileItem]
private let cwd: URL
private unowned let openQuickly: OpenQuicklyWindow
}
private let chunkSize = 100
private let maxResultCount = 500

View File

@ -16,20 +16,19 @@ class OpenQuicklyReducer: ReducerType {
func typedReduce(_ pair: ReduceTuple) -> ReduceTuple {
var appState = pair.state
appState.openQuickly.open = false
appState.openQuickly.flatFileItems = Observable.empty()
appState.openQuickly.cwd = FileUtils.userHomeUrl
switch pair.action {
case let .open(url):
guard let uuid = appState.currentMainWindowUuid else {
return pair
}
case let .setUsesVcsIgnores(usesVcsIgnores):
guard let uuid = appState.currentMainWindowUuid else { return pair }
appState.mainWindows[uuid]?.usesVcsIgnores = usesVcsIgnores
case let .open(url):
guard let uuid = appState.currentMainWindowUuid else { return pair }
appState.mainWindows[uuid]?.urlsToOpen[url] = .newTab
appState.openQuickly.open = false
case .close:
appState.openQuickly.open = false
break
}
@ -48,16 +47,10 @@ class OpenQuicklyReducer: ReducerType {
case .openQuickly:
var appState = pair.state
guard let uuid = appState.currentMainWindowUuid else {
return pair
}
guard let cwd = appState.mainWindows[uuid]?.cwd else {
return pair
}
guard let uuid = appState.currentMainWindowUuid,
appState.mainWindows[uuid]?.cwd != nil else { return pair }
appState.openQuickly.open = true
appState.openQuickly.cwd = cwd
return (appState, pair.action, true)

View File

@ -7,149 +7,221 @@ import Cocoa
import RxSwift
import RxCocoa
import PureLayout
import os
class OpenQuicklyWindow: NSObject,
UiComponent,
NSWindowDelegate,
NSTextFieldDelegate,
NSTableViewDelegate, NSTableViewDataSource {
NSTableViewDelegate {
typealias StateType = AppState
enum Action {
case setUsesVcsIgnores(Bool)
case open(URL)
case close
}
let scanCondition = NSCondition()
var pauseScan = false
@objc dynamic private(set) var unsortedScoredUrls = [ScoredUrl]()
// Call this only when quitting
func cleanUp() {
self.searchServicePerRootUrl.values.forEach { $0.cleanUp() }
self.searchServicePerRootUrl.removeAll()
}
@objc func useVcsAction(_: Any?) {
self.scanToken = Token()
self.currentSearchService?.stopScanScore()
self.endProgress()
self.unsortedScoredUrls.removeAll()
self.emit(.setUsesVcsIgnores(self.useVcsIgnoresCheckBox.boolState))
}
required init(source: Observable<StateType>, emitter: ActionEmitter, state: StateType) {
self.emit = emitter.typedEmit()
self.windowController = NSWindowController(windowNibName: NSNib.Name("OpenQuicklyWindow"))
self.searchStream = self.searchField.rx
.text.orEmpty
.throttle(0.2, scheduler: MainScheduler.instance)
.throttle(.milliseconds(1 * 500), latest: true, scheduler: MainScheduler.instance)
.distinctUntilChanged()
super.init()
self.window.delegate = self
self.filterOpQueue.qualityOfService = .userInitiated
self.filterOpQueue.name = "open-quickly-filter-operation-queue"
self.configureWindow()
self.addViews()
source
.observeOn(MainScheduler.instance)
.subscribe(onNext: { state in
guard state.openQuickly.open else {
self.windowController.close()
return
}
if self.window.isKeyWindow {
// already open, so do nothing
return
}
self.cwd = state.openQuickly.cwd
self.cwdPathCompsCount = self.cwd.pathComponents.count
self.cwdControl.url = self.cwd
self.flatFileItemsSource = FileItemUtils.flatFileItems(
of: state.openQuickly.cwd,
ignorePatterns: state.openQuickly.ignorePatterns,
ignoreToken: state.openQuickly.ignoreToken,
root: state.openQuickly.root
)
self.searchStream
.subscribe(onNext: { pattern in
self.pattern = pattern
self.resetAndAddFilterOperation()
})
.disposed(by: self.perSessionDisposeBag)
self.flatFileItemsSource
.subscribeOn(self.scheduler)
.do(onNext: { items in
self.scanCondition.lock()
while self.pauseScan {
self.scanCondition.wait()
}
self.scanCondition.unlock()
//
self.flatFileItems.append(contentsOf: items)
self.resetAndAddFilterOperation()
})
.observeOn(MainScheduler.instance)
.subscribe(onNext: { items in
self.count += items.count
self.countField.stringValue = "\(self.count) items"
})
.disposed(by: self.perSessionDisposeBag)
self.windowController.showWindow(self)
})
.subscribe(onNext: { [weak self] state in self?.subscription(state) })
.disposed(by: self.disposeBag)
}
func reloadFileView(withScoredItems items: [ScoredFileItem]) {
self.fileViewItems = items
self.fileView.reloadData()
}
func startProgress() {
self.progressIndicator.startAnimation(self)
}
func endProgress() {
self.progressIndicator.stopAnimation(self)
}
// MARK: - Private
private let emit: (Action) -> Void
private let disposeBag = DisposeBag()
private var flatFileItemsSource = Observable<[FileItem]>.empty()
private(set) var cwd = FileUtils.userHomeUrl
private var cwdPathCompsCount = 0
// FIXME: migrate to State later...
private(set) var pattern = ""
private(set) var flatFileItems = [FileItem]()
private(set) var fileViewItems = [ScoredFileItem]()
private var count = 0
private let searchStream: Observable<String>
private var perSessionDisposeBag = DisposeBag()
private let filterOpQueue = OperationQueue()
private var cwdPathCompsCount = 0
private var usesVcsIgnores = true
private var scanToken = Token()
private let scheduler = ConcurrentDispatchQueueScheduler(qos: .userInitiated)
private var searchServicePerRootUrl: [URL: FuzzySearchService] = [:]
private var currentSearchService: FuzzySearchService?
private let scoredUrlsController = NSArrayController()
private let windowController: NSWindowController
private let titleField = NSTextField.defaultTitleTextField()
private let useVcsIgnoresCheckBox = NSButton(forAutoLayout: ())
private let searchField = NSTextField(forAutoLayout: ())
private let progressIndicator = NSProgressIndicator(forAutoLayout: ())
private let cwdControl = NSPathControl(forAutoLayout: ())
private let countField = NSTextField(forAutoLayout: ())
private let fileView = NSTableView.standardTableView()
private let searchStream: Observable<String>
private let log = OSLog(subsystem: Defs.loggerSubsystem,
category: Defs.LoggerCategory.uiComponents)
private var window: NSWindow {
return self.windowController.window!
private var window: NSWindow { self.windowController.window! }
private func configureWindow() {
[
NSWindow.ButtonType.closeButton,
NSWindow.ButtonType.miniaturizeButton,
NSWindow.ButtonType.zoomButton,
].forEach { self.window.standardWindowButton($0)?.isHidden = true }
self.window.delegate = self
}
private func resetAndAddFilterOperation() {
self.filterOpQueue.cancelAllOperations()
let op = OpenQuicklyFilterOperation(forOpenQuickly: self)
self.filterOpQueue.addOperation(op)
private func subscription(_ state: StateType) {
self.updateRootUrls(state: state)
guard state.openQuickly.open, let curWinState = state.currentMainWindow else {
self.windowController.close()
return
}
let windowIsOpen = self.window.isKeyWindow
// The window is open and the user changed the setting
if self.usesVcsIgnores != curWinState.usesVcsIgnores && windowIsOpen {
self.usesVcsIgnores = curWinState.usesVcsIgnores
self.useVcsIgnoresCheckBox.boolState = curWinState.usesVcsIgnores
self.scanToken = Token()
self.currentSearchService?.usesVcsIgnores = self.usesVcsIgnores
self.unsortedScoredUrls.removeAll()
let pattern = self.searchField.stringValue
if pattern.count >= 2 { self.scanAndScore(pattern) }
return
}
// already open, so do nothing
if windowIsOpen { return }
self.usesVcsIgnores = curWinState.usesVcsIgnores
// TODO: read global vcs ignores
self.prepareSearch(curWinState: curWinState)
self.windowController.showWindow(nil)
self.searchField.beFirstResponder()
}
private func prepareSearch(curWinState: MainWindow.State) {
self.usesVcsIgnores = curWinState.usesVcsIgnores
self.useVcsIgnoresCheckBox.boolState = curWinState.usesVcsIgnores
let cwd = curWinState.cwd
self.currentSearchService = self.searchServicePerRootUrl[cwd]
self.cwdPathCompsCount = cwd.pathComponents.count
self.cwdControl.url = cwd
self.searchStream
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] pattern in
self?.scanAndScore(pattern)
})
.disposed(by: self.perSessionDisposeBag)
}
private func reset() {
self.scanToken = Token()
self.currentSearchService?.stopScanScore()
self.endProgress()
self.unsortedScoredUrls.removeAll()
self.searchField.stringValue = ""
self.perSessionDisposeBag = DisposeBag()
}
private func scanAndScore(_ pattern: String) {
self.currentSearchService?.stopScanScore()
guard pattern.count >= 2 else {
self.unsortedScoredUrls.removeAll()
return
}
self.scanToken = Token()
let localToken = self.scanToken
self.unsortedScoredUrls.removeAll()
self.currentSearchService?.scanScore(
for: pattern,
beginCallback: { self.startProgress() },
endCallback: { self.endProgress() }
) { scoredUrls in
DispatchQueue.main.async {
guard localToken == self.scanToken else { return }
self.unsortedScoredUrls.append(contentsOf: scoredUrls)
}
}
}
private func startProgress() { self.progressIndicator.startAnimation(self) }
private func endProgress() { self.progressIndicator.stopAnimation(self) }
private func updateRootUrls(state: AppState) {
let urlsToMonitor = Set(state.mainWindows.map { $1.cwd })
let currentUrls = Set(self.searchServicePerRootUrl.map { url, _ in url })
let newUrls = urlsToMonitor.subtracting(currentUrls)
let obsoleteUrls = currentUrls.subtracting(urlsToMonitor)
newUrls.forEach { url in
self.log.info("Adding \(url) and its service.")
guard let service = try? FuzzySearchService(root: url) else {
self.log.error("Could not create FileService for \(url)")
return
}
self.searchServicePerRootUrl[url] = service
}
obsoleteUrls.forEach { url in
self.log.info("Removing \(url) and its service.")
self.searchServicePerRootUrl.removeValue(forKey: url)
}
}
private func addViews() {
let useVcsIg = self.useVcsIgnoresCheckBox
useVcsIg.setButtonType(.switch)
useVcsIg.controlSize = .mini
useVcsIg.title = "Use VCS Ignores"
useVcsIg.target = self
useVcsIg.action = #selector(OpenQuicklyWindow.useVcsAction)
let title = self.titleField
title.font = .boldSystemFont(ofSize: 11)
title.stringValue = "Open Quickly"
let searchField = self.searchField
searchField.rx.delegate.setForwardToDelegate(self, retainDelegate: false)
@ -161,7 +233,17 @@ class OpenQuicklyWindow: NSObject,
let fileView = self.fileView
fileView.intercellSpacing = CGSize(width: 4, height: 4)
fileView.dataSource = self
let c = self.scoredUrlsController
c.avoidsEmptySelection = false
c.preservesSelection = true
c.objectClass = ScoredUrl.self
c.sortDescriptors = [NSSortDescriptor(key: "score", ascending: false)]
c.automaticallyRearrangesObjects = true
c.bind(.contentArray, to: self, withKeyPath: "unsortedScoredUrls")
fileView.bind(.content, to: c, withKeyPath: "arrangedObjects")
fileView.bind(.selectionIndexes, to: c, withKeyPath: "selectionIndexes")
fileView.delegate = self
let fileScrollView = NSScrollView.standardScrollView()
@ -176,26 +258,23 @@ class OpenQuicklyWindow: NSObject,
cwdControl.cell?.font = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
cwdControl.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
let countField = self.countField
countField.isEditable = false
countField.isBordered = false
countField.alignment = .right
countField.backgroundColor = NSColor.clear
countField.stringValue = "0 items"
let contentView = self.window.contentView!
contentView.addSubview(title)
contentView.addSubview(useVcsIg)
contentView.addSubview(searchField)
contentView.addSubview(progressIndicator)
contentView.addSubview(fileScrollView)
contentView.addSubview(cwdControl)
contentView.addSubview(countField)
searchField.autoPinEdge(toSuperviewEdge: .top, withInset: 8)
searchField.autoPinEdge(toSuperviewEdge: .right, withInset: 8)
searchField.autoPinEdge(toSuperviewEdge: .left, withInset: 8)
title.autoPinEdge(toSuperviewEdge: .left, withInset: 8)
title.autoPinEdge(toSuperviewEdge: .top, withInset: 8)
progressIndicator.autoAlignAxis(.horizontal, toSameAxisOf: searchField)
progressIndicator.autoPinEdge(.right, to: .right, of: searchField, withOffset: -4)
useVcsIg.autoAlignAxis(.horizontal, toSameAxisOf: title)
useVcsIg.autoPinEdge(toSuperviewEdge: .right, withInset: 8)
searchField.autoPinEdge(.top, to: .bottom, of: useVcsIg, withOffset: 8)
searchField.autoPinEdge(.left, to: .left, of: title)
searchField.autoPinEdge(.right, to: .right, of: useVcsIg)
fileScrollView.autoPinEdge(.top, to: .bottom, of: searchField, withOffset: 8)
fileScrollView.autoPinEdge(toSuperviewEdge: .left, withInset: -1)
@ -203,23 +282,12 @@ class OpenQuicklyWindow: NSObject,
fileScrollView.autoSetDimension(.height, toSize: 200, relation: .greaterThanOrEqual)
cwdControl.autoPinEdge(.top, to: .bottom, of: fileScrollView, withOffset: 4)
// cwdControl.autoPinEdge(toSuperviewEdge: .bottom)
cwdControl.autoPinEdge(toSuperviewEdge: .left, withInset: 2)
cwdControl.autoPinEdge(toSuperviewEdge: .bottom, withInset: 4)
// countField.autoPinEdge(toSuperviewEdge: .bottom)
countField.autoPinEdge(.top, to: .bottom, of: fileScrollView, withOffset: 4)
countField.autoPinEdge(toSuperviewEdge: .right, withInset: 2)
countField.autoPinEdge(.left, to: .right, of: cwdControl, withOffset: 4)
}
}
// MARK: - NSTableViewDataSource
extension OpenQuicklyWindow {
@objc(numberOfRowsInTableView:)
func numberOfRows(in _: NSTableView) -> Int {
return self.fileViewItems.count
progressIndicator.autoAlignAxis(.horizontal, toSameAxisOf: cwdControl)
progressIndicator.autoPinEdge(.left, to: .right, of: cwdControl, withOffset: 4)
progressIndicator.autoPinEdge(toSuperviewEdge: .right, withInset: 8)
}
}
@ -230,14 +298,21 @@ extension OpenQuicklyWindow {
return OpenQuicklyFileViewRow()
}
@objc(tableView: viewForTableColumn:row:)
func tableView(_ tableView: NSTableView, viewFor _: NSTableColumn?, row: Int) -> NSView? {
let cachedCell = (tableView.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("file-view-row"), owner: self) as? ImageAndTextTableCell
let cachedCell = (
tableView.makeView(
withIdentifier: NSUserInterfaceItemIdentifier("file-view-row"),
owner: self
) as? ImageAndTextTableCell
)?.reset()
let cell = cachedCell ?? ImageAndTextTableCell(withIdentifier: "file-view-row")
let url = self.fileViewItems[row].url
guard let sortedUrls = self.scoredUrlsController.arrangedObjects as? Array<ScoredUrl> else {
self.log.error("Could not convert arranged objects to [ScoredUrl].")
return nil
}
let url = sortedUrls[row].url
cell.attributedText = self.rowText(for: url as URL)
cell.image = FileUtils.icon(forUrl: url)
@ -249,9 +324,7 @@ extension OpenQuicklyWindow {
let truncatedPathComps = pathComps[self.cwdPathCompsCount..<pathComps.count]
let name = truncatedPathComps.last!
if truncatedPathComps.dropLast().isEmpty {
return NSMutableAttributedString(string: name)
}
if truncatedPathComps.dropLast().isEmpty { return NSMutableAttributedString(string: name) }
let rowText: NSMutableAttributedString
let pathInfo = truncatedPathComps.dropLast().reversed().joined(separator: " / ")
@ -267,16 +340,24 @@ extension OpenQuicklyWindow {
// MARK: - NSTextFieldDelegate
extension OpenQuicklyWindow {
@objc(control: textView:doCommandBySelector:)
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
func control(
_ control: NSControl,
textView: NSTextView,
doCommandBy commandSelector: Selector
) -> Bool {
switch commandSelector {
case NSSelectorFromString("cancelOperation:"):
self.window.performClose(self)
return true
case NSSelectorFromString("insertNewline:"):
// TODO open the url
self.emit(.open(self.fileViewItems[self.fileView.selectedRow].url))
guard let sortedUrls = self.scoredUrlsController.arrangedObjects as? Array<ScoredUrl> else {
self.log.error("Could not convert arranged objects to [ScoredUrl].")
return true
}
self.emit(.open(sortedUrls[self.fileView.selectedRow].url))
self.window.performClose(self)
return true
@ -290,6 +371,7 @@ extension OpenQuicklyWindow {
default:
return false
}
}
@ -320,25 +402,7 @@ extension OpenQuicklyWindow {
return false
}
func windowWillClose(_: Notification) {
self.endProgress()
func windowWillClose(_: Notification) { self.reset() }
self.filterOpQueue.cancelAllOperations()
self.perSessionDisposeBag = DisposeBag()
self.pauseScan = false
self.count = 0
self.pattern = ""
self.flatFileItems = []
self.fileViewItems = []
self.fileView.reloadData()
self.searchField.stringValue = ""
self.countField.stringValue = "0 items"
}
func windowDidResignKey(_: Notification) {
self.window.performClose(self)
}
func windowDidResignKey(_: Notification) { self.window.performClose(self) }
}

View File

@ -29,7 +29,7 @@ class PrefPane: NSView {
extension PrefPane {
func paneTitleTextField(title: String) -> NSTextField {
let field = defaultTitleTextField()
let field = NSTextField.defaultTitleTextField()
field.font = NSFont.boldSystemFont(ofSize: 16)
field.alignment = .left;
field.stringValue = title
@ -37,7 +37,7 @@ extension PrefPane {
}
func titleTextField(title: String) -> NSTextField {
let field = defaultTitleTextField()
let field = NSTextField.defaultTitleTextField()
field.alignment = .right;
field.stringValue = title
return field
@ -65,12 +65,4 @@ extension PrefPane {
button.target = self
button.action = action
}
private func defaultTitleTextField() -> NSTextField {
let field = NSTextField(forAutoLayout: ())
field.backgroundColor = NSColor.clear;
field.isEditable = false;
field.isBordered = false;
return field
}
}

View File

@ -8,34 +8,6 @@ import NvimView
class PrefUtils {
private static let whitespaceCharSet = CharacterSet.whitespaces
static func ignorePatterns(fromString str: String) -> Set<FileItemIgnorePattern> {
if str.trimmingCharacters(in: self.whitespaceCharSet).count == 0 {
return Set()
}
let patterns: [FileItemIgnorePattern] = str
.components(separatedBy: ",")
.compactMap {
let trimmed = $0.trimmingCharacters(in: self.whitespaceCharSet)
if trimmed.count == 0 {
return nil
}
return FileItemIgnorePattern(pattern: trimmed)
}
return Set(patterns)
}
static func ignorePatternString(fromSet set: Set<FileItemIgnorePattern>) -> String {
return Array(set)
.map { $0.pattern }
.sorted()
.joined(separator: ", ")
}
static func value<T>(from dict: [String: Any], for key: String) -> T? {
return dict[key] as? T
}

View File

@ -1,25 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import RxSwift
class ScoredFileItem: Comparable {
let score: Int
let url: URL
init(score: Int, url: URL) {
self.score = score
self.url = url
}
}
func == (left: ScoredFileItem, right: ScoredFileItem) -> Bool {
return left.score == right.score
}
func <(left: ScoredFileItem, right: ScoredFileItem) -> Bool {
return left.score < right.score
}

23
VimR/VimR/ScoredUrl.h Normal file
View File

@ -0,0 +1,23 @@
//
// Created by Tae Won Ha on 05.01.20.
// Copyright (c) 2020 Tae Won Ha. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface ScoredUrl : NSObject
@property (readonly, nonnull) NSURL *url;
@property (readonly) NSInteger score;
- (BOOL)isEqual:(id _Nullable)other;
- (BOOL)isEqualToUrl:(ScoredUrl * _Nullable)url;
- (NSUInteger)hash;
- (instancetype _Nonnull)initWithUrl:(NSURL * _Nonnull)url score:(NSInteger)score;
- (NSString * _Nonnull)description;
+ (instancetype _Nonnull)urlWithUrl:(NSURL * _Nonnull)url score:(NSInteger)score;
@end

62
VimR/VimR/ScoredUrl.m Normal file
View File

@ -0,0 +1,62 @@
//
// Created by Tae Won Ha on 05.01.20.
// Copyright (c) 2020 Tae Won Ha. All rights reserved.
//
#import "ScoredUrl.h"
@implementation ScoredUrl {
}
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![[other class] isEqual:[self class]])
return NO;
return [self isEqualToUrl:other];
}
- (BOOL)isEqualToUrl:(ScoredUrl *)url {
if (self == url)
return YES;
if (url == nil)
return NO;
if (self.url != url.url && ![self.url isEqual:url.url])
return NO;
if (self.score != url.score)
return NO;
return YES;
}
- (NSUInteger)hash {
NSUInteger hash = [self.url hash];
hash = hash * 31u + self.score;
return hash;
}
- (NSString *)description {
NSMutableString *description
= [NSMutableString stringWithFormat:@"<%@: ", NSStringFromClass([self class])];
[description appendFormat:@"self.url=%@", self.url.path];
[description appendFormat:@", self.score=%li", self.score];
[description appendString:@">"];
return description;
}
- (instancetype)initWithUrl:(NSURL *)url score:(NSInteger)score {
self = [super init];
if (!self) {return nil;}
_url = url;
_score = score;
return self;
}
+ (instancetype)urlWithUrl:(NSURL *)url score:(NSInteger)score {
return [[self alloc] initWithUrl:url score:score];
}
@end

View File

@ -1,31 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
class Scorer {
static func score(_ target: String, pattern: String) -> Int {
let fuzzy = Matcher.fuzzyIgnoringCase(target, pattern: pattern)
let upper = Matcher.numberOfUppercaseMatches(target, pattern: pattern)
let exactMatch = Matcher.exactMatchIgnoringCase(target, pattern: pattern)
let wf = Matcher.wagnerFisherDistance(target, pattern: pattern)
let exactScore: Int
switch exactMatch {
case .none:
exactScore = 0
case .exact:
return 1000
case .prefix, .contains, .suffix:
exactScore = 5
}
return exactScore
+ 10 * fuzzy
+ 5 * upper
- wf
}
}

View File

@ -41,6 +41,10 @@ struct AppState: Codable {
var currentMainWindowUuid: UUID?
var mainWindows: [UUID: MainWindow.State] = [:]
var currentMainWindow: MainWindow.State? {
guard let uuid = self.currentMainWindowUuid else { return nil }
return self.mainWindows[uuid]
}
var openQuickly = OpenQuicklyWindow.State.default
@ -73,34 +77,27 @@ extension OpenQuicklyWindow {
struct State: Codable {
static let `default` = State()
static let defaultIgnorePatterns = Set(["*/.git", "*.o", "*.d", "*.dia"].map(FileItemIgnorePattern.init))
enum CodingKeys: String, CodingKey {
case ignorePatterns = "ignore-patterns"
case defaultUsesVcsIgnore = "default-uses-vcs-ignores"
}
let root = FileItem(URL(fileURLWithPath: "/", isDirectory: true))
var flatFileItems = Observable<[FileItem]>.empty()
var cwd = FileUtils.userHomeUrl
var ignorePatterns = State.defaultIgnorePatterns
var ignoreToken = Token()
var defaultUsesVcsIgnores = true
var open = false
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let patternsAsString = try container.decodeIfPresent(String.self, forKey: .ignorePatterns) {
self.ignorePatterns = FileItemIgnorePattern.from(string: patternsAsString)
} else {
self.ignorePatterns = State.defaultIgnorePatterns
}
self.defaultUsesVcsIgnores = try container.decode(
forKey: .defaultUsesVcsIgnore,
default: OpenQuicklyWindow.State.default.defaultUsesVcsIgnores
)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(FileItemIgnorePattern.toString(self.ignorePatterns), forKey: .ignorePatterns)
try container.encode(self.defaultUsesVcsIgnores, forKey: .defaultUsesVcsIgnore)
}
private init() {
@ -285,6 +282,8 @@ extension MainWindow {
var cliPipePath: String?
var envDict: [String: String]?
var usesVcsIgnores = true
var isLeftOptionMeta = false
var isRightOptionMeta = false

View File

@ -24,12 +24,8 @@ class UiRoot: UiComponent {
self.emitter = emitter
self.emit = emitter.typedEmit()
self.fileMonitor = FileMonitor(source: source,
emitter: emitter,
state: state)
self.openQuicklyWindow = OpenQuicklyWindow(source: source,
emitter: emitter,
state: state)
self.fileMonitor = FileMonitor(source: source, emitter: emitter, state: state)
self.openQuicklyWindow = OpenQuicklyWindow(source: source, emitter: emitter, state: state)
self.prefWindow = PrefWindow(source: source, emitter: emitter, state: state)
source
@ -80,6 +76,7 @@ class UiRoot: UiComponent {
.wait()
self.mainWindows.values.forEach { $0.waitTillNvimExits() }
self.openQuicklyWindow.cleanUp()
}
private let source: Observable<AppState>

View File

@ -1,65 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import XCTest
import Nimble
@testable import VimR
class FileItemIgnorePatternTest: XCTestCase {
var pattern: FileItemIgnorePattern = FileItemIgnorePattern(pattern: "dummy")
func testMatchFolder() {
pattern = FileItemIgnorePattern(pattern: "*/.git")
expect(self.pattern.match(absolutePath: "/a/b/c/.git")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/.git/d")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/.git/d/e")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/.gitfolder/d")).to(equal(false))
expect(self.pattern.match(absolutePath: "/a/b/c/1.git/d")).to(equal(false))
expect(self.pattern.match(absolutePath: ".git")).to(equal(false))
expect(self.pattern.match(absolutePath: "/a/b/c/.hg/d")).to(equal(false))
}
func testMatchFolderMultipleWildCards() {
pattern = FileItemIgnorePattern(pattern: "*/*.xcodeproj")
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcodeproj")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcodeproj/somefile")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcodeproj/somefile/deep")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcworkspace/somefile")).to(equal(false))
}
func testMatchSuffix() {
pattern = FileItemIgnorePattern(pattern: "*.png")
expect(self.pattern.match(absolutePath: "/a/b/c/d.png")).to(equal(true))
expect(self.pattern.match(absolutePath: "a.png")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/d.pnge")).to(equal(false))
expect(self.pattern.match(absolutePath: "/a/b/c/d.png/e")).to(equal(false))
}
func testMatchPrefix() {
pattern = FileItemIgnorePattern(pattern: "vr*")
expect(self.pattern.match(absolutePath: "/a/b/c/vr.png")).to(equal(true))
expect(self.pattern.match(absolutePath: "vr.png")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/wvr.png")).to(equal(false))
expect(self.pattern.match(absolutePath: "/a/b/c/wvr.png/e")).to(equal(false))
}
func testMatchExact() {
pattern = FileItemIgnorePattern(pattern: "some")
expect(self.pattern.match(absolutePath: "/a/b/c/some")).to(equal(true))
expect(self.pattern.match(absolutePath: "some")).to(equal(true))
expect(self.pattern.match(absolutePath: "/a/b/c/some1")).to(equal(false))
expect(self.pattern.match(absolutePath: "/a/b/c/1some")).to(equal(false))
}
}

View File

@ -1,42 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import XCTest
import Nimble
class MatcherTest: XCTestCase {
let target = "UserDefaultContextTest.swift"
func testExactMatch() {
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "uSERdEFAULTcONTEXTtEST.SWIFT"))
.to(equal(Matcher.ExactMatchResult.exact))
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "uSERdEFAULt"))
.to(equal(Matcher.ExactMatchResult.prefix))
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "swIFt")).to(equal(Matcher.ExactMatchResult.suffix))
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "userdecon")).to(equal(Matcher.ExactMatchResult.none))
}
func testUppercaseMatcher() {
expect(Matcher.numberOfUppercaseMatches("SwiftNeoVimNeoVimView.swift", pattern: "swnvv")).to(equal(4))
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "xct")).to(equal(2))
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "uct")).to(equal(3))
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "uDcT")).to(equal(4))
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "dct")).to(equal(3))
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "ut")).to(equal(2))
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "de")).to(equal(1))
}
func testFuzzyMatcher() {
expect(Matcher.fuzzyIgnoringCase(self.target, pattern: "ucotft")).to(equal(6 + 5))
expect(Matcher.fuzzyIgnoringCase(self.target, pattern: "uco-tft")).to(equal(3 + 5))
}
func testWagerFischerAlgo() {
expect(Matcher.wagnerFisherDistance("sitting", pattern: "kitten")).to(equal(3))
expect(Matcher.wagnerFisherDistance("saturday", pattern: "sunday")).to(equal(3))
expect(Matcher.wagnerFisherDistance("하태원", pattern: "하태이")).to(equal(1))
}
}

View File

@ -1,32 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import XCTest
import Nimble
class ScorerTest: XCTestCase {
func testScore1() {
let pattern = "sw/nvv".replacingOccurrences(of: "/", with: "")
let targets = [
"SwiftNeoVim/NeoVimView.swift",
"build/Release/NeoVimServer.dSYM/Contents/Resources/DWARF/NeoVimServer",
].map { $0.replacingOccurrences(of: "/", with: "") }
expect(Scorer.score(targets[0], pattern: pattern)).to(beGreaterThan(Scorer.score(targets[1], pattern: pattern)))
}
func testScore2() {
let pattern = "nvv"
let targets = [
"NeoVimView.swift",
"NeoVimViewDelegate.swift",
"NeoVimAgent",
]
expect(Scorer.score(targets[0], pattern: pattern)).to(beGreaterThan(Scorer.score(targets[1], pattern: pattern)))
expect(Scorer.score(targets[1], pattern: pattern)).to(beGreaterThan(Scorer.score(targets[2], pattern: pattern)))
}
}

View File

@ -7,12 +7,104 @@ pushd "$(dirname "${BASH_SOURCE[0]}")/.." > /dev/null
readonly deployment_target_file="./resources/macos_deployment_target.txt"
readonly deployment_target=$(cat ${deployment_target_file})
readonly gettext_version="0.20.1"
readonly pcre_version="8.43"
readonly xz_version="5.2.4"
readonly ag_version="2.2.0"
build_ag () {
pushd .deps > /dev/null
curl -L -o ag.tar.gz https://github.com/ggreer/the_silver_searcher/archive/${ag_version}.tar.gz
tar xf ag.tar.gz
mv the_silver_searcher-${ag_version} ag
pushd ag > /dev/null
./autogen.sh
xz_include=$(pwd)/../../third-party/libxz/include
pcre_include=$(pwd)/../../third-party/libpcre/include
./configure CFLAGS="-mmacosx-version-min=${deployment_target} -I${xz_include} -I${pcre_include}" \
LDFLAGS="-L$(pwd)/../../third-party/libxz/lib -L$(pwd)/../../third-party/libpcre/lib" \
MACOSX_DEPLOYMENT_TARGET=${deployment_target}
pushd src > /dev/null
cc -c ignore.c log.c options.c print.c scandir.c search.c lang.c util.c decompress.c zfile.c
ar -crs libag.a ignore.o log.o options.o print.o scandir.o search.o lang.o util.o decompress.o zfile.o
mkdir -p $(pwd)/../../../third-party/libag/lib
mv libag.a $(pwd)/../../../third-party/libag/lib
mkdir -p $(pwd)/../../../third-party/libag/include
cp *.h $(pwd)/../../../third-party/libag/include
popd > /dev/null
popd > /dev/null
popd > /dev/null
}
build_xz () {
pushd .deps > /dev/null
curl -L -o xz.tar.gz https://tukaani.org/xz/xz-${xz_version}.tar.gz
tar xf xz.tar.gz
mv xz-${xz_version} xz
pushd xz > /dev/null
# configure from https://github.com/Homebrew/homebrew-core/blob/c9882801013d6bc5202b91ef56ff5838d18bbab2/Formula/xz.rb
./configure CFLAGS="-mmacosx-version-min=${deployment_target}" MACOSX_DEPLOYMENT_TARGET=${deployment_target} \
--disable-debug \
--disable-dependency-tracking \
--disable-silent-rules \
--prefix=$(pwd)/../../third-party/libxz
make
make install
rm -rf $(pwd)/../../third-party/libxz/bin
rm -rf $(pwd)/../../third-party/libxz/share
popd > /dev/null
popd > /dev/null
}
build_pcre () {
pushd .deps > /dev/null
curl -L -o pcre.tar.bz2 https://ftp.pcre.org/pub/pcre/pcre-${pcre_version}.tar.bz2
tar xf pcre.tar.bz2
mv pcre-${pcre_version} pcre
pushd pcre > /dev/null
# configure from https://github.com/Homebrew/homebrew-core/blob/c9882801013d6bc5202b91ef56ff5838d18bbab2/Formula/pcre.rb
./configure CFLAGS="-mmacosx-version-min=${deployment_target}" MACOSX_DEPLOYMENT_TARGET=${deployment_target} \
--disable-dependency-tracking \
--prefix=$(pwd)/../../third-party/libpcre \
--enable-utf8 \
--enable-pcre8 \
--enable-pcre16 \
--enable-pcre32 \
--enable-unicode-properties \
--enable-pcregrep-libz \
--enable-pcregrep-libbz2 \
--enable-jit
make
make install
rm -rf $(pwd)/../../third-party/libpcre/bin
rm -rf $(pwd)/../../third-party/libpcre/share
popd > /dev/null
popd > /dev/null
}
build_vimr_deps () {
rm -rf third-party
mkdir third-party
rm -rf .deps
mkdir .deps
build_pcre
build_xz
build_ag
}
build_gettext () {
pushd NvimView > /dev/null
mkdir -p third-party/libintl
rm -rf .deps
mkdir .deps
pushd .deps > /dev/null
curl -o gettext.tar.xz https://ftp.gnu.org/gnu/gettext/gettext-${gettext_version}.tar.xz
curl -L -o gettext.tar.xz https://ftp.gnu.org/gnu/gettext/gettext-${gettext_version}.tar.xz
tar xf gettext.tar.xz
mv gettext-${gettext_version} gettext
@ -52,3 +144,7 @@ popd > /dev/null
popd > /dev/null
echo "### Built deps"
}
build_gettext
build_vimr_deps

View File

@ -1,5 +1,8 @@
# 0.30.0-???
* Improve Open Quickly
- Use [The Silver Searcher](https://github.com/ggreer/the_silver_searcher)'s ignore mechanism
- Use [ccls](https://github.com/MaskRay/ccls)' fuzzy search
* Bugfix: Forward search in Markdown preview does not work.
* Dependencies updates:
- IBM-Swift/BlueSocket 1.0.52

120
third-party/libag/include/config.h vendored Normal file
View File

@ -0,0 +1,120 @@
/* src/config.h. Generated from config.h.in by configure. */
/* src/config.h.in. Generated from configure.ac by autoheader. */
/* Have dirent struct member d_namlen */
#define HAVE_DIRENT_DNAMLEN /**/
/* Have dirent struct member d_type */
#define HAVE_DIRENT_DTYPE /**/
/* Define to 1 if you have the <err.h> header file. */
#define HAVE_ERR_H 1
/* Define to 1 if you have the `fgetln' function. */
#define HAVE_FGETLN 1
/* Define to 1 if you have the `fopencookie' function. */
/* #undef HAVE_FOPENCOOKIE */
/* Define to 1 if you have the `getline' function. */
#define HAVE_GETLINE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `shlwapi' library (-lshlwapi). */
/* #undef HAVE_LIBSHLWAPI */
/* Define to 1 if you have the <lzma.h> header file. */
#define HAVE_LZMA_H 1
/* Define to 1 if you have the `madvise' function. */
#define HAVE_MADVISE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `pledge' function. */
/* #undef HAVE_PLEDGE */
/* Define to 1 if you have the `posix_fadvise' function. */
/* #undef HAVE_POSIX_FADVISE */
/* Define to 1 if you have the <pthread.h> header file. */
#define HAVE_PTHREAD_H 1
/* Have PTHREAD_PRIO_INHERIT. */
#define HAVE_PTHREAD_PRIO_INHERIT 1
/* Define to 1 if you have the `pthread_setaffinity_np' function. */
/* #undef HAVE_PTHREAD_SETAFFINITY_NP */
/* Define to 1 if you have the `realpath' function. */
#define HAVE_REALPATH 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strlcpy' function. */
#define HAVE_STRLCPY 1
/* Define to 1 if you have the `strndup' function. */
#define HAVE_STRNDUP 1
/* Define to 1 if you have the <sys/cpuset.h> header file. */
/* #undef HAVE_SYS_CPUSET_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `vasprintf' function. */
#define HAVE_VASPRINTF 1
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "https://github.com/ggreer/the_silver_searcher/issues"
/* Define to the full name of this package. */
#define PACKAGE_NAME "the_silver_searcher"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "the_silver_searcher 2.2.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "the_silver_searcher"
/* Define to the home page for this package. */
#define PACKAGE_URL "https://github.com/ggreer/the_silver_searcher"
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.2.0"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Use CPU_SET macros */
/* #undef USE_CPU_SET */
/* Use PCRE JIT */
#define USE_PCRE_JIT /**/

26
third-party/libag/include/decompress.h vendored Normal file
View File

@ -0,0 +1,26 @@
#ifndef DECOMPRESS_H
#define DECOMPRESS_H
#include <stdio.h>
#include "config.h"
#include "log.h"
#include "options.h"
typedef enum {
AG_NO_COMPRESSION,
AG_GZIP,
AG_COMPRESS,
AG_ZIP,
AG_XZ,
} ag_compression_type;
ag_compression_type is_zipped(const void *buf, const int buf_len);
void *decompress(const ag_compression_type zip_type, const void *buf, const int buf_len, const char *dir_full_path, int *new_buf_len);
#if HAVE_FOPENCOOKIE
FILE *decompress_open(int fd, const char *mode, ag_compression_type ctype);
#endif
#endif

48
third-party/libag/include/ignore.h vendored Normal file
View File

@ -0,0 +1,48 @@
#ifndef IGNORE_H
#define IGNORE_H
#include <dirent.h>
#include <sys/types.h>
struct ignores {
char **extensions; /* File extensions to ignore */
size_t extensions_len;
char **names; /* Non-regex ignore lines. Sorted so we can binary search them. */
size_t names_len;
char **slash_names; /* Same but starts with a slash */
size_t slash_names_len;
char **regexes; /* For patterns that need fnmatch */
size_t regexes_len;
char **invert_regexes; /* For "!" patterns */
size_t invert_regexes_len;
char **slash_regexes;
size_t slash_regexes_len;
const char *dirname;
size_t dirname_len;
char *abs_path;
size_t abs_path_len;
struct ignores *parent;
};
typedef struct ignores ignores;
ignores *root_ignores;
extern const char *evil_hardcoded_ignore_files[];
extern const char *ignore_pattern_files[];
ignores *init_ignore(ignores *parent, const char *dirname, const size_t dirname_len);
void cleanup_ignore(ignores *ig);
void add_ignore_pattern(ignores *ig, const char *pattern);
void load_ignore_patterns(ignores *ig, const char *path);
int filename_filter(const char *path, const struct dirent *dir, void *baton);
int is_empty(ignores *ig);
#endif

36
third-party/libag/include/lang.h vendored Normal file
View File

@ -0,0 +1,36 @@
#ifndef LANG_H
#define LANG_H
#define MAX_EXTENSIONS 12
#define SINGLE_EXT_LEN 20
typedef struct {
const char *name;
const char *extensions[MAX_EXTENSIONS];
} lang_spec_t;
extern lang_spec_t langs[];
/**
Return the language count.
*/
size_t get_lang_count(void);
/**
Convert a NULL-terminated array of language extensions
into a regular expression of the form \.(extension1|extension2...)$
Caller is responsible for freeing the returned string.
*/
char *make_lang_regex(char *ext_array, size_t num_exts);
/**
Combine multiple file type extensions into one array.
The combined result is returned through *exts*;
*exts* is one-dimension array, which can contain up to 100 extensions;
The number of extensions that *exts* actually contain is returned.
*/
size_t combine_file_extensions(size_t *extension_index, size_t len, char **exts);
#endif

32
third-party/libag/include/log.h vendored Normal file
View File

@ -0,0 +1,32 @@
#ifndef LOG_H
#define LOG_H
#include <stdarg.h>
#include "config.h"
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
pthread_mutex_t print_mtx;
enum log_level {
LOG_LEVEL_DEBUG = 10,
LOG_LEVEL_MSG = 20,
LOG_LEVEL_WARN = 30,
LOG_LEVEL_ERR = 40,
LOG_LEVEL_NONE = 100
};
void set_log_level(enum log_level threshold);
void log_debug(const char *fmt, ...);
void log_msg(const char *fmt, ...);
void log_warn(const char *fmt, ...);
void log_err(const char *fmt, ...);
void vplog(const unsigned int level, const char *fmt, va_list args);
void plog(const unsigned int level, const char *fmt, ...);
#endif

105
third-party/libag/include/options.h vendored Normal file
View File

@ -0,0 +1,105 @@
#ifndef OPTIONS_H
#define OPTIONS_H
#include <getopt.h>
#include <sys/stat.h>
#include <pcre.h>
#define DEFAULT_AFTER_LEN 2
#define DEFAULT_BEFORE_LEN 2
#define DEFAULT_CONTEXT_LEN 2
#define DEFAULT_MAX_SEARCH_DEPTH 25
enum case_behavior {
CASE_DEFAULT, /* Changes to CASE_SMART at the end of option parsing */
CASE_SENSITIVE,
CASE_INSENSITIVE,
CASE_SMART,
CASE_SENSITIVE_RETRY_INSENSITIVE /* for future use */
};
enum path_print_behavior {
PATH_PRINT_DEFAULT, /* PRINT_TOP if > 1 file being searched, else PRINT_NOTHING */
PATH_PRINT_DEFAULT_EACH_LINE, /* PRINT_EACH_LINE if > 1 file being searched, else PRINT_NOTHING */
PATH_PRINT_TOP,
PATH_PRINT_EACH_LINE,
PATH_PRINT_NOTHING
};
typedef struct {
int ackmate;
pcre *ackmate_dir_filter;
pcre_extra *ackmate_dir_filter_extra;
size_t after;
size_t before;
enum case_behavior casing;
const char *file_search_string;
int match_files;
pcre *file_search_regex;
pcre_extra *file_search_regex_extra;
int color;
char *color_line_number;
char *color_match;
char *color_path;
int color_win_ansi;
int column;
int context;
int follow_symlinks;
int invert_match;
int literal;
int literal_starts_wordchar;
int literal_ends_wordchar;
size_t max_matches_per_file;
int max_search_depth;
int mmap;
int multiline;
int one_dev;
int only_matching;
char path_sep;
int path_to_ignore;
int print_break;
int print_count;
int print_filename_only;
int print_path;
int print_all_paths;
int print_line_numbers;
int print_long_lines; /* TODO: support this in print.c */
int passthrough;
pcre *re;
pcre_extra *re_extra;
int recurse_dirs;
int search_all_files;
int skip_vcs_ignores;
int search_binary_files;
int search_zip_files;
int search_hidden_files;
int search_stream; /* true if tail -F blah | ag */
int stats;
size_t stream_line_num; /* This should totally not be in here */
int match_found; /* This should totally not be in here */
ino_t stdout_inode;
char *query;
int query_len;
char *pager;
int paths_len;
int parallel;
int use_thread_affinity;
int vimgrep;
size_t width;
int word_regexp;
int workers;
} cli_options;
/* global options. parse_options gives it sane values, everything else reads from it */
cli_options opts;
typedef struct option option_t;
void usage(void);
void print_version(void);
void init_options(void);
void parse_options(int argc, char **argv, char **base_paths[], char **paths[]);
void cleanup_options(void);
#endif

26
third-party/libag/include/print.h vendored Normal file
View File

@ -0,0 +1,26 @@
#ifndef PRINT_H
#define PRINT_H
#include "util.h"
void print_init_context(void);
void print_cleanup_context(void);
void print_context_append(const char *line, size_t len);
void print_trailing_context(const char *path, const char *buf, size_t n);
void print_path(const char *path, const char sep);
void print_path_count(const char *path, const char sep, const size_t count);
void print_line(const char *buf, size_t buf_pos, size_t prev_line_offset);
void print_binary_file_matches(const char *path);
void print_file_matches(const char *path, const char *buf, const size_t buf_len, const match_t matches[], const size_t matches_len);
void print_line_number(size_t line, const char sep);
void print_column_number(const match_t matches[], size_t last_printed_match,
size_t prev_line_offset, const char sep);
void print_file_separator(void);
const char *normalize_path(const char *path);
#ifdef _WIN32
void windows_use_ansi(int use_ansi);
int fprintf_w32(FILE *fp, const char *format, ...);
#endif
#endif

20
third-party/libag/include/scandir.h vendored Normal file
View File

@ -0,0 +1,20 @@
#ifndef SCANDIR_H
#define SCANDIR_H
#include "ignore.h"
typedef struct {
const ignores *ig;
const char *base_path;
size_t base_path_len;
const char *path_start;
} scandir_baton_t;
typedef int (*filter_fp)(const char *path, const struct dirent *, void *);
int ag_scandir(const char *dirname,
struct dirent ***namelist,
filter_fp filter,
void *baton);
#endif

78
third-party/libag/include/search.h vendored Normal file
View File

@ -0,0 +1,78 @@
#ifndef SEARCH_H
#define SEARCH_H
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pcre.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#endif
#include <sys/stat.h>
#include <unistd.h>
#include "config.h"
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#include "decompress.h"
#include "ignore.h"
#include "log.h"
#include "options.h"
#include "print.h"
#include "uthash.h"
#include "util.h"
size_t alpha_skip_lookup[256];
size_t *find_skip_lookup;
uint8_t h_table[H_SIZE] __attribute__((aligned(64)));
struct work_queue_t {
char *path;
struct work_queue_t *next;
};
typedef struct work_queue_t work_queue_t;
work_queue_t *work_queue;
work_queue_t *work_queue_tail;
int done_adding_files;
pthread_cond_t files_ready;
pthread_mutex_t stats_mtx;
pthread_mutex_t work_queue_mtx;
/* For symlink loop detection */
#define SYMLOOP_ERROR (-1)
#define SYMLOOP_OK (0)
#define SYMLOOP_LOOP (1)
typedef struct {
dev_t dev;
ino_t ino;
} dirkey_t;
typedef struct {
dirkey_t key;
UT_hash_handle hh;
} symdir_t;
symdir_t *symhash;
void search_buf(const char *buf, const size_t buf_len,
const char *dir_full_path);
void search_stream(FILE *stream, const char *path);
void search_file(const char *file_full_path);
void *search_file_worker(void *i);
void search_dir(ignores *ig, const char *base_path, const char *path, const int depth, dev_t original_dev);
#endif

971
third-party/libag/include/uthash.h vendored Normal file
View File

@ -0,0 +1,971 @@
/*
Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
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.
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.
*/
#ifndef UTHASH_H
#define UTHASH_H
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit() */
#include <string.h> /* memcmp,strlen */
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#if defined(_MSC_VER) /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
#define DECLTYPE(x) (decltype(x))
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define DECLTYPE(x)
#endif
#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
#define NO_DECLTYPE
#define DECLTYPE(x)
#else /* GNU, Sun and other compilers */
#define DECLTYPE(x) (__typeof(x))
#endif
#ifdef NO_DECLTYPE
#define DECLTYPE_ASSIGN(dst, src) \
do { \
char **_da_dst = (char **)(&(dst)); \
*_da_dst = (char *)(src); \
} while (0)
#else
#define DECLTYPE_ASSIGN(dst, src) \
do { \
(dst) = DECLTYPE(dst)(src); \
} while (0)
#endif
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
#if defined(_WIN32)
#if defined(_MSC_VER) && _MSC_VER >= 1600
#include <stdint.h>
#elif defined(__WATCOMC__)
#include <stdint.h>
#else
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#endif
#else
#include <stdint.h>
#endif
#define UTHASH_VERSION 1.9.9
#ifndef uthash_fatal
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
#endif
#ifndef uthash_malloc
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#endif
#ifndef uthash_free
#define uthash_free(ptr, sz) free(ptr) /* free fcn */
#endif
#ifndef uthash_noexpand_fyi
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
#endif
#ifndef uthash_expand_fyi
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
#endif
/* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
/* calculate the element whose hash handle address is hhe */
#define ELMT_FROM_HH(tbl, hhp) ((void *)(((char *)(hhp)) - ((tbl)->hho)))
#define HASH_FIND(hh, head, keyptr, keylen, out) \
do { \
unsigned _hf_bkt, _hf_hashv; \
out = NULL; \
if (head) { \
HASH_FCN(keyptr, keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[_hf_bkt], keyptr, keylen, out); \
} \
} \
} while (0)
#ifdef HASH_BLOOM
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN / 8) + ((HASH_BLOOM_BITLEN % 8) ? 1 : 0)
#define HASH_BLOOM_MAKE(tbl) \
do { \
(tbl)->bloom_nbits = HASH_BLOOM; \
(tbl)->bloom_bv = (uint8_t *)uthash_malloc(HASH_BLOOM_BYTELEN); \
if (!((tbl)->bloom_bv)) { \
uthash_fatal("out of memory"); \
} \
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
} while (0)
#define HASH_BLOOM_FREE(tbl) \
do { \
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
} while (0)
#define HASH_BLOOM_BITSET(bv, idx) (bv[(idx) / 8] |= (1U << ((idx) % 8)))
#define HASH_BLOOM_BITTEST(bv, idx) (bv[(idx) / 8] & (1U << ((idx) % 8)))
#define HASH_BLOOM_ADD(tbl, hashv) \
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#define HASH_BLOOM_TEST(tbl, hashv) \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
#define HASH_BLOOM_MAKE(tbl)
#define HASH_BLOOM_FREE(tbl)
#define HASH_BLOOM_ADD(tbl, hashv)
#define HASH_BLOOM_TEST(tbl, hashv) (1)
#define HASH_BLOOM_BYTELEN 0
#endif
#define HASH_MAKE_TABLE(hh, head) \
do { \
(head)->hh.tbl = (UT_hash_table *)uthash_malloc(sizeof(UT_hash_table)); \
if (!((head)->hh.tbl)) { \
uthash_fatal("out of memory"); \
} \
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
(head)->hh.tbl->tail = &((head)->hh); \
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
(head)->hh.tbl->hho = (char *)(&(head)->hh) - (char *)(head); \
(head)->hh.tbl->buckets = (UT_hash_bucket *)uthash_malloc(HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \
if (!(head)->hh.tbl->buckets) { \
uthash_fatal("out of memory"); \
} \
memset((head)->hh.tbl->buckets, 0, HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_MAKE((head)->hh.tbl); \
(head)->hh.tbl->signature = HASH_SIGNATURE; \
} while (0)
#define HASH_ADD(hh, head, fieldname, keylen_in, add) \
HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add)
#define HASH_REPLACE(hh, head, fieldname, keylen_in, add, replaced) \
do { \
replaced = NULL; \
HASH_FIND(hh, head, &((add)->fieldname), keylen_in, replaced); \
if (replaced != NULL) { \
HASH_DELETE(hh, head, replaced); \
}; \
HASH_ADD(hh, head, fieldname, keylen_in, add); \
} while (0)
#define HASH_ADD_KEYPTR(hh, head, keyptr, keylen_in, add) \
do { \
unsigned _ha_bkt; \
(add)->hh.next = NULL; \
(add)->hh.key = (char *)(keyptr); \
(add)->hh.keylen = (unsigned)(keylen_in); \
if (!(head)) { \
head = (add); \
(head)->hh.prev = NULL; \
HASH_MAKE_TABLE(hh, head); \
} else { \
(head)->hh.tbl->tail->next = (add); \
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
(head)->hh.tbl->tail = &((add)->hh); \
} \
(head)->hh.tbl->num_items++; \
(add)->hh.tbl = (head)->hh.tbl; \
HASH_FCN(keyptr, keylen_in, (head)->hh.tbl->num_buckets, (add)->hh.hashv, _ha_bkt); \
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], &(add)->hh); \
HASH_BLOOM_ADD((head)->hh.tbl, (add)->hh.hashv); \
HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \
HASH_FSCK(hh, head); \
} while (0)
#define HASH_TO_BKT(hashv, num_bkts, bkt) \
do { \
bkt = ((hashv) & (num_bkts - 1)); \
} while (0)
/* delete "delptr" from the hash table.
* "the usual" patch-up process for the app-order doubly-linked-list.
* The use of _hd_hh_del below deserves special explanation.
* These used to be expressed using (delptr) but that led to a bug
* if someone used the same symbol for the head and deletee, like
* HASH_DELETE(hh,users,users);
* We want that to work, but by changing the head (users) below
* we were forfeiting our ability to further refer to the deletee (users)
* in the patch-up process. Solution: use scratch space to
* copy the deletee pointer, then the latter references are via that
* scratch pointer rather than through the repointed (users) symbol.
*/
#define HASH_DELETE(hh, head, delptr) \
do { \
unsigned _hd_bkt; \
struct UT_hash_handle *_hd_hh_del; \
if (((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL)) { \
uthash_free((head)->hh.tbl->buckets, (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
head = NULL; \
} else { \
_hd_hh_del = &((delptr)->hh); \
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail)) { \
(head)->hh.tbl->tail = (UT_hash_handle *)((ptrdiff_t)((delptr)->hh.prev) + (head)->hh.tbl->hho); \
} \
if ((delptr)->hh.prev) { \
((UT_hash_handle *)((ptrdiff_t)((delptr)->hh.prev) + (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
} else { \
DECLTYPE_ASSIGN(head, (delptr)->hh.next); \
} \
if (_hd_hh_del->next) { \
((UT_hash_handle *)((ptrdiff_t)_hd_hh_del->next + (head)->hh.tbl->hho))->prev = _hd_hh_del->prev; \
} \
HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
HASH_DEL_IN_BKT(hh, (head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
(head)->hh.tbl->num_items--; \
} \
HASH_FSCK(hh, head); \
} while (0)
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
#define HASH_FIND_STR(head, findstr, out) \
HASH_FIND(hh, head, findstr, strlen(findstr), out)
#define HASH_ADD_STR(head, strfield, add) \
HASH_ADD(hh, head, strfield[0], strlen(add->strfield), add)
#define HASH_REPLACE_STR(head, strfield, add, replaced) \
HASH_REPLACE(hh, head, strfield[0], strlen(add->strfield), add, replaced)
#define HASH_FIND_INT(head, findint, out) \
HASH_FIND(hh, head, findint, sizeof(int), out)
#define HASH_ADD_INT(head, intfield, add) \
HASH_ADD(hh, head, intfield, sizeof(int), add)
#define HASH_REPLACE_INT(head, intfield, add, replaced) \
HASH_REPLACE(hh, head, intfield, sizeof(int), add, replaced)
#define HASH_FIND_PTR(head, findptr, out) \
HASH_FIND(hh, head, findptr, sizeof(void *), out)
#define HASH_ADD_PTR(head, ptrfield, add) \
HASH_ADD(hh, head, ptrfield, sizeof(void *), add)
#define HASH_REPLACE_PTR(head, ptrfield, add, replaced) \
HASH_REPLACE(hh, head, ptrfield, sizeof(void *), add, replaced)
#define HASH_DEL(head, delptr) \
HASH_DELETE(hh, head, delptr)
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
*/
#ifdef HASH_DEBUG
#define HASH_OOPS(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
exit(-1); \
} while (0)
#define HASH_FSCK(hh, head) \
do { \
unsigned _bkt_i; \
unsigned _count, _bkt_count; \
char *_prev; \
struct UT_hash_handle *_thh; \
if (head) { \
_count = 0; \
for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
_bkt_count = 0; \
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
_prev = NULL; \
while (_thh) { \
if (_prev != (char *)(_thh->hh_prev)) { \
HASH_OOPS("invalid hh_prev %p, actual %p\n", _thh->hh_prev, _prev); \
} \
_bkt_count++; \
_prev = (char *)(_thh); \
_thh = _thh->hh_next; \
} \
_count += _bkt_count; \
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
HASH_OOPS("invalid bucket count %d, actual %d\n", (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
} \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid hh item count %d, actual %d\n", (head)->hh.tbl->num_items, _count); \
} \
/* traverse hh in app order; check next/prev integrity, count */ \
_count = 0; \
_prev = NULL; \
_thh = &(head)->hh; \
while (_thh) { \
_count++; \
if (_prev != (char *)(_thh->prev)) { \
HASH_OOPS("invalid prev %p, actual %p\n", _thh->prev, _prev); \
} \
_prev = (char *)ELMT_FROM_HH((head)->hh.tbl, _thh); \
_thh = (_thh->next ? (UT_hash_handle *)((char *)(_thh->next) + (head)->hh.tbl->hho) : NULL); \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid app item count %d, actual %d\n", (head)->hh.tbl->num_items, _count); \
} \
} \
} while (0)
#else
#define HASH_FSCK(hh, head)
#endif
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
#define HASH_EMIT_KEY(hh, head, keyptr, fieldlen) \
do { \
unsigned _klen = fieldlen; \
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
#else
#define HASH_EMIT_KEY(hh, head, keyptr, fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
#define HASH_BER(key, keylen, num_bkts, hashv, bkt) \
do { \
unsigned _hb_keylen = keylen; \
char *_hb_key = (char *)(key); \
(hashv) = 0; \
while (_hb_keylen--) { \
(hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \
} \
bkt = (hashv) & (num_bkts - 1); \
} while (0)
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key, keylen, num_bkts, hashv, bkt) \
do { \
unsigned _sx_i; \
char *_hs_key = (char *)(key); \
hashv = 0; \
for (_sx_i = 0; _sx_i < keylen; _sx_i++) \
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
bkt = hashv & (num_bkts - 1); \
} while (0)
/* FNV-1a variation */
#define HASH_FNV(key, keylen, num_bkts, hashv, bkt) \
do { \
unsigned _fn_i; \
char *_hf_key = (char *)(key); \
hashv = 2166136261UL; \
for (_fn_i = 0; _fn_i < keylen; _fn_i++) \
hashv = hashv ^ _hf_key[_fn_i]; \
hashv = hashv * 16777619; \
bkt = hashv & (num_bkts - 1); \
} while (0)
#define HASH_OAT(key, keylen, num_bkts, hashv, bkt) \
do { \
unsigned _ho_i; \
char *_ho_key = (char *)(key); \
hashv = 0; \
for (_ho_i = 0; _ho_i < keylen; _ho_i++) { \
hashv += _ho_key[_ho_i]; \
hashv += (hashv << 10); \
hashv ^= (hashv >> 6); \
} \
hashv += (hashv << 3); \
hashv ^= (hashv >> 11); \
hashv += (hashv << 15); \
bkt = hashv & (num_bkts - 1); \
} while (0)
#define HASH_JEN_MIX(a, b, c) \
do { \
a -= b; \
a -= c; \
a ^= (c >> 13); \
b -= c; \
b -= a; \
b ^= (a << 8); \
c -= a; \
c -= b; \
c ^= (b >> 13); \
a -= b; \
a -= c; \
a ^= (c >> 12); \
b -= c; \
b -= a; \
b ^= (a << 16); \
c -= a; \
c -= b; \
c ^= (b >> 5); \
a -= b; \
a -= c; \
a ^= (c >> 3); \
b -= c; \
b -= a; \
b ^= (a << 10); \
c -= a; \
c -= b; \
c ^= (b >> 15); \
} while (0)
#define HASH_JEN(key, keylen, num_bkts, hashv, bkt) \
do { \
unsigned _hj_i, _hj_j, _hj_k; \
unsigned char *_hj_key = (unsigned char *)(key); \
hashv = 0xfeedbeef; \
_hj_i = _hj_j = 0x9e3779b9; \
_hj_k = (unsigned)(keylen); \
while (_hj_k >= 12) { \
_hj_i += (_hj_key[0] + ((unsigned)_hj_key[1] << 8) + ((unsigned)_hj_key[2] << 16) + ((unsigned)_hj_key[3] << 24)); \
_hj_j += (_hj_key[4] + ((unsigned)_hj_key[5] << 8) + ((unsigned)_hj_key[6] << 16) + ((unsigned)_hj_key[7] << 24)); \
hashv += (_hj_key[8] + ((unsigned)_hj_key[9] << 8) + ((unsigned)_hj_key[10] << 16) + ((unsigned)_hj_key[11] << 24)); \
\
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
\
_hj_key += 12; \
_hj_k -= 12; \
} \
hashv += keylen; \
switch (_hj_k) { \
case 11: \
hashv += ((unsigned)_hj_key[10] << 24); \
/* fall through */ \
case 10: \
hashv += ((unsigned)_hj_key[9] << 16); \
/* fall through */ \
case 9: \
hashv += ((unsigned)_hj_key[8] << 8); \
/* fall through */ \
case 8: \
_hj_j += ((unsigned)_hj_key[7] << 24); \
/* fall through */ \
case 7: \
_hj_j += ((unsigned)_hj_key[6] << 16); \
/* fall through */ \
case 6: \
_hj_j += ((unsigned)_hj_key[5] << 8); \
/* fall through */ \
case 5: \
_hj_j += _hj_key[4]; \
/* fall through */ \
case 4: \
_hj_i += ((unsigned)_hj_key[3] << 24); \
/* fall through */ \
case 3: \
_hj_i += ((unsigned)_hj_key[2] << 16); \
/* fall through */ \
case 2: \
_hj_i += ((unsigned)_hj_key[1] << 8); \
/* fall through */ \
case 1: \
_hj_i += _hj_key[0]; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
bkt = hashv & (num_bkts - 1); \
} while (0)
/* The Paul Hsieh hash function */
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TURBOC__)
#define get16bits(d) (*((const uint16_t *)(d)))
#endif
#if !defined(get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) + (uint32_t)(((const uint8_t *)(d))[0]))
#endif
#define HASH_SFH(key, keylen, num_bkts, hashv, bkt) \
do { \
unsigned char *_sfh_key = (unsigned char *)(key); \
uint32_t _sfh_tmp, _sfh_len = keylen; \
\
int _sfh_rem = _sfh_len & 3; \
_sfh_len >>= 2; \
hashv = 0xcafebabe; \
\
/* Main loop */ \
for (; _sfh_len > 0; _sfh_len--) { \
hashv += get16bits(_sfh_key); \
_sfh_tmp = (uint32_t)(get16bits(_sfh_key + 2)) << 11 ^ hashv; \
hashv = (hashv << 16) ^ _sfh_tmp; \
_sfh_key += 2 * sizeof(uint16_t); \
hashv += hashv >> 11; \
} \
\
/* Handle end cases */ \
switch (_sfh_rem) { \
case 3: \
hashv += get16bits(_sfh_key); \
hashv ^= hashv << 16; \
hashv ^= (uint32_t)(_sfh_key[sizeof(uint16_t)] << 18); \
hashv += hashv >> 11; \
break; \
case 2: \
hashv += get16bits(_sfh_key); \
hashv ^= hashv << 11; \
hashv += hashv >> 17; \
break; \
case 1: \
hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
} \
\
/* Force "avalanching" of final 127 bits */ \
hashv ^= hashv << 3; \
hashv += hashv >> 5; \
hashv ^= hashv << 4; \
hashv += hashv >> 17; \
hashv ^= hashv << 25; \
hashv += hashv >> 6; \
bkt = hashv & (num_bkts - 1); \
} while (0)
#ifdef HASH_USING_NO_STRICT_ALIASING
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
#define MUR_GETBLOCK(p, i) p[i]
#else /* non intel */
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
#define WP(p) ((uint32_t *)((unsigned long)(p) & ~3UL))
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
#define MUR_THREE_ONE(p) ((((*WP(p)) & 0x00ffffff) << 8) | (((*(WP(p) + 1)) & 0xff000000) >> 24))
#define MUR_TWO_TWO(p) ((((*WP(p)) & 0x0000ffff) << 16) | (((*(WP(p) + 1)) & 0xffff0000) >> 16))
#define MUR_ONE_THREE(p) ((((*WP(p)) & 0x000000ff) << 24) | (((*(WP(p) + 1)) & 0xffffff00) >> 8))
#else /* assume little endian non-intel */
#define MUR_THREE_ONE(p) ((((*WP(p)) & 0xffffff00) >> 8) | (((*(WP(p) + 1)) & 0x000000ff) << 24))
#define MUR_TWO_TWO(p) ((((*WP(p)) & 0xffff0000) >> 16) | (((*(WP(p) + 1)) & 0x0000ffff) << 16))
#define MUR_ONE_THREE(p) ((((*WP(p)) & 0xff000000) >> 24) | (((*(WP(p) + 1)) & 0x00ffffff) << 8))
#endif
#define MUR_GETBLOCK(p, i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : MUR_ONE_THREE(p))))
#endif
#define MUR_ROTL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
#define MUR_FMIX(_h) \
do { \
_h ^= _h >> 16; \
_h *= 0x85ebca6b; \
_h ^= _h >> 13; \
_h *= 0xc2b2ae35l; \
_h ^= _h >> 16; \
} while (0)
#define HASH_MUR(key, keylen, num_bkts, hashv, bkt) \
do { \
const uint8_t *_mur_data = (const uint8_t *)(key); \
const int _mur_nblocks = (keylen) / 4; \
uint32_t _mur_h1 = 0xf88D5353; \
uint32_t _mur_c1 = 0xcc9e2d51; \
uint32_t _mur_c2 = 0x1b873593; \
uint32_t _mur_k1 = 0; \
const uint8_t *_mur_tail; \
const uint32_t *_mur_blocks = (const uint32_t *)(_mur_data + _mur_nblocks * 4); \
int _mur_i; \
for (_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
_mur_k1 = MUR_GETBLOCK(_mur_blocks, _mur_i); \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1, 15); \
_mur_k1 *= _mur_c2; \
\
_mur_h1 ^= _mur_k1; \
_mur_h1 = MUR_ROTL32(_mur_h1, 13); \
_mur_h1 = _mur_h1 * 5 + 0xe6546b64; \
} \
_mur_tail = (const uint8_t *)(_mur_data + _mur_nblocks * 4); \
_mur_k1 = 0; \
switch (keylen & 3) { \
case 3: \
_mur_k1 ^= _mur_tail[2] << 16; \
case 2: \
_mur_k1 ^= _mur_tail[1] << 8; \
case 1: \
_mur_k1 ^= _mur_tail[0]; \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1, 15); \
_mur_k1 *= _mur_c2; \
_mur_h1 ^= _mur_k1; \
} \
_mur_h1 ^= (keylen); \
MUR_FMIX(_mur_h1); \
hashv = _mur_h1; \
bkt = hashv & (num_bkts - 1); \
} while (0)
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
#define HASH_KEYCMP(a, b, len) memcmp(a, b, len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl, hh, head, keyptr, keylen_in, out) \
do { \
if (head.hh_head) \
DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, head.hh_head)); \
else \
out = NULL; \
while (out) { \
if ((out)->hh.keylen == keylen_in) { \
if ((HASH_KEYCMP((out)->hh.key, keyptr, keylen_in)) == 0) \
break; \
} \
if ((out)->hh.hh_next) \
DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \
else \
out = NULL; \
} \
} while (0)
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head, addhh) \
do { \
head.count++; \
(addhh)->hh_next = head.hh_head; \
(addhh)->hh_prev = NULL; \
if (head.hh_head) { \
(head).hh_head->hh_prev = (addhh); \
} \
(head).hh_head = addhh; \
if (head.count >= ((head.expand_mult + 1) * HASH_BKT_CAPACITY_THRESH) && (addhh)->tbl->noexpand != 1) { \
HASH_EXPAND_BUCKETS((addhh)->tbl); \
} \
} while (0)
/* remove an item from a given bucket */
#define HASH_DEL_IN_BKT(hh, head, hh_del) \
(head).count--; \
if ((head).hh_head == hh_del) { \
(head).hh_head = hh_del->hh_next; \
} \
if (hh_del->hh_prev) { \
hh_del->hh_prev->hh_next = hh_del->hh_next; \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
}
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
* the hash function as it applies to the key domain).
*
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
* the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
*
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
* Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
*
* ceil(n/b) = (n/b) + ((n%b)?1:0)
*
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
*
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
*
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
unsigned _he_bkt; \
unsigned _he_bkt_i; \
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket *)uthash_malloc(2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
if (!_he_new_buckets) { \
uthash_fatal("out of memory"); \
} \
memset(_he_new_buckets, 0, 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->ideal_chain_maxlen = (tbl->num_items >> (tbl->log2_num_buckets + 1)) + ((tbl->num_items & ((tbl->num_buckets * 2) - 1)) ? 1 : 0); \
tbl->nonideal_items = 0; \
for (_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) { \
_he_thh = tbl->buckets[_he_bkt_i].hh_head; \
while (_he_thh) { \
_he_hh_nxt = _he_thh->hh_next; \
HASH_TO_BKT(_he_thh->hashv, tbl->num_buckets * 2, _he_bkt); \
_he_newbkt = &(_he_new_buckets[_he_bkt]); \
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
tbl->nonideal_items++; \
_he_newbkt->expand_mult = _he_newbkt->count / tbl->ideal_chain_maxlen; \
} \
_he_thh->hh_prev = NULL; \
_he_thh->hh_next = _he_newbkt->hh_head; \
if (_he_newbkt->hh_head) \
_he_newbkt->hh_head->hh_prev = _he_thh; \
_he_newbkt->hh_head = _he_thh; \
_he_thh = _he_hh_nxt; \
} \
} \
uthash_free(tbl->buckets, tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->num_buckets *= 2; \
tbl->log2_num_buckets++; \
tbl->buckets = _he_new_buckets; \
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? (tbl->ineff_expands + 1) : 0; \
if (tbl->ineff_expands > 1) { \
tbl->noexpand = 1; \
uthash_noexpand_fyi(tbl); \
} \
uthash_expand_fyi(tbl); \
} while (0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head, cmpfcn) HASH_SRT(hh, head, cmpfcn)
#define HASH_SRT(hh, head, cmpfcn) \
do { \
unsigned _hs_i; \
unsigned _hs_looping, _hs_nmerges, _hs_insize, _hs_psize, _hs_qsize; \
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
if (head) { \
_hs_insize = 1; \
_hs_looping = 1; \
_hs_list = &((head)->hh); \
while (_hs_looping) { \
_hs_p = _hs_list; \
_hs_list = NULL; \
_hs_tail = NULL; \
_hs_nmerges = 0; \
while (_hs_p) { \
_hs_nmerges++; \
_hs_q = _hs_p; \
_hs_psize = 0; \
for (_hs_i = 0; _hs_i < _hs_insize; _hs_i++) { \
_hs_psize++; \
_hs_q = (UT_hash_handle *)((_hs_q->next) ? ((void *)((char *)(_hs_q->next) + (head)->hh.tbl->hho)) : NULL); \
if (!(_hs_q)) \
break; \
} \
_hs_qsize = _hs_insize; \
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q)) { \
if (_hs_psize == 0) { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle *)((_hs_q->next) ? ((void *)((char *)(_hs_q->next) + (head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} else if ((_hs_qsize == 0) || !(_hs_q)) { \
_hs_e = _hs_p; \
if (_hs_p) { \
_hs_p = (UT_hash_handle *)((_hs_p->next) ? ((void *)((char *)(_hs_p->next) + (head)->hh.tbl->hho)) : NULL); \
} \
_hs_psize--; \
} else if ((cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)))) <= 0) { \
_hs_e = _hs_p; \
if (_hs_p) { \
_hs_p = (UT_hash_handle *)((_hs_p->next) ? ((void *)((char *)(_hs_p->next) + (head)->hh.tbl->hho)) : NULL); \
} \
_hs_psize--; \
} else { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle *)((_hs_q->next) ? ((void *)((char *)(_hs_q->next) + (head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} \
if (_hs_tail) { \
_hs_tail->next = ((_hs_e) ? ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \
} else { \
_hs_list = _hs_e; \
} \
if (_hs_e) { \
_hs_e->prev = ((_hs_tail) ? ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \
} \
_hs_tail = _hs_e; \
} \
_hs_p = _hs_q; \
} \
if (_hs_tail) { \
_hs_tail->next = NULL; \
} \
if (_hs_nmerges <= 1) { \
_hs_looping = 0; \
(head)->hh.tbl->tail = _hs_tail; \
DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
} \
_hs_insize *= 2; \
} \
HASH_FSCK(hh, head); \
} \
} while (0)
/* This function selects items from one hash into another hash.
* The end result is that the selected items have dual presence
* in both hashes. There is no copy of the items made; rather
* they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
unsigned _src_bkt, _dst_bkt; \
void *_last_elt = NULL, *_elt; \
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh = NULL; \
ptrdiff_t _dst_hho = ((char *)(&(dst)->hh_dst) - (char *)(dst)); \
if (src) { \
for (_src_bkt = 0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; _src_hh; _src_hh = _src_hh->hh_next) { \
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
if (cond(_elt)) { \
_dst_hh = (UT_hash_handle *)(((char *)_elt) + _dst_hho); \
_dst_hh->key = _src_hh->key; \
_dst_hh->keylen = _src_hh->keylen; \
_dst_hh->hashv = _src_hh->hashv; \
_dst_hh->prev = _last_elt; \
_dst_hh->next = NULL; \
if (_last_elt_hh) { \
_last_elt_hh->next = _elt; \
} \
if (!dst) { \
DECLTYPE_ASSIGN(dst, _elt); \
HASH_MAKE_TABLE(hh_dst, dst); \
} else { \
_dst_hh->tbl = (dst)->hh_dst.tbl; \
} \
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], _dst_hh); \
(dst)->hh_dst.tbl->num_items++; \
_last_elt = _elt; \
_last_elt_hh = _dst_hh; \
} \
} \
} \
} \
HASH_FSCK(hh_dst, dst); \
} while (0)
#define HASH_CLEAR(hh, head) \
do { \
if (head) { \
uthash_free((head)->hh.tbl->buckets, (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
(head) = NULL; \
} \
} while (0)
#define HASH_OVERHEAD(hh, head) \
(size_t)((((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
(sizeof(UT_hash_table)) + \
(HASH_BLOOM_BYTELEN)))
#ifdef NO_DECLTYPE
#define HASH_ITER(hh, head, el, tmp) for ((el) = (head), (*(char **)(&(tmp))) = (char *)((head) ? (head)->hh.next : NULL); \
el; (el) = (tmp), (*(char **)(&(tmp))) = (char *)((tmp) ? (tmp)->hh.next : NULL))
#else
#define HASH_ITER(hh, head, el, tmp) for ((el) = (head), (tmp) = DECLTYPE(el)((head) ? (head)->hh.next : NULL); \
el; (el) = (tmp), (tmp) = DECLTYPE(el)((tmp) ? (tmp)->hh.next : NULL))
#endif
/* obtain a count of items in the hash */
#define HASH_COUNT(head) HASH_CNT(hh, head)
#define HASH_CNT(hh, head) ((head) ? ((head)->hh.tbl->num_items) : 0)
typedef struct UT_hash_bucket {
struct UT_hash_handle *hh_head;
unsigned count;
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
* the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* (The multiplier is simply expand_mult+1). The whole idea of this
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
* value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
} UT_hash_bucket;
/* random signature used only to find hash tables in external analysis */
#define HASH_SIGNATURE 0xa0111fe1
#define HASH_BLOOM_SIGNATURE 0xb12220f2
typedef struct UT_hash_table {
UT_hash_bucket *buckets;
unsigned num_buckets, log2_num_buckets;
unsigned num_items;
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
/* in an ideal situation (all buckets used equally), no bucket would have
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
unsigned ideal_chain_maxlen;
/* nonideal_items is the number of items in the hash whose chain position
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
/* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
* function isn't a good fit for the key domain. When expansion is inhibited
* the hash will still work, albeit no longer in constant time. */
unsigned ineff_expands, noexpand;
uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOM
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
uint8_t *bloom_bv;
char bloom_nbits;
#endif
} UT_hash_table;
typedef struct UT_hash_handle {
struct UT_hash_table *tbl;
void *prev; /* prev element in app order */
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
#endif /* UTHASH_H */

119
third-party/libag/include/util.h vendored Normal file
View File

@ -0,0 +1,119 @@
#ifndef UTIL_H
#define UTIL_H
#include <dirent.h>
#include <pcre.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "config.h"
#include "log.h"
#include "options.h"
FILE *out_fd;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define H_SIZE (64 * 1024)
#ifdef __clang__
#define NO_SANITIZE_ALIGNMENT __attribute__((no_sanitize("alignment")))
#else
#define NO_SANITIZE_ALIGNMENT
#endif
void *ag_malloc(size_t size);
void *ag_realloc(void *ptr, size_t size);
void *ag_calloc(size_t nelem, size_t elsize);
char *ag_strdup(const char *s);
char *ag_strndup(const char *s, size_t size);
typedef struct {
size_t start; /* Byte at which the match starts */
size_t end; /* and where it ends */
} match_t;
typedef struct {
size_t total_bytes;
size_t total_files;
size_t total_matches;
size_t total_file_matches;
struct timeval time_start;
struct timeval time_end;
} ag_stats;
ag_stats stats;
/* Union to translate between chars and words without violating strict aliasing */
typedef union {
char as_chars[sizeof(uint16_t)];
uint16_t as_word;
} word_t;
void free_strings(char **strs, const size_t strs_len);
void generate_alpha_skip(const char *find, size_t f_len, size_t skip_lookup[], const int case_sensitive);
int is_prefix(const char *s, const size_t s_len, const size_t pos, const int case_sensitive);
size_t suffix_len(const char *s, const size_t s_len, const size_t pos, const int case_sensitive);
void generate_find_skip(const char *find, const size_t f_len, size_t **skip_lookup, const int case_sensitive);
void generate_hash(const char *find, const size_t f_len, uint8_t *H, const int case_sensitive);
/* max is already defined on spec-violating compilers such as MinGW */
size_t ag_max(size_t a, size_t b);
size_t ag_min(size_t a, size_t b);
const char *boyer_moore_strnstr(const char *s, const char *find, const size_t s_len, const size_t f_len,
const size_t alpha_skip_lookup[], const size_t *find_skip_lookup, const int case_insensitive);
const char *hash_strnstr(const char *s, const char *find, const size_t s_len, const size_t f_len, uint8_t *h_table, const int case_sensitive);
size_t invert_matches(const char *buf, const size_t buf_len, match_t matches[], size_t matches_len);
void realloc_matches(match_t **matches, size_t *matches_size, size_t matches_len);
void compile_study(pcre **re, pcre_extra **re_extra, char *q, const int pcre_opts, const int study_opts);
int is_binary(const void *buf, const size_t buf_len);
int is_regex(const char *query);
int is_fnmatch(const char *filename);
int binary_search(const char *needle, char **haystack, int start, int end);
void init_wordchar_table(void);
int is_wordchar(char ch);
int is_lowercase(const char *s);
int is_directory(const char *path, const struct dirent *d);
int is_symlink(const char *path, const struct dirent *d);
int is_named_pipe(const char *path, const struct dirent *d);
void die(const char *fmt, ...);
void ag_asprintf(char **ret, const char *fmt, ...);
ssize_t buf_getline(const char **line, const char *buf, const size_t buf_len, const size_t buf_offset);
#ifndef HAVE_FGETLN
char *fgetln(FILE *fp, size_t *lenp);
#endif
#ifndef HAVE_GETLINE
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
#endif
#ifndef HAVE_REALPATH
char *realpath(const char *path, char *resolved_path);
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char *dest, const char *src, size_t size);
#endif
#ifndef HAVE_VASPRINTF
int vasprintf(char **ret, const char *fmt, va_list args);
#endif
#endif

3
third-party/libag/lib/libag.a vendored Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:24c1ae7219e2309f7603913e01da2819d91d56ca62ea5263d647044172bc145c
size 118440

677
third-party/libpcre/include/pcre.h vendored Normal file
View File

@ -0,0 +1,677 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* This is the public header file for the PCRE library, to be #included by
applications that call the PCRE functions.
Copyright (c) 1997-2014 University of Cambridge
-----------------------------------------------------------------------------
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 the University of Cambridge nor the names of its
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.
-----------------------------------------------------------------------------
*/
#ifndef _PCRE_H
#define _PCRE_H
/* The current PCRE version information. */
#define PCRE_MAJOR 8
#define PCRE_MINOR 43
#define PCRE_PRERELEASE
#define PCRE_DATE 2019-02-23
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
export setting is defined in pcre_internal.h, which includes this file. So we
don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */
#if defined(_WIN32) && !defined(PCRE_STATIC)
# ifndef PCRE_EXP_DECL
# define PCRE_EXP_DECL extern __declspec(dllimport)
# endif
# ifdef __cplusplus
# ifndef PCRECPP_EXP_DECL
# define PCRECPP_EXP_DECL extern __declspec(dllimport)
# endif
# ifndef PCRECPP_EXP_DEFN
# define PCRECPP_EXP_DEFN __declspec(dllimport)
# endif
# endif
#endif
/* By default, we use the standard "extern" declarations. */
#ifndef PCRE_EXP_DECL
# ifdef __cplusplus
# define PCRE_EXP_DECL extern "C"
# else
# define PCRE_EXP_DECL extern
# endif
#endif
#ifdef __cplusplus
# ifndef PCRECPP_EXP_DECL
# define PCRECPP_EXP_DECL extern
# endif
# ifndef PCRECPP_EXP_DEFN
# define PCRECPP_EXP_DEFN
# endif
#endif
/* Have to include stdlib.h in order to ensure that size_t is defined;
it is needed here for malloc. */
#include <stdlib.h>
/* Allow for C++ users */
#ifdef __cplusplus
extern "C" {
#endif
/* Public options. Some are compile-time only, some are run-time only, and some
are both. Most of the compile-time options are saved with the compiled regex so
that they can be inspected during studying (and therefore JIT compiling). Note
that pcre_study() has its own set of options. Originally, all the options
defined here used distinct bits. However, almost all the bits in a 32-bit word
are now used, so in order to conserve them, option bits that were previously
only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may
also be used for compile-time options that affect only compiling and are not
relevant for studying or JIT compiling.
Some options for pcre_compile() change its behaviour but do not affect the
behaviour of the execution functions. Other options are passed through to the
execution functions and affect their behaviour, with or without affecting the
behaviour of pcre_compile().
Options that can be passed to pcre_compile() are tagged Cx below, with these
variants:
C1 Affects compile only
C2 Does not affect compile; affects exec, dfa_exec
C3 Affects compile, exec, dfa_exec
C4 Affects compile, exec, dfa_exec, study
C5 Affects compile, exec, study
Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with
E and D, respectively. They take precedence over C3, C4, and C5 settings passed
from pcre_compile(). Those that are compatible with JIT execution are flagged
with J. */
#define PCRE_CASELESS 0x00000001 /* C1 */
#define PCRE_MULTILINE 0x00000002 /* C1 */
#define PCRE_DOTALL 0x00000004 /* C1 */
#define PCRE_EXTENDED 0x00000008 /* C1 */
#define PCRE_ANCHORED 0x00000010 /* C4 E D */
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */
#define PCRE_EXTRA 0x00000040 /* C1 */
#define PCRE_NOTBOL 0x00000080 /* E D J */
#define PCRE_NOTEOL 0x00000100 /* E D J */
#define PCRE_UNGREEDY 0x00000200 /* C1 */
#define PCRE_NOTEMPTY 0x00000400 /* E D J */
#define PCRE_UTF8 0x00000800 /* C4 ) */
#define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */
#define PCRE_UTF32 0x00000800 /* C4 ) */
#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */
#define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */
#define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */
#define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */
#define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */
#define PCRE_PARTIAL 0x00008000 /* E D J ) */
/* This pair use the same bit. */
#define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */
#define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */
/* This pair use the same bit. */
#define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */
#define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */
#define PCRE_FIRSTLINE 0x00040000 /* C3 */
#define PCRE_DUPNAMES 0x00080000 /* C1 */
#define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */
#define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */
#define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */
#define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */
#define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */
#define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */
#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */
#define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */
#define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */
#define PCRE_PARTIAL_HARD 0x08000000 /* E D J */
#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */
#define PCRE_UCP 0x20000000 /* C3 */
/* Exec-time and get/set-time error codes */
#define PCRE_ERROR_NOMATCH (-1)
#define PCRE_ERROR_NULL (-2)
#define PCRE_ERROR_BADOPTION (-3)
#define PCRE_ERROR_BADMAGIC (-4)
#define PCRE_ERROR_UNKNOWN_OPCODE (-5)
#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */
#define PCRE_ERROR_NOMEMORY (-6)
#define PCRE_ERROR_NOSUBSTRING (-7)
#define PCRE_ERROR_MATCHLIMIT (-8)
#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */
#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */
#define PCRE_ERROR_PARTIAL (-12)
#define PCRE_ERROR_BADPARTIAL (-13)
#define PCRE_ERROR_INTERNAL (-14)
#define PCRE_ERROR_BADCOUNT (-15)
#define PCRE_ERROR_DFA_UITEM (-16)
#define PCRE_ERROR_DFA_UCOND (-17)
#define PCRE_ERROR_DFA_UMLIMIT (-18)
#define PCRE_ERROR_DFA_WSSIZE (-19)
#define PCRE_ERROR_DFA_RECURSE (-20)
#define PCRE_ERROR_RECURSIONLIMIT (-21)
#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */
#define PCRE_ERROR_BADNEWLINE (-23)
#define PCRE_ERROR_BADOFFSET (-24)
#define PCRE_ERROR_SHORTUTF8 (-25)
#define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */
#define PCRE_ERROR_RECURSELOOP (-26)
#define PCRE_ERROR_JIT_STACKLIMIT (-27)
#define PCRE_ERROR_BADMODE (-28)
#define PCRE_ERROR_BADENDIANNESS (-29)
#define PCRE_ERROR_DFA_BADRESTART (-30)
#define PCRE_ERROR_JIT_BADOPTION (-31)
#define PCRE_ERROR_BADLENGTH (-32)
#define PCRE_ERROR_UNSET (-33)
/* Specific error codes for UTF-8 validity checks */
#define PCRE_UTF8_ERR0 0
#define PCRE_UTF8_ERR1 1
#define PCRE_UTF8_ERR2 2
#define PCRE_UTF8_ERR3 3
#define PCRE_UTF8_ERR4 4
#define PCRE_UTF8_ERR5 5
#define PCRE_UTF8_ERR6 6
#define PCRE_UTF8_ERR7 7
#define PCRE_UTF8_ERR8 8
#define PCRE_UTF8_ERR9 9
#define PCRE_UTF8_ERR10 10
#define PCRE_UTF8_ERR11 11
#define PCRE_UTF8_ERR12 12
#define PCRE_UTF8_ERR13 13
#define PCRE_UTF8_ERR14 14
#define PCRE_UTF8_ERR15 15
#define PCRE_UTF8_ERR16 16
#define PCRE_UTF8_ERR17 17
#define PCRE_UTF8_ERR18 18
#define PCRE_UTF8_ERR19 19
#define PCRE_UTF8_ERR20 20
#define PCRE_UTF8_ERR21 21
#define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */
/* Specific error codes for UTF-16 validity checks */
#define PCRE_UTF16_ERR0 0
#define PCRE_UTF16_ERR1 1
#define PCRE_UTF16_ERR2 2
#define PCRE_UTF16_ERR3 3
#define PCRE_UTF16_ERR4 4 /* Unused (was non-character) */
/* Specific error codes for UTF-32 validity checks */
#define PCRE_UTF32_ERR0 0
#define PCRE_UTF32_ERR1 1
#define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */
#define PCRE_UTF32_ERR3 3
/* Request types for pcre_fullinfo() */
#define PCRE_INFO_OPTIONS 0
#define PCRE_INFO_SIZE 1
#define PCRE_INFO_CAPTURECOUNT 2
#define PCRE_INFO_BACKREFMAX 3
#define PCRE_INFO_FIRSTBYTE 4
#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */
#define PCRE_INFO_FIRSTTABLE 5
#define PCRE_INFO_LASTLITERAL 6
#define PCRE_INFO_NAMEENTRYSIZE 7
#define PCRE_INFO_NAMECOUNT 8
#define PCRE_INFO_NAMETABLE 9
#define PCRE_INFO_STUDYSIZE 10
#define PCRE_INFO_DEFAULT_TABLES 11
#define PCRE_INFO_OKPARTIAL 12
#define PCRE_INFO_JCHANGED 13
#define PCRE_INFO_HASCRORLF 14
#define PCRE_INFO_MINLENGTH 15
#define PCRE_INFO_JIT 16
#define PCRE_INFO_JITSIZE 17
#define PCRE_INFO_MAXLOOKBEHIND 18
#define PCRE_INFO_FIRSTCHARACTER 19
#define PCRE_INFO_FIRSTCHARACTERFLAGS 20
#define PCRE_INFO_REQUIREDCHAR 21
#define PCRE_INFO_REQUIREDCHARFLAGS 22
#define PCRE_INFO_MATCHLIMIT 23
#define PCRE_INFO_RECURSIONLIMIT 24
#define PCRE_INFO_MATCH_EMPTY 25
/* Request types for pcre_config(). Do not re-arrange, in order to remain
compatible. */
#define PCRE_CONFIG_UTF8 0
#define PCRE_CONFIG_NEWLINE 1
#define PCRE_CONFIG_LINK_SIZE 2
#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3
#define PCRE_CONFIG_MATCH_LIMIT 4
#define PCRE_CONFIG_STACKRECURSE 5
#define PCRE_CONFIG_UNICODE_PROPERTIES 6
#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7
#define PCRE_CONFIG_BSR 8
#define PCRE_CONFIG_JIT 9
#define PCRE_CONFIG_UTF16 10
#define PCRE_CONFIG_JITTARGET 11
#define PCRE_CONFIG_UTF32 12
#define PCRE_CONFIG_PARENS_LIMIT 13
/* Request types for pcre_study(). Do not re-arrange, in order to remain
compatible. */
#define PCRE_STUDY_JIT_COMPILE 0x0001
#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002
#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004
#define PCRE_STUDY_EXTRA_NEEDED 0x0008
/* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine
these bits, just add new ones on the end, in order to remain compatible. */
#define PCRE_EXTRA_STUDY_DATA 0x0001
#define PCRE_EXTRA_MATCH_LIMIT 0x0002
#define PCRE_EXTRA_CALLOUT_DATA 0x0004
#define PCRE_EXTRA_TABLES 0x0008
#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010
#define PCRE_EXTRA_MARK 0x0020
#define PCRE_EXTRA_EXECUTABLE_JIT 0x0040
/* Types */
struct real_pcre8_or_16; /* declaration; the definition is private */
typedef struct real_pcre8_or_16 pcre;
struct real_pcre8_or_16; /* declaration; the definition is private */
typedef struct real_pcre8_or_16 pcre16;
struct real_pcre32; /* declaration; the definition is private */
typedef struct real_pcre32 pcre32;
struct real_pcre_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre_jit_stack pcre_jit_stack;
struct real_pcre16_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre16_jit_stack pcre16_jit_stack;
struct real_pcre32_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre32_jit_stack pcre32_jit_stack;
/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain
a 16 bit wide signed data type. Otherwise it can be a dummy data type since
pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */
#ifndef PCRE_UCHAR16
#define PCRE_UCHAR16 unsigned short
#endif
#ifndef PCRE_SPTR16
#define PCRE_SPTR16 const PCRE_UCHAR16 *
#endif
/* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain
a 32 bit wide signed data type. Otherwise it can be a dummy data type since
pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */
#ifndef PCRE_UCHAR32
#define PCRE_UCHAR32 unsigned int
#endif
#ifndef PCRE_SPTR32
#define PCRE_SPTR32 const PCRE_UCHAR32 *
#endif
/* When PCRE is compiled as a C++ library, the subject pointer type can be
replaced with a custom type. For conventional use, the public interface is a
const char *. */
#ifndef PCRE_SPTR
#define PCRE_SPTR const char *
#endif
/* The structure for passing additional data to pcre_exec(). This is defined in
such as way as to be extensible. Always add new fields at the end, in order to
remain compatible. */
typedef struct pcre_extra {
unsigned long int flags; /* Bits for which fields are set */
void *study_data; /* Opaque data from pcre_study() */
unsigned long int match_limit; /* Maximum number of calls to match() */
void *callout_data; /* Data passed back in callouts */
const unsigned char *tables; /* Pointer to character tables */
unsigned long int match_limit_recursion; /* Max recursive calls to match() */
unsigned char **mark; /* For passing back a mark pointer */
void *executable_jit; /* Contains a pointer to a compiled jit code */
} pcre_extra;
/* Same structure as above, but with 16 bit char pointers. */
typedef struct pcre16_extra {
unsigned long int flags; /* Bits for which fields are set */
void *study_data; /* Opaque data from pcre_study() */
unsigned long int match_limit; /* Maximum number of calls to match() */
void *callout_data; /* Data passed back in callouts */
const unsigned char *tables; /* Pointer to character tables */
unsigned long int match_limit_recursion; /* Max recursive calls to match() */
PCRE_UCHAR16 **mark; /* For passing back a mark pointer */
void *executable_jit; /* Contains a pointer to a compiled jit code */
} pcre16_extra;
/* Same structure as above, but with 32 bit char pointers. */
typedef struct pcre32_extra {
unsigned long int flags; /* Bits for which fields are set */
void *study_data; /* Opaque data from pcre_study() */
unsigned long int match_limit; /* Maximum number of calls to match() */
void *callout_data; /* Data passed back in callouts */
const unsigned char *tables; /* Pointer to character tables */
unsigned long int match_limit_recursion; /* Max recursive calls to match() */
PCRE_UCHAR32 **mark; /* For passing back a mark pointer */
void *executable_jit; /* Contains a pointer to a compiled jit code */
} pcre32_extra;
/* The structure for passing out data via the pcre_callout_function. We use a
structure so that new fields can be added on the end in future versions,
without changing the API of the function, thereby allowing old clients to work
without modification. */
typedef struct pcre_callout_block {
int version; /* Identifies version of block */
/* ------------------------ Version 0 ------------------------------- */
int callout_number; /* Number compiled into pattern */
int *offset_vector; /* The offset vector */
PCRE_SPTR subject; /* The subject being matched */
int subject_length; /* The length of the subject */
int start_match; /* Offset to start of this match attempt */
int current_position; /* Where we currently are in the subject */
int capture_top; /* Max current capture */
int capture_last; /* Most recently closed capture */
void *callout_data; /* Data passed in with the call */
/* ------------------- Added for Version 1 -------------------------- */
int pattern_position; /* Offset to next item in the pattern */
int next_item_length; /* Length of next item in the pattern */
/* ------------------- Added for Version 2 -------------------------- */
const unsigned char *mark; /* Pointer to current mark or NULL */
/* ------------------------------------------------------------------ */
} pcre_callout_block;
/* Same structure as above, but with 16 bit char pointers. */
typedef struct pcre16_callout_block {
int version; /* Identifies version of block */
/* ------------------------ Version 0 ------------------------------- */
int callout_number; /* Number compiled into pattern */
int *offset_vector; /* The offset vector */
PCRE_SPTR16 subject; /* The subject being matched */
int subject_length; /* The length of the subject */
int start_match; /* Offset to start of this match attempt */
int current_position; /* Where we currently are in the subject */
int capture_top; /* Max current capture */
int capture_last; /* Most recently closed capture */
void *callout_data; /* Data passed in with the call */
/* ------------------- Added for Version 1 -------------------------- */
int pattern_position; /* Offset to next item in the pattern */
int next_item_length; /* Length of next item in the pattern */
/* ------------------- Added for Version 2 -------------------------- */
const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */
/* ------------------------------------------------------------------ */
} pcre16_callout_block;
/* Same structure as above, but with 32 bit char pointers. */
typedef struct pcre32_callout_block {
int version; /* Identifies version of block */
/* ------------------------ Version 0 ------------------------------- */
int callout_number; /* Number compiled into pattern */
int *offset_vector; /* The offset vector */
PCRE_SPTR32 subject; /* The subject being matched */
int subject_length; /* The length of the subject */
int start_match; /* Offset to start of this match attempt */
int current_position; /* Where we currently are in the subject */
int capture_top; /* Max current capture */
int capture_last; /* Most recently closed capture */
void *callout_data; /* Data passed in with the call */
/* ------------------- Added for Version 1 -------------------------- */
int pattern_position; /* Offset to next item in the pattern */
int next_item_length; /* Length of next item in the pattern */
/* ------------------- Added for Version 2 -------------------------- */
const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */
/* ------------------------------------------------------------------ */
} pcre32_callout_block;
/* Indirection for store get and free functions. These can be set to
alternative malloc/free functions if required. Special ones are used in the
non-recursive case for "frames". There is also an optional callout function
that is triggered by the (?) regex item. For Virtual Pascal, these definitions
have to take another form. */
#ifndef VPCOMPAT
PCRE_EXP_DECL void *(*pcre_malloc)(size_t);
PCRE_EXP_DECL void (*pcre_free)(void *);
PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre_stack_free)(void *);
PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
PCRE_EXP_DECL int (*pcre_stack_guard)(void);
PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_free)(void *);
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
PCRE_EXP_DECL int (*pcre16_stack_guard)(void);
PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_free)(void *);
PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
PCRE_EXP_DECL int (*pcre32_stack_guard)(void);
#else /* VPCOMPAT */
PCRE_EXP_DECL void *pcre_malloc(size_t);
PCRE_EXP_DECL void pcre_free(void *);
PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
PCRE_EXP_DECL void pcre_stack_free(void *);
PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
PCRE_EXP_DECL int pcre_stack_guard(void);
PCRE_EXP_DECL void *pcre16_malloc(size_t);
PCRE_EXP_DECL void pcre16_free(void *);
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
PCRE_EXP_DECL void pcre16_stack_free(void *);
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
PCRE_EXP_DECL int pcre16_stack_guard(void);
PCRE_EXP_DECL void *pcre32_malloc(size_t);
PCRE_EXP_DECL void pcre32_free(void *);
PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
PCRE_EXP_DECL void pcre32_stack_free(void *);
PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
PCRE_EXP_DECL int pcre32_stack_guard(void);
#endif /* VPCOMPAT */
/* User defined callback which provides a stack just before the match starts. */
typedef pcre_jit_stack *(*pcre_jit_callback)(void *);
typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *);
typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *);
/* Exported PCRE functions */
PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *,
const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *,
const unsigned char *);
PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *,
const unsigned char *);
PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
int *, const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **,
int *, const unsigned char *);
PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **,
int *, const unsigned char *);
PCRE_EXP_DECL int pcre_config(int, void *);
PCRE_EXP_DECL int pcre16_config(int, void *);
PCRE_EXP_DECL int pcre32_config(int, void *);
PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *,
int *, int, const char *, char *, int);
PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16,
int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32,
int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int);
PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int,
char *, int);
PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int,
PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int,
PCRE_UCHAR32 *, int);
PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *,
const char *, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
int, int, int, int *, int);
PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int);
PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int);
PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *,
PCRE_SPTR, int, int, int, int *, int,
pcre_jit_stack *);
PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int,
pcre16_jit_stack *);
PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int,
pcre32_jit_stack *);
PCRE_EXP_DECL void pcre_free_substring(const char *);
PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32);
PCRE_EXP_DECL void pcre_free_substring_list(const char **);
PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int,
void *);
PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int,
void *);
PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int,
void *);
PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *,
int *, int, const char *, const char **);
PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16,
int *, int, PCRE_SPTR16, PCRE_SPTR16 *);
PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32,
int *, int, PCRE_SPTR32, PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *);
PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32);
PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *,
char **, char **);
PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16,
PCRE_UCHAR16 **, PCRE_UCHAR16 **);
PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32,
PCRE_UCHAR32 **, PCRE_UCHAR32 **);
PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int,
const char **);
PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int,
PCRE_SPTR16 *);
PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int,
PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
const char ***);
PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int,
PCRE_SPTR16 **);
PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int,
PCRE_SPTR32 **);
PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
PCRE_EXP_DECL const unsigned char *pcre32_maketables(void);
PCRE_EXP_DECL int pcre_refcount(pcre *, int);
PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int);
PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int);
PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **);
PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **);
PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **);
PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *);
PCRE_EXP_DECL const char *pcre_version(void);
PCRE_EXP_DECL const char *pcre16_version(void);
PCRE_EXP_DECL const char *pcre32_version(void);
/* Utility functions for byte order swaps. */
PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *,
const unsigned char *);
PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *,
const unsigned char *);
PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *,
const unsigned char *);
PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
PCRE_SPTR16, int, int *, int);
PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *,
PCRE_SPTR32, int, int *, int);
/* JIT compiler related functions. */
PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int);
PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *);
PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *);
PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *);
PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *,
pcre_jit_callback, void *);
PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *,
pcre16_jit_callback, void *);
PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *,
pcre32_jit_callback, void *);
PCRE_EXP_DECL void pcre_jit_free_unused_memory(void);
PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void);
PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* End of pcre.h */

View File

@ -0,0 +1,172 @@
// Copyright (c) 2005, Google Inc.
// 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 Google Inc. nor the names of its
// 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.
//
// Author: Sanjay Ghemawat
//
// Regular-expression based scanner for parsing an input stream.
//
// Example 1: parse a sequence of "var = number" entries from input:
//
// Scanner scanner(input);
// string var;
// int number;
// scanner.SetSkipExpression("\\s+"); // Skip any white space we encounter
// while (scanner.Consume("(\\w+) = (\\d+)", &var, &number)) {
// ...;
// }
#ifndef _PCRE_SCANNER_H
#define _PCRE_SCANNER_H
#include <assert.h>
#include <string>
#include <vector>
#include <pcrecpp.h>
#include <pcre_stringpiece.h>
namespace pcrecpp {
class PCRECPP_EXP_DEFN Scanner {
public:
Scanner();
explicit Scanner(const std::string& input);
~Scanner();
// Return current line number. The returned line-number is
// one-based. I.e. it returns 1 + the number of consumed newlines.
//
// Note: this method may be slow. It may take time proportional to
// the size of the input.
int LineNumber() const;
// Return the byte-offset that the scanner is looking in the
// input data;
int Offset() const;
// Return true iff the start of the remaining input matches "re"
bool LookingAt(const RE& re) const;
// Return true iff all of the following are true
// a. the start of the remaining input matches "re",
// b. if any arguments are supplied, matched sub-patterns can be
// parsed and stored into the arguments.
// If it returns true, it skips over the matched input and any
// following input that matches the "skip" regular expression.
bool Consume(const RE& re,
const Arg& arg0 = RE::no_arg,
const Arg& arg1 = RE::no_arg,
const Arg& arg2 = RE::no_arg
// TODO: Allow more arguments?
);
// Set the "skip" regular expression. If after consuming some data,
// a prefix of the input matches this RE, it is automatically
// skipped. For example, a programming language scanner would use
// a skip RE that matches white space and comments.
//
// scanner.SetSkipExpression("\\s+|//.*|/[*](.|\n)*?[*]/");
//
// Skipping repeats as long as it succeeds. We used to let people do
// this by writing "(...)*" in the regular expression, but that added
// up to lots of recursive calls within the pcre library, so now we
// control repetition explicitly via the function call API.
//
// You can pass NULL for "re" if you do not want any data to be skipped.
void Skip(const char* re); // DEPRECATED; does *not* repeat
void SetSkipExpression(const char* re);
// Temporarily pause "skip"ing. This
// Skip("Foo"); code ; DisableSkip(); code; EnableSkip()
// is similar to
// Skip("Foo"); code ; Skip(NULL); code ; Skip("Foo");
// but avoids creating/deleting new RE objects.
void DisableSkip();
// Reenable previously paused skipping. Any prefix of the input
// that matches the skip pattern is immediately dropped.
void EnableSkip();
/***** Special wrappers around SetSkip() for some common idioms *****/
// Arranges to skip whitespace, C comments, C++ comments.
// The overall RE is a disjunction of the following REs:
// \\s whitespace
// //.*\n C++ comment
// /[*](.|\n)*?[*]/ C comment (x*? means minimal repetitions of x)
// We get repetition via the semantics of SetSkipExpression, not by using *
void SkipCXXComments() {
SetSkipExpression("\\s|//.*\n|/[*](?:\n|.)*?[*]/");
}
void set_save_comments(bool comments) {
save_comments_ = comments;
}
bool save_comments() {
return save_comments_;
}
// Append to vector ranges the comments found in the
// byte range [start,end] (inclusive) of the input data.
// Only comments that were extracted entirely within that
// range are returned: no range splitting of atomically-extracted
// comments is performed.
void GetComments(int start, int end, std::vector<StringPiece> *ranges);
// Append to vector ranges the comments added
// since the last time this was called. This
// functionality is provided for efficiency when
// interleaving scanning with parsing.
void GetNextComments(std::vector<StringPiece> *ranges);
private:
std::string data_; // All the input data
StringPiece input_; // Unprocessed input
RE* skip_; // If non-NULL, RE for skipping input
bool should_skip_; // If true, use skip_
bool skip_repeat_; // If true, repeat skip_ as long as it works
bool save_comments_; // If true, aggregate the skip expression
// the skipped comments
// TODO: later consider requiring that the StringPieces be added
// in order by their start position
std::vector<StringPiece> *comments_;
// the offset into comments_ that has been returned by GetNextComments
int comments_offset_;
// helper function to consume *skip_ and honour
// save_comments_
void ConsumeSkip();
};
} // namespace pcrecpp
#endif /* _PCRE_SCANNER_H */

View File

@ -0,0 +1,180 @@
// Copyright (c) 2005, Google Inc.
// 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 Google Inc. nor the names of its
// 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.
//
// Author: Sanjay Ghemawat
//
// A string like object that points into another piece of memory.
// Useful for providing an interface that allows clients to easily
// pass in either a "const char*" or a "string".
//
// Arghh! I wish C++ literals were automatically of type "string".
#ifndef _PCRE_STRINGPIECE_H
#define _PCRE_STRINGPIECE_H
#include <cstring>
#include <string>
#include <iosfwd> // for ostream forward-declaration
#if 0
#define HAVE_TYPE_TRAITS
#include <type_traits.h>
#elif 0
#define HAVE_TYPE_TRAITS
#include <bits/type_traits.h>
#endif
#include <pcre.h>
namespace pcrecpp {
using std::memcmp;
using std::strlen;
using std::string;
class PCRECPP_EXP_DEFN StringPiece {
private:
const char* ptr_;
int length_;
public:
// We provide non-explicit singleton constructors so users can pass
// in a "const char*" or a "string" wherever a "StringPiece" is
// expected.
StringPiece()
: ptr_(NULL), length_(0) { }
StringPiece(const char* str)
: ptr_(str), length_(static_cast<int>(strlen(ptr_))) { }
StringPiece(const unsigned char* str)
: ptr_(reinterpret_cast<const char*>(str)),
length_(static_cast<int>(strlen(ptr_))) { }
StringPiece(const string& str)
: ptr_(str.data()), length_(static_cast<int>(str.size())) { }
StringPiece(const char* offset, int len)
: ptr_(offset), length_(len) { }
// data() may return a pointer to a buffer with embedded NULs, and the
// returned buffer may or may not be null terminated. Therefore it is
// typically a mistake to pass data() to a routine that expects a NUL
// terminated string. Use "as_string().c_str()" if you really need to do
// this. Or better yet, change your routine so it does not rely on NUL
// termination.
const char* data() const { return ptr_; }
int size() const { return length_; }
bool empty() const { return length_ == 0; }
void clear() { ptr_ = NULL; length_ = 0; }
void set(const char* buffer, int len) { ptr_ = buffer; length_ = len; }
void set(const char* str) {
ptr_ = str;
length_ = static_cast<int>(strlen(str));
}
void set(const void* buffer, int len) {
ptr_ = reinterpret_cast<const char*>(buffer);
length_ = len;
}
char operator[](int i) const { return ptr_[i]; }
void remove_prefix(int n) {
ptr_ += n;
length_ -= n;
}
void remove_suffix(int n) {
length_ -= n;
}
bool operator==(const StringPiece& x) const {
return ((length_ == x.length_) &&
(memcmp(ptr_, x.ptr_, length_) == 0));
}
bool operator!=(const StringPiece& x) const {
return !(*this == x);
}
#define STRINGPIECE_BINARY_PREDICATE(cmp,auxcmp) \
bool operator cmp (const StringPiece& x) const { \
int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_); \
return ((r auxcmp 0) || ((r == 0) && (length_ cmp x.length_))); \
}
STRINGPIECE_BINARY_PREDICATE(<, <);
STRINGPIECE_BINARY_PREDICATE(<=, <);
STRINGPIECE_BINARY_PREDICATE(>=, >);
STRINGPIECE_BINARY_PREDICATE(>, >);
#undef STRINGPIECE_BINARY_PREDICATE
int compare(const StringPiece& x) const {
int r = memcmp(ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_);
if (r == 0) {
if (length_ < x.length_) r = -1;
else if (length_ > x.length_) r = +1;
}
return r;
}
string as_string() const {
return string(data(), size());
}
void CopyToString(string* target) const {
target->assign(ptr_, length_);
}
// Does "this" start with "x"
bool starts_with(const StringPiece& x) const {
return ((length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0));
}
};
} // namespace pcrecpp
// ------------------------------------------------------------------
// Functions used to create STL containers that use StringPiece
// Remember that a StringPiece's lifetime had better be less than
// that of the underlying string or char*. If it is not, then you
// cannot safely store a StringPiece into an STL container
// ------------------------------------------------------------------
#ifdef HAVE_TYPE_TRAITS
// This makes vector<StringPiece> really fast for some STL implementations
template<> struct __type_traits<pcrecpp::StringPiece> {
typedef __true_type has_trivial_default_constructor;
typedef __true_type has_trivial_copy_constructor;
typedef __true_type has_trivial_assignment_operator;
typedef __true_type has_trivial_destructor;
typedef __true_type is_POD_type;
};
#endif
// allow StringPiece to be logged
PCRECPP_EXP_DECL std::ostream& operator<<(std::ostream& o,
const pcrecpp::StringPiece& piece);
#endif /* _PCRE_STRINGPIECE_H */

710
third-party/libpcre/include/pcrecpp.h vendored Normal file
View File

@ -0,0 +1,710 @@
// Copyright (c) 2005, Google Inc.
// 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 Google Inc. nor the names of its
// 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.
//
// Author: Sanjay Ghemawat
// Support for PCRE_XXX modifiers added by Giuseppe Maxia, July 2005
#ifndef _PCRECPP_H
#define _PCRECPP_H
// C++ interface to the pcre regular-expression library. RE supports
// Perl-style regular expressions (with extensions like \d, \w, \s,
// ...).
//
// -----------------------------------------------------------------------
// REGEXP SYNTAX:
//
// This module is part of the pcre library and hence supports its syntax
// for regular expressions.
//
// The syntax is pretty similar to Perl's. For those not familiar
// with Perl's regular expressions, here are some examples of the most
// commonly used extensions:
//
// "hello (\\w+) world" -- \w matches a "word" character
// "version (\\d+)" -- \d matches a digit
// "hello\\s+world" -- \s matches any whitespace character
// "\\b(\\w+)\\b" -- \b matches empty string at a word boundary
// "(?i)hello" -- (?i) turns on case-insensitive matching
// "/\\*(.*?)\\*/" -- .*? matches . minimum no. of times possible
//
// -----------------------------------------------------------------------
// MATCHING INTERFACE:
//
// The "FullMatch" operation checks that supplied text matches a
// supplied pattern exactly.
//
// Example: successful match
// pcrecpp::RE re("h.*o");
// re.FullMatch("hello");
//
// Example: unsuccessful match (requires full match):
// pcrecpp::RE re("e");
// !re.FullMatch("hello");
//
// Example: creating a temporary RE object:
// pcrecpp::RE("h.*o").FullMatch("hello");
//
// You can pass in a "const char*" or a "string" for "text". The
// examples below tend to use a const char*.
//
// You can, as in the different examples above, store the RE object
// explicitly in a variable or use a temporary RE object. The
// examples below use one mode or the other arbitrarily. Either
// could correctly be used for any of these examples.
//
// -----------------------------------------------------------------------
// MATCHING WITH SUB-STRING EXTRACTION:
//
// You can supply extra pointer arguments to extract matched subpieces.
//
// Example: extracts "ruby" into "s" and 1234 into "i"
// int i;
// string s;
// pcrecpp::RE re("(\\w+):(\\d+)");
// re.FullMatch("ruby:1234", &s, &i);
//
// Example: does not try to extract any extra sub-patterns
// re.FullMatch("ruby:1234", &s);
//
// Example: does not try to extract into NULL
// re.FullMatch("ruby:1234", NULL, &i);
//
// Example: integer overflow causes failure
// !re.FullMatch("ruby:1234567891234", NULL, &i);
//
// Example: fails because there aren't enough sub-patterns:
// !pcrecpp::RE("\\w+:\\d+").FullMatch("ruby:1234", &s);
//
// Example: fails because string cannot be stored in integer
// !pcrecpp::RE("(.*)").FullMatch("ruby", &i);
//
// The provided pointer arguments can be pointers to any scalar numeric
// type, or one of
// string (matched piece is copied to string)
// StringPiece (StringPiece is mutated to point to matched piece)
// T (where "bool T::ParseFrom(const char*, int)" exists)
// NULL (the corresponding matched sub-pattern is not copied)
//
// CAVEAT: An optional sub-pattern that does not exist in the matched
// string is assigned the empty string. Therefore, the following will
// return false (because the empty string is not a valid number):
// int number;
// pcrecpp::RE::FullMatch("abc", "[a-z]+(\\d+)?", &number);
//
// -----------------------------------------------------------------------
// DO_MATCH
//
// The matching interface supports at most 16 arguments per call.
// If you need more, consider using the more general interface
// pcrecpp::RE::DoMatch(). See pcrecpp.h for the signature for DoMatch.
//
// -----------------------------------------------------------------------
// PARTIAL MATCHES
//
// You can use the "PartialMatch" operation when you want the pattern
// to match any substring of the text.
//
// Example: simple search for a string:
// pcrecpp::RE("ell").PartialMatch("hello");
//
// Example: find first number in a string:
// int number;
// pcrecpp::RE re("(\\d+)");
// re.PartialMatch("x*100 + 20", &number);
// assert(number == 100);
//
// -----------------------------------------------------------------------
// UTF-8 AND THE MATCHING INTERFACE:
//
// By default, pattern and text are plain text, one byte per character.
// The UTF8 flag, passed to the constructor, causes both pattern
// and string to be treated as UTF-8 text, still a byte stream but
// potentially multiple bytes per character. In practice, the text
// is likelier to be UTF-8 than the pattern, but the match returned
// may depend on the UTF8 flag, so always use it when matching
// UTF8 text. E.g., "." will match one byte normally but with UTF8
// set may match up to three bytes of a multi-byte character.
//
// Example:
// pcrecpp::RE_Options options;
// options.set_utf8();
// pcrecpp::RE re(utf8_pattern, options);
// re.FullMatch(utf8_string);
//
// Example: using the convenience function UTF8():
// pcrecpp::RE re(utf8_pattern, pcrecpp::UTF8());
// re.FullMatch(utf8_string);
//
// NOTE: The UTF8 option is ignored if pcre was not configured with the
// --enable-utf8 flag.
//
// -----------------------------------------------------------------------
// PASSING MODIFIERS TO THE REGULAR EXPRESSION ENGINE
//
// PCRE defines some modifiers to change the behavior of the regular
// expression engine.
// The C++ wrapper defines an auxiliary class, RE_Options, as a vehicle
// to pass such modifiers to a RE class.
//
// Currently, the following modifiers are supported
//
// modifier description Perl corresponding
//
// PCRE_CASELESS case insensitive match /i
// PCRE_MULTILINE multiple lines match /m
// PCRE_DOTALL dot matches newlines /s
// PCRE_DOLLAR_ENDONLY $ matches only at end N/A
// PCRE_EXTRA strict escape parsing N/A
// PCRE_EXTENDED ignore whitespaces /x
// PCRE_UTF8 handles UTF8 chars built-in
// PCRE_UNGREEDY reverses * and *? N/A
// PCRE_NO_AUTO_CAPTURE disables matching parens N/A (*)
//
// (For a full account on how each modifier works, please check the
// PCRE API reference manual).
//
// (*) Both Perl and PCRE allow non matching parentheses by means of the
// "?:" modifier within the pattern itself. e.g. (?:ab|cd) does not
// capture, while (ab|cd) does.
//
// For each modifier, there are two member functions whose name is made
// out of the modifier in lowercase, without the "PCRE_" prefix. For
// instance, PCRE_CASELESS is handled by
// bool caseless(),
// which returns true if the modifier is set, and
// RE_Options & set_caseless(bool),
// which sets or unsets the modifier.
//
// Moreover, PCRE_EXTRA_MATCH_LIMIT can be accessed through the
// set_match_limit() and match_limit() member functions.
// Setting match_limit to a non-zero value will limit the executation of
// pcre to keep it from doing bad things like blowing the stack or taking
// an eternity to return a result. A value of 5000 is good enough to stop
// stack blowup in a 2MB thread stack. Setting match_limit to zero will
// disable match limiting. Alternately, you can set match_limit_recursion()
// which uses PCRE_EXTRA_MATCH_LIMIT_RECURSION to limit how much pcre
// recurses. match_limit() caps the number of matches pcre does;
// match_limit_recrusion() caps the depth of recursion.
//
// Normally, to pass one or more modifiers to a RE class, you declare
// a RE_Options object, set the appropriate options, and pass this
// object to a RE constructor. Example:
//
// RE_options opt;
// opt.set_caseless(true);
//
// if (RE("HELLO", opt).PartialMatch("hello world")) ...
//
// RE_options has two constructors. The default constructor takes no
// arguments and creates a set of flags that are off by default.
//
// The optional parameter 'option_flags' is to facilitate transfer
// of legacy code from C programs. This lets you do
// RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str);
//
// But new code is better off doing
// RE(pattern,
// RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str);
// (See below)
//
// If you are going to pass one of the most used modifiers, there are some
// convenience functions that return a RE_Options class with the
// appropriate modifier already set:
// CASELESS(), UTF8(), MULTILINE(), DOTALL(), EXTENDED()
//
// If you need to set several options at once, and you don't want to go
// through the pains of declaring a RE_Options object and setting several
// options, there is a parallel method that give you such ability on the
// fly. You can concatenate several set_xxxxx member functions, since each
// of them returns a reference to its class object. e.g.: to pass
// PCRE_CASELESS, PCRE_EXTENDED, and PCRE_MULTILINE to a RE with one
// statement, you may write
//
// RE(" ^ xyz \\s+ .* blah$", RE_Options()
// .set_caseless(true)
// .set_extended(true)
// .set_multiline(true)).PartialMatch(sometext);
//
// -----------------------------------------------------------------------
// SCANNING TEXT INCREMENTALLY
//
// The "Consume" operation may be useful if you want to repeatedly
// match regular expressions at the front of a string and skip over
// them as they match. This requires use of the "StringPiece" type,
// which represents a sub-range of a real string. Like RE, StringPiece
// is defined in the pcrecpp namespace.
//
// Example: read lines of the form "var = value" from a string.
// string contents = ...; // Fill string somehow
// pcrecpp::StringPiece input(contents); // Wrap in a StringPiece
//
// string var;
// int value;
// pcrecpp::RE re("(\\w+) = (\\d+)\n");
// while (re.Consume(&input, &var, &value)) {
// ...;
// }
//
// Each successful call to "Consume" will set "var/value", and also
// advance "input" so it points past the matched text.
//
// The "FindAndConsume" operation is similar to "Consume" but does not
// anchor your match at the beginning of the string. For example, you
// could extract all words from a string by repeatedly calling
// pcrecpp::RE("(\\w+)").FindAndConsume(&input, &word)
//
// -----------------------------------------------------------------------
// PARSING HEX/OCTAL/C-RADIX NUMBERS
//
// By default, if you pass a pointer to a numeric value, the
// corresponding text is interpreted as a base-10 number. You can
// instead wrap the pointer with a call to one of the operators Hex(),
// Octal(), or CRadix() to interpret the text in another base. The
// CRadix operator interprets C-style "0" (base-8) and "0x" (base-16)
// prefixes, but defaults to base-10.
//
// Example:
// int a, b, c, d;
// pcrecpp::RE re("(.*) (.*) (.*) (.*)");
// re.FullMatch("100 40 0100 0x40",
// pcrecpp::Octal(&a), pcrecpp::Hex(&b),
// pcrecpp::CRadix(&c), pcrecpp::CRadix(&d));
// will leave 64 in a, b, c, and d.
//
// -----------------------------------------------------------------------
// REPLACING PARTS OF STRINGS
//
// You can replace the first match of "pattern" in "str" with
// "rewrite". Within "rewrite", backslash-escaped digits (\1 to \9)
// can be used to insert text matching corresponding parenthesized
// group from the pattern. \0 in "rewrite" refers to the entire
// matching text. E.g.,
//
// string s = "yabba dabba doo";
// pcrecpp::RE("b+").Replace("d", &s);
//
// will leave "s" containing "yada dabba doo". The result is true if
// the pattern matches and a replacement occurs, or false otherwise.
//
// GlobalReplace() is like Replace(), except that it replaces all
// occurrences of the pattern in the string with the rewrite.
// Replacements are not subject to re-matching. E.g.,
//
// string s = "yabba dabba doo";
// pcrecpp::RE("b+").GlobalReplace("d", &s);
//
// will leave "s" containing "yada dada doo". It returns the number
// of replacements made.
//
// Extract() is like Replace(), except that if the pattern matches,
// "rewrite" is copied into "out" (an additional argument) with
// substitutions. The non-matching portions of "text" are ignored.
// Returns true iff a match occurred and the extraction happened
// successfully. If no match occurs, the string is left unaffected.
#include <string>
#include <pcre.h>
#include <pcrecpparg.h> // defines the Arg class
// This isn't technically needed here, but we include it
// anyway so folks who include pcrecpp.h don't have to.
#include <pcre_stringpiece.h>
namespace pcrecpp {
#define PCRE_SET_OR_CLEAR(b, o) \
if (b) all_options_ |= (o); else all_options_ &= ~(o); \
return *this
#define PCRE_IS_SET(o) \
(all_options_ & o) == o
/***** Compiling regular expressions: the RE class *****/
// RE_Options allow you to set options to be passed along to pcre,
// along with other options we put on top of pcre.
// Only 9 modifiers, plus match_limit and match_limit_recursion,
// are supported now.
class PCRECPP_EXP_DEFN RE_Options {
public:
// constructor
RE_Options() : match_limit_(0), match_limit_recursion_(0), all_options_(0) {}
// alternative constructor.
// To facilitate transfer of legacy code from C programs
//
// This lets you do
// RE(pattern, RE_Options(PCRE_CASELESS|PCRE_MULTILINE)).PartialMatch(str);
// But new code is better off doing
// RE(pattern,
// RE_Options().set_caseless(true).set_multiline(true)).PartialMatch(str);
RE_Options(int option_flags) : match_limit_(0), match_limit_recursion_(0),
all_options_(option_flags) {}
// we're fine with the default destructor, copy constructor, etc.
// accessors and mutators
int match_limit() const { return match_limit_; };
RE_Options &set_match_limit(int limit) {
match_limit_ = limit;
return *this;
}
int match_limit_recursion() const { return match_limit_recursion_; };
RE_Options &set_match_limit_recursion(int limit) {
match_limit_recursion_ = limit;
return *this;
}
bool caseless() const {
return PCRE_IS_SET(PCRE_CASELESS);
}
RE_Options &set_caseless(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_CASELESS);
}
bool multiline() const {
return PCRE_IS_SET(PCRE_MULTILINE);
}
RE_Options &set_multiline(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_MULTILINE);
}
bool dotall() const {
return PCRE_IS_SET(PCRE_DOTALL);
}
RE_Options &set_dotall(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_DOTALL);
}
bool extended() const {
return PCRE_IS_SET(PCRE_EXTENDED);
}
RE_Options &set_extended(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_EXTENDED);
}
bool dollar_endonly() const {
return PCRE_IS_SET(PCRE_DOLLAR_ENDONLY);
}
RE_Options &set_dollar_endonly(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_DOLLAR_ENDONLY);
}
bool extra() const {
return PCRE_IS_SET(PCRE_EXTRA);
}
RE_Options &set_extra(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_EXTRA);
}
bool ungreedy() const {
return PCRE_IS_SET(PCRE_UNGREEDY);
}
RE_Options &set_ungreedy(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_UNGREEDY);
}
bool utf8() const {
return PCRE_IS_SET(PCRE_UTF8);
}
RE_Options &set_utf8(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_UTF8);
}
bool no_auto_capture() const {
return PCRE_IS_SET(PCRE_NO_AUTO_CAPTURE);
}
RE_Options &set_no_auto_capture(bool x) {
PCRE_SET_OR_CLEAR(x, PCRE_NO_AUTO_CAPTURE);
}
RE_Options &set_all_options(int opt) {
all_options_ = opt;
return *this;
}
int all_options() const {
return all_options_ ;
}
// TODO: add other pcre flags
private:
int match_limit_;
int match_limit_recursion_;
int all_options_;
};
// These functions return some common RE_Options
static inline RE_Options UTF8() {
return RE_Options().set_utf8(true);
}
static inline RE_Options CASELESS() {
return RE_Options().set_caseless(true);
}
static inline RE_Options MULTILINE() {
return RE_Options().set_multiline(true);
}
static inline RE_Options DOTALL() {
return RE_Options().set_dotall(true);
}
static inline RE_Options EXTENDED() {
return RE_Options().set_extended(true);
}
// Interface for regular expression matching. Also corresponds to a
// pre-compiled regular expression. An "RE" object is safe for
// concurrent use by multiple threads.
class PCRECPP_EXP_DEFN RE {
public:
// We provide implicit conversions from strings so that users can
// pass in a string or a "const char*" wherever an "RE" is expected.
RE(const string& pat) { Init(pat, NULL); }
RE(const string& pat, const RE_Options& option) { Init(pat, &option); }
RE(const char* pat) { Init(pat, NULL); }
RE(const char* pat, const RE_Options& option) { Init(pat, &option); }
RE(const unsigned char* pat) {
Init(reinterpret_cast<const char*>(pat), NULL);
}
RE(const unsigned char* pat, const RE_Options& option) {
Init(reinterpret_cast<const char*>(pat), &option);
}
// Copy constructor & assignment - note that these are expensive
// because they recompile the expression.
RE(const RE& re) { Init(re.pattern_, &re.options_); }
const RE& operator=(const RE& re) {
if (this != &re) {
Cleanup();
// This is the code that originally came from Google
// Init(re.pattern_.c_str(), &re.options_);
// This is the replacement from Ari Pollak
Init(re.pattern_, &re.options_);
}
return *this;
}
~RE();
// The string specification for this RE. E.g.
// RE re("ab*c?d+");
// re.pattern(); // "ab*c?d+"
const string& pattern() const { return pattern_; }
// If RE could not be created properly, returns an error string.
// Else returns the empty string.
const string& error() const { return *error_; }
/***** The useful part: the matching interface *****/
// This is provided so one can do pattern.ReplaceAll() just as
// easily as ReplaceAll(pattern-text, ....)
bool FullMatch(const StringPiece& text,
const Arg& ptr1 = no_arg,
const Arg& ptr2 = no_arg,
const Arg& ptr3 = no_arg,
const Arg& ptr4 = no_arg,
const Arg& ptr5 = no_arg,
const Arg& ptr6 = no_arg,
const Arg& ptr7 = no_arg,
const Arg& ptr8 = no_arg,
const Arg& ptr9 = no_arg,
const Arg& ptr10 = no_arg,
const Arg& ptr11 = no_arg,
const Arg& ptr12 = no_arg,
const Arg& ptr13 = no_arg,
const Arg& ptr14 = no_arg,
const Arg& ptr15 = no_arg,
const Arg& ptr16 = no_arg) const;
bool PartialMatch(const StringPiece& text,
const Arg& ptr1 = no_arg,
const Arg& ptr2 = no_arg,
const Arg& ptr3 = no_arg,
const Arg& ptr4 = no_arg,
const Arg& ptr5 = no_arg,
const Arg& ptr6 = no_arg,
const Arg& ptr7 = no_arg,
const Arg& ptr8 = no_arg,
const Arg& ptr9 = no_arg,
const Arg& ptr10 = no_arg,
const Arg& ptr11 = no_arg,
const Arg& ptr12 = no_arg,
const Arg& ptr13 = no_arg,
const Arg& ptr14 = no_arg,
const Arg& ptr15 = no_arg,
const Arg& ptr16 = no_arg) const;
bool Consume(StringPiece* input,
const Arg& ptr1 = no_arg,
const Arg& ptr2 = no_arg,
const Arg& ptr3 = no_arg,
const Arg& ptr4 = no_arg,
const Arg& ptr5 = no_arg,
const Arg& ptr6 = no_arg,
const Arg& ptr7 = no_arg,
const Arg& ptr8 = no_arg,
const Arg& ptr9 = no_arg,
const Arg& ptr10 = no_arg,
const Arg& ptr11 = no_arg,
const Arg& ptr12 = no_arg,
const Arg& ptr13 = no_arg,
const Arg& ptr14 = no_arg,
const Arg& ptr15 = no_arg,
const Arg& ptr16 = no_arg) const;
bool FindAndConsume(StringPiece* input,
const Arg& ptr1 = no_arg,
const Arg& ptr2 = no_arg,
const Arg& ptr3 = no_arg,
const Arg& ptr4 = no_arg,
const Arg& ptr5 = no_arg,
const Arg& ptr6 = no_arg,
const Arg& ptr7 = no_arg,
const Arg& ptr8 = no_arg,
const Arg& ptr9 = no_arg,
const Arg& ptr10 = no_arg,
const Arg& ptr11 = no_arg,
const Arg& ptr12 = no_arg,
const Arg& ptr13 = no_arg,
const Arg& ptr14 = no_arg,
const Arg& ptr15 = no_arg,
const Arg& ptr16 = no_arg) const;
bool Replace(const StringPiece& rewrite,
string *str) const;
int GlobalReplace(const StringPiece& rewrite,
string *str) const;
bool Extract(const StringPiece &rewrite,
const StringPiece &text,
string *out) const;
// Escapes all potentially meaningful regexp characters in
// 'unquoted'. The returned string, used as a regular expression,
// will exactly match the original string. For example,
// 1.5-2.0?
// may become:
// 1\.5\-2\.0\?
// Note QuoteMeta behaves the same as perl's QuoteMeta function,
// *except* that it escapes the NUL character (\0) as backslash + 0,
// rather than backslash + NUL.
static string QuoteMeta(const StringPiece& unquoted);
/***** Generic matching interface *****/
// Type of match (TODO: Should be restructured as part of RE_Options)
enum Anchor {
UNANCHORED, // No anchoring
ANCHOR_START, // Anchor at start only
ANCHOR_BOTH // Anchor at start and end
};
// General matching routine. Stores the length of the match in
// "*consumed" if successful.
bool DoMatch(const StringPiece& text,
Anchor anchor,
int* consumed,
const Arg* const* args, int n) const;
// Return the number of capturing subpatterns, or -1 if the
// regexp wasn't valid on construction.
int NumberOfCapturingGroups() const;
// The default value for an argument, to indicate the end of the argument
// list. This must be used only in optional argument defaults. It should NOT
// be passed explicitly. Some people have tried to use it like this:
//
// FullMatch(x, y, &z, no_arg, &w);
//
// This is a mistake, and will not work.
static Arg no_arg;
private:
void Init(const string& pattern, const RE_Options* options);
void Cleanup();
// Match against "text", filling in "vec" (up to "vecsize" * 2/3) with
// pairs of integers for the beginning and end positions of matched
// text. The first pair corresponds to the entire matched text;
// subsequent pairs correspond, in order, to parentheses-captured
// matches. Returns the number of pairs (one more than the number of
// the last subpattern with a match) if matching was successful
// and zero if the match failed.
// I.e. for RE("(foo)|(bar)|(baz)") it will return 2, 3, and 4 when matching
// against "foo", "bar", and "baz" respectively.
// When matching RE("(foo)|hello") against "hello", it will return 1.
// But the values for all subpattern are filled in into "vec".
int TryMatch(const StringPiece& text,
int startpos,
Anchor anchor,
bool empty_ok,
int *vec,
int vecsize) const;
// Append the "rewrite" string, with backslash subsitutions from "text"
// and "vec", to string "out".
bool Rewrite(string *out,
const StringPiece& rewrite,
const StringPiece& text,
int *vec,
int veclen) const;
// internal implementation for DoMatch
bool DoMatchImpl(const StringPiece& text,
Anchor anchor,
int* consumed,
const Arg* const args[],
int n,
int* vec,
int vecsize) const;
// Compile the regexp for the specified anchoring mode
pcre* Compile(Anchor anchor);
string pattern_;
RE_Options options_;
pcre* re_full_; // For full matches
pcre* re_partial_; // For partial matches
const string* error_; // Error indicator (or points to empty string)
};
} // namespace pcrecpp
#endif /* _PCRECPP_H */

174
third-party/libpcre/include/pcrecpparg.h vendored Normal file
View File

@ -0,0 +1,174 @@
// Copyright (c) 2005, Google Inc.
// 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 Google Inc. nor the names of its
// 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.
//
// Author: Sanjay Ghemawat
#ifndef _PCRECPPARG_H
#define _PCRECPPARG_H
#include <stdlib.h> // for NULL
#include <string>
#include <pcre.h>
namespace pcrecpp {
class StringPiece;
// Hex/Octal/Binary?
// Special class for parsing into objects that define a ParseFrom() method
template <class T>
class _RE_MatchObject {
public:
static inline bool Parse(const char* str, int n, void* dest) {
if (dest == NULL) return true;
T* object = reinterpret_cast<T*>(dest);
return object->ParseFrom(str, n);
}
};
class PCRECPP_EXP_DEFN Arg {
public:
// Empty constructor so we can declare arrays of Arg
Arg();
// Constructor specially designed for NULL arguments
Arg(void*);
typedef bool (*Parser)(const char* str, int n, void* dest);
// Type-specific parsers
#define PCRE_MAKE_PARSER(type,name) \
Arg(type* p) : arg_(p), parser_(name) { } \
Arg(type* p, Parser parser) : arg_(p), parser_(parser) { }
PCRE_MAKE_PARSER(char, parse_char);
PCRE_MAKE_PARSER(unsigned char, parse_uchar);
PCRE_MAKE_PARSER(short, parse_short);
PCRE_MAKE_PARSER(unsigned short, parse_ushort);
PCRE_MAKE_PARSER(int, parse_int);
PCRE_MAKE_PARSER(unsigned int, parse_uint);
PCRE_MAKE_PARSER(long, parse_long);
PCRE_MAKE_PARSER(unsigned long, parse_ulong);
#if 1
PCRE_MAKE_PARSER(long long, parse_longlong);
#endif
#if 1
PCRE_MAKE_PARSER(unsigned long long, parse_ulonglong);
#endif
PCRE_MAKE_PARSER(float, parse_float);
PCRE_MAKE_PARSER(double, parse_double);
PCRE_MAKE_PARSER(std::string, parse_string);
PCRE_MAKE_PARSER(StringPiece, parse_stringpiece);
#undef PCRE_MAKE_PARSER
// Generic constructor
template <class T> Arg(T*, Parser parser);
// Generic constructor template
template <class T> Arg(T* p)
: arg_(p), parser_(_RE_MatchObject<T>::Parse) {
}
// Parse the data
bool Parse(const char* str, int n) const;
private:
void* arg_;
Parser parser_;
static bool parse_null (const char* str, int n, void* dest);
static bool parse_char (const char* str, int n, void* dest);
static bool parse_uchar (const char* str, int n, void* dest);
static bool parse_float (const char* str, int n, void* dest);
static bool parse_double (const char* str, int n, void* dest);
static bool parse_string (const char* str, int n, void* dest);
static bool parse_stringpiece (const char* str, int n, void* dest);
#define PCRE_DECLARE_INTEGER_PARSER(name) \
private: \
static bool parse_ ## name(const char* str, int n, void* dest); \
static bool parse_ ## name ## _radix( \
const char* str, int n, void* dest, int radix); \
public: \
static bool parse_ ## name ## _hex(const char* str, int n, void* dest); \
static bool parse_ ## name ## _octal(const char* str, int n, void* dest); \
static bool parse_ ## name ## _cradix(const char* str, int n, void* dest)
PCRE_DECLARE_INTEGER_PARSER(short);
PCRE_DECLARE_INTEGER_PARSER(ushort);
PCRE_DECLARE_INTEGER_PARSER(int);
PCRE_DECLARE_INTEGER_PARSER(uint);
PCRE_DECLARE_INTEGER_PARSER(long);
PCRE_DECLARE_INTEGER_PARSER(ulong);
PCRE_DECLARE_INTEGER_PARSER(longlong);
PCRE_DECLARE_INTEGER_PARSER(ulonglong);
#undef PCRE_DECLARE_INTEGER_PARSER
};
inline Arg::Arg() : arg_(NULL), parser_(parse_null) { }
inline Arg::Arg(void* p) : arg_(p), parser_(parse_null) { }
inline bool Arg::Parse(const char* str, int n) const {
return (*parser_)(str, n, arg_);
}
// This part of the parser, appropriate only for ints, deals with bases
#define MAKE_INTEGER_PARSER(type, name) \
inline Arg Hex(type* ptr) { \
return Arg(ptr, Arg::parse_ ## name ## _hex); } \
inline Arg Octal(type* ptr) { \
return Arg(ptr, Arg::parse_ ## name ## _octal); } \
inline Arg CRadix(type* ptr) { \
return Arg(ptr, Arg::parse_ ## name ## _cradix); }
MAKE_INTEGER_PARSER(short, short) /* */
MAKE_INTEGER_PARSER(unsigned short, ushort) /* */
MAKE_INTEGER_PARSER(int, int) /* Don't use semicolons */
MAKE_INTEGER_PARSER(unsigned int, uint) /* after these statement */
MAKE_INTEGER_PARSER(long, long) /* because they can cause */
MAKE_INTEGER_PARSER(unsigned long, ulong) /* compiler warnings if */
#if 1 /* the checking level is */
MAKE_INTEGER_PARSER(long long, longlong) /* turned up high enough. */
#endif /* */
#if 1 /* */
MAKE_INTEGER_PARSER(unsigned long long, ulonglong) /* */
#endif
#undef PCRE_IS_SET
#undef PCRE_SET_OR_CLEAR
#undef MAKE_INTEGER_PARSER
} // namespace pcrecpp
#endif /* _PCRECPPARG_H */

146
third-party/libpcre/include/pcreposix.h vendored Normal file
View File

@ -0,0 +1,146 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
#ifndef _PCREPOSIX_H
#define _PCREPOSIX_H
/* This is the header for the POSIX wrapper interface to the PCRE Perl-
Compatible Regular Expression library. It defines the things POSIX says should
be there. I hope.
Copyright (c) 1997-2012 University of Cambridge
-----------------------------------------------------------------------------
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 the University of Cambridge nor the names of its
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.
-----------------------------------------------------------------------------
*/
/* Have to include stdlib.h in order to ensure that size_t is defined. */
#include <stdlib.h>
/* Allow for C++ users */
#ifdef __cplusplus
extern "C" {
#endif
/* Options, mostly defined by POSIX, but with some extras. */
#define REG_ICASE 0x0001 /* Maps to PCRE_CASELESS */
#define REG_NEWLINE 0x0002 /* Maps to PCRE_MULTILINE */
#define REG_NOTBOL 0x0004 /* Maps to PCRE_NOTBOL */
#define REG_NOTEOL 0x0008 /* Maps to PCRE_NOTEOL */
#define REG_DOTALL 0x0010 /* NOT defined by POSIX; maps to PCRE_DOTALL */
#define REG_NOSUB 0x0020 /* Maps to PCRE_NO_AUTO_CAPTURE */
#define REG_UTF8 0x0040 /* NOT defined by POSIX; maps to PCRE_UTF8 */
#define REG_STARTEND 0x0080 /* BSD feature: pass subject string by so,eo */
#define REG_NOTEMPTY 0x0100 /* NOT defined by POSIX; maps to PCRE_NOTEMPTY */
#define REG_UNGREEDY 0x0200 /* NOT defined by POSIX; maps to PCRE_UNGREEDY */
#define REG_UCP 0x0400 /* NOT defined by POSIX; maps to PCRE_UCP */
/* This is not used by PCRE, but by defining it we make it easier
to slot PCRE into existing programs that make POSIX calls. */
#define REG_EXTENDED 0
/* Error values. Not all these are relevant or used by the wrapper. */
enum {
REG_ASSERT = 1, /* internal error ? */
REG_BADBR, /* invalid repeat counts in {} */
REG_BADPAT, /* pattern error */
REG_BADRPT, /* ? * + invalid */
REG_EBRACE, /* unbalanced {} */
REG_EBRACK, /* unbalanced [] */
REG_ECOLLATE, /* collation error - not relevant */
REG_ECTYPE, /* bad class */
REG_EESCAPE, /* bad escape sequence */
REG_EMPTY, /* empty expression */
REG_EPAREN, /* unbalanced () */
REG_ERANGE, /* bad range inside [] */
REG_ESIZE, /* expression too big */
REG_ESPACE, /* failed to get memory */
REG_ESUBREG, /* bad back reference */
REG_INVARG, /* bad argument */
REG_NOMATCH /* match failed */
};
/* The structure representing a compiled regular expression. */
typedef struct {
void *re_pcre;
size_t re_nsub;
size_t re_erroffset;
} regex_t;
/* The structure in which a captured offset is returned. */
typedef int regoff_t;
typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
export settings are needed, and are set in pcreposix.c before including this
file. */
#if defined(_WIN32) && !defined(PCRE_STATIC) && !defined(PCREPOSIX_EXP_DECL)
# define PCREPOSIX_EXP_DECL extern __declspec(dllimport)
# define PCREPOSIX_EXP_DEFN __declspec(dllimport)
#endif
/* By default, we use the standard "extern" declarations. */
#ifndef PCREPOSIX_EXP_DECL
# ifdef __cplusplus
# define PCREPOSIX_EXP_DECL extern "C"
# define PCREPOSIX_EXP_DEFN extern "C"
# else
# define PCREPOSIX_EXP_DECL extern
# define PCREPOSIX_EXP_DEFN extern
# endif
#endif
/* The functions */
PCREPOSIX_EXP_DECL int regcomp(regex_t *, const char *, int);
PCREPOSIX_EXP_DECL int regexec(const regex_t *, const char *, size_t,
regmatch_t *, int);
PCREPOSIX_EXP_DECL size_t regerror(int, const regex_t *, char *, size_t);
PCREPOSIX_EXP_DECL void regfree(regex_t *);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* End of pcreposix.h */

3
third-party/libpcre/lib/libpcre.1.dylib vendored Executable file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:52e5aa3f2246d84fc74f8ec5fbe15a2b61b8494bba32a2d1d6509853ab93c307
size 654340

3
third-party/libpcre/lib/libpcre.a vendored Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fef5947e8a3f84de4aee965e5f9f1123966c9910ef9502ee43b07070f89ebbdf
size 721312

1
third-party/libpcre/lib/libpcre.dylib vendored Symbolic link
View File

@ -0,0 +1 @@
libpcre.1.dylib

41
third-party/libpcre/lib/libpcre.la vendored Executable file
View File

@ -0,0 +1,41 @@
# libpcre.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6.42-b88ce
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpcre.1.dylib'
# Names of this library.
library_names='libpcre.1.dylib libpcre.dylib'
# The name of the static archive.
old_library='libpcre.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpcre.
current=3
age=2
revision=11
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib'

3
third-party/libpcre/lib/libpcre16.0.dylib vendored Executable file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:551a2bcb404a54be6ef6ab736afcb7627c19811e6b89eb2d82c4c4a0b2748846
size 592844

3
third-party/libpcre/lib/libpcre16.a vendored Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e3a9ecf7e4185f52da12582ebae779cf035d965c664604ff64a8474a35ca16cb
size 659920

1
third-party/libpcre/lib/libpcre16.dylib vendored Symbolic link
View File

@ -0,0 +1 @@
libpcre16.0.dylib

41
third-party/libpcre/lib/libpcre16.la vendored Executable file
View File

@ -0,0 +1,41 @@
# libpcre16.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6.42-b88ce
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpcre16.0.dylib'
# Names of this library.
library_names='libpcre16.0.dylib libpcre16.dylib'
# The name of the static archive.
old_library='libpcre16.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpcre16.
current=2
age=2
revision=11
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib'

3
third-party/libpcre/lib/libpcre32.0.dylib vendored Executable file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4e4798fe9c0bb6022859f2cab8aea6281595f93d02d7b9d259b7de8698c008a2
size 572492

3
third-party/libpcre/lib/libpcre32.a vendored Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:28ee632d8c2220d3e6cfc453a13401ae9fb07067ddebb488c45af03d66e77f3a
size 639864

1
third-party/libpcre/lib/libpcre32.dylib vendored Symbolic link
View File

@ -0,0 +1 @@
libpcre32.0.dylib

41
third-party/libpcre/lib/libpcre32.la vendored Executable file
View File

@ -0,0 +1,41 @@
# libpcre32.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6.42-b88ce
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpcre32.0.dylib'
# Names of this library.
library_names='libpcre32.0.dylib libpcre32.dylib'
# The name of the static archive.
old_library='libpcre32.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=''
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpcre32.
current=0
age=0
revision=11
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib'

3
third-party/libpcre/lib/libpcrecpp.0.dylib vendored Executable file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c2b75c8667fcb3b98434bab78e3ca4ac5fad4a89846038b024a4b88aa2783151
size 45184

3
third-party/libpcre/lib/libpcrecpp.a vendored Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b15f03c25c3bc3226c5efb611b4ff956b5ec957a53ae8e9000a86cc88f60c4b3
size 47336

1
third-party/libpcre/lib/libpcrecpp.dylib vendored Symbolic link
View File

@ -0,0 +1 @@
libpcrecpp.0.dylib

41
third-party/libpcre/lib/libpcrecpp.la vendored Executable file
View File

@ -0,0 +1,41 @@
# libpcrecpp.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6.42-b88ce
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpcrecpp.0.dylib'
# Names of this library.
library_names='libpcrecpp.0.dylib libpcrecpp.dylib'
# The name of the static archive.
old_library='libpcrecpp.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=' /Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib/libpcre.la'
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpcrecpp.
current=0
age=0
revision=1
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib'

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:45c900d74a340ad53d709b0054b1a0f4b14281d24506b2595aa5ed3299fed634
size 13208

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a4bb917a427de0d20ba1eb8e87d1dfeb3e053486c0067d014791f19b7f1c29a1
size 5336

View File

@ -0,0 +1 @@
libpcreposix.0.dylib

41
third-party/libpcre/lib/libpcreposix.la vendored Executable file
View File

@ -0,0 +1,41 @@
# libpcreposix.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6.42-b88ce
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libpcreposix.0.dylib'
# Names of this library.
library_names='libpcreposix.0.dylib libpcreposix.dylib'
# The name of the static archive.
old_library='libpcreposix.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=' /Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib/libpcre.la'
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libpcreposix.
current=0
age=0
revision=6
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/hat/vimr/.deps/pcre/../../third-party/libpcre/lib'

View File

@ -0,0 +1,13 @@
# Package Information for pkg-config
prefix=/Users/hat/vimr/.deps/pcre/../../third-party/libpcre
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libpcre
Description: PCRE - Perl compatible regular expressions C library with 8 bit character support
Version: 8.43
Libs: -L${libdir} -lpcre
Libs.private: -D_THREAD_SAFE -pthread
Cflags: -I${includedir}

View File

@ -0,0 +1,13 @@
# Package Information for pkg-config
prefix=/Users/hat/vimr/.deps/pcre/../../third-party/libpcre
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libpcre16
Description: PCRE - Perl compatible regular expressions C library with 16 bit character support
Version: 8.43
Libs: -L${libdir} -lpcre16
Libs.private: -D_THREAD_SAFE -pthread
Cflags: -I${includedir}

View File

@ -0,0 +1,13 @@
# Package Information for pkg-config
prefix=/Users/hat/vimr/.deps/pcre/../../third-party/libpcre
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libpcre32
Description: PCRE - Perl compatible regular expressions C library with 32 bit character support
Version: 8.43
Libs: -L${libdir} -lpcre32
Libs.private: -D_THREAD_SAFE -pthread
Cflags: -I${includedir}

View File

@ -0,0 +1,12 @@
# Package Information for pkg-config
prefix=/Users/hat/vimr/.deps/pcre/../../third-party/libpcre
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libpcrecpp
Description: PCRECPP - C++ wrapper for PCRE
Version: 8.43
Libs: -L${libdir} -lpcre -lpcrecpp
Cflags: -I${includedir}

View File

@ -0,0 +1,13 @@
# Package Information for pkg-config
prefix=/Users/hat/vimr/.deps/pcre/../../third-party/libpcre
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libpcreposix
Description: PCREPosix - Posix compatible interface to libpcre
Version: 8.43
Libs: -L${libdir} -lpcreposix
Cflags: -I${includedir}
Requires.private: libpcre

325
third-party/libxz/include/lzma.h vendored Normal file
View File

@ -0,0 +1,325 @@
/**
* \file api/lzma.h
* \brief The public API of liblzma data compression library
*
* liblzma is a public domain general-purpose data compression library with
* a zlib-like API. The native file format is .xz, but also the old .lzma
* format and raw (no headers) streams are supported. Multiple compression
* algorithms (filters) are supported. Currently LZMA2 is the primary filter.
*
* liblzma is part of XZ Utils <http://tukaani.org/xz/>. XZ Utils includes
* a gzip-like command line tool named xz and some other tools. XZ Utils
* is developed and maintained by Lasse Collin.
*
* Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK
* <http://7-zip.org/sdk.html>.
*
* The SHA-256 implementation is based on the public domain code found from
* 7-Zip <http://7-zip.org/>, which has a modified version of the public
* domain SHA-256 code found from Crypto++ <http://www.cryptopp.com/>.
* The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai.
*/
/*
* Author: Lasse Collin
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
#ifndef LZMA_H
#define LZMA_H
/*****************************
* Required standard headers *
*****************************/
/*
* liblzma API headers need some standard types and macros. To allow
* including lzma.h without requiring the application to include other
* headers first, lzma.h includes the required standard headers unless
* they already seem to be included already or if LZMA_MANUAL_HEADERS
* has been defined.
*
* Here's what types and macros are needed and from which headers:
* - stddef.h: size_t, NULL
* - stdint.h: uint8_t, uint32_t, uint64_t, UINT32_C(n), uint64_C(n),
* UINT32_MAX, UINT64_MAX
*
* However, inttypes.h is a little more portable than stdint.h, although
* inttypes.h declares some unneeded things compared to plain stdint.h.
*
* The hacks below aren't perfect, specifically they assume that inttypes.h
* exists and that it typedefs at least uint8_t, uint32_t, and uint64_t,
* and that, in case of incomplete inttypes.h, unsigned int is 32-bit.
* If the application already takes care of setting up all the types and
* macros properly (for example by using gnulib's stdint.h or inttypes.h),
* we try to detect that the macros are already defined and don't include
* inttypes.h here again. However, you may define LZMA_MANUAL_HEADERS to
* force this file to never include any system headers.
*
* Some could argue that liblzma API should provide all the required types,
* for example lzma_uint64, LZMA_UINT64_C(n), and LZMA_UINT64_MAX. This was
* seen as an unnecessary mess, since most systems already provide all the
* necessary types and macros in the standard headers.
*
* Note that liblzma API still has lzma_bool, because using stdbool.h would
* break C89 and C++ programs on many systems. sizeof(bool) in C99 isn't
* necessarily the same as sizeof(bool) in C++.
*/
#ifndef LZMA_MANUAL_HEADERS
/*
* I suppose this works portably also in C++. Note that in C++,
* we need to get size_t into the global namespace.
*/
# include <stddef.h>
/*
* Skip inttypes.h if we already have all the required macros. If we
* have the macros, we assume that we have the matching typedefs too.
*/
# if !defined(UINT32_C) || !defined(UINT64_C) \
|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
/*
* MSVC versions older than 2013 have no C99 support, and
* thus they cannot be used to compile liblzma. Using an
* existing liblzma.dll with old MSVC can work though(*),
* but we need to define the required standard integer
* types here in a MSVC-specific way.
*
* (*) If you do this, the existing liblzma.dll probably uses
* a different runtime library than your MSVC-built
* application. Mixing runtimes is generally bad, but
* in this case it should work as long as you avoid
* the few rarely-needed liblzma functions that allocate
* memory and expect the caller to free it using free().
*/
# if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800
typedef unsigned __int8 uint8_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
# else
/* Use the standard inttypes.h. */
# ifdef __cplusplus
/*
* C99 sections 7.18.2 and 7.18.4 specify
* that C++ implementations define the limit
* and constant macros only if specifically
* requested. Note that if you want the
* format macros (PRIu64 etc.) too, you need
* to define __STDC_FORMAT_MACROS before
* including lzma.h, since re-including
* inttypes.h with __STDC_FORMAT_MACROS
* defined doesn't necessarily work.
*/
# ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS 1
# endif
# ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS 1
# endif
# endif
# include <inttypes.h>
# endif
/*
* Some old systems have only the typedefs in inttypes.h, and
* lack all the macros. For those systems, we need a few more
* hacks. We assume that unsigned int is 32-bit and unsigned
* long is either 32-bit or 64-bit. If these hacks aren't
* enough, the application has to setup the types manually
* before including lzma.h.
*/
# ifndef UINT32_C
# if defined(_WIN32) && defined(_MSC_VER)
# define UINT32_C(n) n ## UI32
# else
# define UINT32_C(n) n ## U
# endif
# endif
# ifndef UINT64_C
# if defined(_WIN32) && defined(_MSC_VER)
# define UINT64_C(n) n ## UI64
# else
/* Get ULONG_MAX. */
# include <limits.h>
# if ULONG_MAX == 4294967295UL
# define UINT64_C(n) n ## ULL
# else
# define UINT64_C(n) n ## UL
# endif
# endif
# endif
# ifndef UINT32_MAX
# define UINT32_MAX (UINT32_C(4294967295))
# endif
# ifndef UINT64_MAX
# define UINT64_MAX (UINT64_C(18446744073709551615))
# endif
# endif
#endif /* ifdef LZMA_MANUAL_HEADERS */
/******************
* LZMA_API macro *
******************/
/*
* Some systems require that the functions and function pointers are
* declared specially in the headers. LZMA_API_IMPORT is for importing
* symbols and LZMA_API_CALL is to specify the calling convention.
*
* By default it is assumed that the application will link dynamically
* against liblzma. #define LZMA_API_STATIC in your application if you
* want to link against static liblzma. If you don't care about portability
* to operating systems like Windows, or at least don't care about linking
* against static liblzma on them, don't worry about LZMA_API_STATIC. That
* is, most developers will never need to use LZMA_API_STATIC.
*
* The GCC variants are a special case on Windows (Cygwin and MinGW).
* We rely on GCC doing the right thing with its auto-import feature,
* and thus don't use __declspec(dllimport). This way developers don't
* need to worry about LZMA_API_STATIC. Also the calling convention is
* omitted on Cygwin but not on MinGW.
*/
#ifndef LZMA_API_IMPORT
# if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
# define LZMA_API_IMPORT __declspec(dllimport)
# else
# define LZMA_API_IMPORT
# endif
#endif
#ifndef LZMA_API_CALL
# if defined(_WIN32) && !defined(__CYGWIN__)
# define LZMA_API_CALL __cdecl
# else
# define LZMA_API_CALL
# endif
#endif
#ifndef LZMA_API
# define LZMA_API(type) LZMA_API_IMPORT type LZMA_API_CALL
#endif
/***********
* nothrow *
***********/
/*
* None of the functions in liblzma may throw an exception. Even
* the functions that use callback functions won't throw exceptions,
* because liblzma would break if a callback function threw an exception.
*/
#ifndef lzma_nothrow
# if defined(__cplusplus)
# if __cplusplus >= 201103L
# define lzma_nothrow noexcept
# else
# define lzma_nothrow throw()
# endif
# elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
# define lzma_nothrow __attribute__((__nothrow__))
# else
# define lzma_nothrow
# endif
#endif
/********************
* GNU C extensions *
********************/
/*
* GNU C extensions are used conditionally in the public API. It doesn't
* break anything if these are sometimes enabled and sometimes not, only
* affects warnings and optimizations.
*/
#if __GNUC__ >= 3
# ifndef lzma_attribute
# define lzma_attribute(attr) __attribute__(attr)
# endif
/* warn_unused_result was added in GCC 3.4. */
# ifndef lzma_attr_warn_unused_result
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
# define lzma_attr_warn_unused_result
# endif
# endif
#else
# ifndef lzma_attribute
# define lzma_attribute(attr)
# endif
#endif
#ifndef lzma_attr_pure
# define lzma_attr_pure lzma_attribute((__pure__))
#endif
#ifndef lzma_attr_const
# define lzma_attr_const lzma_attribute((__const__))
#endif
#ifndef lzma_attr_warn_unused_result
# define lzma_attr_warn_unused_result \
lzma_attribute((__warn_unused_result__))
#endif
/**************
* Subheaders *
**************/
#ifdef __cplusplus
extern "C" {
#endif
/*
* Subheaders check that this is defined. It is to prevent including
* them directly from applications.
*/
#define LZMA_H_INTERNAL 1
/* Basic features */
#include "lzma/version.h"
#include "lzma/base.h"
#include "lzma/vli.h"
#include "lzma/check.h"
/* Filters */
#include "lzma/filter.h"
#include "lzma/bcj.h"
#include "lzma/delta.h"
#include "lzma/lzma12.h"
/* Container formats */
#include "lzma/container.h"
/* Advanced features */
#include "lzma/stream_flags.h"
#include "lzma/block.h"
#include "lzma/index.h"
#include "lzma/index_hash.h"
/* Hardware information */
#include "lzma/hardware.h"
/*
* All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
* re-including the subheaders.
*/
#undef LZMA_H_INTERNAL
#ifdef __cplusplus
}
#endif
#endif /* ifndef LZMA_H */

659
third-party/libxz/include/lzma/base.h vendored Normal file
View File

@ -0,0 +1,659 @@
/**
* \file lzma/base.h
* \brief Data types and functions used in many places in liblzma API
*/
/*
* Author: Lasse Collin
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*
* See ../lzma.h for information about liblzma as a whole.
*/
#ifndef LZMA_H_INTERNAL
# error Never include this file directly. Use <lzma.h> instead.
#endif
/**
* \brief Boolean
*
* This is here because C89 doesn't have stdbool.h. To set a value for
* variables having type lzma_bool, you can use
* - C99's `true' and `false' from stdbool.h;
* - C++'s internal `true' and `false'; or
* - integers one (true) and zero (false).
*/
typedef unsigned char lzma_bool;
/**
* \brief Type of reserved enumeration variable in structures
*
* To avoid breaking library ABI when new features are added, several
* structures contain extra variables that may be used in future. Since
* sizeof(enum) can be different than sizeof(int), and sizeof(enum) may
* even vary depending on the range of enumeration constants, we specify
* a separate type to be used for reserved enumeration variables. All
* enumeration constants in liblzma API will be non-negative and less
* than 128, which should guarantee that the ABI won't break even when
* new constants are added to existing enumerations.
*/
typedef enum {
LZMA_RESERVED_ENUM = 0
} lzma_reserved_enum;
/**
* \brief Return values used by several functions in liblzma
*
* Check the descriptions of specific functions to find out which return
* values they can return. With some functions the return values may have
* more specific meanings than described here; those differences are
* described per-function basis.
*/
typedef enum {
LZMA_OK = 0,
/**<
* \brief Operation completed successfully
*/
LZMA_STREAM_END = 1,
/**<
* \brief End of stream was reached
*
* In encoder, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or
* LZMA_FINISH was finished. In decoder, this indicates
* that all the data was successfully decoded.
*
* In all cases, when LZMA_STREAM_END is returned, the last
* output bytes should be picked from strm->next_out.
*/
LZMA_NO_CHECK = 2,
/**<
* \brief Input stream has no integrity check
*
* This return value can be returned only if the
* LZMA_TELL_NO_CHECK flag was used when initializing
* the decoder. LZMA_NO_CHECK is just a warning, and
* the decoding can be continued normally.
*
* It is possible to call lzma_get_check() immediately after
* lzma_code has returned LZMA_NO_CHECK. The result will
* naturally be LZMA_CHECK_NONE, but the possibility to call
* lzma_get_check() may be convenient in some applications.
*/
LZMA_UNSUPPORTED_CHECK = 3,
/**<
* \brief Cannot calculate the integrity check
*
* The usage of this return value is different in encoders
* and decoders.
*
* Encoders can return this value only from the initialization
* function. If initialization fails with this value, the
* encoding cannot be done, because there's no way to produce
* output with the correct integrity check.
*
* Decoders can return this value only from lzma_code() and
* only if the LZMA_TELL_UNSUPPORTED_CHECK flag was used when
* initializing the decoder. The decoding can still be
* continued normally even if the check type is unsupported,
* but naturally the check will not be validated, and possible
* errors may go undetected.
*
* With decoder, it is possible to call lzma_get_check()
* immediately after lzma_code() has returned
* LZMA_UNSUPPORTED_CHECK. This way it is possible to find
* out what the unsupported Check ID was.
*/
LZMA_GET_CHECK = 4,
/**<
* \brief Integrity check type is now available
*
* This value can be returned only by the lzma_code() function
* and only if the decoder was initialized with the
* LZMA_TELL_ANY_CHECK flag. LZMA_GET_CHECK tells the
* application that it may now call lzma_get_check() to find
* out the Check ID. This can be used, for example, to
* implement a decoder that accepts only files that have
* strong enough integrity check.
*/
LZMA_MEM_ERROR = 5,
/**<
* \brief Cannot allocate memory
*
* Memory allocation failed, or the size of the allocation
* would be greater than SIZE_MAX.
*
* Due to internal implementation reasons, the coding cannot
* be continued even if more memory were made available after
* LZMA_MEM_ERROR.
*/
LZMA_MEMLIMIT_ERROR = 6,
/**
* \brief Memory usage limit was reached
*
* Decoder would need more memory than allowed by the
* specified memory usage limit. To continue decoding,
* the memory usage limit has to be increased with
* lzma_memlimit_set().
*/
LZMA_FORMAT_ERROR = 7,
/**<
* \brief File format not recognized
*
* The decoder did not recognize the input as supported file
* format. This error can occur, for example, when trying to
* decode .lzma format file with lzma_stream_decoder,
* because lzma_stream_decoder accepts only the .xz format.
*/
LZMA_OPTIONS_ERROR = 8,
/**<
* \brief Invalid or unsupported options
*
* Invalid or unsupported options, for example
* - unsupported filter(s) or filter options; or
* - reserved bits set in headers (decoder only).
*
* Rebuilding liblzma with more features enabled, or
* upgrading to a newer version of liblzma may help.
*/
LZMA_DATA_ERROR = 9,
/**<
* \brief Data is corrupt
*
* The usage of this return value is different in encoders
* and decoders. In both encoder and decoder, the coding
* cannot continue after this error.
*
* Encoders return this if size limits of the target file
* format would be exceeded. These limits are huge, thus
* getting this error from an encoder is mostly theoretical.
* For example, the maximum compressed and uncompressed
* size of a .xz Stream is roughly 8 EiB (2^63 bytes).
*
* Decoders return this error if the input data is corrupt.
* This can mean, for example, invalid CRC32 in headers
* or invalid check of uncompressed data.
*/
LZMA_BUF_ERROR = 10,
/**<
* \brief No progress is possible
*
* This error code is returned when the coder cannot consume
* any new input and produce any new output. The most common
* reason for this error is that the input stream being
* decoded is truncated or corrupt.
*
* This error is not fatal. Coding can be continued normally
* by providing more input and/or more output space, if
* possible.
*
* Typically the first call to lzma_code() that can do no
* progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only
* the second consecutive call doing no progress will return
* LZMA_BUF_ERROR. This is intentional.
*
* With zlib, Z_BUF_ERROR may be returned even if the
* application is doing nothing wrong, so apps will need
* to handle Z_BUF_ERROR specially. The above hack
* guarantees that liblzma never returns LZMA_BUF_ERROR
* to properly written applications unless the input file
* is truncated or corrupt. This should simplify the
* applications a little.
*/
LZMA_PROG_ERROR = 11,
/**<
* \brief Programming error
*
* This indicates that the arguments given to the function are
* invalid or the internal state of the decoder is corrupt.
* - Function arguments are invalid or the structures
* pointed by the argument pointers are invalid
* e.g. if strm->next_out has been set to NULL and
* strm->avail_out > 0 when calling lzma_code().
* - lzma_* functions have been called in wrong order
* e.g. lzma_code() was called right after lzma_end().
* - If errors occur randomly, the reason might be flaky
* hardware.
*
* If you think that your code is correct, this error code
* can be a sign of a bug in liblzma. See the documentation
* how to report bugs.
*/
} lzma_ret;
/**
* \brief The `action' argument for lzma_code()
*
* After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, LZMA_FULL_BARRIER,
* or LZMA_FINISH, the same `action' must is used until lzma_code() returns
* LZMA_STREAM_END. Also, the amount of input (that is, strm->avail_in) must
* not be modified by the application until lzma_code() returns
* LZMA_STREAM_END. Changing the `action' or modifying the amount of input
* will make lzma_code() return LZMA_PROG_ERROR.
*/
typedef enum {
LZMA_RUN = 0,
/**<
* \brief Continue coding
*
* Encoder: Encode as much input as possible. Some internal
* buffering will probably be done (depends on the filter
* chain in use), which causes latency: the input used won't
* usually be decodeable from the output of the same
* lzma_code() call.
*
* Decoder: Decode as much input as possible and produce as
* much output as possible.
*/
LZMA_SYNC_FLUSH = 1,
/**<
* \brief Make all the input available at output
*
* Normally the encoder introduces some latency.
* LZMA_SYNC_FLUSH forces all the buffered data to be
* available at output without resetting the internal
* state of the encoder. This way it is possible to use
* compressed stream for example for communication over
* network.
*
* Only some filters support LZMA_SYNC_FLUSH. Trying to use
* LZMA_SYNC_FLUSH with filters that don't support it will
* make lzma_code() return LZMA_OPTIONS_ERROR. For example,
* LZMA1 doesn't support LZMA_SYNC_FLUSH but LZMA2 does.
*
* Using LZMA_SYNC_FLUSH very often can dramatically reduce
* the compression ratio. With some filters (for example,
* LZMA2), fine-tuning the compression options may help
* mitigate this problem significantly (for example,
* match finder with LZMA2).
*
* Decoders don't support LZMA_SYNC_FLUSH.
*/
LZMA_FULL_FLUSH = 2,
/**<
* \brief Finish encoding of the current Block
*
* All the input data going to the current Block must have
* been given to the encoder (the last bytes can still be
* pending in *next_in). Call lzma_code() with LZMA_FULL_FLUSH
* until it returns LZMA_STREAM_END. Then continue normally
* with LZMA_RUN or finish the Stream with LZMA_FINISH.
*
* This action is currently supported only by Stream encoder
* and easy encoder (which uses Stream encoder). If there is
* no unfinished Block, no empty Block is created.
*/
LZMA_FULL_BARRIER = 4,
/**<
* \brief Finish encoding of the current Block
*
* This is like LZMA_FULL_FLUSH except that this doesn't
* necessarily wait until all the input has been made
* available via the output buffer. That is, lzma_code()
* might return LZMA_STREAM_END as soon as all the input
* has been consumed (avail_in == 0).
*
* LZMA_FULL_BARRIER is useful with a threaded encoder if
* one wants to split the .xz Stream into Blocks at specific
* offsets but doesn't care if the output isn't flushed
* immediately. Using LZMA_FULL_BARRIER allows keeping
* the threads busy while LZMA_FULL_FLUSH would make
* lzma_code() wait until all the threads have finished
* until more data could be passed to the encoder.
*
* With a lzma_stream initialized with the single-threaded
* lzma_stream_encoder() or lzma_easy_encoder(),
* LZMA_FULL_BARRIER is an alias for LZMA_FULL_FLUSH.
*/
LZMA_FINISH = 3
/**<
* \brief Finish the coding operation
*
* All the input data must have been given to the encoder
* (the last bytes can still be pending in next_in).
* Call lzma_code() with LZMA_FINISH until it returns
* LZMA_STREAM_END. Once LZMA_FINISH has been used,
* the amount of input must no longer be changed by
* the application.
*
* When decoding, using LZMA_FINISH is optional unless the
* LZMA_CONCATENATED flag was used when the decoder was
* initialized. When LZMA_CONCATENATED was not used, the only
* effect of LZMA_FINISH is that the amount of input must not
* be changed just like in the encoder.
*/
} lzma_action;
/**
* \brief Custom functions for memory handling
*
* A pointer to lzma_allocator may be passed via lzma_stream structure
* to liblzma, and some advanced functions take a pointer to lzma_allocator
* as a separate function argument. The library will use the functions
* specified in lzma_allocator for memory handling instead of the default
* malloc() and free(). C++ users should note that the custom memory
* handling functions must not throw exceptions.
*
* Single-threaded mode only: liblzma doesn't make an internal copy of
* lzma_allocator. Thus, it is OK to change these function pointers in
* the middle of the coding process, but obviously it must be done
* carefully to make sure that the replacement `free' can deallocate
* memory allocated by the earlier `alloc' function(s).
*
* Multithreaded mode: liblzma might internally store pointers to the
* lzma_allocator given via the lzma_stream structure. The application
* must not change the allocator pointer in lzma_stream or the contents
* of the pointed lzma_allocator structure until lzma_end() has been used
* to free the memory associated with that lzma_stream. The allocation
* functions might be called simultaneously from multiple threads, and
* thus they must be thread safe.
*/
typedef struct {
/**
* \brief Pointer to a custom memory allocation function
*
* If you don't want a custom allocator, but still want
* custom free(), set this to NULL and liblzma will use
* the standard malloc().
*
* \param opaque lzma_allocator.opaque (see below)
* \param nmemb Number of elements like in calloc(). liblzma
* will always set nmemb to 1, so it is safe to
* ignore nmemb in a custom allocator if you like.
* The nmemb argument exists only for
* compatibility with zlib and libbzip2.
* \param size Size of an element in bytes.
* liblzma never sets this to zero.
*
* \return Pointer to the beginning of a memory block of
* `size' bytes, or NULL if allocation fails
* for some reason. When allocation fails, functions
* of liblzma return LZMA_MEM_ERROR.
*
* The allocator should not waste time zeroing the allocated buffers.
* This is not only about speed, but also memory usage, since the
* operating system kernel doesn't necessarily allocate the requested
* memory in physical memory until it is actually used. With small
* input files, liblzma may actually need only a fraction of the
* memory that it requested for allocation.
*
* \note LZMA_MEM_ERROR is also used when the size of the
* allocation would be greater than SIZE_MAX. Thus,
* don't assume that the custom allocator must have
* returned NULL if some function from liblzma
* returns LZMA_MEM_ERROR.
*/
void *(LZMA_API_CALL *alloc)(void *opaque, size_t nmemb, size_t size);
/**
* \brief Pointer to a custom memory freeing function
*
* If you don't want a custom freeing function, but still
* want a custom allocator, set this to NULL and liblzma
* will use the standard free().
*
* \param opaque lzma_allocator.opaque (see below)
* \param ptr Pointer returned by lzma_allocator.alloc(),
* or when it is set to NULL, a pointer returned
* by the standard malloc().
*/
void (LZMA_API_CALL *free)(void *opaque, void *ptr);
/**
* \brief Pointer passed to .alloc() and .free()
*
* opaque is passed as the first argument to lzma_allocator.alloc()
* and lzma_allocator.free(). This intended to ease implementing
* custom memory allocation functions for use with liblzma.
*
* If you don't need this, you should set this to NULL.
*/
void *opaque;
} lzma_allocator;
/**
* \brief Internal data structure
*
* The contents of this structure is not visible outside the library.
*/
typedef struct lzma_internal_s lzma_internal;
/**
* \brief Passing data to and from liblzma
*
* The lzma_stream structure is used for
* - passing pointers to input and output buffers to liblzma;
* - defining custom memory hander functions; and
* - holding a pointer to coder-specific internal data structures.
*
* Typical usage:
*
* - After allocating lzma_stream (on stack or with malloc()), it must be
* initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details).
*
* - Initialize a coder to the lzma_stream, for example by using
* lzma_easy_encoder() or lzma_auto_decoder(). Some notes:
* - In contrast to zlib, strm->next_in and strm->next_out are
* ignored by all initialization functions, thus it is safe
* to not initialize them yet.
* - The initialization functions always set strm->total_in and
* strm->total_out to zero.
* - If the initialization function fails, no memory is left allocated
* that would require freeing with lzma_end() even if some memory was
* associated with the lzma_stream structure when the initialization
* function was called.
*
* - Use lzma_code() to do the actual work.
*
* - Once the coding has been finished, the existing lzma_stream can be
* reused. It is OK to reuse lzma_stream with different initialization
* function without calling lzma_end() first. Old allocations are
* automatically freed.
*
* - Finally, use lzma_end() to free the allocated memory. lzma_end() never
* frees the lzma_stream structure itself.
*
* Application may modify the values of total_in and total_out as it wants.
* They are updated by liblzma to match the amount of data read and
* written but aren't used for anything else except as a possible return
* values from lzma_get_progress().
*/
typedef struct {
const uint8_t *next_in; /**< Pointer to the next input byte. */
size_t avail_in; /**< Number of available input bytes in next_in. */
uint64_t total_in; /**< Total number of bytes read by liblzma. */
uint8_t *next_out; /**< Pointer to the next output position. */
size_t avail_out; /**< Amount of free space in next_out. */
uint64_t total_out; /**< Total number of bytes written by liblzma. */
/**
* \brief Custom memory allocation functions
*
* In most cases this is NULL which makes liblzma use
* the standard malloc() and free().
*
* \note In 5.0.x this is not a const pointer.
*/
const lzma_allocator *allocator;
/** Internal state is not visible to applications. */
lzma_internal *internal;
/*
* Reserved space to allow possible future extensions without
* breaking the ABI. Excluding the initialization of this structure,
* you should not touch these, because the names of these variables
* may change.
*/
void *reserved_ptr1;
void *reserved_ptr2;
void *reserved_ptr3;
void *reserved_ptr4;
uint64_t reserved_int1;
uint64_t reserved_int2;
size_t reserved_int3;
size_t reserved_int4;
lzma_reserved_enum reserved_enum1;
lzma_reserved_enum reserved_enum2;
} lzma_stream;
/**
* \brief Initialization for lzma_stream
*
* When you declare an instance of lzma_stream, you can immediately
* initialize it so that initialization functions know that no memory
* has been allocated yet:
*
* lzma_stream strm = LZMA_STREAM_INIT;
*
* If you need to initialize a dynamically allocated lzma_stream, you can use
* memset(strm_pointer, 0, sizeof(lzma_stream)). Strictly speaking, this
* violates the C standard since NULL may have different internal
* representation than zero, but it should be portable enough in practice.
* Anyway, for maximum portability, you can use something like this:
*
* lzma_stream tmp = LZMA_STREAM_INIT;
* *strm = tmp;
*/
#define LZMA_STREAM_INIT \
{ NULL, 0, 0, NULL, 0, 0, NULL, NULL, \
NULL, NULL, NULL, NULL, 0, 0, 0, 0, \
LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM }
/**
* \brief Encode or decode data
*
* Once the lzma_stream has been successfully initialized (e.g. with
* lzma_stream_encoder()), the actual encoding or decoding is done
* using this function. The application has to update strm->next_in,
* strm->avail_in, strm->next_out, and strm->avail_out to pass input
* to and get output from liblzma.
*
* See the description of the coder-specific initialization function to find
* out what `action' values are supported by the coder.
*/
extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Free memory allocated for the coder data structures
*
* \param strm Pointer to lzma_stream that is at least initialized
* with LZMA_STREAM_INIT.
*
* After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
* members of the lzma_stream structure are touched.
*
* \note zlib indicates an error if application end()s unfinished
* stream structure. liblzma doesn't do this, and assumes that
* application knows what it is doing.
*/
extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
/**
* \brief Get progress information
*
* In single-threaded mode, applications can get progress information from
* strm->total_in and strm->total_out. In multi-threaded mode this is less
* useful because a significant amount of both input and output data gets
* buffered internally by liblzma. This makes total_in and total_out give
* misleading information and also makes the progress indicator updates
* non-smooth.
*
* This function gives realistic progress information also in multi-threaded
* mode by taking into account the progress made by each thread. In
* single-threaded mode *progress_in and *progress_out are set to
* strm->total_in and strm->total_out, respectively.
*/
extern LZMA_API(void) lzma_get_progress(lzma_stream *strm,
uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow;
/**
* \brief Get the memory usage of decoder filter chain
*
* This function is currently supported only when *strm has been initialized
* with a function that takes a memlimit argument. With other functions, you
* should use e.g. lzma_raw_encoder_memusage() or lzma_raw_decoder_memusage()
* to estimate the memory requirements.
*
* This function is useful e.g. after LZMA_MEMLIMIT_ERROR to find out how big
* the memory usage limit should have been to decode the input. Note that
* this may give misleading information if decoding .xz Streams that have
* multiple Blocks, because each Block can have different memory requirements.
*
* \return How much memory is currently allocated for the filter
* decoders. If no filter chain is currently allocated,
* some non-zero value is still returned, which is less than
* or equal to what any filter chain would indicate as its
* memory requirement.
*
* If this function isn't supported by *strm or some other error
* occurs, zero is returned.
*/
extern LZMA_API(uint64_t) lzma_memusage(const lzma_stream *strm)
lzma_nothrow lzma_attr_pure;
/**
* \brief Get the current memory usage limit
*
* This function is supported only when *strm has been initialized with
* a function that takes a memlimit argument.
*
* \return On success, the current memory usage limit is returned
* (always non-zero). On error, zero is returned.
*/
extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
lzma_nothrow lzma_attr_pure;
/**
* \brief Set the memory usage limit
*
* This function is supported only when *strm has been initialized with
* a function that takes a memlimit argument.
*
* liblzma 5.2.3 and earlier has a bug where memlimit value of 0 causes
* this function to do nothing (leaving the limit unchanged) and still
* return LZMA_OK. Later versions treat 0 as if 1 had been specified (so
* lzma_memlimit_get() will return 1 even if you specify 0 here).
*
* \return - LZMA_OK: New memory usage limit successfully set.
* - LZMA_MEMLIMIT_ERROR: The new limit is too small.
* The limit was not changed.
* - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
* support memory usage limit.
*/
extern LZMA_API(lzma_ret) lzma_memlimit_set(
lzma_stream *strm, uint64_t memlimit) lzma_nothrow;

90
third-party/libxz/include/lzma/bcj.h vendored Normal file
View File

@ -0,0 +1,90 @@
/**
* \file lzma/bcj.h
* \brief Branch/Call/Jump conversion filters
*/
/*
* Author: Lasse Collin
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*
* See ../lzma.h for information about liblzma as a whole.
*/
#ifndef LZMA_H_INTERNAL
# error Never include this file directly. Use <lzma.h> instead.
#endif
/* Filter IDs for lzma_filter.id */
#define LZMA_FILTER_X86 LZMA_VLI_C(0x04)
/**<
* Filter for x86 binaries
*/
#define LZMA_FILTER_POWERPC LZMA_VLI_C(0x05)
/**<
* Filter for Big endian PowerPC binaries
*/
#define LZMA_FILTER_IA64 LZMA_VLI_C(0x06)
/**<
* Filter for IA-64 (Itanium) binaries.
*/
#define LZMA_FILTER_ARM LZMA_VLI_C(0x07)
/**<
* Filter for ARM binaries.
*/
#define LZMA_FILTER_ARMTHUMB LZMA_VLI_C(0x08)
/**<
* Filter for ARM-Thumb binaries.
*/
#define LZMA_FILTER_SPARC LZMA_VLI_C(0x09)
/**<
* Filter for SPARC binaries.
*/
/**
* \brief Options for BCJ filters
*
* The BCJ filters never change the size of the data. Specifying options
* for them is optional: if pointer to options is NULL, default value is
* used. You probably never need to specify options to BCJ filters, so just
* set the options pointer to NULL and be happy.
*
* If options with non-default values have been specified when encoding,
* the same options must also be specified when decoding.
*
* \note At the moment, none of the BCJ filters support
* LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified,
* LZMA_OPTIONS_ERROR will be returned. If there is need,
* partial support for LZMA_SYNC_FLUSH can be added in future.
* Partial means that flushing would be possible only at
* offsets that are multiple of 2, 4, or 16 depending on
* the filter, except x86 which cannot be made to support
* LZMA_SYNC_FLUSH predictably.
*/
typedef struct {
/**
* \brief Start offset for conversions
*
* This setting is useful only when the same filter is used
* _separately_ for multiple sections of the same executable file,
* and the sections contain cross-section branch/call/jump
* instructions. In that case it is beneficial to set the start
* offset of the non-first sections so that the relative addresses
* of the cross-section branch/call/jump instructions will use the
* same absolute addresses as in the first section.
*
* When the pointer to options is NULL, the default value (zero)
* is used.
*/
uint32_t start_offset;
} lzma_options_bcj;

581
third-party/libxz/include/lzma/block.h vendored Normal file
View File

@ -0,0 +1,581 @@
/**
* \file lzma/block.h
* \brief .xz Block handling
*/
/*
* Author: Lasse Collin
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*
* See ../lzma.h for information about liblzma as a whole.
*/
#ifndef LZMA_H_INTERNAL
# error Never include this file directly. Use <lzma.h> instead.
#endif
/**
* \brief Options for the Block and Block Header encoders and decoders
*
* Different Block handling functions use different parts of this structure.
* Some read some members, other functions write, and some do both. Only the
* members listed for reading need to be initialized when the specified
* functions are called. The members marked for writing will be assigned
* new values at some point either by calling the given function or by
* later calls to lzma_code().
*/
typedef struct {
/**
* \brief Block format version
*
* To prevent API and ABI breakages when new features are needed,
* a version number is used to indicate which fields in this
* structure are in use:
* - liblzma >= 5.0.0: version = 0 is supported.
* - liblzma >= 5.1.4beta: Support for version = 1 was added,
* which adds the ignore_check field.
*
* If version is greater than one, most Block related functions
* will return LZMA_OPTIONS_ERROR (lzma_block_header_decode() works
* with any version value).
*
* Read by:
* - All functions that take pointer to lzma_block as argument,
* including lzma_block_header_decode().
*
* Written by:
* - lzma_block_header_decode()
*/
uint32_t version;
/**
* \brief Size of the Block Header field
*
* This is always a multiple of four.
*
* Read by:
* - lzma_block_header_encode()
* - lzma_block_header_decode()
* - lzma_block_compressed_size()
* - lzma_block_unpadded_size()
* - lzma_block_total_size()
* - lzma_block_decoder()
* - lzma_block_buffer_decode()
*
* Written by:
* - lzma_block_header_size()
* - lzma_block_buffer_encode()
*/
uint32_t header_size;
# define LZMA_BLOCK_HEADER_SIZE_MIN 8
# define LZMA_BLOCK_HEADER_SIZE_MAX 1024
/**
* \brief Type of integrity Check
*
* The Check ID is not stored into the Block Header, thus its value
* must be provided also when decoding.
*
* Read by:
* - lzma_block_header_encode()
* - lzma_block_header_decode()
* - lzma_block_compressed_size()
* - lzma_block_unpadded_size()
* - lzma_block_total_size()
* - lzma_block_encoder()
* - lzma_block_decoder()
* - lzma_block_buffer_encode()
* - lzma_block_buffer_decode()
*/
lzma_check check;
/**
* \brief Size of the Compressed Data in bytes
*
* Encoding: If this is not LZMA_VLI_UNKNOWN, Block Header encoder
* will store this value to the Block Header. Block encoder doesn't
* care about this value, but will set it once the encoding has been
* finished.
*
* Decoding: If this is not LZMA_VLI_UNKNOWN, Block decoder will
* verify that the size of the Compressed Data field matches
* compressed_size.
*
* Usually you don't know this value when encoding in streamed mode,
* and thus cannot write this field into the Block Header.
*
* In non-streamed mode you can reserve space for this field before
* encoding the actual Block. After encoding the data, finish the
* Block by encoding the Block Header. Steps in detail:
*
* - Set compressed_size to some big enough value. If you don't know
* better, use LZMA_VLI_MAX, but remember that bigger values take
* more space in Block Header.
*
* - Call lzma_block_header_size() to see how much space you need to
* reserve for the Block Header.
*
* - Encode the Block using lzma_block_encoder() and lzma_code().
* It sets compressed_size to the correct value.
*
* - Use lzma_block_header_encode() to encode the Block Header.
* Because space was reserved in the first step, you don't need
* to call lzma_block_header_size() anymore, because due to
* reserving, header_size has to be big enough. If it is "too big",
* lzma_block_header_encode() will add enough Header Padding to
* make Block Header to match the size specified by header_size.
*
* Read by:
* - lzma_block_header_size()
* - lzma_block_header_encode()
* - lzma_block_compressed_size()
* - lzma_block_unpadded_size()
* - lzma_block_total_size()
* - lzma_block_decoder()
* - lzma_block_buffer_decode()
*
* Written by:
* - lzma_block_header_decode()
* - lzma_block_compressed_size()
* - lzma_block_encoder()
* - lzma_block_decoder()
* - lzma_block_buffer_encode()
* - lzma_block_buffer_decode()
*/
lzma_vli compressed_size;
/**
* \brief Uncompressed Size in bytes
*
* This is handled very similarly to compressed_size above.
*
* uncompressed_size is needed by fewer functions than
* compressed_size. This is because uncompressed_size isn't
* needed to validate that Block stays within proper limits.
*
* Read by:
* - lzma_block_header_size()
* - lzma_block_header_encode()
* - lzma_block_decoder()
* - lzma_block_buffer_decode()
*
* Written by:
* - lzma_block_header_decode()
* - lzma_block_encoder()
* - lzma_block_decoder()
* - lzma_block_buffer_encode()
* - lzma_block_buffer_decode()
*/
lzma_vli uncompressed_size;
/**
* \brief Array of filters
*
* There can be 1-4 filters. The end of the array is marked with
* .id = LZMA_VLI_UNKNOWN.
*
* Read by:
* - lzma_block_header_size()
* - lzma_block_header_encode()
* - lzma_block_encoder()
* - lzma_block_decoder()
* - lzma_block_buffer_encode()
* - lzma_block_buffer_decode()
*
* Written by:
* - lzma_block_header_decode(): Note that this does NOT free()
* the old filter options structures. All unused filters[] will
* have .id == LZMA_VLI_UNKNOWN and .options == NULL. If
* decoding fails, all filters[] are guaranteed to be
* LZMA_VLI_UNKNOWN and NULL.
*
* \note Because of the array is terminated with
* .id = LZMA_VLI_UNKNOWN, the actual array must
* have LZMA_FILTERS_MAX + 1 members or the Block
* Header decoder will overflow the buffer.
*/
lzma_filter *filters;
/**
* \brief Raw value stored in the Check field
*
* After successful coding, the first lzma_check_size(check) bytes
* of this array contain the raw value stored in the Check field.
*
* Note that CRC32 and CRC64 are stored in little endian byte order.
* Take it into account if you display the Check values to the user.
*
* Written by:
* - lzma_block_encoder()
* - lzma_block_decoder()
* - lzma_block_buffer_encode()
* - lzma_block_buffer_decode()
*/
uint8_t raw_check[LZMA_CHECK_SIZE_MAX];
/*
* Reserved space to allow possible future extensions without
* breaking the ABI. You should not touch these, because the names
* of these variables may change. These are and will never be used
* with the currently supported options, so it is safe to leave these
* uninitialized.
*/
void *reserved_ptr1;
void *reserved_ptr2;
void *reserved_ptr3;
uint32_t reserved_int1;
uint32_t reserved_int2;
lzma_vli reserved_int3;
lzma_vli reserved_int4;
lzma_vli reserved_int5;
lzma_vli reserved_int6;
lzma_vli reserved_int7;
lzma_vli reserved_int8;
lzma_reserved_enum reserved_enum1;
lzma_reserved_enum reserved_enum2;
lzma_reserved_enum reserved_enum3;
lzma_reserved_enum reserved_enum4;
/**
* \brief A flag to Block decoder to not verify the Check field
*
* This field is supported by liblzma >= 5.1.4beta if .version >= 1.
*
* If this is set to true, the integrity check won't be calculated
* and verified. Unless you know what you are doing, you should
* leave this to false. (A reason to set this to true is when the
* file integrity is verified externally anyway and you want to
* speed up the decompression, which matters mostly when using
* SHA-256 as the integrity check.)
*
* If .version >= 1, read by:
* - lzma_block_decoder()
* - lzma_block_buffer_decode()
*
* Written by (.version is ignored):
* - lzma_block_header_decode() always sets this to false
*/
lzma_bool ignore_check;
lzma_bool reserved_bool2;
lzma_bool reserved_bool3;
lzma_bool reserved_bool4;
lzma_bool reserved_bool5;
lzma_bool reserved_bool6;
lzma_bool reserved_bool7;
lzma_bool reserved_bool8;
} lzma_block;
/**
* \brief Decode the Block Header Size field
*
* To decode Block Header using lzma_block_header_decode(), the size of the
* Block Header has to be known and stored into lzma_block.header_size.
* The size can be calculated from the first byte of a Block using this macro.
* Note that if the first byte is 0x00, it indicates beginning of Index; use
* this macro only when the byte is not 0x00.
*
* There is no encoding macro, because Block Header encoder is enough for that.
*/
#define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
/**
* \brief Calculate Block Header Size
*
* Calculate the minimum size needed for the Block Header field using the
* settings specified in the lzma_block structure. Note that it is OK to
* increase the calculated header_size value as long as it is a multiple of
* four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
* just means that lzma_block_header_encode() will add Header Padding.
*
* \return - LZMA_OK: Size calculated successfully and stored to
* block->header_size.
* - LZMA_OPTIONS_ERROR: Unsupported version, filters or
* filter options.
* - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
*
* \note This doesn't check that all the options are valid i.e. this
* may return LZMA_OK even if lzma_block_header_encode() or
* lzma_block_encoder() would fail. If you want to validate the
* filter chain, consider using lzma_memlimit_encoder() which as
* a side-effect validates the filter chain.
*/
extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Encode Block Header
*
* The caller must have calculated the size of the Block Header already with
* lzma_block_header_size(). If a value larger than the one calculated by
* lzma_block_header_size() is used, the Block Header will be padded to the
* specified size.
*
* \param out Beginning of the output buffer. This must be
* at least block->header_size bytes.
* \param block Block options to be encoded.
*
* \return - LZMA_OK: Encoding was successful. block->header_size
* bytes were written to output buffer.
* - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
* - LZMA_PROG_ERROR: Invalid arguments, for example
* block->header_size is invalid or block->filters is NULL.
*/
extern LZMA_API(lzma_ret) lzma_block_header_encode(
const lzma_block *block, uint8_t *out)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Decode Block Header
*
* block->version should (usually) be set to the highest value supported
* by the application. If the application sets block->version to a value
* higher than supported by the current liblzma version, this function will
* downgrade block->version to the highest value supported by it. Thus one
* should check the value of block->version after calling this function if
* block->version was set to a non-zero value and the application doesn't
* otherwise know that the liblzma version being used is new enough to
* support the specified block->version.
*
* The size of the Block Header must have already been decoded with
* lzma_block_header_size_decode() macro and stored to block->header_size.
*
* The integrity check type from Stream Header must have been stored
* to block->check.
*
* block->filters must have been allocated, but they don't need to be
* initialized (possible existing filter options are not freed).
*
* \param block Destination for Block options.
* \param allocator lzma_allocator for custom allocator functions.
* Set to NULL to use malloc() (and also free()
* if an error occurs).
* \param in Beginning of the input buffer. This must be
* at least block->header_size bytes.
*
* \return - LZMA_OK: Decoding was successful. block->header_size
* bytes were read from the input buffer.
* - LZMA_OPTIONS_ERROR: The Block Header specifies some
* unsupported options such as unsupported filters. This can
* happen also if block->version was set to a too low value
* compared to what would be required to properly represent
* the information stored in the Block Header.
* - LZMA_DATA_ERROR: Block Header is corrupt, for example,
* the CRC32 doesn't match.
* - LZMA_PROG_ERROR: Invalid arguments, for example
* block->header_size is invalid or block->filters is NULL.
*/
extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
const lzma_allocator *allocator, const uint8_t *in)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Validate and set Compressed Size according to Unpadded Size
*
* Block Header stores Compressed Size, but Index has Unpadded Size. If the
* application has already parsed the Index and is now decoding Blocks,
* it can calculate Compressed Size from Unpadded Size. This function does
* exactly that with error checking:
*
* - Compressed Size calculated from Unpadded Size must be positive integer,
* that is, Unpadded Size must be big enough that after Block Header and
* Check fields there's still at least one byte for Compressed Size.
*
* - If Compressed Size was present in Block Header, the new value
* calculated from Unpadded Size is compared against the value
* from Block Header.
*
* \note This function must be called _after_ decoding the Block Header
* field so that it can properly validate Compressed Size if it
* was present in Block Header.
*
* \return - LZMA_OK: block->compressed_size was set successfully.
* - LZMA_DATA_ERROR: unpadded_size is too small compared to
* block->header_size and lzma_check_size(block->check).
* - LZMA_PROG_ERROR: Some values are invalid. For example,
* block->header_size must be a multiple of four and
* between 8 and 1024 inclusive.
*/
extern LZMA_API(lzma_ret) lzma_block_compressed_size(
lzma_block *block, lzma_vli unpadded_size)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Calculate Unpadded Size
*
* The Index field stores Unpadded Size and Uncompressed Size. The latter
* can be taken directly from the lzma_block structure after coding a Block,
* but Unpadded Size needs to be calculated from Block Header Size,
* Compressed Size, and size of the Check field. This is where this function
* is needed.
*
* \return Unpadded Size on success, or zero on error.
*/
extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
lzma_nothrow lzma_attr_pure;
/**
* \brief Calculate the total encoded size of a Block
*
* This is equivalent to lzma_block_unpadded_size() except that the returned
* value includes the size of the Block Padding field.
*
* \return On success, total encoded size of the Block. On error,
* zero is returned.
*/
extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block)
lzma_nothrow lzma_attr_pure;
/**
* \brief Initialize .xz Block encoder
*
* Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
* filter chain supports it), and LZMA_FINISH.
*
* \return - LZMA_OK: All good, continue with lzma_code().
* - LZMA_MEM_ERROR
* - LZMA_OPTIONS_ERROR
* - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
* that is not supported by this buid of liblzma. Initializing
* the encoder failed.
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_encoder(
lzma_stream *strm, lzma_block *block)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Initialize .xz Block decoder
*
* Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
* LZMA_FINISH is not required. It is supported only for convenience.
*
* \return - LZMA_OK: All good, continue with lzma_code().
* - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but
* the given Check ID is not supported, thus Check will be
* ignored.
* - LZMA_PROG_ERROR
* - LZMA_MEM_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_decoder(
lzma_stream *strm, lzma_block *block)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Calculate maximum output size for single-call Block encoding
*
* This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks.
* See the documentation of lzma_stream_buffer_bound().
*/
extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
lzma_nothrow;
/**
* \brief Single-call .xz Block encoder
*
* In contrast to the multi-call encoder initialized with
* lzma_block_encoder(), this function encodes also the Block Header. This
* is required to make it possible to write appropriate Block Header also
* in case the data isn't compressible, and different filter chain has to be
* used to encode the data in uncompressed form using uncompressed chunks
* of the LZMA2 filter.
*
* When the data isn't compressible, header_size, compressed_size, and
* uncompressed_size are set just like when the data was compressible, but
* it is possible that header_size is too small to hold the filter chain
* specified in block->filters, because that isn't necessarily the filter
* chain that was actually used to encode the data. lzma_block_unpadded_size()
* still works normally, because it doesn't read the filters array.
*
* \param block Block options: block->version, block->check,
* and block->filters must have been initialized.
* \param allocator lzma_allocator for custom allocator functions.
* Set to NULL to use malloc() and free().
* \param in Beginning of the input buffer
* \param in_size Size of the input buffer
* \param out Beginning of the output buffer
* \param out_pos The next byte will be written to out[*out_pos].
* *out_pos is updated only if encoding succeeds.
* \param out_size Size of the out buffer; the first byte into
* which no data is written to is out[out_size].
*
* \return - LZMA_OK: Encoding was successful.
* - LZMA_BUF_ERROR: Not enough output buffer space.
* - LZMA_UNSUPPORTED_CHECK
* - LZMA_OPTIONS_ERROR
* - LZMA_MEM_ERROR
* - LZMA_DATA_ERROR
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Single-call uncompressed .xz Block encoder
*
* This is like lzma_block_buffer_encode() except this doesn't try to
* compress the data and instead encodes the data using LZMA2 uncompressed
* chunks. The required output buffer size can be determined with
* lzma_block_buffer_bound().
*
* Since the data won't be compressed, this function ignores block->filters.
* This function doesn't take lzma_allocator because this function doesn't
* allocate any memory from the heap.
*/
extern LZMA_API(lzma_ret) lzma_block_uncomp_encode(lzma_block *block,
const uint8_t *in, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow lzma_attr_warn_unused_result;
/**
* \brief Single-call .xz Block decoder
*
* This is single-call equivalent of lzma_block_decoder(), and requires that
* the caller has already decoded Block Header and checked its memory usage.
*
* \param block Block options just like with lzma_block_decoder().
* \param allocator lzma_allocator for custom allocator functions.
* Set to NULL to use malloc() and free().
* \param in Beginning of the input buffer
* \param in_pos The next byte will be read from in[*in_pos].
* *in_pos is updated only if decoding succeeds.
* \param in_size Size of the input buffer; the first byte that
* won't be read is in[in_size].
* \param out Beginning of the output buffer
* \param out_pos The next byte will be written to out[*out_pos].
* *out_pos is updated only if encoding succeeds.
* \param out_size Size of the out buffer; the first byte into
* which no data is written to is out[out_size].
*
* \return - LZMA_OK: Decoding was successful.
* - LZMA_OPTIONS_ERROR
* - LZMA_DATA_ERROR
* - LZMA_MEM_ERROR
* - LZMA_BUF_ERROR: Output buffer was too small.
* - LZMA_PROG_ERROR
*/
extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
lzma_block *block, const lzma_allocator *allocator,
const uint8_t *in, size_t *in_pos, size_t in_size,
uint8_t *out, size_t *out_pos, size_t out_size)
lzma_nothrow;

150
third-party/libxz/include/lzma/check.h vendored Normal file
View File

@ -0,0 +1,150 @@
/**
* \file lzma/check.h
* \brief Integrity checks
*/
/*
* Author: Lasse Collin
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*
* See ../lzma.h for information about liblzma as a whole.
*/
#ifndef LZMA_H_INTERNAL
# error Never include this file directly. Use <lzma.h> instead.
#endif
/**
* \brief Type of the integrity check (Check ID)
*
* The .xz format supports multiple types of checks that are calculated
* from the uncompressed data. They vary in both speed and ability to
* detect errors.
*/
typedef enum {
LZMA_CHECK_NONE = 0,
/**<
* No Check is calculated.
*
* Size of the Check field: 0 bytes
*/
LZMA_CHECK_CRC32 = 1,
/**<
* CRC32 using the polynomial from the IEEE 802.3 standard
*
* Size of the Check field: 4 bytes
*/
LZMA_CHECK_CRC64 = 4,
/**<
* CRC64 using the polynomial from the ECMA-182 standard
*
* Size of the Check field: 8 bytes
*/
LZMA_CHECK_SHA256 = 10
/**<
* SHA-256
*
* Size of the Check field: 32 bytes
*/
} lzma_check;
/**
* \brief Maximum valid Check ID
*
* The .xz file format specification specifies 16 Check IDs (0-15). Some
* of them are only reserved, that is, no actual Check algorithm has been
* assigned. When decoding, liblzma still accepts unknown Check IDs for
* future compatibility. If a valid but unsupported Check ID is detected,
* liblzma can indicate a warning; see the flags LZMA_TELL_NO_CHECK,
* LZMA_TELL_UNSUPPORTED_CHECK, and LZMA_TELL_ANY_CHECK in container.h.
*/
#define LZMA_CHECK_ID_MAX 15
/**
* \brief Test if the given Check ID is supported
*
* Return true if the given Check ID is supported by this liblzma build.
* Otherwise false is returned. It is safe to call this with a value that
* is not in the range [0, 15]; in that case the return value is always false.
*
* You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always
* supported (even if liblzma is built with limited features).
*/
extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
lzma_nothrow lzma_attr_const;
/**
* \brief Get the size of the Check field with the given Check ID
*
* Although not all Check IDs have a check algorithm associated, the size of
* every Check is already frozen. This function returns the size (in bytes) of
* the Check field with the specified Check ID. The values are:
* { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
*
* If the argument is not in the range [0, 15], UINT32_MAX is returned.
*/
extern LZMA_API(uint32_t) lzma_check_size(lzma_check check)
lzma_nothrow lzma_attr_const;
/**
* \brief Maximum size of a Check field
*/
#define LZMA_CHECK_SIZE_MAX 64
/**
* \brief Calculate CRC32
*
* Calculate CRC32 using the polynomial from the IEEE 802.3 standard.
*
* \param buf Pointer to the input buffer
* \param size Size of the input buffer
* \param crc Previously returned CRC value. This is used to
* calculate the CRC of a big buffer in smaller chunks.
* Set to zero when starting a new calculation.
*
* \return Updated CRC value, which can be passed to this function
* again to continue CRC calculation.
*/
extern LZMA_API(uint32_t) lzma_crc32(
const uint8_t *buf, size_t size, uint32_t crc)
lzma_nothrow lzma_attr_pure;
/**
* \brief Calculate CRC64
*
* Calculate CRC64 using the polynomial from the ECMA-182 standard.
*
* This function is used similarly to lzma_crc32(). See its documentation.
*/
extern LZMA_API(uint64_t) lzma_crc64(
const uint8_t *buf, size_t size, uint64_t crc)
lzma_nothrow lzma_attr_pure;
/*
* SHA-256 functions are currently not exported to public API.
* Contact Lasse Collin if you think it should be.
*/
/**
* \brief Get the type of the integrity check
*
* This function can be called only immediately after lzma_code() has
* returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
* Calling this function in any other situation has undefined behavior.
*/
extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm)
lzma_nothrow;

Some files were not shown because too many files have changed in this diff Show More