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:
commit
ab68de2dce
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9cfd2a5d30525406eb4326171a7d43641105bea0d11eebea2bd161186c459929
|
||||
oid sha256:d26911f127c071ad3614ffe5506cb48eb018ebf4f203e528e5ca3be5648eebad
|
||||
size 71680
|
||||
|
4
NvimView/third-party/libintl/lib/libintl.a
vendored
4
NvimView/third-party/libintl/lib/libintl.a
vendored
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:14bcee7757d7dfa751eb33c554a1c3b6230ae9fe4e9dd5a22d5a238aaa1036bd
|
||||
size 100832
|
||||
oid sha256:da69917872f71d621ac0083cb03b7bd585ef7d8c7ac8e8c709569e3eaa049aae
|
||||
size 100824
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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}}\
|
||||
|
@ -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"/>
|
||||
|
@ -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"
|
||||
|
38
VimR/VimR/ConditionVariable.swift
Normal file
38
VimR/VimR/ConditionVariable.swift
Normal 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()
|
||||
}
|
118
VimR/VimR/CoreDataStack.swift
Normal file
118
VimR/VimR/CoreDataStack.swift
Normal 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)
|
||||
}
|
@ -16,6 +16,7 @@ struct Defs {
|
||||
|
||||
static let uiComponents = "ui-components"
|
||||
static let middleware = "middleware"
|
||||
static let service = "service"
|
||||
}
|
||||
|
||||
static let webViewProcessPool = WKProcessPool()
|
||||
|
21
VimR/VimR/FileItem+CoreDataClass.h
Normal file
21
VimR/VimR/FileItem+CoreDataClass.h
Normal 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"
|
14
VimR/VimR/FileItem+CoreDataClass.m
Normal file
14
VimR/VimR/FileItem+CoreDataClass.m
Normal 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
|
39
VimR/VimR/FileItem+CoreDataProperties.h
Normal file
39
VimR/VimR/FileItem+CoreDataProperties.h
Normal 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
|
27
VimR/VimR/FileItem+CoreDataProperties.m
Normal file
27
VimR/VimR/FileItem+CoreDataProperties.m
Normal 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
|
@ -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 }
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
23
VimR/VimR/FileScanBaton.h
Normal 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
205
VimR/VimR/FileScanBaton.m
Normal 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
|
||||
|
13
VimR/VimR/FoundationCommons.h
Normal file
13
VimR/VimR/FoundationCommons.h
Normal 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
|
40
VimR/VimR/FoundationCommons.m
Normal file
40
VimR/VimR/FoundationCommons.m
Normal 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
|
@ -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
|
||||
|
18
VimR/VimR/FuzzyMatcher/FuzzyMatcher.h
Normal file
18
VimR/VimR/FuzzyMatcher/FuzzyMatcher.h
Normal 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
|
33
VimR/VimR/FuzzyMatcher/FuzzyMatcher.mm
Normal file
33
VimR/VimR/FuzzyMatcher/FuzzyMatcher.mm
Normal 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
|
58
VimR/VimR/FuzzyMatcher/FuzzyMatcherPool.swift
Normal file
58
VimR/VimR/FuzzyMatcher/FuzzyMatcherPool.swift
Normal 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()
|
||||
}
|
||||
}
|
191
VimR/VimR/FuzzyMatcher/fuzzy_match.cc
Normal file
191
VimR/VimR/FuzzyMatcher/fuzzy_match.cc
Normal 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
|
34
VimR/VimR/FuzzyMatcher/fuzzy_match.hh
Normal file
34
VimR/VimR/FuzzyMatcher/fuzzy_match.hh
Normal 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
|
24
VimR/VimR/FuzzySearch.xcdatamodel/contents
Normal file
24
VimR/VimR/FuzzySearch.xcdatamodel/contents
Normal 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>
|
49
VimR/VimR/FuzzySearchFileMonitor.swift
Normal file
49
VimR/VimR/FuzzySearchFileMonitor.swift
Normal 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)
|
457
VimR/VimR/FuzzySearchService.swift
Normal file
457
VimR/VimR/FuzzySearchService.swift
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
@ -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/Wagner–Fischer_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]
|
||||
}
|
||||
}
|
@ -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
|
@ -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)
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
23
VimR/VimR/ScoredUrl.h
Normal 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
62
VimR/VimR/ScoredUrl.m
Normal 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
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
@ -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)))
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
120
third-party/libag/include/config.h
vendored
Normal 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
26
third-party/libag/include/decompress.h
vendored
Normal 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
48
third-party/libag/include/ignore.h
vendored
Normal 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
36
third-party/libag/include/lang.h
vendored
Normal 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
32
third-party/libag/include/log.h
vendored
Normal 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
105
third-party/libag/include/options.h
vendored
Normal 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
26
third-party/libag/include/print.h
vendored
Normal 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
20
third-party/libag/include/scandir.h
vendored
Normal 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
78
third-party/libag/include/search.h
vendored
Normal 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
971
third-party/libag/include/uthash.h
vendored
Normal 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
119
third-party/libag/include/util.h
vendored
Normal 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
3
third-party/libag/lib/libag.a
vendored
Normal 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
677
third-party/libpcre/include/pcre.h
vendored
Normal 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 */
|
172
third-party/libpcre/include/pcre_scanner.h
vendored
Normal file
172
third-party/libpcre/include/pcre_scanner.h
vendored
Normal 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 */
|
180
third-party/libpcre/include/pcre_stringpiece.h
vendored
Normal file
180
third-party/libpcre/include/pcre_stringpiece.h
vendored
Normal 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
710
third-party/libpcre/include/pcrecpp.h
vendored
Normal 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
174
third-party/libpcre/include/pcrecpparg.h
vendored
Normal 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
146
third-party/libpcre/include/pcreposix.h
vendored
Normal 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
3
third-party/libpcre/lib/libpcre.1.dylib
vendored
Executable 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
3
third-party/libpcre/lib/libpcre.a
vendored
Normal 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
1
third-party/libpcre/lib/libpcre.dylib
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
libpcre.1.dylib
|
41
third-party/libpcre/lib/libpcre.la
vendored
Executable file
41
third-party/libpcre/lib/libpcre.la
vendored
Executable 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
3
third-party/libpcre/lib/libpcre16.0.dylib
vendored
Executable 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
3
third-party/libpcre/lib/libpcre16.a
vendored
Normal 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
1
third-party/libpcre/lib/libpcre16.dylib
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
libpcre16.0.dylib
|
41
third-party/libpcre/lib/libpcre16.la
vendored
Executable file
41
third-party/libpcre/lib/libpcre16.la
vendored
Executable 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
3
third-party/libpcre/lib/libpcre32.0.dylib
vendored
Executable 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
3
third-party/libpcre/lib/libpcre32.a
vendored
Normal 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
1
third-party/libpcre/lib/libpcre32.dylib
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
libpcre32.0.dylib
|
41
third-party/libpcre/lib/libpcre32.la
vendored
Executable file
41
third-party/libpcre/lib/libpcre32.la
vendored
Executable 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
3
third-party/libpcre/lib/libpcrecpp.0.dylib
vendored
Executable 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
3
third-party/libpcre/lib/libpcrecpp.a
vendored
Normal 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
1
third-party/libpcre/lib/libpcrecpp.dylib
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
libpcrecpp.0.dylib
|
41
third-party/libpcre/lib/libpcrecpp.la
vendored
Executable file
41
third-party/libpcre/lib/libpcrecpp.la
vendored
Executable 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'
|
3
third-party/libpcre/lib/libpcreposix.0.dylib
vendored
Executable file
3
third-party/libpcre/lib/libpcreposix.0.dylib
vendored
Executable file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:45c900d74a340ad53d709b0054b1a0f4b14281d24506b2595aa5ed3299fed634
|
||||
size 13208
|
3
third-party/libpcre/lib/libpcreposix.a
vendored
Normal file
3
third-party/libpcre/lib/libpcreposix.a
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a4bb917a427de0d20ba1eb8e87d1dfeb3e053486c0067d014791f19b7f1c29a1
|
||||
size 5336
|
1
third-party/libpcre/lib/libpcreposix.dylib
vendored
Symbolic link
1
third-party/libpcre/lib/libpcreposix.dylib
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
libpcreposix.0.dylib
|
41
third-party/libpcre/lib/libpcreposix.la
vendored
Executable file
41
third-party/libpcre/lib/libpcreposix.la
vendored
Executable 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'
|
13
third-party/libpcre/lib/pkgconfig/libpcre.pc
vendored
Normal file
13
third-party/libpcre/lib/pkgconfig/libpcre.pc
vendored
Normal 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}
|
13
third-party/libpcre/lib/pkgconfig/libpcre16.pc
vendored
Normal file
13
third-party/libpcre/lib/pkgconfig/libpcre16.pc
vendored
Normal 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}
|
13
third-party/libpcre/lib/pkgconfig/libpcre32.pc
vendored
Normal file
13
third-party/libpcre/lib/pkgconfig/libpcre32.pc
vendored
Normal 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}
|
12
third-party/libpcre/lib/pkgconfig/libpcrecpp.pc
vendored
Normal file
12
third-party/libpcre/lib/pkgconfig/libpcrecpp.pc
vendored
Normal 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}
|
13
third-party/libpcre/lib/pkgconfig/libpcreposix.pc
vendored
Normal file
13
third-party/libpcre/lib/pkgconfig/libpcreposix.pc
vendored
Normal 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
325
third-party/libxz/include/lzma.h
vendored
Normal 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
659
third-party/libxz/include/lzma/base.h
vendored
Normal 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
90
third-party/libxz/include/lzma/bcj.h
vendored
Normal 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
581
third-party/libxz/include/lzma/block.h
vendored
Normal 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
150
third-party/libxz/include/lzma/check.h
vendored
Normal 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
Loading…
Reference in New Issue
Block a user