mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Compare commits
	
		
			277 Commits
		
	
	
		
			FluxEngine
			...
			firmware
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 3601f9f487 | ||
|  | 7f95f6b43f | ||
|  | b2d7ba1a65 | ||
|  | b550bbbd08 | ||
|  | 4cbb75df60 | ||
|  | 7d8926659e | ||
|  | 37ca3f74c7 | ||
|  | 56cbf39d59 | ||
|  | a783e7f500 | ||
|  | 2f4ac42684 | ||
|  | ec689e100e | ||
|  | 6f0909d992 | ||
|  | 0092dec49e | ||
|  | 3447689c19 | ||
|  | d4563fd842 | ||
|  | d2ecec6009 | ||
|  | 26f26aec50 | ||
|  | 34dfc2767f | ||
|  | bc3d3cabce | ||
|  | 23d80b93ae | ||
|  | 0d59d3d195 | ||
|  | 192427cf80 | ||
|  | 98e4094d70 | ||
|  | e88b939866 | ||
|  | aed5a02ee1 | ||
|  | 9f1e1bb2b6 | ||
|  | 15e9383d0b | ||
|  | 4ec056900c | ||
|  | 983feb59b0 | ||
|  | 8b2ce33f83 | ||
|  | 44b452b30b | ||
|  | f60c9981b8 | ||
|  | 7c3df93580 | ||
|  | 601d7dfcf8 | ||
|  | 41cb53a550 | ||
|  | 87c13ae20c | ||
|  | c30482af66 | ||
|  | 5f4f2f10d7 | ||
|  | ae630a0e18 | ||
|  | c66931cb12 | ||
|  | fb2dbe25cd | ||
|  | bf4831be9f | ||
|  | 0f83082cf0 | ||
|  | fbfde604e7 | ||
|  | 5e2dfbed73 | ||
|  | 571602d3de | ||
|  | 85693f2577 | ||
|  | 60bc8ad888 | ||
|  | 9bf309eb5c | ||
|  | eeddfa87b6 | ||
|  | 861fe2466c | ||
|  | 3a2cce78ca | ||
|  | 4e01f1de0d | ||
|  | 4f0a5e854c | ||
|  | c669a9c808 | ||
|  | e4d827256f | ||
|  | 1c1ad2725e | ||
|  | d18e54c5a3 | ||
|  | 7a885e23d3 | ||
|  | 33dde3a465 | ||
|  | 8d4ac59f03 | ||
|  | 4fbfc492ce | ||
|  | ac1fb71bc5 | ||
|  | 01d6b37b83 | ||
|  | 2284b4dce1 | ||
|  | b92f80e6be | ||
|  | bd5596fa30 | ||
|  | 4614b63c30 | ||
|  | cf41b6cbb2 | ||
|  | 87f3e0e291 | ||
|  | 1997abcde6 | ||
|  | 8b761298ee | ||
|  | df0356b841 | ||
|  | dc158ebff4 | ||
|  | f8192b90f4 | ||
|  | 5237049e2c | ||
|  | 9d70fb261e | ||
|  | 8370b8a743 | ||
|  | 25656d81a1 | ||
|  | be97791428 | ||
|  | 18b683d22e | ||
|  | 34e9742f71 | ||
|  | 087eb7777e | ||
|  | c469c5e3a1 | ||
|  | 485c29bb49 | ||
|  | aa0cf150bd | ||
|  | 91c52e91cd | ||
|  | a1f4014738 | ||
|  | 8a136ac4f6 | ||
|  | ea43b3dc6a | ||
|  | 57fc787819 | ||
|  | a0164b8de3 | ||
|  | 9df35c1814 | ||
|  | 9d2a5fee86 | ||
|  | a6b2e932fa | ||
|  | 05aaa2634b | ||
|  | 2c98f5c542 | ||
|  | d246fca9df | ||
|  | c79feb405c | ||
|  | b1145f8da3 | ||
|  | 3588d681a2 | ||
|  | 55d894ae1f | ||
|  | 0509caf432 | ||
|  | 5d1d807e78 | ||
|  | 22ba38b2e0 | ||
|  | 42f858267c | ||
|  | 5b1a3173f8 | ||
|  | 97822bd9a8 | ||
|  | b926f5a692 | ||
|  | 191dfdf13f | ||
|  | a100f1fe1e | ||
|  | 471ccf281c | ||
|  | 6c959be188 | ||
|  | 010887f18f | ||
|  | e4b5e4c502 | ||
|  | 2de3b4f92e | ||
|  | 225a93330d | ||
|  | 41b36649a9 | ||
|  | 55c26ab1c4 | ||
|  | 8b1e60a1fd | ||
|  | ed0f38748b | ||
|  | 7d75a720ca | ||
|  | 5a38db166f | ||
|  | 3c9fb79263 | ||
|  | 98d5a2dad9 | ||
|  | 4ab8b4984d | ||
|  | f741ad058e | ||
|  | 2512a4fc32 | ||
|  | 5554d5e608 | ||
|  | 48d5ed2ff9 | ||
|  | 2632668d0e | ||
|  | f46e444aa2 | ||
|  | 1149ad86a2 | ||
|  | e1398d98b0 | ||
|  | 8133e2b7aa | ||
|  | ebe678b18b | ||
|  | 509217606c | ||
|  | 6fb694669c | ||
|  | 5a63172a86 | ||
|  | 93dcc7e242 | ||
|  | 243eea33e9 | ||
|  | 38a8367f62 | ||
|  | a02953cccc | ||
|  | f13f96967e | ||
|  | f7c31281e0 | ||
|  | ac34a43d9b | ||
|  | c8d0950979 | ||
|  | a4ff59eccb | ||
|  | c3a50f9442 | ||
|  | 57e81ee72e | ||
|  | 05df0a37b1 | ||
|  | 25f2c3a8c1 | ||
|  | c3aa12db78 | ||
|  | a3bd7cc644 | ||
|  | 5a186b6960 | ||
|  | 639588fa68 | ||
|  | f9510c54b2 | ||
|  | 3a8ddf8025 | ||
| a2801ea88c | |||
|  | c2aae7ee18 | ||
|  | 9d0804eff4 | ||
|  | 6ff84b3693 | ||
|  | b641e0282b | ||
|  | 37a467cabc | ||
|  | e01a7110ac | ||
|  | 5dad5de548 | ||
|  | 295325a20b | ||
|  | df0a9bac96 | ||
|  | cf9cef6f87 | ||
|  | f92814b24b | ||
|  | 331b59cd1e | ||
|  | ed6d211aff | ||
|  | a8f1469d36 | ||
|  | 74cb332706 | ||
|  | 89165369b1 | ||
|  | a54e3d33a6 | ||
|  | 0f17984f41 | ||
|  | 6527ceb913 | ||
|  | 64a57ba837 | ||
|  | 74da9330f8 | ||
|  | 4fa1dd6860 | ||
|  | e55effc9ca | ||
|  | 924b862f7c | ||
|  | 5f077762d5 | ||
|  | 1b0ec50711 | ||
|  | 22f320f1c4 | ||
|  | 9949476584 | ||
|  | 1b5b170557 | ||
|  | 925a3a4bdb | ||
|  | 720fe9f95f | ||
|  | 7c4f8e1443 | ||
|  | 79d24dff46 | ||
|  | 928435a31d | ||
|  | 26ac92eaa3 | ||
|  | 2974c08b08 | ||
|  | 5a7b0b3050 | ||
|  | cc2d9bbdd1 | ||
|  | e912152784 | ||
|  | d00681f623 | ||
|  | 52942c3d2a | ||
|  | dedabdd8d8 | ||
|  | 3061499860 | ||
|  | 20f18755ed | ||
|  | 333f2aba54 | ||
|  | 1cb673ed80 | ||
|  | 57e0bc784a | ||
|  | 425afa93da | ||
|  | 259b2cebc7 | ||
|  | 06589826c8 | ||
|  | 2245cd982a | ||
|  | 065b50769f | ||
|  | d1e99852bc | ||
|  | bf8f6ae687 | ||
|  | 4ad6805ea1 | ||
|  | 4f4e3f0b89 | ||
|  | b51f2c1ec8 | ||
|  | 1bec06fd75 | ||
|  | 451d2e2d1d | ||
|  | 9cee12f9f4 | ||
|  | f5d6011a77 | ||
|  | 64b2ff19ea | ||
|  | 9c17a64773 | ||
|  | 69c877ff66 | ||
|  | ac557ffedc | ||
|  | b1e41bc583 | ||
|  | a144395ec9 | ||
|  | 0cf9d05489 | ||
|  | 0e6c0a41d0 | ||
|  | 8a83652d08 | ||
|  | 91ee72a8d6 | ||
|  | 91b1c8c13c | ||
|  | 26effeabe6 | ||
|  | 611c9740ed | ||
|  | 2a048c3228 | ||
|  | f4fd83d999 | ||
|  | cf68585808 | ||
|  | 9f9e926cff | ||
|  | 9dc0dd75fd | ||
|  | 9f285710f8 | ||
|  | ee1c448327 | ||
|  | e85bf1713e | ||
|  | 7341c71277 | ||
|  | d579863311 | ||
|  | c79cfc19aa | ||
|  | 997a6be267 | ||
|  | 762bb3006d | ||
|  | 07f2bd8cab | ||
|  | daf83db9b3 | ||
|  | 55c6e19af4 | ||
|  | 9cadc94c5a | ||
|  | cacdf9ef56 | ||
|  | a3042fc6c0 | ||
|  | 3efd492525 | ||
|  | 55a5cbc356 | ||
|  | 2887b024ab | ||
|  | 917303edb9 | ||
|  | c712c15a30 | ||
|  | 0c541db8e0 | ||
|  | 603b1520d7 | ||
|  | c7eb8ad5c8 | ||
|  | 0b285aa7f4 | ||
|  | e8665bd00c | ||
|  | fb4eaa4332 | ||
|  | 874a9eae76 | ||
|  | 8230520956 | ||
|  | 66da9675f1 | ||
|  | 61ff48c005 | ||
|  | 5fc8a1e52a | ||
|  | df1ac74069 | ||
|  | 91f718bf38 | ||
|  | 46e987e393 | ||
|  | a59b4f7be7 | ||
|  | ca66e3c35c | ||
|  | 31e2ad8cba | ||
|  | 320f32895a | ||
|  | d4db131d3c | ||
|  | 27c2c9045e | 
| @@ -1,42 +0,0 @@ | ||||
| version: '{branch}.{build}' | ||||
| clone_depth: 1 | ||||
| skip_tags: true | ||||
| image: Visual Studio 2019 | ||||
|  | ||||
| environment: | ||||
|   MSYSTEM: MINGW32 | ||||
|  | ||||
| init: | ||||
|   - git config --global core.autocrlf input | ||||
|  | ||||
| install: | ||||
|   - set PATH=c:\msys64\mingw32\bin;c:\msys64\usr\bin;c:\msys64\bin;%PATH% | ||||
|   - echo %PATH% | ||||
|   - pacman -S --noconfirm --needed make ninja mingw-w64-i686-libusb mingw-w64-i686-sqlite3 mingw-w64-i686-zlib mingw-w64-i686-gcc zip | ||||
|  | ||||
| build_script: | ||||
|   - make | ||||
|   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex | ||||
|  | ||||
| artifacts: | ||||
|   - path: fluxengine.zip | ||||
|     name: fluxengine.zip | ||||
|  | ||||
| deploy: | ||||
|   release: FluxEngine Windows client version $(APPVEYOR_BUILD_NUMBER) | ||||
|   description: > | ||||
|     This is an automatically built version of the FluxEngine Windows client | ||||
|     which is generated whenever a significant checkin has happened. It's had | ||||
|     no testing whatsoever. | ||||
|  | ||||
|     To use, download it, put it somewhere, and then run it from a cmd window | ||||
|     or other command line shell. | ||||
|   provider: GitHub | ||||
|   auth_token: | ||||
|     secure: dfJjj7fWCoDUz+Ni11OcNPB/U3TNJFwNA2AsL++ChFjniUsZLlC6SDWHiL/t4FZo | ||||
|   artifact: fluxengine.zip | ||||
|   draft: false | ||||
|   prerelease: false | ||||
|   on: | ||||
|     branch: master | ||||
|  | ||||
							
								
								
									
										45
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										45
									
								
								.github/workflows/ccpp.yml
									
									
									
									
										vendored
									
									
								
							| @@ -10,32 +10,45 @@ jobs: | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: apt | ||||
|       run: sudo apt update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build | ||||
|       run: sudo apt update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build protobuf-compiler | ||||
|     - name: make | ||||
|       run: make | ||||
|  | ||||
|   build-macos: | ||||
|     runs-on: macos-latest | ||||
|     steps: | ||||
|     - uses: actions/checkout@v1 | ||||
|     - uses: actions/checkout@v2 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: brew | ||||
|       run: brew install sqlite pkg-config libusb ninja | ||||
|       run: brew install sqlite pkg-config libusb ninja protobuf | ||||
|     - name: make | ||||
|       run: make | ||||
|  | ||||
| #  build-windows: | ||||
| #    runs-on: windows-latest | ||||
| #    steps: | ||||
| #    - uses: numworks/setup-msys2@v1 | ||||
| #      with: | ||||
| #        path-type: inherit | ||||
| #    - uses: actions/checkout@v1 | ||||
| #    - name: pacman | ||||
| #      run: | | ||||
| #        msys2do pacman -S --noconfirm --needed make ninja mingw-w64-i686-libusb mingw-w64-i686-sqlite3 mingw-w64-i686-zlib mingw-w64-i686-gcc zip | ||||
| #    - name: build | ||||
| #      run: | | ||||
| #        msys2do make | ||||
|   build-windows: | ||||
|     runs-on: windows-latest | ||||
|     defaults: | ||||
|       run: | ||||
|         shell: msys2 {0} | ||||
|     steps: | ||||
|     - uses: msys2/setup-msys2@v2 | ||||
|       with: | ||||
|         update: true | ||||
|         msystem: MINGW32 | ||||
|         install: >- | ||||
|           make | ||||
|           ninja | ||||
|           mingw-w64-i686-libusb | ||||
|           mingw-w64-i686-sqlite3 | ||||
|           mingw-w64-i686-zlib | ||||
|           mingw-w64-i686-gcc | ||||
|           zip | ||||
|           mingw-w64-i686-protobuf | ||||
|           vim | ||||
|     - uses: actions/checkout@v1 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: build | ||||
|       run: | | ||||
|         make | ||||
|  | ||||
|   | ||||
							
								
								
									
										63
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| name: Autorelease | ||||
|  | ||||
| on: | ||||
|   push: | ||||
|     branches: | ||||
|       - "master" | ||||
|  | ||||
| jobs: | ||||
|   dev-release: | ||||
|     runs-on: windows-latest | ||||
|     defaults: | ||||
|       run: | ||||
|         shell: msys2 {0} | ||||
|     steps: | ||||
|     - uses: msys2/setup-msys2@v2 | ||||
|       with: | ||||
|         update: true | ||||
|         msystem: MINGW32 | ||||
|         install: >- | ||||
|           make | ||||
|           ninja | ||||
|           mingw-w64-i686-libusb | ||||
|           mingw-w64-i686-sqlite3 | ||||
|           mingw-w64-i686-zlib | ||||
|           mingw-w64-i686-gcc | ||||
|           zip | ||||
|           mingw-w64-i686-protobuf | ||||
|           vim | ||||
|     - uses: actions/checkout@v2 | ||||
|       with: | ||||
|         fetch-depth: 1 | ||||
|     - name: build | ||||
|       run: | | ||||
|         make | ||||
|     - name: zip | ||||
|       run: | | ||||
|         zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex | ||||
|     - name: date | ||||
|       run: | | ||||
|         echo "RELEASE_DATE=$(date --rfc-3339=date)" >> ${GITHUB_ENV} | ||||
|     - name: tag | ||||
|       uses: EndBug/latest-tag@latest | ||||
|       with: | ||||
|         tag-name: dev | ||||
|       env: | ||||
|         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|     - name: delete-old-assets | ||||
|       uses: mknejp/delete-release-assets@v1 | ||||
|       with: | ||||
|         token: ${{ github.token }} | ||||
|         tag: dev | ||||
|         assets: |  | ||||
|           fluxengine.zip | ||||
|         fail-if-no-assets: false | ||||
|     - name: release | ||||
|       uses: softprops/action-gh-release@v1 | ||||
|       with: | ||||
|         name: Development build ${{ env.RELEASE_DATE }} | ||||
|         files: | | ||||
|           fluxengine.zip | ||||
|         tag_name: dev | ||||
|       env: | ||||
|         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
| @@ -1,246 +1,246 @@ | ||||
| :4000000000800020110000003110000031100000064A08B5136843F020031360044B1A6803F53F5302331A6001F020F8E8460040FA46004010B5054C237833B9044B13B18B | ||||
| :400040000448AFF300800123237010BD6881FF1F00000000B8380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000051 | ||||
| :400080006C81FF1FB8380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FCC | ||||
| :4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F0000800E4BDA681AB901215F | ||||
| :4001000019745A7410E05A7C1A741A7C0AB1002207E059699A69D8688A1A82428CBF002201225A745A699A611B7C13B1002002F043B970478881FF1F10B5C4B2204601F054 | ||||
| :4001400057F90128FAD110BD08B572B60F4B0F495A6901325A61DA690132C82A08BF0022DA611A6AD8690132A72A08BF00220A621B6A002B0CBF02230023002814BF184660 | ||||
| :4001800043F0010002F080FE62B608BD8881FF1F38B50446C5B2284602F0B0F8062002F0CDFA44F00200C0B202F0A8F8062002F0C5FA284602F0A2F8BDE83840062002F0C2 | ||||
| :4001C000A7BA10B5642402F093F828B9FFF7E0FF013CF8D1204610BD012010BD70B5C4B2054620460E4601F003F9012805D0204601F01CFA2846FFF79FFF204601F000F9AD | ||||
| :40020000314605460246204601F0BCF9204601F0EFF80028FAD1284670BD000038B5044D0024285D013402F039FA402CF9D138BDAC81FF1F08B502F053FC002002F05CFCBD | ||||
| :4002400002F06EFC02F078FC80B208BD10B50446012002F06BF8642002F05AFAFFF7EAFF2080002002F062F8642002F051FAFFF7E1FF608010BD08B502F05EFD002002F02B | ||||
| :4002800067FD02F079FD02F083FD80B208BD10B50446FFF796FF322002F03AFAFFF7EBFF20800120FFF774FF322002F031FAFFF7E2FF608010BD0FB400B593B014AB53F835 | ||||
| :4002C000042B402102A8019302F0DEFE02A802F07AF802F084F813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF723FF62782146BDE81040042001F0D0B8B5 | ||||
| :40030000CC38000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8643043B1002001F0D8FF002002F06BFD002384F864304E | ||||
| :4003400010BD00BF8881FF1F38B5104D837895F8672004469A4204D0FFF7E4FF002385F86A302368C5F865302279094B1A71A378002B14BF0220012002F04AFDE07802F02E | ||||
| :4003800041FD2079BDE8384002F078BD8881FF1FED81FF1F38B50D4C94F8645065B904F16500FFF7D1FF012001F09CFF4FF47A7002F0AEF984F86A506369E366012384F84D | ||||
| :4003C0006430BDE8384002F0E1B900BF8881FF1FF8B5214C0546FFF7DDFF94F86A3003B15DB91E48FFF767FFFFF7EBFE0120002384F86A00236702F0A1F92A46216F184872 | ||||
| :40040000FFF759FF144E0027236F9D4216D001F06FFF00B13767236F9D4205DD0120FFF7B7FE336F013305E005DA0020FFF7B0FE336F013B336702F0A9F9E5E7322002F047 | ||||
| :4004400067F92A2DCCBF0020012002F023FDBDE8F8400448FFF72FBF8881FF1FD9380000E0380000FD3800002DE9F04F99B062B602F0F6F99D49042002F01AFA9C4801F0D9 | ||||
| :4004800043FF9C4802F0E6FC9B4801F077FF02F0C7FB02F099FA002002F0BAFC01F092FF0221002000F05AFF944C012001F0D2F8002384F86730FFF76DFFFFF782FE84F8A3 | ||||
| :4004C0007400FFF72FFF012384F86730FFF762FFFFF777FE84F87500FFF724FF884B94F87400884994F875202546002A14BF0A461A46002808BF19468348FFF7DCFE032177 | ||||
| :40050000084602F023F9264602F040F994F8643043B1EA6E6B699B1A41F28832934201D9FFF700FF00F052FF18B97848FFF7C3FE04E000F051FF0028F7D10BE000F046FF85 | ||||
| :4005400010B902F023F9F9E77148FFF7B4FE032001F06CF8032000F04BFF0128D4D16D48FFF7F2FE6C490320FFF738FE94F876106A48FFF7A0FE94F87630023B142B00F229 | ||||
| :40058000D483DFE813F01500D2031E00D2032400D2034F00D2037500D203D700D203BF01D2030603D2032A03D2033103D2034B0303238DF820308DF821300F238DF8223084 | ||||
| :4005C00028E394F87800FFF703FF554B1FE3FFF7E1FE002323746069227C02F0FF0132B96B691B1AB3F57A7FF6DD0B4611E083B10022174696F878107069277494F810E007 | ||||
| :40060000BEF1000F02D16B691B1AF7E701329142F3DA07228DF8202004228DF82120ADF82230F7E20220FFF787FD4FF000080DF1200A02F0ABF84FF480790027C9EB080303 | ||||
| :40064000DA1907F80A200137402FF9D10220FFF773FD3A465146022000F022FFB9F10109EBD108F10108B8F1400FE2D12D4B38E04FF0010A4FF000080DF1200B02F086F844 | ||||
| :400680004FF0000959460120FFF7A8FD08EB090300270493049B1BF807203B44DBB29A4209D08DE80C0041463B464A461E48FFF702FE4FF0000A0137402FEBD109F101091B | ||||
| :4006C000B9F5807FDED108F10108B8F1400FD5D151461648FFF7EFFDBAF1000F00F01A81134B1B8807A8ADF81C3094E249010000F900000091000000C50000008881FF1F0B | ||||
| :400700000F3900000B390000123900002A3900003D390000ED81FF1FFE81FF1F47390000BC380000BE3800005639000072390000C0380000206FFFF74BFE94F8780001F081 | ||||
| :40074000F5FD94F8780001F0D9FD02F009FCB94BDFF8FC821A78002702F0FB021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F0F7FB0220FFF7DCFCF9 | ||||
| :40078000012141F6FF734FF48042084602F046FB84F8B60001F068FF08F807000137402FF8D1DFF8B0A200270AF195091FFA89F80137402F14BF3A4600221AF8010F2244C0 | ||||
| :4007C000062392F82420402101F082FF424646F24E419AF8000001F08DFF08F14008402F1FFA88F8E4D196F8793053B196F87C30F36000233374237C002BFCD000233374E1 | ||||
| :40080000F36000234FF0FF32236062602372236894F8B600234493F8241001F0DDFE94F8B60001F09BFE012194F8B60001F06EFE2368002BFCD0002398467360D6F814A0D4 | ||||
| :40084000012701F0A3FF6369B4F87A20CAEB030393420DD367B1042195F8B60001F0C8FE94F8B60001F0D4FE0028F9D107463072237AFBB96A682B689A4202D1002FE0D1D9 | ||||
| :4008800018E00220FFF758FC6968402209EB8111022000F005FE6A68674B01321340002BBEBF03F1FF3363F03F03013308F101086360C6E70220277AFFF73EFC0022114687 | ||||
| :4008C000022000F0EDFD0220FFF736FCFFB2FFF7A5FC002001F012FD37B15848FFF7EBFC0220FFF70FFD06E0554B08A81B88ADF82030FFF7F5FC227C4146237A5148FFF7BB | ||||
| :40090000DAFC15E25048FFF7D6FCD4F87A7017F03F0701D0032009E2286FFFF759FD95F8780001F003FD95F8780001F0E7FC012001F002FD02F014FB444BDFF814811A7857 | ||||
| :4009400042F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F003FB01214FF4804341F6FF72084601F0E9FC85F8B60001F077FE08F8070001378C | ||||
| :40098000402FF8D1DFF8CC90002709F195031FFA83F804930137402F14BF3A46002219F8010F2244052392F82420402101F090FE414646F24B5299F8000001F09BFE08F1FF | ||||
| :4009C0004008402F1FFA88F8E4D100274FF0FF33376098467360BB463B46D6F87A9037725FEA99190CBF4FF0010A4FF0000A2168114A01310A40002ABCBF02F1FF3262F03B | ||||
| :400A00003F026068B8BF013282426FD02BB1227A002A7AD12A7C002A77D12068049A059302EB8010BAF1000F16D040223F2102F0F7FA1CE09E6400403F0000807C390000C9 | ||||
| :400A4000C238000096390000A93900009B650040AC81FF1FAB81FF1F014601370120FFF7BDFBC7EB0903D3F1000A4AEB030A2168B34A01310A40002ABEBF02F1FF3262F0BB | ||||
| :400A80003F02013222606268059B01322ED12A683F2A2BD14FF00008C5F8048001F080FC85F808806B6895F8B6002B4493F8241001F092FD95F8B60001F050FD012195F8BF | ||||
| :400AC000B60001F023FD95F87E30EB6085F81080237C002BFCD04FF00008012086F8108001F06AFC404601F027FC00E023B1237A5BB92B7C4BB90123626842453FF477AFC1 | ||||
| :400B00000BF1010BD5F8048071E701F04FFC012001F012FC002001F04FFC042194F8B60001F066FD94F8B60001F072FD80460028F8D196F8B60001F0FFFC337C327A029318 | ||||
| :400B4000012303920193CDF800A05B463A4649467C48FFF7B0FBC6F80C80BAF1000F0BD0FFF75CFB002001F0C9FB237A63B17648FFF7A1FB0220D9E0B945F1D07349012035 | ||||
| :400B8000FFF72CFB0137F7E77148FFF794FB714B3DE094F8780001F0C9FB206FFFF718FC6D48FFF788FB94F87930E36000232374237C002BFCD0012001F0FEFB00233374CE | ||||
| :400BC000237C002BFCD0002001F0F6FB00236348F360FFF770FB624B19E0002084F86A00FFF7F6FB5F4B12E094F8743023B195F875200AB985F8782094F875201AB113B9F6 | ||||
| :400C0000012385F878305848FFF79EFB574B1B88ADF8203008A8FFF763FB89E0FFF782FB02F07CF8002002F01FF82A2701F04AFF002001F0EDFE3A46002108A802F0F0F9E0 | ||||
| :400C400017238DF820308DF8217001F09FFD002001F048FB002002F0DBF8C82001F058FD0DF12200FFF7F2FA0DF13600FFF70FFB01F08CFD012002F0CBF8322001F048FD4D | ||||
| :400C80000DF12600FFF7E2FA0DF13A00FFF7FFFA012001F027FB4FF4967001F039FD01F075FD0DF12E00FFF7D1FA0DF14200FFF7EEFA002001F016FB4FF4967001F028FD84 | ||||
| :400CC00001F064FD022002F0A3F8322001F020FD0DEB0700FFF7BAFA0DF13E00FFF7D7FA012001F0FFFA4FF4967001F011FD01F04DFD0DF13200FFF7A9FA0DF14600FFF756 | ||||
| :400D0000C6FA002001F0EEFA4FF4967001F000FD01F03CFD002002F07BF8002384F86A3001F07EFF01F050FE74E70120FFF7EAFA032000F07BFC0E48FFF7BDFAFFF7E4BBB6 | ||||
| :400D40003F000080B3390000E33900004092FF1FED390000C4380000F5390000033A0000C6380000C8380000FE81FF1FCA380000103A00002DE9F04172B6884B61221A70F9 | ||||
| :400D8000A3F5F06301221A801924854A9C7092E803008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2137040F618027E4B00251A8041F25122A6 | ||||
| :400DC00023F8022C33784FF4F07003F0010343EA450502F0BDF8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A002548211570917002221D705D7103F893 | ||||
| :400E0000032C0422DA716D4A6D4C13786D4E43F00103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70654A137843F02003137000E0FEE707FBAD | ||||
| :400E4000056300219A881868013502F0E9F8072DF5D15E485E4E002550F8041F05F1105303F1480221F0FF074933C9B20B4452005B0002329A4206D012F802EC12F801CC0C | ||||
| :400E80000EF807C0F5E7B0420D44E5D1514A002313609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A137843F002031370137C43F002031374F7 | ||||
| :400EC0002378A2F5863243F040032370413A137843F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C33B | ||||
| :400F00001A80404A083307CA03C31A803E4A3F4BA2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C329F | ||||
| :400F40001B091170F6B2537045F003033B7046F0030388F800302F4B48221A702E4A402313702E49937013729372082382F81F3220220A7048710A72294A0A20137001F0C7 | ||||
| :400F8000DDFB284B88F8006044223D70264D1A7094E80F0007C52B80BDE8F081004800405C0900480F010049A146004025420040224200400440004006400040A2430040AF | ||||
| :400FC000A0430040153A0000E8460040FCFFFF478C0000480076004064090048F8460040207600406809004828760040035001401C090048C051004028090048300900485A | ||||
| :401000003C090048480900483251004054090048CF0100491D51004001590040235B0040585B004076580040B0430040F946004008B501F0C9FF03680C2B00D1FEE7FEE79D | ||||
| :40104000084908B50B68084A1844821A802A01DC086005E001F0B8FF0C2303604FF0FF33184608BDCC80FF1F9093FF1F80B51148114B0025C0B1A3F1100192C92246043933 | ||||
| :40108000161BB74204D051F8046F42F8046BF7E7114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F094FFFFF7DCF9FEE700BF01000000E43B0000124A134BF0 | ||||
| :4010C00010B51A60124A134C1368134843F4007313600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF73BFEBDE8CA | ||||
| :40110000104001F0EDB900BF0004FA050CED00E014ED00E0000000000080FF1F31100000BC760040C080FF1F08ED00E0F8B501F017FF4B4A01271378022643F001031370EA | ||||
| :40114000137C484C43F001031374474B02F5E3521F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F90323701378384603F0DF03137023783B4325 | ||||
| :40118000237001F0DBFA282001F0D8FA384B30461A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0040323700023137053702F4AFF2199544A | ||||
| :4011C0000133092BFBD1284601F0CEFE0721172001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052032 | ||||
| :4012000001F0E4FA2049052001F0D2FA0721062001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162047 | ||||
| :4012400001F0C4FA1449162001F0B2FA07210C2001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D60004012600040F851004084600040B592FF1FFB1A00008A | ||||
| :4012800035190000F91A00002D1A0000591A0000891A0000C11A0000011B0000751B0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A1370D9 | ||||
| :4012C0001F4A13701F4A13701F4B4FF400021A604FF080721A604FF400121A6020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7851 | ||||
| :4013000002F0FE0202E01A7842F001021A70114B03221A70802203F8202C012001F018FE0D4B04221A7010BDD092FF1FD692FF1FD492FF1FD592FF1FD192FF1FC092FF1F97 | ||||
| :40134000D392FF1F4893FF1F00E100E09E6000409C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BF8092FF1F7A | ||||
| :401380000A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F8202C7047D692FF1FD492FF1FD592FF1FD192FF1FC092FF1F05 | ||||
| :4013C000D392FF1F4893FF1F28600040014B1878704700BFD592FF1F044B1A7802F0FF001AB118780022C0B21A707047D492FF1F024A0C2303FB002040787047DC92FF1FB8 | ||||
| :40140000431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044670 | ||||
| :4014400019BF8AB24FF480438BB24FF48042032D18D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF3E | ||||
| :40148000054B1855EDB2072D03D801F0EDF8034B185538BDDC92FF1FAC92FF1FB592FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB274 | ||||
| :4014C000C3F500739D424FF00C0303FB007388BFD588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FBBF | ||||
| :40150000047200215170B9F1000F28D03DB31B4F385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8040001F0DFF8124D18F80410385D01F004 | ||||
| :401540004BF80121385D00F0E1FF735D43F002037355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BFDC92FF1FFC5F0040B592FF1FAC92FF1FD4 | ||||
| :40158000706000402DE9F047044615468846002940D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF893 | ||||
| :4015C000040000F0B9FF1223FE222946305D01F07FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FF01211AF8040000F089FF17F8093043F0F1 | ||||
| :40160000020307F8093017F8093003F0FD0307F8093002E00D4600E000252846BDE8F087B592FF1FAC92FF1F70600040431E072B0AD8064A0C2303FB002300225A705A7991 | ||||
| :40164000034BD2B200011A54704700BFDC92FF1FFE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488E7 | ||||
| :40168000D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F23237022 | ||||
| :4016C000022301E0022323701370094B1870087030BD00BF4C93FF1F4893FF1F00600040C492FF1FC192FF1FD692FF1FD292FF1F4993FF1F074B02221A70074B80221A70AE | ||||
| :40170000064B0F221A70064A00231370054A012013707047D692FF1FD292FF1FC192FF1F4893FF1F4993FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80CC | ||||
| :40174000124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A70DF | ||||
| :4017800030BD00BF296000404C93FF1F00600040C492FF1F4993FF1FD292FF1FC192FF1F064A06231370064A01201370054B80221A70054B00221A70704700BFD692FF1F52 | ||||
| :4017C000C192FF1FD292FF1F4993FF1F054B9A683AB19A68044910709A680988518000229A607047C492FF1F4C93FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A1E | ||||
| :40180000137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F012FC04E001F0A5FB01E000F046FD10B9034B03221A7008BD00BF28600040C192FF1FC0 | ||||
| :401840000060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BD4C93FF1F4893FF1FD692FF1FC192FF1F08B50C4B1B78DBB25E | ||||
| :40188000042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BFD692FF1FC192FF1F08B5054B002201201A70FFF7B6 | ||||
| :4018C00085FF034B03221A7008BD00BFD692FF1FC192FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFA5 | ||||
| :40190000C092FF1F08600040D692FF1FC192FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF7047D692FF1F38B51D4C2378DBB2DD0634D51B | ||||
| :4019400018060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13705F | ||||
| :401980001278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD28600040C192FF1FD292FF1F4993FF1F29600040AD | ||||
| :4019C000054A00231380054A916819B191680B7092685380704700BF4C93FF1FC492FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FFAC | ||||
| :401A0000094AD1799379028843EA012392B2934238BF0380FFF728FE012008BDC492FF1FD692FF1FD292FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A07 | ||||
| :401A40001EBFDA7B82F08002DA7301225A7370470B600040DC92FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BFFE | ||||
| :401A80000B600040DC92FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B600040DC92FF1F78 | ||||
| :401AC0000B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B600040DC92FF1F7047FFF741BC000081 | ||||
| :401B0000F0B5184B184E19780C27C9B201234FF0000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4C35 | ||||
| :401B4000EDB204F80E50840706D507FB036425792D0658BF84F801C090700133DBB24908D7E7F0BD9F600040DC92FF1F70600040FE5F004000F0ACBC70B50446184B88B021 | ||||
| :401B800003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE002220461146AB5C08AC04EB131414F8144C03F053 | ||||
| :401BC0000F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD3F3A00002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02580B | ||||
| :401C00001401234418705F70164998F805902144B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71A2 | ||||
| :401C4000CC88E4B21C71C988C1F307215971D4D1054BFF221A70BDE8F08300BFDC92FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EB6F | ||||
| :401C8000C003586900207047D092FF1FA03A00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C260027FE | ||||
| :401CC0004FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0A6 | ||||
| :401D0000B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEAA3 | ||||
| :401D400002191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F8FE | ||||
| :401D80000790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BFD592FF1FDC92FF1FD192FF1FFC5F004070600040C292FF1F08B5064B187801384A | ||||
| :401DC000C0B2FFF753FF20B143681B7900EBC300406908BDD592FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD37013819372537031 | ||||
| :401E00005371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010273 | ||||
| :401E400002F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B34576 | ||||
| :401E80001AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092D89 | ||||
| :401EC000C3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D38012890131134463 | ||||
| :401F00009BB203F00102134409299BB2F2D1BDE8F84FFFF767BEBDE8F88F00BFDC92FF1FC292FF1F4A93FF1FD592FF1FD392FF1FD892FF1F114B1B7903F07F035A1E072A3C | ||||
| :401F400019D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF0060004065 | ||||
| :401F8000DC92FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F013 | ||||
| :401FC000FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF00600040DC92FF1FFC5F004010B50D4BA5 | ||||
| :402000000D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BDD592FF1F00600040C292FF1FB6 | ||||
| :402040004A93FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B0003017E0003018200D3787C49012B9C | ||||
| :4020800009D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7843EA02232380BDE83840FFF7EE | ||||
| :4020C0008FBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D018780344EAE764499278097C914203D180 | ||||
| :402100006248FFF739FD614B1A78002A00F0AD801A78228018E0BDE8384000F029BF13F0030313D0022B40F0A0802380504B0C211B7903F07F02564B01FB02339A78554BC3 | ||||
| :40214000D2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E701390A2977D8DFE801F0377608 | ||||
| :402180004F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF793 | ||||
| :4021C0001DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B47 | ||||
| :4022000033D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1B7 | ||||
| :40224000154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BF00600040C492FF1FD092FF1FA03A000049 | ||||
| :40228000043B00008C3A0000773B00006893FF1FDC92FF1F8192FF1FD392FF1FD592FF1FC292FF1FC092FF1FD492FF1FD192FF1F4A93FF1FD792FF1F074B1A78120609D546 | ||||
| :4022C0005B78012B06D1054B054A5A6012781A80FFF786BB0020704700600040C492FF1F643A0000014B1870704700BF7A640040014B1878704700BF6B650040014B18702D | ||||
| :40230000704700BF79640040064A0123136002F688321268E0211064034A1170A2F540721360704780E100E000E400E0014B1870704700BF7A650040014B1870704700BF89 | ||||
| :402340007865004073B515461E460B4C05230022019200920A4601461846237000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A04232E | ||||
| :40238000136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF30 | ||||
| :4023C0007E640040704738B505460078012428B100F066FD285D0134E4B2F8E738BD08B50D2000F05DFDBDE808400A2000F058BDF7B516461F460B4C002303250193009359 | ||||
| :402400000A4601462846257000F00EF93A463146207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257030 | ||||
| :4024400000F0F2F83A463146207800F0ADF82946207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146DE | ||||
| :40248000207800F091F80221207800F07BF8207803B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F8022120782A | ||||
| :4024C00000F060F8207802B070BD00BFE380FF1F024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFCC | ||||
| :40250000E480FF1FF87B00400078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001EA | ||||
| :40254000C25C02F0FE02C254C25C02F0DF02C25400207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F001034354002070470120704740 | ||||
| :402580001070004017280BD8064A0001835C490003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBF85 | ||||
| :4025C000C00000F1804000F5EC4081809ABFC280002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBFDC | ||||
| :402600001143195400200120704700BF1470004017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC4422 | ||||
| :40264000D2B222709DF8082003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F079FC0A4A5378182B0AD91478013B5370E30003F1FB | ||||
| :40268000804303F5F0431B78137000E0FF2400F06BFC204610BD00BFE480FF1F030610B5044611D400F05CFC084AE300117803F1804303F5F0431970537814700133537094 | ||||
| :4026C000BDE8104000F050BC10BD00BFE480FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5D2 | ||||
| :40270000F04081805ABFC280002001207047000038B50446084DB4F5004F05D9286800F017FCA4F50044F6E7034B58686043BDE8384000F00DBC00BFEC80FF1F024B1B7AB4 | ||||
| :40274000584300F005BC00BFEC80FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F060 | ||||
| :4027800010021A70704700BF83430040014B01221A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230009 | ||||
| :4027C00042F82310704700BF08ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040334 | ||||
| :4028000013600A4B4FF47A72DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD8492FF1F8D28000010E000E0EC80FF1F14E000E018E000E0024A136843F0020334 | ||||
| :402840001360704710E000E008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BF8492FF1F024B186891 | ||||
| :40288000C0F30040704700BF10E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF8892FF1F024B03EB80035868596070478492FF1F1F | ||||
| :4028C000134B144A1B78DBB20360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA024382 | ||||
| :402900000A4A4360127843EA02634360704700BF0301004904010049EC460040020100490101004900010049050100490601004910B500F015FB204A044613780A2043F07D | ||||
| :4029400002031370137C43F00203137412F80A3C43F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F837 | ||||
| :40298000012C02F0FC0203F8012CCE2203F8062CA3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D8BAAB4300400E59004026 | ||||
| :4029C0002F5B004080E200E008B500F0C9FA0F4A137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE0388 | ||||
| :402A00009371BDE8084000F0AFBA00BF08590040044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B2042812 | ||||
| :402A4000137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040503A00005293FF1FB7 | ||||
| :402A80005493FF1F5893FF1F08B5102000F0A6F907210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BD812B0000095900402E | ||||
| :402AC0005093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF72ABFA092FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0F1 | ||||
| :402B0000010403D10028F9D0002404E02046FFF715FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF5893FF1FA25B00400E4A13881BB223B1D5 | ||||
| :402B400011880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475293FF1F5493FF1F5093FF1F29 | ||||
| :402B80007047000010B500F0EBF9214A044613780A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F0030343 | ||||
| :402BC0001370144B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074BEE | ||||
| :402C000008222046BDE810401A6000F0ADB900BFAB43004006590040275B004080E200E008B500F09DF90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C9E | ||||
| :402C400003F0FE03137412F80A3C03F0FD0302F80A3C937903F0FD039371BDE8084000F083B900BF00590040044A137803F03F0343EA8010C0B21070704700BF0059004016 | ||||
| :402C8000082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBDD | ||||
| :402CC000F1F305490B60054B1A807047025900405A3A00005E93FF1F6493FF1F5C93FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F035 | ||||
| :402D000006031370FFF7BCFF034B00221A8008BDD92D0000015900406093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BFA192FF1F044B1A7802F0FB02D6 | ||||
| :402D40001A701A7842F001021A7070470059004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B88108822 | ||||
| :402D8000181A00B2704700BF5C93FF1FA05B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF86 | ||||
| :402DC0005B42134493FBF1F000B270475E93FF1F6493FF1F6093FF1F70470000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF9A | ||||
| :402E000006410040014B1870704700BF78640040014B1870704700BF7965004073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7AB | ||||
| :402E4000B3FB02212078FFF79DFB207802B070BDFC80FF1F074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B18708C | ||||
| :402E8000704700BF7C640040014B1870704700BF7B640040014B1870704700BF7F640040FEB5494652465B460EB40746244909688A46244A12682448022100F071F803009B | ||||
| :402EC00020480068C018204900F06AF8143883460121C9430C460125002600F041F8814651460B7823400B705846013000F030F83800F04028400B78234003430B705846AA | ||||
| :402F000000F026F80136072EF2D9002001300138013001200B78234003430B705846043000F016F8484600F01FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF3008039 | ||||
| :402F4000D480FF1FF880FF1F00C20100000000000230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BF094A137803F00303012B0AD0022B09D181 | ||||
| :402F800013790C2103F07F02044B01FB02339B7A00E013790020704700600040DC92FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB0B | ||||
| :402FC00011217047704700BF014B1868704700BF6081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E700F0DEFD084B094C1E46E41AA41000251E | ||||
| :40300000A54204D056F8253098470135F8E770BDBC3B0000BC3B0000BC3B0000C43B000003460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B232B6026 | ||||
| :403040004FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F073F8431CBCBF8B232B6014B1009B0022F6 | ||||
| :403080001A701BB030BD000007B5009313460A46014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD025685F | ||||
| :4030C000096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F04AFB064698B13A46216900F0D2FAA38923F4906343F08003A38113E02A462B | ||||
| :4031000000F098FB064670B92169504600F0E8FA0C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF4646494632462068B9 | ||||
| :4031400000F0B3FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F001FB2860286118B90C23C8F8D4 | ||||
| :403180000030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF7EA | ||||
| :4031C00071FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C46E7 | ||||
| :40320000801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F002006C | ||||
| :40324000079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E010 | ||||
| :40328000002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B01371843049053 | ||||
| :4032C000397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A937 | ||||
| :40330000404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF8B3B0000913B0000953B000000000000A5300000D1 | ||||
| :403340002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F00605F2 | ||||
| :4033800010D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F84E | ||||
| :4033C00045102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE57500252C | ||||
| :403400009342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9BE3 | ||||
| :4034400001F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B880A0 | ||||
| :403480000A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F104011960E2 | ||||
| :4034C00002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2A40 | ||||
| :4035000014BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F020022260102266 | ||||
| :40354000002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D131 | ||||
| :40358000082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F1040087 | ||||
| :4035C0001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F8A9 | ||||
| :403600004330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A4639463046F8 | ||||
| :40364000C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F0833F3A00009C3B000010B5C9B202449042CF | ||||
| :40368000034605D01C7801308C42F8D1184610BD002010BD10B5431E0A44914204D011F8014B03F8014FF8E710BD884210B501EB020301D8421E0BE09842FBD28118D21A41 | ||||
| :4036C000D34204D013F8014D01F8014DF8E710BD994204D011F8014B02F8014FF8E710BD38B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B912 | ||||
| :403700006360146030E0A3420DD92268A018834201BF18685B681218226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D1F2 | ||||
| :4037400010685268014419605A600DE002D90C232B6009E021686018824201BF106852680918216062605C602846BDE8384000F098B838BDA892FF1F70B5CD1C25F003051A | ||||
| :4037800008350C2D38BF0C25002D064601DBA94202D90C23336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B6896 | ||||
| :4037C0001360636018BF0C4615E00C464968E9E7174C23681BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B005E | ||||
| :40380000231D20F00700C31A0ED05A42E25070BD211A304600F034F80130EBD10C233360304600F03EF8002070BD00BFA892FF1FA492FF1FF8B5074615460E4621B91146D1 | ||||
| :40384000BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F885420ED929463846FFF78BFF044650B131462A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD40 | ||||
| :4038800038B5064C0023054608462360FDF7D8FB431C02D1236803B12B6038BD8C93FF1F7047704751F8040C0028BEBF091851F8043CC018043870470000000005020902A2 | ||||
| :4038C0000B020D020F021102130215027265706C792030782530327800686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F2025640066696E08 | ||||
| :403900006973686564207365656B00796573006E6F00647269766520303A20257320647269766520313A2025730057616974696E6720666F72205553422E2E2E00555342F3 | ||||
| :4039400020726561647900636F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E646544 | ||||
| :403980007272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D256400636D645F777269746500703D25642063723D256420637729 | ||||
| :4039C0003D256420663D256420773D256420696E6465783D256420756E64657272756E3D256400756E64657272756E21007375636365737300737461727420657261736912 | ||||
| :403A00006E670073746F702065726173696E670069646C650000510040100040510040300000000140001000140140000800400140000A004C0140000200500140200030F9 | ||||
| :403A400031323334353637383941424344454600000100000004000000100001000000040000001028000000000104000100000000000000000157494E5553420000303043 | ||||
| :403A800030303100000000000000000012034D005300460054003100300030000100000001000000A83A000001000000773B0000000000000000000001000000C03A000003 | ||||
| :403AC00001000000493B000004000000E23A0000000000000000000000000000E03A0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000F7 | ||||
| :403B0000FF00020304030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0003 | ||||
| :403B400067006900650073000009022E0001010080320904000004FF00000107050102400000070582024000000705030340000A0705840340000A12010002FF0001080921 | ||||
| :403B800012006E0100020180014300232D302B2000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E4670475900000094 | ||||
| :403BC000BD100000F8B500BFF8BC08BC9E46704735000000E83B0000C880FF1FA00000002812000000000000000000009093FF1FFF000000675000400C0000000700000097 | ||||
| :403C0000FFFFFFFF7F8000003F0000000000007D00FA0000400000000090D003FF000000000000000000000000000000000000000000000000000000000000000000000031 | ||||
| :403C4000893B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 | ||||
| :403C80000081FF1F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065 | ||||
| :4000000000800020110000004910000049100000064A08B5136843F020031360044B1A6803F53F5302331A6001F02CF8E8460040FA46004010B5054C237833B9044B13B14F | ||||
| :400040000448AFF300800123237010BD6881FF1F00000000D0380000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000039 | ||||
| :400080006C81FF1FD0380000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FB4 | ||||
| :4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080114BDA68196919B9FD | ||||
| :4001000001221A75597514E09969521A19698A4294BF587D00201875187D094908B1002204E0086982428CBF002201224A75DA689A611B7D13B1002002F04AB9704700BF6C | ||||
| :400140008881FF1F10B5C4B2204601F05DF90128FAD110BD08B572B60F4B0F49DA680132DA60DA690132C82A08BF0022DA611A6AD8690132A72A08BF00220A621B6A002B0F | ||||
| :400180000CBF02230023002814BF184643F0010002F086FE62B608BD8881FF1F38B50446C5B2284602F0B6F8062002F0D3FA44F00200C0B202F0AEF8062002F0CBFA2846F9 | ||||
| :4001C00002F0A8F8BDE83840062002F0ADBA10B5642402F099F828B9FFF7E0FF013CF8D1204610BD012010BD70B5C4B2054620460E4601F009F9012805D0204601F022FA20 | ||||
| :400200002846FFF79FFF204601F006F9314605460246204601F0C2F9204601F0F5F80028FAD1284670BD000038B5044D0024285D013402F03FFA402CF9D138BDAC81FF1FBB | ||||
| :4002400008B502F059FC002002F062FC02F074FC02F07EFC80B208BD10B50446012002F071F8642002F060FAFFF7EAFF2080002002F068F8642002F057FAFFF7E1FF60807C | ||||
| :4002800010BD08B502F064FD002002F06DFD02F07FFD02F089FD80B208BD10B50446FFF796FF322002F040FAFFF7EBFF20800120FFF774FF322002F037FAFFF7E2FF6080BA | ||||
| :4002C00010BD0FB400B593B014AB53F8042B402102A8019302F0E4FE02A802F080F802F08AF813B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF723FF62780A | ||||
| :400300002146BDE81040042001F0D6B8E438000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8643043B1002001F0DEFFDE | ||||
| :40034000002002F071FD002384F8643010BD00BF8881FF1F38B5104D837895F8672004469A4204D0FFF7E4FF002385F86A302368C5F865302279094B1A71A378002B14BF41 | ||||
| :400380000220012002F050FDE07802F047FD2079BDE8384002F07EBD8881FF1FED81FF1F38B50D4C94F8645065B904F16500FFF7D1FF012001F0A2FF4FF47A7002F0B4F954 | ||||
| :4003C00084F86A50E368E366012384F86430BDE8384002F0E7B900BF8881FF1FF8B5214C0546FFF7DDFF94F86A3003B15DB91E48FFF767FFFFF7EBFE0120002384F86A0078 | ||||
| :40040000236702F0A7F92A46216F1848FFF759FF144E0027236F9D4216D001F075FF00B13767236F9D4205DD0120FFF7B7FE336F013305E005DA0020FFF7B0FE336F013B03 | ||||
| :40044000336702F0AFF9E5E7322002F06DF92A2DCCBF0020012002F029FDBDE8F8400448FFF72FBF8881FF1FF1380000F8380000153900002DE9F04F99B062B602F0FCF91F | ||||
| :400480009E49042002F020FA9D4801F049FF9D4802F0ECFC9C4801F07DFF02F0CDFB02F09FFA002002F0C0FC01F098FF0221002000F060FF954C012001F0D8F8002384F868 | ||||
| :4004C0006730FFF76DFFFFF782FE84F87400FFF72FFF012384F86730FFF762FFFFF777FE84F87500FFF724FF894B94F87400894994F875202546002A14BF0A461A4600286F | ||||
| :4005000008BF19468448FFF7DCFE0321084602F029F9264602F046F994F8643043B1EA6EEB689B1A41F28832934201D9FFF700FF00F058FF18B97948FFF7C3FE04E000F06D | ||||
| :4005400057FF0028F7D10BE000F04CFF10B902F029F9F9E77248FFF7B4FE032001F072F8032000F051FF0128D4D16E48FFF7F2FE6D490320FFF738FE94F876106B48FFF7E5 | ||||
| :40058000A0FE94F87630023B142B00F2D683DFE813F01500D4031E00D4032400D4035000D4037600D403D900D403C101D4030803D4032C03D4033303D4034D0303238DF851 | ||||
| :4005C00020308DF821300F238DF822302AE394F87800FFF703FF564B21E340F2DC57FFF7DFFE00232375E068227D02F0FF012AB9EB681B1ABB42F7DD0B4611E083B100227E | ||||
| :40060000174696F87810F068277594F814E0BEF1000F02D1EB681B1AF7E701329142F3DA07228DF8202004228DF82120ADF82230F8E20220FFF786FD4FF000080DF1200A54 | ||||
| :4006400002F0B0F84FF480790027C9EB0803DA1907F80A200137402FF9D10220FFF772FD3A465146022000F027FFB9F10109EBD108F10108B8F1400FE2D12E4B38E04FF06E | ||||
| :40068000010A4FF000080DF1200B02F08BF84FF0000959460120FFF7A7FD08EB090300270493049B1BF807203B44DBB29A4209D08DE80C0041463B464A461F48FFF701FEDC | ||||
| :4006C0004FF0000A0137402FEBD109F10109B9F5807FDED108F10108B8F1400FD5D151461648FFF7EEFDBAF1000F00F01B81144B1B8807A8ADF81C3095E200BF5501000004 | ||||
| :40070000F900000091000000C50000008881FF1F27390000233900002A3900004239000055390000ED81FF1FFE81FF1F5F390000D4380000D63800006E3900008A390000D6 | ||||
| :40074000D8380000206FFFF749FE94F8780001F0F9FD94F8780001F0DDFD02F00DFCB94BDFF8FC821A78002702F0FB021A701A7842F001021A701A7802F0FE021A701A786C | ||||
| :4007800002F0FE021A7002F0FBFB0220FFF7DAFC012141F6FF734FF48042084602F04AFB84F8B60001F06CFF08F807000137402FF8D1DFF8B0A200270AF195091FFA89F80A | ||||
| :4007C0000137402F14BF3A4600221AF8010F2244062392F82420402101F086FF424646F24F419AF8000001F091FF08F14008402F1FFA88F8E4D196F8793053B196F87C30B1 | ||||
| :40080000336100233375237D002BFCD000233375336100234FF0FF32236062602372236894F8B600234493F8241001F0E1FE94F8B60001F09FFE012194F8B60001F072FE9E | ||||
| :400840002368002BFCD0002398467360D6F80CA0012701F0A7FFE368B4F87A20CAEB030393420DD367B1042195F8B60001F0CCFE94F8B60001F0D8FE0028F9D107463072C3 | ||||
| :40088000237AFBB96A682B689A4202D1002FE0D118E00220FFF756FC6968402209EB8111022000F009FE6A68674B01321340002BBEBF03F1FF3363F03F03013308F101081C | ||||
| :4008C0006360C6E70220277AFFF73CFC00221146022000F0F1FD0220FFF734FCFFB2FFF7A3FC002001F016FD37B15848FFF7E9FC0220FFF70DFD06E0554B08A81B88ADF869 | ||||
| :400900002030FFF7F3FC227D4146237A5148FFF7D8FC15E25048FFF7D4FCD4F87A7017F03F0701D0032009E2286FFFF757FD95F8780001F007FD95F8780001F0EBFC01204C | ||||
| :4009400001F006FD02F018FB444BDFF814811A7842F004021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7002F007FB01214FF4804341F6FF72084601F0BF | ||||
| :40098000EDFC85F8B60001F07BFE08F807000137402FF8D1DFF8CC90002709F195031FFA83F804930137402F14BF3A46002219F8010F2244052392F82420402101F094FEA6 | ||||
| :4009C000414646F24A5299F8000001F09FFE08F14008402F1FFA88F8E4D100274FF0FF33376098467360BB463B46D6F87A9037725FEA99190CBF4FF0010A4FF0000A2168BA | ||||
| :400A0000114A01310A40002ABCBF02F1FF3262F03F026068B8BF013282426FD02BB1227A002A7AD12A7D002A77D12068049A059302EB8010BAF1000F16D040223F2102F079 | ||||
| :400A4000FBFA1CE09F6400403F00008094390000DA380000AE390000C13900009A650040AC81FF1FAB81FF1F014601370120FFF7BBFBC7EB0903D3F1000A4AEB030A21684C | ||||
| :400A8000B34A01310A40002ABEBF02F1FF3262F03F02013222606268059B01322ED12A683F2A2BD14FF00008C5F8048001F084FC85F808806B6895F8B6002B4493F82410D5 | ||||
| :400AC00001F096FD95F8B60001F054FD012195F8B60001F027FD95F87E302B6185F81480237D002BFCD04FF00008012086F8148001F06EFC404601F02BFC00E023B1237A40 | ||||
| :400B00005BB92B7D4BB90123626842453FF477AF0BF1010BD5F8048071E701F053FC012001F016FC002001F053FC042194F8B60001F06AFD94F8B60001F076FD804600285F | ||||
| :400B4000F8D196F8B60001F003FD337D327A0293012303920193CDF800A05B463A4649467C48FFF7AEFBC6F81080BAF1000F0BD0FFF75AFB002001F0CDFB237A63B176484B | ||||
| :400B8000FFF79FFB0220D9E0B945F1D073490120FFF72AFB0137F7E77148FFF792FB714B3DE094F8780001F0CDFB206FFFF716FC6D48FFF786FB94F87930236100232375F4 | ||||
| :400BC000237D002BFCD0012001F002FC00233375237D002BFCD0002001F0FAFB002363483361FFF76EFB624B19E0002084F86A00FFF7F4FB5F4B12E094F8743023B195F867 | ||||
| :400C000075200AB985F8782094F875201AB113B9012385F878305848FFF79CFB574B1B88ADF8203008A8FFF761FB89E0FFF780FB02F080F8002002F023F82A2701F04EFFDD | ||||
| :400C4000002001F0F1FE3A46002108A802F0F4F917238DF820308DF8217001F0A3FD002001F04CFB002002F0DFF8C82001F05CFD0DF12200FFF7F0FA0DF13600FFF70DFBE9 | ||||
| :400C800001F090FD012002F0CFF8322001F04CFD0DF12600FFF7E0FA0DF13A00FFF7FDFA012001F02BFB4FF4967001F03DFD01F079FD0DF12E00FFF7CFFA0DF14200FFF703 | ||||
| :400CC000ECFA002001F01AFB4FF4967001F02CFD01F068FD022002F0A7F8322001F024FD0DEB0700FFF7B8FA0DF13E00FFF7D5FA012001F003FB4FF4967001F015FD01F023 | ||||
| :400D000051FD0DF13200FFF7A7FA0DF14600FFF7C4FA002001F0F2FA4FF4967001F004FD01F040FD002002F07FF8002384F86A3001F082FF01F054FE74E70120FFF7E8FA75 | ||||
| :400D4000032000F07FFC0E48FFF7BBFAFFF7E2BB3F000080CB390000FB3900004092FF1F053A0000DC3800000D3A00001B3A0000DE380000E0380000FE81FF1FE238000096 | ||||
| :400D8000283A00002DE9F04172B6874A874D1378002443F020031370062606FB045300219A881868013402F047F9072CF5D18048804D002450F8041F04F1105303F14C02D0 | ||||
| :400DC00021F0FF064D33C9B20B4452005B0002329A4206D012F8027C12F801EC07F806E0F5E7A8420C44E5D1734A00231360936013619361714A724D1168724A724C116044 | ||||
| :400E0000724A19261168724A724F116072490A7842F002020A700A7C42F002020A742A78A1F5863142F040022A7041390A7842F010020A70694A07CA03C469492280086863 | ||||
| :400E4000684A2834106009791171674A07CA03C42280664AE83C07CA03C42280644A083407CA03C42280634A03CAC4F80A006248C4F80E100178614C41F008010170604995 | ||||
| :400E800061200870A1F5F061012008808E7092E803005C4A84E80300062111705221A2F580721170584A594912781C46D2B20A70574A4FF4E261118041F2512122F8021C31 | ||||
| :400EC0003B784FF4F07003F0010343EA440303F0030402F049F8013E64D0032CF0D14D4A4FF4807313804C49072313704B4800230B704821017013705371494B02221A706B | ||||
| :400F000004229A7290F89A33464F43F0010380F89A3390F89933DFF82C8143F0030380F899332B78C12043F080032B70344B18703D4B3E481B783C78DBB298F80060E4B280 | ||||
| :400F400003F0070ED34080F800E0F6B2437044F003033B7046F0030388F80030344B1970344940230B708B700B728B72082381F81F32202180F8B51280F8BA222E4A0A208F | ||||
| :400F8000117082F82D3001F0E5FB2C4B88F8006044223C702A4C1A7095E80F0007C42380BDE8F081FEE700BFE84600402D3A0000FCFFFF4794000048007600405C0B004894 | ||||
| :400FC000A043004020760040C0510040600B0048287600402542004003500140140B0048200B0048CB510040280B0048340B0048400B00484C0B004822430040004100404B | ||||
| :4010000000480040004300400F010049A14600402242004004400040064000400840004001400040F8460040CF0100496E5800401D510040015900402B5B004076580040B5 | ||||
| :40104000B0430040F946004008B501F0C9FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E001F0B8FF0C2303604FF0FF33184608BDCC80FF1F34 | ||||
| :401080009093FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F8046C8C1AA64202D041F8045BF9E701381033E5E757 | ||||
| :4010C00001F094FFFFF7D6F9FEE700BF01000000FC3B0000124A134B10B51A60124A134C1368134843F4007313600023032B98BF54F823204FEA830188BF0E4A0133302B02 | ||||
| :401100004250F3D10C4B1A780C4B1A700C4B084A1A60FFF737FEBDE8104001F0EDB900BF0004FA050CED00E014ED00E0000000000080FF1F49100000BC760040C080FF1F72 | ||||
| :4011400008ED00E0F8B501F017FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E3521F700B3203F8946C1378054603F07F031370002001F0EAFA93 | ||||
| :401180002378404A03F0F90323701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B30461A7802F07F021A701A7802F0BF021A7023783343237001F0BE | ||||
| :4011C000C9FA2378314A43F0040323700023137053702F4AFF2199540133092BFBD1284601F0CEFE0721172001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182051 | ||||
| :4012000001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A490720CB | ||||
| :4012400001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C2001F0BCFABDE8F84010490C2001F0A8BAA54300409443004068 | ||||
| :401280009D60004012600040F851004084600040B592FF1F131B00004D190000111B0000451A0000711A0000A11A0000D91A0000191B00008D1B0000214B224A10B51870D4 | ||||
| :4012C00000231370204A40201370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A604FF080721A604FF400121A6020221A601860802018604FF4F9 | ||||
| :4013000080701860174804704FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B03221A70802203F8202C012001F018FE0D4B04221A7010BD04 | ||||
| :40134000D092FF1FD692FF1FD492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F00E100E09E6000409C600040286000401260004070B5074C054623780E461BB9B6 | ||||
| :40138000FFF7E0FE0123237031462846BDE87040FFF792BF8092FF1F0A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F84C | ||||
| :4013C000202C7047D692FF1FD492FF1FD592FF1FD192FF1FC092FF1FD392FF1F4893FF1F28600040014B1878704700BFD592FF1F044B1A7802F0FF001AB118780022C0B28E | ||||
| :401400001A707047D492FF1F024A0C2303FB002040787047DC92FF1F431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F004062 | ||||
| :401440001A4A38B50C2303FB00231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032D18D8DFE805F002070C110021084601F01BF80DE000210846F4 | ||||
| :4014800000F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034B185538BDDC92FF1FAC92FF1FB592FF1F431E072B2DE9F0470D | ||||
| :4014C0000446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BFD588DB7884BFC5F50075ADB2254A43EA15230601B354B244E9 | ||||
| :40150000EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F385D01F011F811232946FE2218F8040001F0D6F806F5C04262 | ||||
| :4015400078321FFA89F118F8040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F002037355735D03F0FD037355BDE8F08703FB04746379DBB28AF8A7 | ||||
| :401580000230BDE8F08700BFDC92FF1FFC5F0040B592FF1FAC92FF1F706000402DE9F047044615468846002940D0431E072B3FD8FFF732FFA84203D22046FFF72DFF0546CA | ||||
| :4015C0001D4E335DFF2B03D141462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F07FF807F5C0411FFA88F27831305D01F089F8DFF84490315DE9 | ||||
| :401600001AF8040000F0F4FF01211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F8093002E00D4600E000252846BDE8F087B592FF1FAC92FF1F51 | ||||
| :4016400070600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BFDC92FF1FFE5F0040431E072B9FBF024B000108221A547047FE5F00407B | ||||
| :4016800030B51A4A1A491B4D0878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B78A4 | ||||
| :4016C0000E4C082B0E4A00D040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087030BD00BF4C93FF1F4893FF1F00600040C492FF1FC192FF1F34 | ||||
| :40170000D692FF1FD292FF1F4993FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012013707047D692FF1FD292FF1FC192FF1F4893FF1F4993FF1F11 | ||||
| :4017400030B5164B16491B780A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B2B5 | ||||
| :401780001180ECE7094A1370094A137883F080031370084B0B221A7030BD00BF296000404C93FF1F00600040C492FF1F4993FF1FD292FF1FC192FF1F064A06231370064ACF | ||||
| :4017C00001201370054B80221A70054B00221A70704700BFD692FF1FC192FF1FD292FF1F4993FF1F054B9A683AB19A68044910709A680988518000229A607047C492FF1F2D | ||||
| :401800004C93FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F012FC04E001F0A5FB01E04F | ||||
| :4018400000F046FD10B9034B03221A7008BD00BF28600040C192FF1F0060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BDC9 | ||||
| :401880004C93FF1F4893FF1FD692FF1FC192FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A70E0 | ||||
| :4018C00008BD00BFD692FF1FC192FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BFD692FF1FC192FF1F08B50A4B1A7832B11A78094942F080020A700022E6 | ||||
| :401900001A70074B002201201A70FFF76BFF054B03221A7008BD00BFC092FF1F08600040D692FF1FC192FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF742 | ||||
| :40194000C5BFFFF7D3BF7047D692FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5DF | ||||
| :40198000FFF786FF23781B061BD4104B1A78104B1B7813430F4A13701278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D1E2 | ||||
| :4019C00038BD38BD28600040C192FF1FD292FF1F4993FF1F29600040054A00231380054A916819B191680B7092685380704700BF4C93FF1FC492FF1F0E4808B503889BB255 | ||||
| :401A000013B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B2934238BF0380FFF728FE012008BDC492FF1FD692FF1FD292FF1F00 | ||||
| :401A400000600040084B01221A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B600040DC92FF1F094B02221A700F3B93F82230074B1A7EF8 | ||||
| :401A800002F00302012A1EBFDA7E82F08002DA7601225A76704700BF0B600040DC92FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F048 | ||||
| :401AC000800283F82720012283F82520704700BF0B600040DC92FF1F0B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F833200122D0 | ||||
| :401B000083F83120704700BF0B600040DC92FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF0000C31B3CA0720D5144A4FEA031E7244947850782040C5074E | ||||
| :401B40000DD507FB03652C79240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425792D0658BF84F801C090700133DBB24908D7E7F0BD9F60004080 | ||||
| :401B8000DC92FF1F70600040FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD0323284663703F | ||||
| :401BC00000F08AFE002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD573A00002DE9F043B7 | ||||
| :401C00001C4D01222E460C201F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144B9F1000F07D098F8044024064CBF887081F802C001E081F877 | ||||
| :401C400002E000FB0261CC880132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D1054BFF221A70BDE8F08300BFDC92FF1F70600040FC5F004028 | ||||
| :401C80000A600040064B074A1B7802EBC30253681A7C824286BF03EBC003586900207047D092FF1FB83A00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFEA | ||||
| :401CC000A8463F4AC3681478007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB77 | ||||
| :401D00000A01CF7093F802B009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E007 | ||||
| :401D400009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F81A | ||||
| :401D800006A011495FFA8AFA494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BFD592FF1FDC92FF1F91 | ||||
| :401DC000D192FF1FFC5F004070600040C292FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BDD592FF1F00212DE9F84F0B464E4E0C2707FB01F46E | ||||
| :401E000001313219092933554FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8E0 | ||||
| :401E4000F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F8A4 | ||||
| :401E800004B0B6B25E4538BFA1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F80180C8 | ||||
| :401EC00006E0012E0CBF052609264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF737 | ||||
| :401F000067FF114B0121186000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF767BEBDE8F88F00BFDC92FF1FC292FF1F4A93FF1F7A | ||||
| :401F4000D592FF1FD392FF1FD892FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A54 | ||||
| :401F80001A4414BF8D2389239370FFF715BC0020704700BF00600040DC92FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0155 | ||||
| :401FC00099700021D97029461201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB3C | ||||
| :40200000002030BC704700BF00600040DC92FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A378F6 | ||||
| :402040000120DBB2535410BD002010BDD592FF1F00600040C292FF1F4A93FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D00030155 | ||||
| :4020800003010301030103010B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E18000 | ||||
| :4020C000436863606368DA7863689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E046 | ||||
| :40210000187801320028F1D018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD801A78228018E0BDE8384000F029BF13F0030313D0022B40F0A3 | ||||
| :40214000A0802380504B0C211B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE722 | ||||
| :402180000123238013794C4A1344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B012062 | ||||
| :4021C0001870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF788 | ||||
| :4022000053FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B3C | ||||
| :402240001FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF71A | ||||
| :402280009BBA002038BD00BF00600040C492FF1FD092FF1FB83A00001C3B0000A43A00008F3B00006893FF1FDC92FF1F8192FF1FD392FF1FD592FF1FC292FF1FC092FF1FB0 | ||||
| :4022C000D492FF1FD192FF1F4A93FF1FD792FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A80FFF786BB0020704700600040C492FF1F7C3A0000014B18707E | ||||
| :40230000704700BF7B650040014B1878704700BF6B640040014B1870704700BF75650040064A0123136002F688321268E0211064034A1170A2F540721360704780E100E038 | ||||
| :4023400000E400E0014B1870704700BF7E640040014B1870704700BF7D64004073B515461E460B4C05230022019200920A4601461846237000F064F932462946207800F0D1 | ||||
| :402380001FF90221207800F009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A607047FE | ||||
| :4023C00000E100E0014B04221A60704780E100E0014B1870704700BF78650040704738B505460078012428B100F066FD285D0134E4B2F8E738BD08B50D2000F05DFDBDE81C | ||||
| :4024000008400A2000F058BDF7B516461F460B4C00230325019300930A4601462846257000F00EF93A463146207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1F52 | ||||
| :40244000F7B516461F460B4C00230225019300930A4601462846257000F0F2F83A463146207800F0ADF82946207800F097F8207803B0F0BDE180FF1FF7B516461F460B4CCE | ||||
| :4024800000230125019300930A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207803B0F0BDE280FF1F73B515461E460B4C0023019300930A46DE | ||||
| :4024C00001461846237000F0BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1F024B1878C0F38010704700BF8F450040074A7F2380211370A9 | ||||
| :402500005170064A013BDBB202F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F096 | ||||
| :402540000102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C25400207047012070471070004017280DD8074900010B460344B6 | ||||
| :402580001A7942F004021A71435C43F00103435400207047012070471070004017280BD8064A0001835C490003F0F10301F00E0119438154002070470120704710700040C7 | ||||
| :4025C00041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC280002001207047000017289FBF034B00011954002088BF012020 | ||||
| :40260000704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120704700BF1470004017289FBF034B0001185C00F0070088BFFF207047147000402E | ||||
| :40264000172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BDC8 | ||||
| :4026800010B500F079FC0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F06BFC204610BD00BFE480FF1F030610B5044611D400F05CFC32 | ||||
| :4026C000084AE300117803F1804303F5F04319705378147001335370BDE8104000F050BC10BD00BFE480FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180BE | ||||
| :40270000A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC280002001207047000038B50446084DB4F5004F05D9286800F017FCA4F50044F6E70B | ||||
| :40274000034B58686043BDE8384000F00DBC00BFEC80FF1F024B1B7A584300F005BC00BFEC80FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F0800287 | ||||
| :402780001A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B01221A70704784430040044B00F00F021B6853F8220043F82210C4 | ||||
| :4027C000704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F490024CC | ||||
| :402800000F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD8492FF1FA5280000F5 | ||||
| :4028400010E000E0EC80FF1F14E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9F6 | ||||
| :40288000FFF7BAFF0123A361BDE81040FFF7E8BF8492FF1F024B1868C0F30040704700BF10E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D1C3 | ||||
| :4028C00038BD00BF8892FF1F024B03EB80035868596070478492FF1F134B144A1B78DBB20360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B60 | ||||
| :402900000E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF0301004904010049EC46004002010049010100490001004991 | ||||
| :40294000050100490601004910B500F015FB204A044613780A2043F002031370137C43F00203137412F80A3C43F0010302F80A3C937943F00103937102F5AB52137843F0C1 | ||||
| :4029800003031370134B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222183B1A70094A137843F008031370FFF7CAFE4B | ||||
| :4029C000064B10222046BDE810401A6000F0D8BAAB4300400E5900402F5B004080E200E008B500F0C9FA0F4A137803F0FE031370A2F5AA521D3A137803F0FD031370137CD7 | ||||
| :402A000003F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0AFBA00BF08590040044A137803F03F0343EA8010C0B21070704700BF085900401A | ||||
| :402A4000082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FB1F | ||||
| :402A8000F1F305490B60054B1A8070470A590040683A00005293FF1F5493FF1F5893FF1F08B5102000F0A6F907210420FFF79AFE07490420FFF788FE064A0C20137843F002 | ||||
| :402AC00006031370FFF7BCFF034B00221A8008BD992B0000095900405093FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF72ABFA092FF1F044B1A7802F0FB0262 | ||||
| :402B00001A701A7842F001021A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF715FE024B1B78204610BD00BF09590040034A044B1B88108826 | ||||
| :402B4000181A00B2704700BF5893FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BFCA | ||||
| :402B80005B42134493FBF1F000B270475293FF1F5493FF1F5093FF1F7047000010B500F0EBF9214A044613780A2043F001031370137C43F00103137412F80A3C43F00203F7 | ||||
| :402BC00002F80A3C937943F00203937102F5AA521832137843F003031370144B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F5CD | ||||
| :402C000097530222123B1A70094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0ADB900BFAB43004006590040275B004080E200E008B500F09DF90F4AAB | ||||
| :402C4000137803F0FE031370A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F80A3C937903F0FD039371BDE8084000F083B900BF005900406D | ||||
| :402C8000044A137803F03F0343EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F910102D | ||||
| :402CC0000A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A80704702590040723A00005E93FF1F6493FF1F5C93FF1F08B5102000F084F8A9 | ||||
| :402D000007210320FFF76EFD07490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BDF12D0000015900406093FF1F10B5054C23781BB9FFF7DCFFC0 | ||||
| :402D400001232370BDE81040FFF728BFA192FF1F044B1A7802F0FB021A701A7842F001021A7070470059004010B5084B1C7814F0010403D10028F9D0002404E02046FFF7A0 | ||||
| :402D8000E9FC024B1B78204610BD00BF01590040034A044B1B881088181A00B2704700BF5C93FF1FA05B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B8A | ||||
| :402DC0001B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270475E93FF1F6493FF1F6093FF1F70470000034A00F0F80013780343137066 | ||||
| :402E0000704700BF02410040034A00F0F800137803431370704700BF06410040014B1870704700BF77650040014B1870704700BF7465004073B515461E460B4C04230022C3 | ||||
| :402E4000019200920A46014618462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDFC80FF1F074A0223136002F688321268E0215064044A1170A6 | ||||
| :402E80006FF440710A441360704700BF80E100E001E400E0014B1870704700BF78640040014B1870704700BF7B640040014B1870704700BF79650040FEB5494652465B460F | ||||
| :402EC0000EB40746244909688A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C460125002600F041F8814651460B7823400B7016 | ||||
| :402F00005846013000F030F83800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B78234003430B705846043000F016F8484600F07F | ||||
| :402F40001FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BF01380046FCD17047EFF3108072B67047A4 | ||||
| :402F800080F31088704700BF094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E013790020704700600040DC92FF1F002902D0B0FBF1F0F4 | ||||
| :402FC000704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B51E460E4C0025E41AA410A54204D056F8C7 | ||||
| :40300000253098470135F8E700F0DEFD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDD43B0000D43B0000D43B0000DC3B000003460244934202D0A0 | ||||
| :4030400003F8011BFAE7704730B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E300246EB | ||||
| :403080001E9B6946284600F073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF7CBFF03B05DF804FB6081FF1F2DE9F04703 | ||||
| :4030C0008E6882469E420C46914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F04AFB064698B1FA | ||||
| :403100003A46216900F0D2FAA38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A3894FF0FF3043F04003A381BDE8F087266174 | ||||
| :403140003E44266046466561ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D46C4 | ||||
| :4031800016460DD50B695BB9402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB2C | ||||
| :4031C000060910D003E0252BF9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF8533038 | ||||
| :403200001A930126052221784E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079AE1 | ||||
| :4032400000210A200BE0039A111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2BC0 | ||||
| :403280000AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224843 | ||||
| :4032C00000F0E6F940B14023CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00936E | ||||
| :403300002A46144B04A94046AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE883 | ||||
| :40334000F08F00BFA33B0000A93B0000AD3B000000000000BD3000002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F83C | ||||
| :4033800000302368990642BFD9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843306A | ||||
| :4033C0002268003318BF012392060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F8005092 | ||||
| :40340000E36802F00602042A08BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E700207C | ||||
| :40344000BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0BC | ||||
| :40348000692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E02168C0 | ||||
| :4034C0001A6811F0800F02D0111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E072 | ||||
| :4035000011F0400F02F10401196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E061 | ||||
| :403540000368D00744BF42F0200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B3D | ||||
| :4035800079D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A687C | ||||
| :4035C00010F0800F496903D0101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B172 | ||||
| :40360000401B6060636804E004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C047013070 | ||||
| :40364000F5D023689B0710D5002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F8423012 | ||||
| :403680008AE705B0BDE8F083573A0000B43B000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431E0A44914204D011F8014B03F8014FF8E7C8 | ||||
| :4036C00010BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B02F8014FF8E710BD38B50546002944D089 | ||||
| :4037000051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B681218226063600C6023E0A24203D813465A68A1 | ||||
| :40374000002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018824201BF106852680918216062605C609A | ||||
| :403780002846BDE8384000F098B838BDA892FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E000F082F8234B1C681A462146A1B10B683D | ||||
| :4037C0005B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304600F052F820602946304600F04DF8431C4D | ||||
| :4038000018D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F80130EBD10C233360304600F03EF800206A | ||||
| :4038400070BD00BFA892FF1FA492FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F885420ED929463846FFF78BFF044650B131468C | ||||
| :403880002A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7D8FB431C02D1236803B12B6038BD8C93FF1F7047704751F8040C10 | ||||
| :4038C0000028BEBF091851F8043CC0180438704700000000050209020B020D020F021102130215027265706C792030782530327800686F6D696E6700626567696E6E696E71 | ||||
| :4039000067207365656B2066726F6D20256420746F2025640066696E6973686564207365656B00796573006E6F00647269766520303A20257320647269766520313A202589 | ||||
| :40394000730057616974696E6720666F72205553422E2E2E0055534220726561647900636F6D6D616E6420307825303278006661696C2025642B25642B2564203D3D2025B5 | ||||
| :40398000642C206E6F74202564007061737365643D256400756E64657272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D256436 | ||||
| :4039C00000636D645F777269746500703D25642063723D25642063773D256420663D256420773D256420696E6465783D256420756E64657272756E3D256400756E6465723A | ||||
| :403A000072756E2100737563636573730073746172742065726173696E670073746F702065726173696E670069646C65000051004010004051004030000000014000100080 | ||||
| :403A4000140140000800400140000A004C0140000200500140200030313233343536373839414243444546000001000000040000001000010000000400000010280000002A | ||||
| :403A8000000104000100000000000000000157494E5553420000303030303100000000000000000012034D005300460054003100300030000100000001000000C03A00005A | ||||
| :403AC000010000008F3B0000000000000000000001000000D83A000001000000613B000004000000FA3A0000000000000000000000000000F83A0000FF000000010240009F | ||||
| :403B0000FF00000082024000FF00000003034000FF00000084034000FF00020304030904160346006C007500780045006E00670069006E0065002A0343006F0077006C00CF | ||||
| :403B4000610072006B00200054006500630068006E006F006C006F0067006900650073000009022E0001010080320904000004FF00000107050102400000070582024000E6 | ||||
| :403B8000000705030340000A0705840340000A12010002FF0001080912006E0100020180014300232D302B2000686C4C00656667454647003031323334353637383961629F | ||||
| :403BC0006364656600000000F8B500BFF8BC08BC9E46704759000000D5100000F8B500BFF8BC08BC9E46704735000000003C0000C880FF1FA0000000281200000000000046 | ||||
| :403C0000000000009093FF1FFF000000675000400C00000007000000FFFFFFFF7F8000003F0000000000C05D80BB000030000000006CDC02FF00000000000000000000002F | ||||
| :403C4000000000000000000000000000000000000000000000000000A13B000000000000000000000000000000000000000000000000000000000000000000000000000068 | ||||
| :403C80000000000000000000000000000000000000000000000000000081FF1F00000000000000000000000000000000000000000000000000000000000000000000000065 | ||||
| :403CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C4 | ||||
| :403D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083 | ||||
| :403D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043 | ||||
| @@ -4098,52 +4098,52 @@ | ||||
| :40FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041 | ||||
| :40FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 | ||||
| :0200000480007A | ||||
| :400000000145004009520040015B0040016500400101014003030140010501400307014052080140500901404F0A0140480B0140490C0140470D0140400E0140360F01409E | ||||
| :4000400002150140031701405C18014057190140471A0140531B01400B400140124101400B4201400D43014002440140074501400B4601400C470140104801401149014069 | ||||
| :40008000154C01400D4D014005500140045101407E02080209411080110218041902600C61157C402721290AE204E601EA20EE02E202E608EA10EE04000801080404050568 | ||||
| :4000C0000708080809080C400D080E1011011201130E143A16401708180819081C021E042305240825042701280629082A782C202D012E402F02307F310F327F330F380AE4 | ||||
| :400100003B0A580459045B045C995F018203830187018A108C018D018E248F08907C9282930E961097019A809D019E1C9F04A101A210A302A510A610AA10AB01AC01AE48FD | ||||
| :40014000B01FB10FB4F0B510BA20BB02BF10D608D80BD90BDB04DC99DD90DF01012202010488051007800A860B100C020DA00E2011011208134414021504162017201804BE | ||||
| :4001800019021A041B011CA01E202008220126012790282029202A012C022E282F4032493514360139013B443C803D2A5980614069906F0278417B0288049141928093D450 | ||||
| :4001C00094249602970A982299249A019B409C019D019EC0A188A208A402A504A709B404B502B604C0FBC2FFC4EFCAF7CCEBCEFBD608D808DE01E608EA10EE0400FC0108A1 | ||||
| :4002000002020310071408200AD00BE40CE10D100E080F8212031314161017141D1F1E101F4020802110223C2321261028402A302B142CE12E04301F310F33F034E03B08A2 | ||||
| :40024000580B590B5B045C995F0180368209852A86128740882D89098A128B148E098F209080924093C09440968098079C249D089F13A03FA180A320A840A908ADEAB0076D | ||||
| :40028000B1E0B280B301B438B518B640B706BE44D808D904DB04DC99DF0100820120040A07050A420B100EA80F01110112091304171219201A401D8A1E081F4020602101B0 | ||||
| :4002C000231025102652275029202A012C022F483249364239033B543D283E806102620169406C0C6F0178017F0187058C028D04900292809345946495029642971298206E | ||||
| :4003000099049B069C019D219E449F01A041A208A418A701B040B204B7C0C0FBC2FDC45FCAB5CC9BCE7FDE11E40800020104040806140A010C1C101012081301140215050D | ||||
| :400340001601170220032B022D062E022F0130043107320336183A083F015608580459045B045C095D905F018128829083118401853F86448A9C8C208D3F8EC090C191FFA2 | ||||
| :40038000922895149690972199019A039B0E9D409E90A0FCA202A902AA90AB01ADC0AE90B140B330B41FB50FB6E0B780BA80D608D80BD90BDB04DC99DD90DF0101A604240E | ||||
| :4003C0000501070208400A240B400EA0120113121401164019801A041B401D841EA02080229C2344260129602C082F0230023294370539063A053B403F01580259025A0213 | ||||
| :400400005B405F806140670168036A806B026C016F06780182019440950296E4974698209C429D209E049F02A412A580A741B240B420B540C0FFC23FC49BCA3CCCCFCE8BAA | ||||
| :40044000D618D818DE01EA20EE0203900401060407900A100B9C0D010E100F4812101520161017C01A031B031DFC1E1C1F02201C2202239025C127242A102B902C012E08A9 | ||||
| :400480002F9033E0341F351F3B08420147E0482049FF4AFF4BFF4F83580859085A045B045C995D095F018310871C8B108D018F0893109F03A310A501A704AB10AD1CAF0254 | ||||
| :4004C000B71FD908DB04DC90DF0100400120032008420A281110134219101A0820042120220826802701284229202A042B202C422D202F20312032483402368039123B4544 | ||||
| :400500003C203D103F454180520159105A445B0160046208638269406E8078807C807F018201C007C20FC40BCAFFCC9ECEFFD008D60FD80FDE18EA01EE08E020E623EE0BF2 | ||||
| :40054000022005880612083209880C080E010F011049118812321432151017A0182119461A1C1BB81D9A1E091F20206321422204230424322588282029882A022C322D04B6 | ||||
| :400580003020313F324033C1341F37C1398A3A203E055608580459045B045C995D905F018401860289018D028E039002920199089B049D049F08A004B002B102B204B304D8 | ||||
| :4005C000B401B501B708B822B988BE15BF55C043C520C802C9FFCAFFCBFFCD20CEF0D110D804D904DA04DB04DD09DF01E108E240E340E480E640E740000801400320051496 | ||||
| :40060000060107400A800D800EA8108016441799181019021B101C401E081F0420012111220424A02505264227A02D202F52324033203504360137A039903C243E4040504B | ||||
| :40064000488049204A0459405A205D045E085F4064016580670268046A806C036E406F01831085118B4491D0938094A89504970A984099449B509C019D119EC89F20A0500A | ||||
| :40068000A188A211A402A535A708A980C0F5C2F8C4F8CAF0CCFCCE7CD003D61CD810E022E620EA04EE0B010129022C013102350136013E403F115608580459045B045D9048 | ||||
| :4006C0005F0180478208830885218626874E880189018A388B708D4E8E40914E92029426974E98269B029D809E11A010A201A321A520A604A701A811AA26AB04AC26AD0FF1 | ||||
| :40070000AF10B040B380B43FB57FB63FBAA0BB20BF04C003C50EC70CC811C9FFCAFFCBFFD004D601D804D904DA04DB04DC99DD09DF01E2C0040205940DA20E201002150580 | ||||
| :40074000162017A01B401D111E011F102040221024042530260827082B042E642F40344035043602371038013C803D283E0145084F04570858905C406001630868026C042B | ||||
| :400780006D016E046F02768981028410860888808D028E049002910492409380940C96209724984099869A049BB09D119E899F08A040A18CA212A530A74AA881AE04B74049 | ||||
| :4007C000C0F0C2F0C4F1CAF4CCF0CEF1D040D61CD80CE008E404E602E8041B011F083180330836843B408340C630CCF0CE10E22032043380364037023B043F808180A0042B | ||||
| :40080000A340A580A604AE80AF41B004CCF0CE60E680EE40531057208510960897049F02A004A644A780D460E240860491209608972498809F02A004A640A7A0AA04B48062 | ||||
| :40084000E610EE201680C40458405E019A80A404AC04D401D6011B04844096019C40A404A710B680B710C608EA08EE0808080B080E020F4087048A209601A404A710AB043D | ||||
| :40088000C20FE00425808004871089808B04912097249880A004A720AB02AE40AF80C820E6C0EED0511054045880700477809008912098809B80A004AB80AF20D4E0DC8000 | ||||
| :4008C000DE20EA80EE1005200A400C100F201C0852225620610186029641A220A404A710AA41AC08AF40C001C20DC601D407D80270018001852086018810960198109920A0 | ||||
| :40090000AA20B501DC01E204EC0201010D010F0111011D0100FF01AB02021105BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B88D | ||||
| :4009400047004700000100008000000282008200000000000007070007000000270018012700180100040000000500000000000000000000000000000000000000000000C4 | ||||
| :400980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037 | ||||
| :4009C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F7 | ||||
| :400A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B6 | ||||
| :400A40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076 | ||||
| :400A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036 | ||||
| :400AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F6 | ||||
| :400B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5 | ||||
| :400B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075 | ||||
| :400000000145004009520040015B0040016400400301014002030140080501400C0701405A0801404F0901405E0A0140480B0140510C0140490D01404F0E01403E0F014057 | ||||
| :40004000261401403215014028160140371701405B1801404A190140521A0140561B01400C4001400D4101400B4201400E4301400244014007450140094601400E47014042 | ||||
| :400080000D4801400F490140194C01400D4D014006500140045101407E02084409021080110218011904601361197C4027212A0A8840E204E620A440EE028602980CA44036 | ||||
| :4000C000A808AC04E282EA08EE04870289028A048F10980C9940A202A440AD40E64AEA01EE0C02080301041706E80701080809020A400C800D030E08100F11021408150176 | ||||
| :4001000016201702181019021A071C081EF01F0220012204230224012502260628012A022B012CFF2D0330FF35033E013F105608580459045B045D905F01808081748301C8 | ||||
| :400140008480867E8752884089528A108C408D528E20907E910793089524975B983E9A409B049C409D329E049FC0A040A152A202A440A552A608A87EA952AD20AE01AF8055 | ||||
| :40018000B103B31CB6FFB7E0BB88BE40D804D904DB04DC90DF010008011002800301051007620A050B400D200E020F501080114412091554170119801E8020402101228854 | ||||
| :4001C00023612704284029942D512F103001312032883510368939023B943C083E013F505C80640268016A406D806F08840288019140928293809408950A964097159801FC | ||||
| :400200009B089C229D159E069F20A004A128A201A401A540A648A708AC80C0FFC2FBC4FFCAFFCCFFCEFFD610D810E280E608E808EA01EE0C002001110250050106100901A8 | ||||
| :400240000A030B1E0D110E1C107C110D120213221440151116301D041E1020802461260428612A082E103060310332803330341F350437083E043F1040234520480249FF27 | ||||
| :400280004AFF4BFF4D204EF05110580B59045A045C995D095F0161086240634064806640674081408201840188078B128C078D368E088F0992109309940799249A069C019B | ||||
| :4002C0009D079E02A006A209A401A604A801A92DAA06AB12AC0FAD3FB140B401B507B61EB738BE10BF01D804D90BDB04DC99DF0100800122032005550A410B200E800F1598 | ||||
| :400300001080112012221401154A172019221A101D401E061F40201821AA22012308244026A027042E402F0831823208342036803701381839423D903E02421448805C40CC | ||||
| :400340006D106F0178027C028701891091409281932096409C029D229E049F04A040A110A202A320A401A940AF48B340C0FFC2FDC4FFCA30CCBBCEBFD006D610DE81E2802C | ||||
| :40038000007C0160028206100710080109400A240D7C0E030F02121013031501161C1704180119011A481B081E101F1022102310268027102B102E102F1C301F311F3320DC | ||||
| :4003C000354036F03A805608580B590B5B045C995D905F01800482118314851086E08782881F89088A208B108D1F8F40901F9240951097219B149C019E1E9F14A3E4A41F55 | ||||
| :40040000A680A808AA11AC02AE11AF14B1F0B30FB4F0B60FBA20BB02D80BD90BDB04DC99DF010102024003240444068007240A410C800D220F201222131014011502170861 | ||||
| :4004400019C01A031B301C401F412080210223B024182530262128402A402C812D822E102F2031403324344036213784380839023A803B303C143EC03F015F40670169402A | ||||
| :4004800078027C0291029290960297129C029D629E049F04A202A441A522A621A730AA12C0FEC2F9C4B7CAF9CCFECEFFD610D810DE81EE02001C010102020306061008010D | ||||
| :4004C00009040A040B010E0312101507180119071A081E102102221023012A1C2D072E10301F3107580B590B5B045C995F0181E782908310878488208AC08B188E908F84EC | ||||
| :40050000929093849508969097229801990E9A489B419D019E039F06A29CA3E4A4C1A624A784AA90AB84ACFCAE02B21FB4E0B5F8B707BA20BB80C202C60EC804C9FFCAFF6A | ||||
| :40054000CBFFCF83D80BD90BDA04DB04DC99DD09DF01004203640552070109220A020D620F201080120213101522174418401D181F10210122022550269029022B012C803A | ||||
| :400580002D022E102F203120330436A0370539223B103C8A3D203F0245484605470848044B1057405C405E225F086520660167226A8078027C0283408D48C0DFC2FBC4FBE9 | ||||
| :4005C000CAE9CCF6CEF5D020D6F0D8F0DE810A010C01130115012301260134013501382039203E103F105608580459045B045D905F018C029001930195019C04A602A902A1 | ||||
| :40060000B002B204B301B401B702B802B908BE15BF44D804D904DB04DF01030507010E400F011308170418041E281F022304268027102B402F08330537055B405D805E2030 | ||||
| :40064000614065C06B056E406F0883488B068C048E808F4093019F10A604A844AA10AF50B001B220B404C083C290C424CA21CCC3D638D808E204E6A0E811EA08EE035608FE | ||||
| :400680005B045D9080018505870289088D068F019002930194049510972098089B029D04A130A204A520A710A908AA08AD08B002B107B208B330B404B508B601BE41BF11A1 | ||||
| :4006C000D608D804D904DB04DC99DD90DF01000208080A080B8010041302188419081A012080210822202809290A3004329238083A803B2059605F406110628067016801DA | ||||
| :4007000081088204868087408A018D209208980C99429A809B029D109F10A202A440A910B280C008C20EC40ACA0FCC0FCE0ED61CD81CE001E408E662EC04EE0A00100260BB | ||||
| :4007400003010453070209020A080B200C010D030F0410401210130115081604170119091A531BF21C011D801E021F022053210223102401250226022740280129022BFC12 | ||||
| :400780002C132DFF2E203070320F340F35FF360F3A023F10580459045B045C095F018020840185028602870188208C028D018E01902094F89604970198109A039C049D0478 | ||||
| :4007C0009E40A020A10BA480A508A604A813A902AAE4AC07AE08AF02B104B2FFB308B503B703BBA0BE04BF01D804D904DB04DC90DF01002A03010501072509200B920D227D | ||||
| :400800000E211365155619081C021D051F1420102180228223162610280229082A212C042D402F64324835203680372938403B043E093F506A406F027D017E808204842025 | ||||
| :4008400088208E4290409142928293C19408951D9605973498029A019B2C9CE09D159E049F03A128A209A308A480AA02B140B504B740C0FFC2FFC4FFCAFFCCFACEFAE210B7 | ||||
| :40088000E480E662EE2A0001011F02080401050106400704080109010A200B080C010D1F0E021001121013401401154016FE18041B1F1C801D011E011F0221012201231E7A | ||||
| :4008C00027202804291F2AF92CFF2D012F1032FF333F35403E043F10400246E0470C481849FF4AFF4BFF50045601580459045A045B045C905D095F0162C08040843286C42E | ||||
| :4009000088408C068E08922294F8960498809A049C40A040A410A602A840AE01B0FFB4FFB822D804DB04DC09DF010052032004500640072009A00B900E620F04114012402C | ||||
| :40094000132114441540170819081D101F21202421042204231029282A82312832013340351036103956400442804301502466086710680469146A416B416F02708071025A | ||||
| :40098000720683028440860490509142920293859408951C96059702980499209B289C409D109E089F01A001A1A8A201A4B4A502A720AB08AF42B320B480B620C0FFC2FFD1 | ||||
| :4009C000C4FBCA0FCC0FCE0FD004E040E210E440E831EC40EE201B011F083020330836843B4083408820C630CCF0CE10E22032043380364037043B043F80A340A604AE80F7 | ||||
| :400A0000AF41CCF0CE60EE405010570484408A80960897049F04A644A780D460E24086048C10942096089704A040A280A640A784AA04AB04E610EA80EE201420C40458108D | ||||
| :400A40005E019820A404AC04D401D6011B049502960198209C10A404B101C608EA0408080B080F41870495029601970199809C10A404AB05AC20AD80C20F240883048B04A7 | ||||
| :400A80008E409704A040A280A704AE40AF80C820E620EE50528054405A40722076808AA09240A040A280AA80B404D4E0DC80DE20EC20070208020D811C085320568059806E | ||||
| :400AC0005F0185808A018F039502960199809C10A404AC08AF40C001C20DC601D407D601E208E40975018C028D018F209802A720AA80B010DE04E002E208E402E804010148 | ||||
| :400B00000D010F0111011B011D0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B8470047000001000013 | ||||
| :400B400080000002820082000000000000070700070000001D0018011D00180100040000000500000000000000000000000000000000000000000000000000000000000065 | ||||
| :400B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035 | ||||
| :400BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F5 | ||||
| :400C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B4 | ||||
| @@ -4615,12 +4615,12 @@ | ||||
| :0200000490105A | ||||
| :04000000BC90ACAF55 | ||||
| :0200000490303A | ||||
| :02000000CEC56B | ||||
| :0200000064D4C6 | ||||
| :0200000490402A | ||||
| :4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0 | ||||
| :400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 | ||||
| :400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040 | ||||
| :4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| :0200000490501A | ||||
| :0C00000000012E16106900002E2FDF2ECC | ||||
| :0C00000000012E16106900002E30753D26 | ||||
| :00000001FF | ||||
| @@ -272,7 +272,7 @@ | ||||
|         <Data key="derive_type" value="AUTO" /> | ||||
|         <Data key="desired_freq" value="1600000" /> | ||||
|         <Data key="desired_unit" value="0" /> | ||||
|         <Data key="divider" value="40" /> | ||||
|         <Data key="divider" value="30" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
| @@ -390,7 +390,7 @@ | ||||
|         <Data key="derive_type" value="AUTO" /> | ||||
|         <Data key="desired_freq" value="1600000" /> | ||||
|         <Data key="desired_unit" value="0" /> | ||||
|         <Data key="divider" value="40" /> | ||||
|         <Data key="divider" value="30" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
| @@ -604,7 +604,7 @@ | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="BUILTIN" /> | ||||
|         <Data key="desired_freq" value="64" /> | ||||
|         <Data key="desired_freq" value="48" /> | ||||
|         <Data key="desired_unit" value="6" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="0" /> | ||||
| @@ -814,7 +814,7 @@ | ||||
|   </Group> | ||||
|   <Group key="Component"> | ||||
|     <Group key="v1"> | ||||
|       <Data key="cy_boot" value="cy_boot_v5_81" /> | ||||
|       <Data key="cy_boot" value="cy_boot_v6_10" /> | ||||
|       <Data key="Em_EEPROM_Dynamic" value="Em_EEPROM_Dynamic_v2_20" /> | ||||
|       <Data key="LIN_Dynamic" value="LIN_Dynamic_v5_0" /> | ||||
|     </Group> | ||||
| @@ -4214,7 +4214,7 @@ | ||||
|   </Group> | ||||
|   <Group key="System3"> | ||||
|     <Data key="CYDEV_CONFIG_FASTBOOT_ENABLED" value="True" /> | ||||
|     <Data key="CYDEV_CONFIG_UNUSED_IO" value="AllowButWarn" /> | ||||
|     <Data key="CYDEV_CONFIG_UNUSED_IO" value="Disallowed" /> | ||||
|     <Data key="CYDEV_CONFIGURATION_ECC" value="True" /> | ||||
|     <Data key="CYDEV_CONFIGURATION_MODE" value="COMPRESSED" /> | ||||
|     <Data key="CYDEV_DEBUGGING_DPS" value="Disable" /> | ||||
|   | ||||
| @@ -2913,6 +2913,110 @@ | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_2" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||
| <dependencies> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_2.c" persistent="Generated_Source\PSoC5\Clock_2.c"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_2.h" persistent="Generated_Source\PSoC5\Clock_2.h"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="HEADER;;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_3" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||
| <dependencies> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_3.c" persistent="Generated_Source\PSoC5\Clock_3.c"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_3.h" persistent="Generated_Source\PSoC5\Clock_3.h"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="HEADER;;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_5" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||
| <dependencies> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_5.c" persistent="Generated_Source\PSoC5\Clock_5.c"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="Clock_5.h" persistent="Generated_Source\PSoC5\Clock_5.h"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="HEADER;;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="USBFS_ep5" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||
| <dependencies> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="USBFS_ep5_dma.c" persistent="Generated_Source\PSoC5\USBFS_ep5_dma.c"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="USBFS_ep5_dma.h" persistent="Generated_Source\PSoC5\USBFS_ep5_dma.h"> | ||||
| <Hidden v="True" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="HEADER;;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| @@ -3480,8 +3584,8 @@ | ||||
| </platforms> | ||||
| <project_current_platform v="c9323d49-d323-40b8-9b59-cc008d68a989" /> | ||||
| <last_selected_tab v="Cypress" /> | ||||
| <WriteAppVersionLastSavedWith v="4.2.0.641" /> | ||||
| <WriteAppMarketingVersionLastSavedWith v=" 4.2" /> | ||||
| <WriteAppVersionLastSavedWith v="4.4.0.80" /> | ||||
| <WriteAppMarketingVersionLastSavedWith v=" 4.4" /> | ||||
| <project_id v="ff3eb327-f593-4eb3-a00f-72497469e963" /> | ||||
| <GenerateDescriptionFiles v="False" /> | ||||
| </CyGuid_49cfd574-032a-4a64-b7be-d4eeeaf25e43> | ||||
| @@ -3493,9 +3597,7 @@ | ||||
| <library_dep persistent="${CyRoot}\psoc\content\default\CyAnnotationLibrary\CyAnnotationLibrary.cylib\CyAnnotationLibrary.cyprj" /> | ||||
| </library_deps> | ||||
| <CyGuid_b0d670ad-d48f-47cb-9d0b-b1642bab195c type_name="CyDesigner.Common.Base.CyExprTypeMgr" version="1" /> | ||||
| <ignored_deps> | ||||
| <library_dep persistent="C:\Users\dg\Documents\PSoC Creator\4.1\Downloads ( 4.1).cylib\Downloads ( 4.1).cyprj" /> | ||||
| </ignored_deps> | ||||
| <ignored_deps /> | ||||
| </CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37> | ||||
| <boot_component v="" /> | ||||
| <current_generation v="150" /> | ||||
|   | ||||
| @@ -20,13 +20,14 @@ module Sequencer ( | ||||
|  | ||||
| localparam STATE_LOAD = 0; | ||||
| localparam STATE_WRITING = 1; | ||||
| localparam STATE_WAITING = 2; | ||||
|  | ||||
| reg state; | ||||
| reg [1:0] state; | ||||
| reg [5:0] countdown; | ||||
| reg pulsepending; | ||||
|  | ||||
| assign req = (!reset && (state == STATE_LOAD)); | ||||
| assign wdata = (!reset && (state == STATE_WRITING) && (countdown == 0) && pulsepending); | ||||
| assign wdata = (!reset && (state == STATE_WAITING) && (countdown == 0) && pulsepending); | ||||
| assign debug_state = 0; | ||||
|  | ||||
| reg olddataclock; | ||||
| @@ -37,11 +38,6 @@ assign dataclocked = !olddataclock && dataclock; | ||||
| reg oldsampleclock; | ||||
| reg sampleclocked; | ||||
|  | ||||
| reg oldindex; | ||||
| wire indexed; | ||||
| always @(posedge clock) oldindex <= index; | ||||
| assign indexed = !oldindex && index; | ||||
|  | ||||
| always @(posedge clock) | ||||
| begin | ||||
|     if (reset) | ||||
| @@ -65,7 +61,7 @@ begin | ||||
|                 if (dataclocked) | ||||
|                 begin | ||||
|                     pulsepending <= opcode[7]; | ||||
|                     countdown <= opcode[5:0]; | ||||
|                     countdown <= opcode[5:0] - 1; /* compensate for extra tick in state machine */ | ||||
|                      | ||||
|                     state <= STATE_WRITING; | ||||
|                 end | ||||
| @@ -76,12 +72,15 @@ begin | ||||
|                 if (sampleclocked) | ||||
|                 begin | ||||
|                     if (countdown == 0) | ||||
|                         state <= STATE_LOAD; | ||||
|                         state <= STATE_WAITING; | ||||
|                     else | ||||
|                         countdown <= countdown - 1; | ||||
|                     sampleclocked <= 0; | ||||
|                 end | ||||
|             end | ||||
|              | ||||
|             STATE_WAITING: | ||||
|                 state <= STATE_LOAD; | ||||
|         endcase | ||||
|     end | ||||
| end | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| @@ -79,6 +79,7 @@ CY_ISR(index_irq_cb) | ||||
|      * the track. */ | ||||
|     static bool hardsec_index_irq_primed = false; | ||||
|     static uint32_t hardsec_last_pulse_time = 0; | ||||
|     uint32_t index_pulse_duration = clock - hardsec_last_pulse_time; | ||||
|  | ||||
|     if (!hardsec_index_threshold) | ||||
|     { | ||||
| @@ -87,12 +88,18 @@ CY_ISR(index_irq_cb) | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         index_irq = hardsec_index_irq_primed; | ||||
|         /* It's only an index pulse if the previous pulse is less than | ||||
|          * the threshold. | ||||
|          */ | ||||
|         index_irq = (index_pulse_duration <= hardsec_index_threshold) ? | ||||
|             hardsec_index_irq_primed : false; | ||||
|  | ||||
|         if (index_irq) | ||||
|             hardsec_index_irq_primed = false; | ||||
|         else | ||||
|             hardsec_index_irq_primed = | ||||
|                 clock - hardsec_last_pulse_time <= hardsec_index_threshold; | ||||
|                 index_pulse_duration <= hardsec_index_threshold; | ||||
|  | ||||
|         hardsec_last_pulse_time = clock; | ||||
|     } | ||||
|      | ||||
| @@ -275,7 +282,6 @@ static void seek_to(int track) | ||||
|         CyWdtClear(); | ||||
|     } | ||||
|     CyDelay(STEP_SETTLING_TIME); | ||||
|      | ||||
|     TK43_REG_Write(track < 43); /* high if 0..42, low if 43 or up */ | ||||
|     print("finished seek"); | ||||
| } | ||||
| @@ -305,7 +311,7 @@ static void cmd_measure_speed(struct measurespeed_frame* f) | ||||
|     while (!index_irq) | ||||
|     { | ||||
|         elapsed = clock - start_clock; | ||||
|         if (elapsed > 1000) | ||||
|         if (elapsed > 1500) | ||||
|         { | ||||
|             elapsed = 0; | ||||
|             break; | ||||
| @@ -416,7 +422,6 @@ static void cmd_read(struct read_frame* f) | ||||
|     seek_to(current_track); | ||||
|     SIDE_REG_Write(f->side); | ||||
|     STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */ | ||||
|      | ||||
|     /* Do slow setup *before* we go into the real-time bit. */ | ||||
|      | ||||
|     { | ||||
| @@ -562,7 +567,6 @@ static void cmd_write(struct write_frame* f) | ||||
|     seek_to(current_track);     | ||||
|     SIDE_REG_Write(f->side); | ||||
|     STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */ | ||||
|      | ||||
|     SEQUENCER_CONTROL_Write(1); /* put the sequencer into reset */ | ||||
|     { | ||||
|         uint8_t i = CyEnterCriticalSection();         | ||||
| @@ -627,7 +631,6 @@ static void cmd_write(struct write_frame* f) | ||||
|  | ||||
|                 /* Wait for the index marker. While this happens, the DMA engine | ||||
|                  * will prime the FIFO. */ | ||||
|  | ||||
|                 hardsec_index_threshold = f->hardsec_threshold_ms; | ||||
|                 index_irq = false; | ||||
|                 while (!index_irq) | ||||
| @@ -693,7 +696,7 @@ abort: | ||||
| static void cmd_erase(struct erase_frame* f) | ||||
| { | ||||
|     SIDE_REG_Write(f->side); | ||||
|     seek_to(current_track);     | ||||
|     seek_to(current_track); | ||||
|     /* Disk is now spinning. */ | ||||
|      | ||||
|     print("start erasing"); | ||||
|   | ||||
							
								
								
									
										30
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,21 +1,23 @@ | ||||
| PACKAGES = zlib sqlite3 libusb-1.0 | ||||
| PACKAGES = zlib sqlite3 libusb-1.0 protobuf | ||||
|  | ||||
| export CFLAGS = --std=c++14 -ffunction-sections -fdata-sections | ||||
| export LDFLAGS = | ||||
| export CFLAGS = -x c++ --std=c++14 -ffunction-sections -fdata-sections | ||||
| export LDFLAGS = -pthread | ||||
|  | ||||
| export COPTFLAGS = -Os | ||||
| export LDOPTFLAGS = -Os -s | ||||
| export LDOPTFLAGS = -Os | ||||
|  | ||||
| export CDBGFLAGS = -O0 -g | ||||
| export LDDBGFLAGS = -O0 -g | ||||
|  | ||||
| ifeq ($(OS), Windows_NT) | ||||
| export PROTOC = /mingw32/bin/protoc | ||||
| export CXX = /mingw32/bin/g++ | ||||
| export AR = /mingw32/bin/ar rcs | ||||
| export AR = /mingw32/bin/ar rc | ||||
| export RANLIB = /mingw32/bin/ranlib | ||||
| export STRIP = /mingw32/bin/strip | ||||
| export CFLAGS += -I/mingw32/include/libusb-1.0 | ||||
| export CFLAGS += -I/mingw32/include/libusb-1.0 -I/mingw32/include | ||||
| export LDFLAGS += | ||||
| export LIBS = -static -lz -lsqlite3 -lusb-1.0 | ||||
| export LIBS += -L/mingw32/lib -static -lz -lsqlite3 -lusb-1.0 -lprotobuf | ||||
| export EXTENSION = .exe | ||||
| else | ||||
|  | ||||
| @@ -25,21 +27,31 @@ $(warning These pkg-config packages are installed: $(shell pkg-config --list-all | ||||
| $(error You must have these pkg-config packages installed: $(PACKAGES)) | ||||
| endif | ||||
|  | ||||
| export PROTOC = protoc | ||||
| export CXX = g++ | ||||
| export AR = ar rcs | ||||
| export AR = ar rc | ||||
| export RANLIB = ranlib | ||||
| export STRIP = strip | ||||
| export CFLAGS += $(shell pkg-config --cflags $(PACKAGES)) | ||||
| export LDFLAGS += | ||||
| export LIBS = $(shell pkg-config --libs $(PACKAGES)) | ||||
| export LIBS += $(shell pkg-config --libs $(PACKAGES)) | ||||
| export EXTENSION = | ||||
|  | ||||
| ifeq ($(shell uname),Darwin) | ||||
| AR = ar rcS | ||||
| RANLIB += -c -no_warning_for_no_symbols | ||||
| endif | ||||
|  | ||||
| endif | ||||
| export XXD = xxd | ||||
|  | ||||
| CFLAGS += -Ilib -Idep/fmt -Iarch | ||||
|  | ||||
| export OBJDIR = .obj | ||||
|  | ||||
| all: .obj/build.ninja | ||||
| 	@ninja -f .obj/build.ninja | ||||
| 	@if command -v cscope > /dev/null; then cscope -bRq; fi | ||||
|  | ||||
| clean: | ||||
| 	@echo CLEAN | ||||
|   | ||||
							
								
								
									
										39
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								README.md
									
									
									
									
									
								
							| @@ -4,6 +4,11 @@ FluxEngine | ||||
| (If you're reading this on GitHub, the formatting's a bit messed up. [Try the | ||||
| version on cowlark.com instead.](http://cowlark.com/fluxengine/) | ||||
|  | ||||
| **Breaking news!** As of 2021-05-21, the command line environment has changed | ||||
| _substantially_ (to make it more consistent and flexible, and allow some new | ||||
| backend features like multi-format IBM scheme disks, which are popular with | ||||
| CP/M). If things don't work the way you expect, please check the documentation. | ||||
|  | ||||
| What? | ||||
| ----- | ||||
|  | ||||
| @@ -85,20 +90,20 @@ people who've had it work). | ||||
|  | ||||
| ### Old disk formats | ||||
|  | ||||
| | Format                                   | Read? | Write? | Notes | | ||||
| |:-----------------------------------------|:-----:|:------:|-------| | ||||
| | [IBM PC compatible](doc/disk-ibm.md)     |  🦄   |   🦄   | and compatibles (like the Atari ST) | | ||||
| | [Acorn ADFS](doc/disk-acornadfs.md)      |  🦄   |   🦖*  | single- and double- sided           | | ||||
| | [Acorn DFS](doc/disk-acorndfs.md)        |  🦄   |   🦖*  |                                     | | ||||
| | [Ampro Little Board](doc/disk-ampro.md)  |  🦖   |   🦖*   |                                     | | ||||
| | [Apple II DOS 3.3](doc/disk-apple2.md)   |  🦄   |        | doesn't do logical sector remapping | | ||||
| | [Amiga](doc/disk-amiga.md)               |  🦄   |        |                                     | | ||||
| | [Commodore 64 1541](doc/disk-c64.md)     |  🦖   |        | and probably the other GCR formats  | | ||||
| | [Brother 120kB](doc/disk-brother.md)     |  🦄   |        |                                     | | ||||
| | [Brother 240kB](doc/disk-brother.md)     |  🦄   |   🦄   |                                     | | ||||
| | [Brother FB-100](doc/disk-fb100.md)      |  🦖   |        | Tandy Model 100, Husky Hunter, knitting machines | | ||||
| | [Macintosh 800kB](doc/disk-macintosh.md) |  🦄   |   🦄   | and probably the 400kB too          | | ||||
| | [TRS-80](doc/disk-trs80.md)              |  🦖   |   🦖*  | a minor variation of the IBM scheme | | ||||
| | Format                                    | Read? | Write? | Notes | | ||||
| |:------------------------------------------|:-----:|:------:|-------| | ||||
| | [IBM PC compatible](doc/disk-ibm.md)      |  🦄   |   🦄   | and compatibles (like the Atari ST) | | ||||
| | [Acorn ADFS](doc/disk-acornadfs.md)       |  🦄   |   🦖*  | single- and double- sided           | | ||||
| | [Acorn DFS](doc/disk-acorndfs.md)         |  🦄   |   🦖*  |                                     | | ||||
| | [Ampro Little Board](doc/disk-ampro.md)   |  🦖   |   🦖*  |                                     | | ||||
| | [Apple II DOS 3.3](doc/disk-apple2.md)    |  🦄   |        | doesn't do logical sector remapping | | ||||
| | [Amiga](doc/disk-amiga.md)                |  🦄   |   🦄   |                                     | | ||||
| | [Commodore 64 1541/1581](doc/disk-c64.md) |  🦄   |   🦄   | and probably the other formats      | | ||||
| | [Brother 120kB](doc/disk-brother.md)      |  🦄   |   🦖   |                                     | | ||||
| | [Brother 240kB](doc/disk-brother.md)      |  🦄   |   🦄   |                                     | | ||||
| | [Brother FB-100](doc/disk-fb100.md)       |  🦖   |        | Tandy Model 100, Husky Hunter, knitting machines | | ||||
| | [Macintosh 800kB](doc/disk-macintosh.md)  |  🦄   |   🦄   | and probably the 400kB too          | | ||||
| | [TRS-80](doc/disk-trs80.md)               |  🦖   |   🦖*  | a minor variation of the IBM scheme | | ||||
| {: .datatable } | ||||
|  | ||||
| `*`: these formats are variations of the generic IBM format, and since the | ||||
| @@ -118,7 +123,9 @@ at least, check the CRC so what data's there is probably good. | ||||
| | [AES Superplus / No Problem](doc/disk-aeslanier.md) |  🦖   | | hard sectors! | | ||||
| | [Durango F85](doc/disk-durangof85.md)    |  🦖   |        | 5.25" | | ||||
| | [DVK MX](doc/disk-mx.md)                 |  🦖   |        | Soviet PDP-11 clone | | ||||
| | [VDS Eco1](doc/disk-eco1.md)             |  🦖   |        | 8" mixed format | | ||||
| | [Micropolis](doc/disk-micropolis.md)     |  🦄   |        | Micropolis 100tpi drives | | ||||
| | [Northstar(doc/disk-northstar.md)        |  🦖   |   🦖   | 5.25" hard sectors | | ||||
| | [TI DS990 FD1000](doc/disk-tids990.md)   |  🦄   |  🦄    | 8" | | ||||
| | [Victor 9000](doc/disk-victor9k.md)      |  🦖   |        | 8" | | ||||
| | [Zilog MCZ](doc/disk-zilogmcz.md)        |  🦖   |        | 8" _and_ hard sectors | | ||||
| @@ -219,3 +226,7 @@ written by Sean T Barett (and others). It is public domain/Unlicense/MIT | ||||
| licensed, at your choice. Please see the contents of the directory for the full | ||||
| text. | ||||
|  | ||||
| As an exception, `dep/snowhouse` contains the snowhouse assertion library, | ||||
| taken from https://github.com/banditcpp/snowhouse. It is Boost Standard License | ||||
| 1.0 licensed. Please see the contents of the directory for the full text. | ||||
|  | ||||
|   | ||||
| @@ -7,10 +7,12 @@ | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class AesLanierDecoderProto; | ||||
|  | ||||
| class AesLanierDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	AesLanierDecoder(const AesLanierDecoderProto&) {} | ||||
|     virtual ~AesLanierDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/aeslanier/aeslanier.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/aeslanier/aeslanier.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message AesLanierDecoderProto {} | ||||
|  | ||||
| @@ -12,10 +12,13 @@ | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class SectorSet; | ||||
| class AmigaDecoderProto; | ||||
| class AmigaEncoderProto; | ||||
|  | ||||
| class AmigaDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	AmigaDecoder(const AmigaDecoderProto&) {} | ||||
|     virtual ~AmigaDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
| @@ -27,13 +30,16 @@ public: | ||||
| class AmigaEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	AmigaEncoder(const AmigaEncoderProto& config): | ||||
| 		_config(config) {} | ||||
| 	virtual ~AmigaEncoder() {} | ||||
|  | ||||
| public: | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors); | ||||
| }; | ||||
|  | ||||
| extern FlagGroup amigaEncoderFlags; | ||||
| private: | ||||
| 	const AmigaEncoderProto& _config; | ||||
| }; | ||||
|  | ||||
| extern uint32_t amigaChecksum(const Bytes& bytes); | ||||
| extern Bytes amigaInterleave(const Bytes& input); | ||||
|   | ||||
							
								
								
									
										13
									
								
								arch/amiga/amiga.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								arch/amiga/amiga.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message AmigaDecoderProto {} | ||||
|  | ||||
| message AmigaEncoderProto { | ||||
| 	optional double clock_rate_us = 1 | ||||
| 		[default=2.00, (help)="Encoded data clock rate."]; | ||||
| 	optional double post_index_gap_ms = 2 | ||||
| 		[default=0.5, (help)="Post-index gap before first sector header."]; | ||||
| } | ||||
|  | ||||
| @@ -6,18 +6,7 @@ | ||||
| #include "crc.h" | ||||
| #include "sectorset.h" | ||||
| #include "writer.h" | ||||
|  | ||||
| FlagGroup amigaEncoderFlags; | ||||
|  | ||||
| static DoubleFlag clockRateUs( | ||||
| 	{ "--clock-rate" }, | ||||
| 	"Encoded data clock rate (microseconds).", | ||||
| 	2.00); | ||||
|  | ||||
| static DoubleFlag postIndexGapMs( | ||||
| 	{ "--post-index-gap" }, | ||||
| 	"Post-index gap before first sector header (milliseconds).", | ||||
| 	0.5); | ||||
| #include "arch/amiga/amiga.pb.h" | ||||
|  | ||||
| static bool lastBit; | ||||
|  | ||||
| @@ -33,13 +22,14 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vec | ||||
| 	for (bool bit : src) | ||||
| 	{ | ||||
| 		if (cursor < bits.size()) | ||||
| 			bits[cursor++] = bit; | ||||
| 			lastBit = bits[cursor++] = bit; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width) | ||||
| { | ||||
| 	cursor += width; | ||||
| 	lastBit = data & 1; | ||||
| 	for (int i=0; i<width; i++) | ||||
| 	{ | ||||
| 		unsigned pos = cursor - i - 1; | ||||
| @@ -49,19 +39,16 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes) | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes) | ||||
| { | ||||
| 	assert(!(bytes.size() & 3)); | ||||
| 	Bytes interleaved = amigaInterleave(bytes); | ||||
| 	encodeMfm(bits, cursor, interleaved, lastBit); | ||||
| } | ||||
| 	ByteReader br(bytes); | ||||
| 	BitReader bitr(br); | ||||
|  | ||||
| static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, uint32_t data) | ||||
| { | ||||
| 	Bytes b(4); | ||||
| 	ByteWriter bw(b); | ||||
| 	bw.write_be32(data); | ||||
| 	write_interleaved_bytes(bits, cursor, b); | ||||
| 	while (!bitr.eof()) | ||||
| 	{ | ||||
| 		if (cursor < bits.size()) | ||||
| 			bits[cursor++] = bitr.get(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) | ||||
| @@ -69,11 +56,27 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector | ||||
| 	if ((sector->data.size() != 512) && (sector->data.size() != 528)) | ||||
| 		Error() << "unsupported sector size --- you must pick 512 or 528"; | ||||
|  | ||||
| 	uint32_t checksum = 0; | ||||
|  | ||||
| 	auto write_interleaved_bytes = [&](const Bytes& bytes) | ||||
| 	{ | ||||
| 		Bytes interleaved = amigaInterleave(bytes); | ||||
| 		Bytes mfm = encodeMfm(interleaved, lastBit); | ||||
| 		checksum ^= amigaChecksum(mfm); | ||||
| 		checksum &= 0x55555555; | ||||
| 		write_bits(bits, cursor, mfm); | ||||
| 	}; | ||||
|  | ||||
| 	auto write_interleaved_word = [&](uint32_t word) | ||||
| 	{ | ||||
| 		Bytes b(4); | ||||
| 		b.writer().write_be32(word); | ||||
| 		write_interleaved_bytes(b); | ||||
| 	}; | ||||
|  | ||||
|     write_bits(bits, cursor, AMIGA_SECTOR_RECORD, 6*8); | ||||
|  | ||||
| 	std::vector<bool> headerBits(20*16); | ||||
| 	unsigned headerCursor = 0; | ||||
|  | ||||
| 	checksum = 0; | ||||
| 	Bytes header =  | ||||
| 		{ | ||||
| 			0xff, /* Amiga 1.0 format byte */ | ||||
| @@ -81,22 +84,16 @@ static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector | ||||
| 			(uint8_t) sector->logicalSector, | ||||
| 			(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector) | ||||
| 		}; | ||||
| 	write_interleaved_bytes(headerBits, headerCursor, header); | ||||
| 	write_interleaved_bytes(header); | ||||
| 	Bytes recoveryInfo(16); | ||||
| 	if (sector->data.size() == 528) | ||||
| 		recoveryInfo = sector->data.slice(512, 16); | ||||
| 	write_interleaved_bytes(headerBits, headerCursor, recoveryInfo); | ||||
| 	write_interleaved_bytes(recoveryInfo); | ||||
| 	write_interleaved_word(checksum); | ||||
|  | ||||
| 	std::vector<bool> dataBits(512*16); | ||||
| 	unsigned dataCursor = 0; | ||||
| 	write_interleaved_bytes(dataBits, dataCursor, sector->data); | ||||
|  | ||||
| 	write_bits(bits, cursor, headerBits); | ||||
| 	uint32_t headerChecksum = amigaChecksum(toBytes(headerBits)); | ||||
| 	write_interleaved_bytes(bits, cursor, headerChecksum); | ||||
| 	uint32_t dataChecksum = amigaChecksum(toBytes(dataBits)); | ||||
| 	write_interleaved_bytes(bits, cursor, dataChecksum); | ||||
| 	write_bits(bits, cursor, dataBits); | ||||
| 	Bytes data = sector->data.slice(0, 512); | ||||
| 	write_interleaved_word(amigaChecksum(encodeMfm(amigaInterleave(data), lastBit))); | ||||
| 	write_interleaved_bytes(data); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> AmigaEncoder::encode( | ||||
| @@ -105,11 +102,11 @@ std::unique_ptr<Fluxmap> AmigaEncoder::encode( | ||||
| 	if ((physicalTrack < 0) || (physicalTrack >= AMIGA_TRACKS_PER_DISK)) | ||||
| 		return std::unique_ptr<Fluxmap>(); | ||||
|  | ||||
| 	int bitsPerRevolution = 200000.0 / clockRateUs; | ||||
| 	int bitsPerRevolution = 200000.0 / _config.clock_rate_us(); | ||||
| 	std::vector<bool> bits(bitsPerRevolution); | ||||
| 	unsigned cursor = 0; | ||||
|  | ||||
|     fillBitmapTo(bits, cursor, postIndexGapMs * 1000 / clockRateUs, { true, false }); | ||||
|     fillBitmapTo(bits, cursor, _config.post_index_gap_ms() * 1000 / _config.clock_rate_us(), { true, false }); | ||||
| 	lastBit = false; | ||||
|  | ||||
| 	for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++) | ||||
| @@ -123,7 +120,7 @@ std::unique_ptr<Fluxmap> AmigaEncoder::encode( | ||||
| 	fillBitmapTo(bits, cursor, bits.size(), { true, false }); | ||||
|  | ||||
| 	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 	fluxmap->appendBits(bits, clockRateUs*1e3); | ||||
| 	fluxmap->appendBits(bits, _config.clock_rate_us()*1e3); | ||||
| 	return fluxmap; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,10 +9,12 @@ | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class Apple2DecoderProto; | ||||
|  | ||||
| class Apple2Decoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	Apple2Decoder(const Apple2DecoderProto&) {} | ||||
|     virtual ~Apple2Decoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/apple2/apple2.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/apple2/apple2.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message Apple2DecoderProto {} | ||||
|  | ||||
| @@ -14,11 +14,15 @@ | ||||
| #define BROTHER_SECTORS_PER_TRACK        12 | ||||
|  | ||||
| class Sector; | ||||
| class SectorSet; | ||||
| class Fluxmap; | ||||
| class BrotherDecoderProto; | ||||
| class BrotherEncoderProto; | ||||
|  | ||||
| class BrotherDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
|     BrotherDecoder(const BrotherDecoderProto& config) {} | ||||
|     virtual ~BrotherDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
| @@ -29,20 +33,17 @@ public: | ||||
| class BrotherEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	BrotherEncoder(int format, int bias): | ||||
| 		_format(format), | ||||
| 		_bias(bias) | ||||
| 	BrotherEncoder(const BrotherEncoderProto& config): | ||||
| 		_config(config) | ||||
| 	{} | ||||
|  | ||||
| 	virtual ~BrotherEncoder() {} | ||||
|  | ||||
| private: | ||||
| 	int _format; | ||||
| 	int _bias; | ||||
| 	const BrotherEncoderProto& _config; | ||||
|  | ||||
| public: | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors); | ||||
| }; | ||||
|  | ||||
| extern FlagGroup brotherEncoderFlags; | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										20
									
								
								arch/brother/brother.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								arch/brother/brother.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message BrotherDecoderProto {} | ||||
|  | ||||
| enum BrotherFormat { | ||||
| 	BROTHER240 = 0; | ||||
| 	BROTHER120 = 1; | ||||
| }; | ||||
|  | ||||
| message BrotherEncoderProto { | ||||
| 	optional double clock_rate_us = 1 [default = 3.83]; | ||||
| 	optional double post_index_gap_ms = 2 [default = 1.0]; | ||||
| 	optional double sector_spacing_ms = 3 [default = 16.2]; | ||||
| 	optional double post_header_spacing_ms = 4 [default = 0.69]; | ||||
| 	optional string sector_skew = 5 [default = "05a3816b4927"]; | ||||
|  | ||||
| 	optional BrotherFormat format = 6 [default = BROTHER240]; | ||||
| 	optional int32 bias = 7 [default = 0]; | ||||
| } | ||||
|  | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "crc.h" | ||||
| #include "sectorset.h" | ||||
| #include "writer.h" | ||||
| #include "arch/brother/brother.pb.h" | ||||
|  | ||||
| FlagGroup brotherEncoderFlags; | ||||
|  | ||||
| @@ -132,17 +133,17 @@ std::unique_ptr<Fluxmap> BrotherEncoder::encode( | ||||
| 	int logicalTrack; | ||||
| 	if (physicalSide != 0) | ||||
| 		return std::unique_ptr<Fluxmap>(); | ||||
| 	physicalTrack -= _bias; | ||||
| 	switch (_format) | ||||
| 	physicalTrack -= _config.bias(); | ||||
| 	switch (_config.format()) | ||||
| 	{ | ||||
| 		case 120: | ||||
| 		case BROTHER120: | ||||
| 			if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2)) | ||||
| 					|| (physicalTrack & 1)) | ||||
| 				return std::unique_ptr<Fluxmap>(); | ||||
| 			logicalTrack = physicalTrack/2; | ||||
| 			break; | ||||
|  | ||||
| 		case 240: | ||||
| 		case BROTHER240: | ||||
| 			if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK)) | ||||
| 				return std::unique_ptr<Fluxmap>(); | ||||
| 			logicalTrack = physicalTrack; | ||||
|   | ||||
| @@ -1,16 +1,42 @@ | ||||
| #ifndef C64_H | ||||
| #define C64_H | ||||
|  | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
|  | ||||
| #define C64_SECTOR_RECORD    0xffd49 | ||||
| #define C64_DATA_RECORD      0xffd57 | ||||
| #define C64_SECTOR_LENGTH    256 | ||||
|  | ||||
| /* Source: http://www.unusedino.de/ec64/technical/formats/g64.html  | ||||
|    1. Header sync       FF FF FF FF FF (40 'on' bits, not GCR) | ||||
|    2. Header info       52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes) | ||||
|    3. Header gap        55 55 55 55 55 55 55 55 55 (9 bytes, never read) | ||||
|    4. Data sync         FF FF FF FF FF (40 'on' bits, not GCR) | ||||
|    5. Data block        55...4A (325 GCR bytes) | ||||
|    6. Inter-sector gap  55 55 55 55...55 55 (4 to 12 bytes, never read) | ||||
|    1. Header sync       (SYNC for the next sector) | ||||
| */ | ||||
| #define C64_HEADER_DATA_SYNC        0xFF | ||||
| #define C64_HEADER_BLOCK_ID         0x08 | ||||
| #define C64_DATA_BLOCK_ID           0x07 | ||||
| #define C64_HEADER_GAP              0x55 | ||||
| #define C64_INTER_SECTOR_GAP        0x55 | ||||
| #define C64_PADDING                 0x0F | ||||
|  | ||||
| #define C64_TRACKS_PER_DISK         40 | ||||
| #define C64_BAM_TRACK               17 | ||||
|  | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class Commodore64DecoderProto; | ||||
| class Commodore64EncoderProto; | ||||
|  | ||||
| class Commodore64Decoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	Commodore64Decoder(const Commodore64DecoderProto&) {} | ||||
|     virtual ~Commodore64Decoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
| @@ -18,4 +44,25 @@ public: | ||||
|     void decodeDataRecord(); | ||||
| }; | ||||
|  | ||||
| class Commodore64Encoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	Commodore64Encoder(const Commodore64EncoderProto& config): | ||||
| 		_config(config) | ||||
| 	{} | ||||
|  | ||||
| 	virtual ~Commodore64Encoder() {} | ||||
|  | ||||
| public: | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors); | ||||
|  | ||||
| private: | ||||
| 	void writeSector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) const; | ||||
| 	 | ||||
| private: | ||||
| 	const Commodore64EncoderProto& _config; | ||||
| 	uint8_t _formatByte1; | ||||
| 	uint8_t _formatByte2; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										13
									
								
								arch/c64/c64.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								arch/c64/c64.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message Commodore64DecoderProto {} | ||||
|  | ||||
| message Commodore64EncoderProto { | ||||
| 	optional double post_index_gap_us = 1 [default=0.0, | ||||
| 		(help) = "post-index gap before first sector header."]; | ||||
| 	optional double clock_compensation_factor = 2 [default=1.0, | ||||
| 		(help) = "scale the output clock by this much."]; | ||||
| } | ||||
|  | ||||
							
								
								
									
										349
									
								
								arch/c64/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								arch/c64/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,349 @@ | ||||
| #include "globals.h" | ||||
| #include "record.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "c64.h" | ||||
| #include "crc.h" | ||||
| #include "sectorset.h" | ||||
| #include "sector.h" | ||||
| #include "writer.h" | ||||
| #include "fmt/format.h" | ||||
| #include "arch/c64/c64.pb.h" | ||||
| #include <ctype.h> | ||||
| #include "bytes.h" | ||||
|  | ||||
| static bool lastBit; | ||||
|  | ||||
| static double clockRateUsForTrack(unsigned track) | ||||
| { | ||||
|     /* | ||||
|      * Track   # Sectors/Track Speed Zone  bits/rotation        | ||||
|      * 1 – 17          21          3       61,538.4 | ||||
|      * 18 – 24         19          2       57,142.8 | ||||
|      * 25 – 30         18          1       53,333.4 | ||||
|      * 31 – 35         17          0       50,000.0 | ||||
|     */ | ||||
|     if (track < 17) | ||||
|         return 200000.0/61538.4; | ||||
|     if (track < 24) | ||||
|         return 200000.0/57142.8; | ||||
|     if (track < 30) | ||||
|         return 200000.0/53333.4; | ||||
|     return 200000.0/50000.0; | ||||
|  | ||||
| } | ||||
|  | ||||
| static unsigned sectorsForTrack(unsigned track) | ||||
| { | ||||
|     /* | ||||
|      * Track   Sectors/track   # Sectors   Storage in Bytes | ||||
|      *   -----   -------------   ---------   ---------------- | ||||
|      *    1-17        21            357           7820 | ||||
|      *   18-24        19            133           7170 | ||||
|      *   25-30        18            108           6300 | ||||
|      *   31-40(*)     17             85           6020 | ||||
|      *                              --- | ||||
|      *                              683 (for a 35 track image) | ||||
|      */ | ||||
|     if (track < 17) | ||||
|         return 21; | ||||
|     if (track < 24) | ||||
|         return 19; | ||||
|     if (track < 30) | ||||
|         return 18; | ||||
|     return 17; | ||||
| } | ||||
|  | ||||
| static int encode_data_gcr(uint8_t data) | ||||
| { | ||||
|     switch (data) | ||||
|     { | ||||
|         #define GCR_ENTRY(gcr, data) \ | ||||
|             case data: return gcr; | ||||
|         #include "data_gcr.h" | ||||
|         #undef GCR_ENTRY | ||||
|     } | ||||
|     return -1; | ||||
| }; | ||||
|  | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src) | ||||
| { | ||||
|     for (bool bit : src)  //Range-based for loop | ||||
|     { | ||||
|         if (cursor < bits.size()) | ||||
|             bits[cursor++] = bit; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width) | ||||
| { | ||||
|     cursor += width; | ||||
|     for (int i=0; i<width; i++) | ||||
|     { | ||||
|         unsigned pos = cursor - i - 1;               | ||||
|         if (pos < bits.size()) | ||||
|             bits[pos] = data & 1; | ||||
|         data >>= 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void bindump(std::ostream& stream, std::vector<bool>& buffer) | ||||
| { | ||||
|     size_t pos = 0; | ||||
|  | ||||
|     while ((pos < buffer.size()) and (pos <520)) | ||||
|     { | ||||
|         stream << fmt::format("{:5d} : ", pos); | ||||
|         for (int i=0; i<40; i++) | ||||
|         { | ||||
|             if ((pos+i) < buffer.size()) | ||||
|                 stream << fmt::format("{:01b}", (buffer[pos+i])); | ||||
|             else | ||||
|                 stream << "-- "; | ||||
|             if ((((pos + i + 1) % 8) == 0) and i != 0) | ||||
|                 stream << "  "; | ||||
|  | ||||
|         } | ||||
|         stream << std::endl; | ||||
|         pos += 40; | ||||
|     } | ||||
| } | ||||
| static std::vector<bool> encode_data(uint8_t input) | ||||
| { | ||||
|     /* | ||||
|     * Four 8-bit data bytes are converted to four 10-bit GCR bytes at a time by | ||||
|     * the 1541 DOS.  RAM is only an 8-bit storage device though. This hardware | ||||
|     * limitation prevents a 10-bit GCR byte from being stored in a single | ||||
|     * memory location. Four 10-bit GCR bytes total 40 bits - a number evenly | ||||
|     * divisible by our overriding 8-bit constraint. Commodore sub- divides the | ||||
|     * 40 GCR bits into five 8-bit bytes to solve this dilemma. This explains | ||||
|     * why four 8-bit data bytes are converted to GCR form at a time. The | ||||
|     * following step by step example demonstrates how this bit manipulation is | ||||
|     * performed by the DOS. | ||||
|     * | ||||
|     * STEP 1. Four 8-bit Data Bytes | ||||
|     * $08 $10 $00 $12 | ||||
|     * | ||||
|     * STEP 2. Hexadecimal to Binary Conversion | ||||
|     * 1. Binary Equivalents | ||||
|     * $08       $10         $00         $12 | ||||
|     * 00001000  00010000    00000000    00010010 | ||||
|     * | ||||
|     * STEP 3. Binary to GCR Conversion | ||||
|     * 1. Four 8-bit Data Bytes | ||||
|     * 00001000 00010000 00000000 00010010 | ||||
|     * 2. High and Low Nybbles | ||||
|     * 0000 1000 0001 0000 0000 0000 0001 0010 | ||||
|     * 3. High and Low Nybble GCR Equivalents | ||||
|     * 01010 01001 01011 01010 01010 01010 01011 10010 | ||||
|     * 4. Four 10-bit GCR Bytes | ||||
|     * 0101001001 0101101010 0101001010 0101110010 | ||||
|     * | ||||
|     * STEP 4. 10-bit GCR to 8-bit GCR Conversion | ||||
|     *   1. Concatenate Four 10-bit GCR Bytes | ||||
|     *   0101001001010110101001010010100101110010 | ||||
|     *   2. Five 8-bit Subdivisions | ||||
|     *   01010010 01010110 10100101 00101001 01110010 | ||||
|     * | ||||
|     * STEP 5. Binary to Hexadecimal Conversion | ||||
|     * 1. Hexadecimal Equivalents | ||||
|     *   01010010    01010110    10100101    00101001    01110010 | ||||
|     *   $52         $56         $A5         $29         $72 | ||||
|     * | ||||
|     * STEP 6. Four 8-bit Data Bytes are Recorded as Five 8-bit GCR Bytes | ||||
|     *   $08 $10 $00 $12 | ||||
|     * | ||||
|     * are recorded as | ||||
|     *   $52 $56 $A5 $29 $72 | ||||
|     */ | ||||
|  | ||||
|     std::vector<bool> output(10, false); | ||||
|     uint8_t hi = 0; | ||||
|     uint8_t lo = 0; | ||||
|     uint8_t lo_GCR = 0; | ||||
|     uint8_t hi_GCR = 0; | ||||
|  | ||||
|     //Convert the byte in high and low nibble | ||||
|     lo = input >> 4; //get the lo nibble shift the bits 4 to the right           | ||||
|     hi = input & 15; //get the hi nibble bij masking the lo bits (00001111)      | ||||
|  | ||||
|  | ||||
|     lo_GCR = encode_data_gcr(lo);   //example value: 0000   GCR = 01010 | ||||
|     hi_GCR = encode_data_gcr(hi);   //example value: 1000   GCR = 01001 | ||||
|     //output = [0,1,2,3,4,5,6,7,8,9] | ||||
|     //value  = [0,1,0,1,0,0,1,0,0,1] | ||||
|     //          01010 01001 | ||||
|  | ||||
|     int b = 4; | ||||
|     for (int i = 0; i < 10; i++) | ||||
|     { | ||||
|         if (i < 5) //01234 | ||||
|         {       //i = 0 op  | ||||
|             output[4-i] = (lo_GCR & 1); //01010 | ||||
|  | ||||
|             //01010 -> & 00001 -> 00000 output[4] = 0 | ||||
|             //00101 -> & 00001 -> 00001 output[3] = 1 | ||||
|             //00010 -> & 00001 -> 00000 output[2] = 0 | ||||
|             //00001 -> & 00001 -> 00001 output[1] = 1 | ||||
|             //00000 -> & 00001 -> 00000 output[0] = 0 | ||||
|             lo_GCR >>= 1; | ||||
|         } else   | ||||
|         { | ||||
|             output[i+b] = (hi_GCR & 1); //01001 | ||||
|             //01001 -> & 00001 -> 00001 output[9] = 1 | ||||
|             //00100 -> & 00001 -> 00000 output[8] = 0 | ||||
|             //00010 -> & 00001 -> 00000 output[7] = 0 | ||||
|             //00001 -> & 00001 -> 00001 output[6] = 1 | ||||
|             //00000 -> & 00001 -> 00000 output[5] = 0 | ||||
|             hi_GCR >>= 1; | ||||
|             b = b-2; | ||||
|         } | ||||
|     } | ||||
|     return output; | ||||
| } | ||||
|  | ||||
| void Commodore64Encoder::writeSector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) const | ||||
| { | ||||
|     /* Source: http://www.unusedino.de/ec64/technical/formats/g64.html  | ||||
|      * 1. Header sync       FF FF FF FF FF (40 'on' bits, not GCR) | ||||
|      * 2. Header info       52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes) | ||||
|      * 3. Header gap        55 55 55 55 55 55 55 55 55 (9 bytes, never read) | ||||
|      * 4. Data sync         FF FF FF FF FF (40 'on' bits, not GCR) | ||||
|      * 5. Data block        55...4A (325 GCR bytes) | ||||
|      * 6. Inter-sector gap  55 55 55 55...55 55 (4 to 12 bytes, never read) | ||||
|      * 1. Header sync       (SYNC for the next sector) | ||||
|     */ | ||||
|     if ((sector->status == Sector::OK) or (sector->status == Sector::BAD_CHECKSUM)) | ||||
|     { | ||||
|         // There is data to encode to disk. | ||||
|         if ((sector->data.size() != C64_SECTOR_LENGTH)) | ||||
|             Error() << fmt::format("unsupported sector size {} --- you must pick 256", sector->data.size());     | ||||
|  | ||||
|         // 1. Write header Sync (not GCR) | ||||
|         for (int i=0; i<6; i++) | ||||
|             write_bits(bits, cursor, C64_HEADER_DATA_SYNC, 1*8); /* sync */ | ||||
|  | ||||
|         // 2. Write Header info 10 GCR bytes | ||||
|         /* | ||||
|          * The 10 byte header info (#2) is GCR encoded and must be decoded  to | ||||
|          * it's normal 8 bytes to be understood. Once decoded, its breakdown is | ||||
|          * as follows: | ||||
|          *  | ||||
|          * Byte $00 - header block ID           ($08) | ||||
|          *   01 - header block checksum 16  (EOR of $02-$05) | ||||
|          *   02 - Sector | ||||
|          *   03 - Track | ||||
|          *   04 - Format ID byte #2 | ||||
|          *   05 - Format ID byte #1 | ||||
|          *   06-07 - $0F ("off" bytes) | ||||
|          */ | ||||
|         uint8_t encodedTrack = ((sector->logicalTrack) + 1); // C64 track numbering starts with 1. Fluxengine with 0. | ||||
|         uint8_t encodedSector = sector->logicalSector; | ||||
|         // uint8_t formatByte1 = C64_FORMAT_ID_BYTE1; | ||||
|         // uint8_t formatByte2 = C64_FORMAT_ID_BYTE2; | ||||
|         uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ _formatByte1 ^ _formatByte2); | ||||
|         write_bits(bits, cursor, encode_data(C64_HEADER_BLOCK_ID)); | ||||
|         write_bits(bits, cursor, encode_data(headerChecksum)); | ||||
|         write_bits(bits, cursor, encode_data(encodedSector)); | ||||
|         write_bits(bits, cursor, encode_data(encodedTrack)); | ||||
|         write_bits(bits, cursor, encode_data(_formatByte2)); | ||||
|         write_bits(bits, cursor, encode_data(_formatByte1)); | ||||
|         write_bits(bits, cursor, encode_data(C64_PADDING)); | ||||
|         write_bits(bits, cursor, encode_data(C64_PADDING)); | ||||
|  | ||||
|         // 3. Write header GAP not GCR | ||||
|         for (int i=0; i<9; i++) | ||||
|             write_bits(bits, cursor, C64_HEADER_GAP, 1*8); /* header gap */ | ||||
|  | ||||
|         // 4. Write Data sync not GCR | ||||
|         for (int i=0; i<6; i++) | ||||
|             write_bits(bits, cursor, C64_HEADER_DATA_SYNC, 1*8); /* sync */ | ||||
|  | ||||
|         // 5. Write data block 325 GCR bytes | ||||
|         /* | ||||
|          * The 325 byte data block (#5) is GCR encoded and must be  decoded  to  its | ||||
|          * normal 260 bytes to be understood. The data block is made up of the following: | ||||
|          *  | ||||
|          * Byte    $00 - data block ID ($07) | ||||
|          *      01-100 - 256 bytes data | ||||
|          *      101 - data block checksum (EOR of $01-100) | ||||
|          *      102-103 - $00 ("off" bytes, to make the sector size a multiple of 5) | ||||
|          */ | ||||
|  | ||||
|         write_bits(bits, cursor, encode_data(C64_DATA_BLOCK_ID)); | ||||
|         uint8_t dataChecksum = xorBytes(sector->data); | ||||
|         ByteReader br(sector->data); | ||||
|         int i = 0; | ||||
|         for (i = 0; i < C64_SECTOR_LENGTH; i++) | ||||
|         { | ||||
|             uint8_t val = br.read_8(); | ||||
|             write_bits(bits, cursor, encode_data(val));      | ||||
|         } | ||||
|         write_bits(bits, cursor, encode_data(dataChecksum)); | ||||
|         write_bits(bits, cursor, encode_data(C64_PADDING)); | ||||
|         write_bits(bits, cursor, encode_data(C64_PADDING)); | ||||
|  | ||||
|         //6. Write inter-sector gap 9 - 12 bytes nor gcr | ||||
|         for (int i=0; i<9; i++) | ||||
|             write_bits(bits, cursor, C64_INTER_SECTOR_GAP, 1*8); /* sync */ | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> Commodore64Encoder::encode( | ||||
|     int physicalTrack, int physicalSide, const SectorSet& allSectors) | ||||
| { | ||||
|     /* The format ID Character # 1 and # 2 are in the .d64 image only present | ||||
|      * in track 18 sector zero which contains the BAM info in byte 162 and 163. | ||||
|      * it is written in every header of every sector and track. headers are not | ||||
|      * stored in a d64 disk image so we have to get it from track 18 which | ||||
|      * contains the BAM. | ||||
|     */ | ||||
|  | ||||
|     const auto& sectorData = allSectors.get(C64_BAM_TRACK*2, 0, 0); //Read de BAM to get the DISK ID bytes | ||||
|     if (sectorData) | ||||
|     { | ||||
|         ByteReader br(sectorData->data); | ||||
|         br.seek(162); //goto position of the first Disk ID Byte | ||||
|         _formatByte1 = br.read_8(); | ||||
|         _formatByte2 = br.read_8(); | ||||
|     } | ||||
|     else | ||||
|         _formatByte1 = _formatByte2 = 0; | ||||
|      | ||||
|     int logicalTrack = physicalTrack / 2; | ||||
|     double clockRateUs = clockRateUsForTrack(logicalTrack) * _config.clock_compensation_factor(); | ||||
|  | ||||
|     int bitsPerRevolution = 200000.0 / clockRateUs; | ||||
|  | ||||
|     std::vector<bool> bits(bitsPerRevolution); | ||||
|     unsigned cursor = 0; | ||||
|  | ||||
|     fillBitmapTo(bits, cursor, _config.post_index_gap_us() / clockRateUs, { true, false }); | ||||
|     lastBit = false; | ||||
|  | ||||
|     unsigned numSectors = sectorsForTrack(logicalTrack); | ||||
|     unsigned writtenSectors = 0; | ||||
|     for (int sectorId=0; sectorId<numSectors; sectorId++) | ||||
|     { | ||||
|         const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId); | ||||
|         if (sectorData) | ||||
|         { | ||||
|             writeSector(bits, cursor, sectorData); | ||||
|             writtenSectors++; | ||||
|         } | ||||
|     } | ||||
|     if (writtenSectors == 0) | ||||
|         return std::unique_ptr<Fluxmap>(); | ||||
|  | ||||
|     if (cursor >= bits.size()) | ||||
|         Error() << fmt::format("track data overrun by {} bits", cursor - bits.size()); | ||||
|     fillBitmapTo(bits, cursor, bits.size(), { true, false }); | ||||
|  | ||||
|     std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
|     fluxmap->appendBits(bits, clockRateUs*1e3); | ||||
|     return fluxmap; | ||||
| } | ||||
|  | ||||
| // vim: sw=4 ts=4 et | ||||
|  | ||||
| @@ -7,10 +7,12 @@ | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class F85DecoderProto; | ||||
|  | ||||
| class DurangoF85Decoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	DurangoF85Decoder(const F85DecoderProto&) {} | ||||
|     virtual ~DurangoF85Decoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/f85/f85.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/f85/f85.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message F85DecoderProto {} | ||||
|  | ||||
| @@ -8,10 +8,12 @@ | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class Track; | ||||
| class Fb100DecoderProto; | ||||
|  | ||||
| class Fb100Decoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	Fb100Decoder(const Fb100DecoderProto&) {} | ||||
|     virtual ~Fb100Decoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/fb100/fb100.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/fb100/fb100.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message Fb100DecoderProto {} | ||||
|  | ||||
| @@ -6,6 +6,8 @@ | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "sector.h" | ||||
| #include "record.h" | ||||
| #include "arch/ibm/ibm.pb.h" | ||||
| #include "proto.h" | ||||
| #include <string.h> | ||||
|  | ||||
| static_assert(std::is_trivially_copyable<IbmIdam>::value, | ||||
| @@ -89,6 +91,11 @@ const FluxMatchers ANY_RECORD_PATTERN( | ||||
|     } | ||||
| ); | ||||
|  | ||||
| std::set<unsigned> IbmDecoder::requiredSectors(Track& track) const | ||||
| { | ||||
| 	return iterate(_config.required_sectors()); | ||||
| } | ||||
|  | ||||
| AbstractDecoder::RecordType IbmDecoder::advanceToNextRecord() | ||||
| { | ||||
| 	const FluxMatcher* matcher = nullptr; | ||||
| @@ -131,14 +138,14 @@ void IbmDecoder::decodeSectorRecord() | ||||
|     br.read_8(); /* skip ID byte */ | ||||
|     _sector->logicalTrack = br.read_8(); | ||||
|     _sector->logicalSide = br.read_8(); | ||||
|     _sector->logicalSector = br.read_8() - _sectorBase; | ||||
|     _sector->logicalSector = br.read_8() - _config.sector_id_base(); | ||||
|     _currentSectorSize = 1 << (br.read_8() + 7); | ||||
|     uint16_t wantCrc = br.read_be16(); | ||||
|     uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5)); | ||||
|     if (wantCrc == gotCrc) | ||||
|         _sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ | ||||
|  | ||||
|     if (_ignoreSideByte) | ||||
|     if (_config.ignore_side_byte()) | ||||
|         _sector->logicalSide = _sector->physicalSide; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "crc.h" | ||||
| #include "sectorset.h" | ||||
| #include "writer.h" | ||||
| #include "arch/ibm/ibm.pb.h" | ||||
| #include "fmt/format.h" | ||||
| #include <ctype.h> | ||||
|  | ||||
| @@ -76,21 +77,6 @@ void IbmEncoder::writeRawBits(uint32_t data, int width) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void IbmEncoder::writeBytes(const Bytes& bytes) | ||||
| { | ||||
| 	if (_parameters.useFm) | ||||
| 		encodeFm(_bits, _cursor, bytes); | ||||
| 	else | ||||
| 		encodeMfm(_bits, _cursor, bytes, _lastBit); | ||||
| } | ||||
|  | ||||
| void IbmEncoder::writeBytes(int count, uint8_t byte) | ||||
| { | ||||
| 	Bytes bytes = { byte }; | ||||
| 	for (int i=0; i<count; i++) | ||||
| 		writeBytes(bytes); | ||||
| } | ||||
|  | ||||
| static uint8_t decodeUint16(uint16_t raw) | ||||
| { | ||||
| 	Bytes b; | ||||
| @@ -99,24 +85,56 @@ static uint8_t decodeUint16(uint16_t raw) | ||||
| 	return decodeFmMfm(b.toBits())[0]; | ||||
| } | ||||
|  | ||||
| void IbmEncoder::getTrackFormat(IbmEncoderProto::TrackdataProto& trackdata, unsigned cylinder, unsigned head) | ||||
| { | ||||
| 	trackdata.Clear(); | ||||
| 	for (const auto& f : _config.trackdata()) | ||||
| 	{ | ||||
| 		if (f.has_cylinder() && (f.cylinder() != cylinder)) | ||||
| 			continue; | ||||
| 		if (f.has_head() && (f.head() != head)) | ||||
| 			continue; | ||||
|  | ||||
| 		trackdata.MergeFrom(f); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> IbmEncoder::encode( | ||||
| 	int physicalTrack, int physicalSide, const SectorSet& allSectors) | ||||
| { | ||||
| 	if (_parameters.swapSides) | ||||
| 	IbmEncoderProto::TrackdataProto trackdata; | ||||
| 	getTrackFormat(trackdata, physicalTrack, physicalSide); | ||||
|  | ||||
| 	auto writeBytes = [&](const Bytes& bytes) | ||||
| 	{ | ||||
| 		if (trackdata.use_fm()) | ||||
| 			encodeFm(_bits, _cursor, bytes); | ||||
| 		else | ||||
| 			encodeMfm(_bits, _cursor, bytes, _lastBit); | ||||
| 	}; | ||||
|  | ||||
| 	auto writeFillerBytes = [&](int count, uint8_t byte) | ||||
| 	{ | ||||
| 		Bytes bytes = { byte }; | ||||
| 		for (int i=0; i<count; i++) | ||||
| 			writeBytes(bytes); | ||||
| 	}; | ||||
|  | ||||
| 	if (trackdata.swap_sides()) | ||||
| 		physicalSide = 1 - physicalSide; | ||||
| 	double clockRateUs = 1e3 / _parameters.clockRateKhz; | ||||
| 	if (!_parameters.useFm) | ||||
| 	double clockRateUs = 1e3 / trackdata.clock_rate_khz(); | ||||
| 	if (!trackdata.use_fm()) | ||||
| 		clockRateUs /= 2.0; | ||||
| 	int bitsPerRevolution = (_parameters.trackLengthMs * 1000.0) / clockRateUs; | ||||
| 	int bitsPerRevolution = (trackdata.track_length_ms() * 1000.0) / clockRateUs; | ||||
| 	_bits.resize(bitsPerRevolution); | ||||
| 	_cursor = 0; | ||||
|  | ||||
| 	uint8_t idamUnencoded = decodeUint16(_parameters.idamByte); | ||||
| 	uint8_t damUnencoded = decodeUint16(_parameters.damByte); | ||||
| 	uint8_t idamUnencoded = decodeUint16(trackdata.idam_byte()); | ||||
| 	uint8_t damUnencoded = decodeUint16(trackdata.dam_byte()); | ||||
|  | ||||
| 	uint8_t sectorSize = 0; | ||||
| 	{ | ||||
| 		int s = _parameters.sectorSize >> 7; | ||||
| 		int s = trackdata.sector_size() >> 7; | ||||
| 		while (s > 1) | ||||
| 		{ | ||||
| 			s >>= 1; | ||||
| @@ -124,32 +142,35 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode( | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	uint8_t gapFill = _parameters.useFm ? 0x00 : 0x4e; | ||||
| 	uint8_t gapFill = trackdata.use_fm() ? 0x00 : 0x4e; | ||||
|  | ||||
| 	writeBytes(_parameters.gap0, gapFill); | ||||
| 	if (_parameters.emitIam) | ||||
| 	writeFillerBytes(trackdata.gap0(), gapFill); | ||||
| 	if (trackdata.emit_iam()) | ||||
| 	{ | ||||
| 		writeBytes(_parameters.useFm ? 6 : 12, 0x00); | ||||
| 		if (!_parameters.useFm) | ||||
| 		writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00); | ||||
| 		if (!trackdata.use_fm()) | ||||
| 		{ | ||||
| 			for (int i=0; i<3; i++) | ||||
| 				writeRawBits(MFM_IAM_SEPARATOR, 16); | ||||
| 		} | ||||
| 		writeRawBits(_parameters.useFm ? FM_IAM_RECORD : MFM_IAM_RECORD, 16); | ||||
| 		writeBytes(_parameters.gap1, gapFill); | ||||
| 		writeRawBits(trackdata.use_fm() ? FM_IAM_RECORD : MFM_IAM_RECORD, 16); | ||||
| 		writeFillerBytes(trackdata.gap1(), gapFill); | ||||
| 	} | ||||
|  | ||||
| 	bool first = true; | ||||
| 	for (char sectorChar : _parameters.sectorSkew) | ||||
| 	for (char sectorChar : trackdata.sector_skew()) | ||||
| 	{ | ||||
| 		int sectorId = charToInt(sectorChar); | ||||
| 		if (!first) | ||||
| 			writeBytes(_parameters.gap3, gapFill); | ||||
| 			writeFillerBytes(trackdata.gap3(), gapFill); | ||||
| 		first = false; | ||||
|  | ||||
| 		const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId); | ||||
| 		if (!sectorData) | ||||
| 			Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId); | ||||
| 		{ | ||||
| 			/* If there are any missing sectors, this is an empty track. */ | ||||
| 			return std::unique_ptr<Fluxmap>(); | ||||
| 		} | ||||
|  | ||||
| 		/* Writing the sector and data records are fantastically annoying. | ||||
| 		 * The CRC is calculated from the *very start* of the record, and | ||||
| @@ -163,8 +184,8 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode( | ||||
| 			Bytes header; | ||||
| 			ByteWriter bw(header); | ||||
|  | ||||
| 			writeBytes(_parameters.useFm ? 6 : 12, 0x00); | ||||
| 			if (!_parameters.useFm) | ||||
| 			writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00); | ||||
| 			if (!trackdata.use_fm()) | ||||
| 			{ | ||||
| 				for (int i=0; i<3; i++) | ||||
| 					bw.write_8(MFM_RECORD_SEPARATOR_BYTE); | ||||
| @@ -172,53 +193,53 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode( | ||||
| 			bw.write_8(idamUnencoded); | ||||
| 			bw.write_8(sectorData->logicalTrack); | ||||
| 			bw.write_8(sectorData->logicalSide); | ||||
| 			bw.write_8(sectorData->logicalSector + _parameters.startSectorId); | ||||
| 			bw.write_8(sectorData->logicalSector + trackdata.start_sector_id()); | ||||
| 			bw.write_8(sectorSize); | ||||
| 			uint16_t crc = crc16(CCITT_POLY, header); | ||||
| 			bw.write_be16(crc); | ||||
|  | ||||
| 			int conventionalHeaderStart = 0; | ||||
| 			if (!_parameters.useFm) | ||||
| 			if (!trackdata.use_fm()) | ||||
| 			{ | ||||
| 				for (int i=0; i<3; i++) | ||||
| 					writeRawBits(MFM_RECORD_SEPARATOR, 16); | ||||
| 				conventionalHeaderStart += 3; | ||||
|  | ||||
| 			} | ||||
| 			writeRawBits(_parameters.idamByte, 16); | ||||
| 			writeRawBits(trackdata.idam_byte(), 16); | ||||
| 			conventionalHeaderStart += 1; | ||||
|  | ||||
| 			writeBytes(header.slice(conventionalHeaderStart)); | ||||
| 		} | ||||
|  | ||||
| 		writeBytes(_parameters.gap2, gapFill); | ||||
| 		writeFillerBytes(trackdata.gap2(), gapFill); | ||||
|  | ||||
| 		{ | ||||
| 			Bytes data; | ||||
| 			ByteWriter bw(data); | ||||
|  | ||||
| 			writeBytes(_parameters.useFm ? 6 : 12, 0x00); | ||||
| 			if (!_parameters.useFm) | ||||
| 			writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00); | ||||
| 			if (!trackdata.use_fm()) | ||||
| 			{ | ||||
| 				for (int i=0; i<3; i++) | ||||
| 					bw.write_8(MFM_RECORD_SEPARATOR_BYTE); | ||||
| 			} | ||||
| 			bw.write_8(damUnencoded); | ||||
|  | ||||
| 			Bytes truncatedData = sectorData->data.slice(0, _parameters.sectorSize); | ||||
| 			Bytes truncatedData = sectorData->data.slice(0, trackdata.sector_size()); | ||||
| 			bw += truncatedData; | ||||
| 			uint16_t crc = crc16(CCITT_POLY, data); | ||||
| 			bw.write_be16(crc); | ||||
|  | ||||
| 			int conventionalHeaderStart = 0; | ||||
| 			if (!_parameters.useFm) | ||||
| 			if (!trackdata.use_fm()) | ||||
| 			{ | ||||
| 				for (int i=0; i<3; i++) | ||||
| 					writeRawBits(MFM_RECORD_SEPARATOR, 16); | ||||
| 				conventionalHeaderStart += 3; | ||||
|  | ||||
| 			} | ||||
| 			writeRawBits(_parameters.damByte, 16); | ||||
| 			writeRawBits(trackdata.dam_byte(), 16); | ||||
| 			conventionalHeaderStart += 1; | ||||
|  | ||||
| 			writeBytes(data.slice(conventionalHeaderStart)); | ||||
| @@ -228,7 +249,7 @@ std::unique_ptr<Fluxmap> IbmEncoder::encode( | ||||
| 	if (_cursor >= _bits.size()) | ||||
| 		Error() << "track data overrun"; | ||||
| 	while (_cursor < _bits.size()) | ||||
| 		writeBytes(1, gapFill); | ||||
| 		writeFillerBytes(1, gapFill); | ||||
|  | ||||
| 	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 	fluxmap->appendBits(_bits, clockRateUs*1e3); | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
|  | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "arch/ibm/ibm.pb.h" | ||||
|  | ||||
| /* IBM format (i.e. ordinary PC floppies). */ | ||||
|  | ||||
| @@ -32,51 +33,27 @@ struct IbmIdam | ||||
| class IbmDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
|     IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false, | ||||
| 			const std::set<unsigned> requiredSectors=std::set<unsigned>()): | ||||
|         _sectorBase(sectorBase), | ||||
|         _ignoreSideByte(ignoreSideByte), | ||||
| 		_requiredSectors(requiredSectors) | ||||
|     IbmDecoder(const IbmDecoderProto& config): | ||||
| 		_config(config) | ||||
|     {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|     void decodeSectorRecord(); | ||||
|     void decodeDataRecord(); | ||||
|  | ||||
| 	std::set<unsigned> requiredSectors(Track& track) const | ||||
| 	{ return _requiredSectors; } | ||||
| 	std::set<unsigned> requiredSectors(Track& track) const; | ||||
|  | ||||
| private: | ||||
|     unsigned _sectorBase; | ||||
|     bool _ignoreSideByte; | ||||
| 	std::set<unsigned> _requiredSectors; | ||||
| 	const IbmDecoderProto& _config; | ||||
|     unsigned _currentSectorSize; | ||||
|     unsigned _currentHeaderLength; | ||||
| }; | ||||
|  | ||||
| struct IbmParameters | ||||
| { | ||||
| 	int trackLengthMs; | ||||
| 	int sectorSize; | ||||
| 	bool emitIam; | ||||
| 	int startSectorId; | ||||
| 	int clockRateKhz; | ||||
| 	bool useFm; | ||||
| 	uint16_t idamByte; | ||||
| 	uint16_t damByte; | ||||
| 	int gap0; | ||||
| 	int gap1; | ||||
| 	int gap2; | ||||
| 	int gap3; | ||||
| 	std::string sectorSkew; | ||||
| 	bool swapSides; | ||||
| }; | ||||
|  | ||||
| class IbmEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	IbmEncoder(const IbmParameters& parameters): | ||||
| 		_parameters(parameters) | ||||
| 	IbmEncoder(const IbmEncoderProto& config): | ||||
| 		_config(config) | ||||
| 	{} | ||||
|  | ||||
| 	virtual ~IbmEncoder() {} | ||||
| @@ -86,12 +63,12 @@ public: | ||||
|  | ||||
| private: | ||||
| 	void writeRawBits(uint32_t data, int width); | ||||
| 	void writeBytes(const Bytes& bytes); | ||||
| 	void writeBytes(int count, uint8_t value); | ||||
| 	void writeSync(); | ||||
| 	 | ||||
| 	void getTrackFormat(IbmEncoderProto::TrackdataProto& format, unsigned track, unsigned side); | ||||
|  | ||||
| private: | ||||
| 	IbmParameters _parameters; | ||||
| 	const IbmEncoderProto& _config; | ||||
| 	std::vector<bool> _bits; | ||||
| 	unsigned _cursor; | ||||
| 	bool _lastBit; | ||||
|   | ||||
							
								
								
									
										34
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								arch/ibm/ibm.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message IbmDecoderProto { | ||||
| 	optional int32 sector_id_base = 1        [default = 1, (help) = "ID of first sector"]; | ||||
| 	optional bool ignore_side_byte = 2       [default = false, (help) = "ignore side byte in sector header"]; | ||||
| 	optional RangeProto required_sectors = 3 [(help) = "require these sectors to exist for a good read"]; | ||||
| } | ||||
|  | ||||
| message IbmEncoderProto { | ||||
| 	message TrackdataProto { | ||||
| 		optional int32 cylinder = 15        [(help) = "if set, the format applies only to this track"]; | ||||
| 		optional int32 head = 16            [(help) = "if set, the format applies only to this head"]; | ||||
|  | ||||
| 		optional double track_length_ms = 1 [(help) = "length of track"]; | ||||
| 		optional int32 sector_size = 2      [default=512, (help) = "number of bytes per sector"]; | ||||
| 		optional bool emit_iam = 3          [default=true, (help) = "whether to emit an IAM record"]; | ||||
| 		optional int32 start_sector_id = 4  [default=1, (help) = "ID of first sector"]; | ||||
| 		optional double clock_rate_khz = 5  [(help) = "data clock rate"]; | ||||
| 		optional bool use_fm = 6            [default=false, (help) = "whether to use FM encoding rather than MFM"]; | ||||
| 		optional int32 idam_byte = 7        [default=0x5554, (help) = "16-bit raw bit pattern of IDAM byte"]; | ||||
| 		optional int32 dam_byte = 8         [default=0x5545, (help) = "16-bit raw bit pattern of DAM byte"]; | ||||
| 		optional int32 gap0 = 9             [default=80, (help) = "size of gap 1 (the post-index gap)"]; | ||||
| 		optional int32 gap1 = 10            [default=50, (help) = "size of gap 2 (the post-ID gap)"]; | ||||
| 		optional int32 gap2 = 11            [default=22, (help) = "size of gap 3 (the pre-data gap)"]; | ||||
| 		optional int32 gap3 = 12            [default=80, (help) = "size of gap 4 (the post-data or format gap)"]; | ||||
| 		optional string sector_skew = 13    [(help) = "order to emit sectors"]; | ||||
| 		optional bool swap_sides = 14       [default=false, (help) = "swap side bytes when writing"]; | ||||
| 	} | ||||
|  | ||||
| 	repeated TrackdataProto trackdata = 1; | ||||
| } | ||||
|  | ||||
| @@ -15,10 +15,13 @@ | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class MacintoshDecoderProto; | ||||
| class MacintoshEncoderProto; | ||||
|  | ||||
| class MacintoshDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	MacintoshDecoder(const MacintoshDecoderProto&) {} | ||||
|     virtual ~MacintoshDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
| @@ -31,6 +34,7 @@ public: | ||||
| class MacintoshEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	MacintoshEncoder(const MacintoshEncoderProto&) {} | ||||
| 	virtual ~MacintoshEncoder() {} | ||||
|  | ||||
| public: | ||||
|   | ||||
							
								
								
									
										5
									
								
								arch/macintosh/macintosh.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								arch/macintosh/macintosh.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message MacintoshDecoderProto {} | ||||
| message MacintoshEncoderProto {} | ||||
|  | ||||
| @@ -1,14 +1,16 @@ | ||||
| #ifndef ZILOGMCZ_H | ||||
| #define ZILOGMCZ_H | ||||
| #ifndef MICROPOLIS_H | ||||
| #define MICROPOLIS_H | ||||
|  | ||||
| #define MICROPOLIS_ENCODED_SECTOR_SIZE (1+2+266+6) | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class MicropolisDecoderProto; | ||||
|  | ||||
| class MicropolisDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	MicropolisDecoder(const MicropolisDecoderProto&) {} | ||||
| 	virtual ~MicropolisDecoder() {} | ||||
|  | ||||
| 	RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/micropolis/micropolis.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/micropolis/micropolis.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message MicropolisDecoderProto {} | ||||
|  | ||||
| @@ -3,9 +3,12 @@ | ||||
|  | ||||
| #include "decoders/decoders.h" | ||||
|  | ||||
| class MxDecoderProto; | ||||
|  | ||||
| class MxDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	MxDecoder(const MxDecoderProto&) {} | ||||
|     virtual ~MxDecoder() {} | ||||
|  | ||||
|     void beginTrack(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/mx/mx.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/mx/mx.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message MxDecoderProto {} | ||||
|  | ||||
							
								
								
									
										175
									
								
								arch/northstar/decoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								arch/northstar/decoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| /* Decoder for North Star 10-sector hard-sectored disks. | ||||
|  * | ||||
|  * Supports both single- and double-density.  For the sector format and | ||||
|  * checksum algorithm, see pp. 33 of the North Star Double Density Controller | ||||
|  * manual: | ||||
|  * | ||||
|  * http://bitsavers.org/pdf/northstar/boards/Northstar_MDS-A-D_1978.pdf | ||||
|  * | ||||
|  * North Star disks do not contain any track/head/sector information | ||||
|  * encoded in the sector record.  For this reason, we have to be absolutely | ||||
|  * sure that the hardSectorId is correct. | ||||
|  */ | ||||
|  | ||||
| #include "globals.h" | ||||
| #include "fluxmap.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "sector.h" | ||||
| #include "northstar.h" | ||||
| #include "bytes.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| /* | ||||
|  * MFM sectors have 32 bytes of 00's followed by two sync characters, | ||||
|  * specified in the North Star MDS manual as 0xFBFB. | ||||
|  * | ||||
|  * This is true for most disks; however, I found a few disks, including an | ||||
|  * original North Star DOS/BASIC v2.2.1 DQ disk) that uses 0xFBnn, where | ||||
|  * nn is an incrementing pattern. | ||||
|  * | ||||
|  * 00        00        00        F         B | ||||
|  * 0000 0000 0000 0000 0000 0000 0101 0101 0100 0101 | ||||
|  * A    A    A    A    A    A    5    5    4    5 | ||||
|  */ | ||||
| static const FluxPattern MFM_PATTERN(64, 0xAAAAAAAAAAAA5545LL); | ||||
|  | ||||
| /* FM sectors have 16 bytes of 00's followed by 0xFB. | ||||
|  * 00        FB | ||||
|  * 0000 0000 1111 1111 1110 1111 | ||||
|  * A    A    F    F    E    F | ||||
|  */ | ||||
| static const FluxPattern FM_PATTERN(64, 0xAAAAAAAAAAAAFFEFLL); | ||||
|  | ||||
| const FluxMatchers ANY_SECTOR_PATTERN( | ||||
| 	{ | ||||
| 		&MFM_PATTERN, | ||||
| 		&FM_PATTERN, | ||||
| 	} | ||||
| ); | ||||
|  | ||||
| /* Search for FM or MFM sector record */ | ||||
| AbstractDecoder::RecordType NorthstarDecoder::advanceToNextRecord() | ||||
| { | ||||
| 	nanoseconds_t now = _fmr->tell().ns(); | ||||
|  | ||||
| 	/* For all but the first sector, seek to the next sector pulse. | ||||
| 	 * The first sector does not contain the sector pulse in the fluxmap. | ||||
| 	 */ | ||||
| 	if (now != 0) { | ||||
| 		_fmr->seekToIndexMark(); | ||||
| 		now = _fmr->tell().ns(); | ||||
| 	} | ||||
|  | ||||
| 	/* Discard a possible partial sector at the end of the track. | ||||
| 	 * This partial sector could be mistaken for a conflicted sector, if | ||||
| 	 * whatever data read happens to match the checksum of 0, which is | ||||
| 	 * rare, but has been observed on some disks. | ||||
| 	 */ | ||||
| 	if (now > (_fmr->getDuration() - 21e6)) { | ||||
| 		_fmr->seekToIndexMark(); | ||||
| 		return(UNKNOWN_RECORD); | ||||
| 	} | ||||
|  | ||||
| 	int msSinceIndex = std::round(now / 1e6); | ||||
|  | ||||
| 	const FluxMatcher* matcher = nullptr; | ||||
|  | ||||
| 	/* Note that the seekToPattern ignores the sector pulses, so if | ||||
| 	 * a sector is not found for some reason, the seek will advance | ||||
| 	 * past one or more sector pulses.  For this reason, calculate | ||||
| 	 * _hardSectorId after the sector header is found. | ||||
| 	 */ | ||||
| 	_sector->clock = _fmr->seekToPattern(ANY_SECTOR_PATTERN, matcher); | ||||
|  | ||||
| 	int sectorFoundTimeRaw = std::round((_fmr->tell().ns()) / 1e6); | ||||
| 	int sectorFoundTime; | ||||
|  | ||||
| 	/* Round time to the nearest 20ms */ | ||||
| 	if ((sectorFoundTimeRaw % 20) < 10) { | ||||
| 		sectorFoundTime = (sectorFoundTimeRaw / 20) * 20; | ||||
| 	} | ||||
| 	else { | ||||
| 		sectorFoundTime = ((sectorFoundTimeRaw + 20) / 20) * 20; | ||||
| 	} | ||||
|  | ||||
| 	/* Calculate the sector ID based on time since the index */ | ||||
| 	_hardSectorId = (sectorFoundTime / 20) % 10; | ||||
|  | ||||
| //	std::cout << fmt::format( | ||||
| //		"Sector ID {}: hole at {}ms, sector start at {}ms", | ||||
| //		_hardSectorId, msSinceIndex, sectorFoundTimeRaw) << std::endl; | ||||
|  | ||||
| 	if (matcher == &MFM_PATTERN) { | ||||
| 		_sectorType = SECTOR_TYPE_MFM; | ||||
| 		readRawBits(48); | ||||
| 		return SECTOR_RECORD; | ||||
| 	} | ||||
|  | ||||
| 	if (matcher == &FM_PATTERN) { | ||||
| 		_sectorType = SECTOR_TYPE_FM; | ||||
| 		readRawBits(48); | ||||
| 		return SECTOR_RECORD; | ||||
| 	} | ||||
|  | ||||
| 	return UNKNOWN_RECORD; | ||||
| } | ||||
|  | ||||
| /* Checksum is initially 0. | ||||
|  * For each data byte, XOR with the current checksum. | ||||
|  * Rotate checksum left, carrying bit 7 to bit 0. | ||||
|  */ | ||||
| uint8_t northstarChecksum(const Bytes& bytes) { | ||||
| 	ByteReader br(bytes); | ||||
| 	uint8_t checksum = 0; | ||||
|  | ||||
| 	while (!br.eof()) { | ||||
| 		checksum ^= br.read_8(); | ||||
| 		checksum = ((checksum << 1) | ((checksum >> 7))); | ||||
| 	} | ||||
|  | ||||
| 	return checksum; | ||||
| } | ||||
|  | ||||
| void NorthstarDecoder::decodeSectorRecord() | ||||
| { | ||||
| 	unsigned recordSize, payloadSize, headerSize; | ||||
|  | ||||
| 	if (_sectorType == SECTOR_TYPE_MFM) { | ||||
| 		recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_DD; | ||||
| 		payloadSize = NORTHSTAR_PAYLOAD_SIZE_DD; | ||||
| 		headerSize = NORTHSTAR_HEADER_SIZE_DD; | ||||
| 	} | ||||
| 	else { | ||||
| 		recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_SD; | ||||
| 		payloadSize = NORTHSTAR_PAYLOAD_SIZE_SD; | ||||
| 		headerSize = NORTHSTAR_HEADER_SIZE_SD; | ||||
| 	} | ||||
|  | ||||
| 	auto rawbits = readRawBits(recordSize * 16); | ||||
| 	auto bytes = decodeFmMfm(rawbits).slice(0, recordSize); | ||||
| 	ByteReader br(bytes); | ||||
| 	uint8_t sync_char; | ||||
|  | ||||
| 	_sector->logicalSide = _sector->physicalSide; | ||||
| 	_sector->logicalSector = _hardSectorId; | ||||
| 	_sector->logicalTrack = _sector->physicalTrack; | ||||
|  | ||||
| 	sync_char = br.read_8();	/* Sync char: 0xFB */ | ||||
| 	if (_sectorType == SECTOR_TYPE_MFM) { | ||||
| 		sync_char = br.read_8();/* MFM second Sync char, usually 0xFB */ | ||||
| 	} | ||||
|  | ||||
| 	_sector->data = br.read(payloadSize); | ||||
|  | ||||
| 	uint8_t wantChecksum = br.read_8(); | ||||
| 	uint8_t gotChecksum = northstarChecksum(bytes.slice(headerSize, payloadSize)); | ||||
|  | ||||
| 	_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM; | ||||
| } | ||||
|  | ||||
| std::set<unsigned> NorthstarDecoder::requiredSectors(Track& track) const | ||||
| { | ||||
| 	static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; | ||||
| 	return sectors; | ||||
| } | ||||
							
								
								
									
										130
									
								
								arch/northstar/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								arch/northstar/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| #include "globals.h" | ||||
| #include "northstar.h" | ||||
| #include "sectorset.h" | ||||
|  | ||||
| #define GAP_FILL_SIZE_SD 30 | ||||
| #define PRE_HEADER_GAP_FILL_SIZE_SD 9 | ||||
| #define GAP_FILL_SIZE_DD 62 | ||||
| #define PRE_HEADER_GAP_FILL_SIZE_DD 16 | ||||
|  | ||||
| #define GAP1_FILL_BYTE	(0x4F) | ||||
| #define GAP2_FILL_BYTE	(0x4F) | ||||
|  | ||||
| #define TOTAL_SECTOR_BYTES () | ||||
|  | ||||
| static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) | ||||
| { | ||||
| 	int preambleSize = 0; | ||||
| 	int encodedSectorSize = 0; | ||||
| 	int gapFillSize = 0; | ||||
| 	int preHeaderGapFillSize = 0; | ||||
|  | ||||
| 	bool doubleDensity; | ||||
|  | ||||
| 	switch (sector->data.size()) { | ||||
| 	case NORTHSTAR_PAYLOAD_SIZE_SD: | ||||
| 		preambleSize = NORTHSTAR_PREAMBLE_SIZE_SD; | ||||
| 		encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_SD + NORTHSTAR_ENCODED_SECTOR_SIZE_SD + GAP_FILL_SIZE_SD; | ||||
| 		gapFillSize = GAP_FILL_SIZE_SD; | ||||
| 		preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_SD; | ||||
| 		doubleDensity = false; | ||||
| 		break; | ||||
| 	case NORTHSTAR_PAYLOAD_SIZE_DD: | ||||
| 		preambleSize = NORTHSTAR_PREAMBLE_SIZE_DD; | ||||
| 		encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_DD + NORTHSTAR_ENCODED_SECTOR_SIZE_DD + GAP_FILL_SIZE_DD; | ||||
| 		gapFillSize = GAP_FILL_SIZE_DD; | ||||
| 		preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_DD; | ||||
| 		doubleDensity = true; | ||||
| 		break; | ||||
| 	default: | ||||
| 		Error() << "unsupported sector size --- you must pick 256 or 512"; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	int fullSectorSize = preambleSize + encodedSectorSize; | ||||
| 	auto fullSector = std::make_shared<std::vector<uint8_t>>(); | ||||
| 	fullSector->reserve(fullSectorSize); | ||||
|  | ||||
| 	/* sector gap after index pulse */ | ||||
| 	for (int i = 0; i < preHeaderGapFillSize; i++) | ||||
| 		fullSector->push_back(GAP1_FILL_BYTE); | ||||
|  | ||||
| 	/* sector preamble */ | ||||
| 	for (int i = 0; i < preambleSize; i++) | ||||
| 		fullSector->push_back(0); | ||||
|  | ||||
| 	Bytes sectorData; | ||||
| 	if (sector->data.size() == encodedSectorSize) | ||||
| 		sectorData = sector->data; | ||||
| 	else { | ||||
| 		ByteWriter writer(sectorData); | ||||
| 		writer.write_8(0xFB);     /* sync character */ | ||||
| 		if (doubleDensity == true) { | ||||
| 			writer.write_8(0xFB); /* Double-density has two sync characters */ | ||||
| 		} | ||||
| 		writer += sector->data; | ||||
| 		if (doubleDensity == true) { | ||||
| 			writer.write_8(northstarChecksum(sectorData.slice(2))); | ||||
| 		} else { | ||||
| 			writer.write_8(northstarChecksum(sectorData.slice(1))); | ||||
| 		} | ||||
| 	} | ||||
| 	for (uint8_t b : sectorData) | ||||
| 		fullSector->push_back(b); | ||||
|  | ||||
| 	if (sector->logicalSector != 9) { | ||||
| 		/* sector postamble */ | ||||
| 		for (int i = 0; i < gapFillSize; i++) | ||||
| 			fullSector->push_back(GAP2_FILL_BYTE); | ||||
|  | ||||
| 		if (fullSector->size() != fullSectorSize) | ||||
| 			Error() << "sector mismatched length (" << sector->data.size() << ") expected: " << fullSector->size() << " got " << fullSectorSize; | ||||
| 	} else { | ||||
| 		/* sector postamble */ | ||||
| 		for (int i = 0; i < gapFillSize; i++) | ||||
| 			fullSector->push_back(GAP2_FILL_BYTE); | ||||
| 	} | ||||
|  | ||||
| 	bool lastBit = false; | ||||
|  | ||||
| 	if (doubleDensity == true) { | ||||
| 		encodeMfm(bits, cursor, fullSector, lastBit); | ||||
| 	} | ||||
| 	else { | ||||
| 		encodeFm(bits, cursor, fullSector); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> NorthstarEncoder::encode( | ||||
| 	int physicalTrack, int physicalSide, const SectorSet& allSectors) | ||||
| { | ||||
| 	int bitsPerRevolution = 100000; | ||||
| 	double clockRateUs = 4.00; | ||||
|  | ||||
| 	if ((physicalTrack < 0) || (physicalTrack >= 35)) | ||||
| 		return std::unique_ptr<Fluxmap>(); | ||||
|  | ||||
| 	const auto& sector = allSectors.get(physicalTrack, physicalSide, 0); | ||||
|  | ||||
| 	if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) { | ||||
| 		bitsPerRevolution /= 2;		// FM | ||||
| 	} else { | ||||
| 		clockRateUs /= 2.00; | ||||
| 	} | ||||
|  | ||||
| 	std::vector<bool> bits(bitsPerRevolution); | ||||
| 	unsigned cursor = 0; | ||||
|  | ||||
| 	for (int sectorId = 0; sectorId < 10; sectorId++) | ||||
| 	{ | ||||
| 		const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId); | ||||
| 		write_sector(bits, cursor, sectorData); | ||||
| 	} | ||||
|  | ||||
| 	if (cursor > bits.size()) | ||||
| 		Error() << "track data overrun"; | ||||
|  | ||||
| 	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 	fluxmap->appendBits(bits, clockRateUs * 1e3); | ||||
| 	return fluxmap; | ||||
| } | ||||
							
								
								
									
										72
									
								
								arch/northstar/northstar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								arch/northstar/northstar.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| #ifndef NORTHSTAR_H | ||||
| #define NORTHSTAR_H | ||||
|  | ||||
| /* Northstar floppies are 10-hard sectored disks with a sector format as follows: | ||||
|  * | ||||
|  * |----------------------------------| | ||||
|  * | SYNC Byte  | Payload  | Checksum | | ||||
|  * |------------+----------+----------| | ||||
|  * | 1 (0xFB)   | 256 (SD) |    1     | | ||||
|  * | 2 (0xFBFB) | 512 (DD) |          | | ||||
|  * |----------------------------------| | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
|  | ||||
| #define NORTHSTAR_PREAMBLE_SIZE_SD		(16) | ||||
| #define NORTHSTAR_PREAMBLE_SIZE_DD		(32) | ||||
| #define NORTHSTAR_HEADER_SIZE_SD		(1) | ||||
| #define NORTHSTAR_HEADER_SIZE_DD		(2) | ||||
| #define NORTHSTAR_PAYLOAD_SIZE_SD		(256) | ||||
| #define NORTHSTAR_PAYLOAD_SIZE_DD		(512) | ||||
| #define NORTHSTAR_CHECKSUM_SIZE		(1) | ||||
| #define NORTHSTAR_ENCODED_SECTOR_SIZE_SD	(NORTHSTAR_HEADER_SIZE_SD + NORTHSTAR_PAYLOAD_SIZE_SD + NORTHSTAR_CHECKSUM_SIZE) | ||||
| #define NORTHSTAR_ENCODED_SECTOR_SIZE_DD	(NORTHSTAR_HEADER_SIZE_DD + NORTHSTAR_PAYLOAD_SIZE_DD + NORTHSTAR_CHECKSUM_SIZE) | ||||
|  | ||||
| #define SECTOR_TYPE_MFM			(0) | ||||
| #define SECTOR_TYPE_FM				(1) | ||||
|  | ||||
| class NorthstarEncoderProto; | ||||
| class NorthstarDecoderProto; | ||||
|  | ||||
| class NorthstarDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	NorthstarDecoder(const NorthstarDecoderProto& config): | ||||
| 		_config(config) | ||||
| 	{ | ||||
| 		_sectorType = SECTOR_TYPE_MFM; | ||||
| 	} | ||||
|  | ||||
| 	virtual ~NorthstarDecoder() {} | ||||
|  | ||||
| 	RecordType advanceToNextRecord(); | ||||
| 	void decodeSectorRecord(); | ||||
| 	std::set<unsigned> requiredSectors(Track& track) const; | ||||
|  | ||||
| private: | ||||
| 	const NorthstarDecoderProto& _config; | ||||
| 	uint8_t _sectorType; | ||||
| 	uint8_t _hardSectorId; | ||||
| }; | ||||
|  | ||||
| class NorthstarEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	NorthstarEncoder(const NorthstarEncoderProto& config): | ||||
| 		_config(config) | ||||
| 	{} | ||||
|  | ||||
| 	virtual ~NorthstarEncoder() {} | ||||
| 	std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors); | ||||
|  | ||||
| private: | ||||
| 	const NorthstarEncoderProto& _config; | ||||
| }; | ||||
|  | ||||
| extern FlagGroup northstarEncoderFlags; | ||||
| extern uint8_t northstarChecksum(const Bytes& bytes); | ||||
|  | ||||
| #endif /* NORTHSTAR */ | ||||
							
								
								
									
										5
									
								
								arch/northstar/northstar.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								arch/northstar/northstar.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message NorthstarDecoderProto {} | ||||
| message NorthstarEncoderProto {} | ||||
|  | ||||
| @@ -40,7 +40,7 @@ const FluxPattern DATA_RECORD_PATTERN(32, 0x11112245); | ||||
|  | ||||
| const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN }); | ||||
|  | ||||
| AbstractDecoder::RecordType TiDs990Decoder::advanceToNextRecord() | ||||
| AbstractDecoder::RecordType Tids990Decoder::advanceToNextRecord() | ||||
| { | ||||
| 	const FluxMatcher* matcher = nullptr; | ||||
| 	_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher); | ||||
| @@ -51,7 +51,7 @@ AbstractDecoder::RecordType TiDs990Decoder::advanceToNextRecord() | ||||
| 	return RecordType::UNKNOWN_RECORD; | ||||
| } | ||||
|  | ||||
| void TiDs990Decoder::decodeSectorRecord() | ||||
| void Tids990Decoder::decodeSectorRecord() | ||||
| { | ||||
|     auto bits = readRawBits(TIDS990_SECTOR_RECORD_SIZE*16); | ||||
|     auto bytes = decodeFmMfm(bits).slice(0, TIDS990_SECTOR_RECORD_SIZE); | ||||
| @@ -71,7 +71,7 @@ void TiDs990Decoder::decodeSectorRecord() | ||||
|         _sector->status = Sector::DATA_MISSING; /* correct but unintuitive */ | ||||
| } | ||||
|  | ||||
| void TiDs990Decoder::decodeDataRecord() | ||||
| void Tids990Decoder::decodeDataRecord() | ||||
| { | ||||
| 	auto bits = readRawBits(TIDS990_DATA_RECORD_SIZE*16); | ||||
| 	auto bytes = decodeFmMfm(bits).slice(0, TIDS990_DATA_RECORD_SIZE); | ||||
|   | ||||
| @@ -6,55 +6,9 @@ | ||||
| #include "crc.h" | ||||
| #include "sectorset.h" | ||||
| #include "writer.h" | ||||
| #include "arch/tids990/tids990.pb.h" | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| FlagGroup tids990EncoderFlags; | ||||
|  | ||||
| static IntFlag trackLengthMs( | ||||
| 	{ "--tids990-track-length-ms" }, | ||||
| 	"Length of a track in milliseconds.", | ||||
| 	166); | ||||
|  | ||||
| static IntFlag sectorCount( | ||||
| 	{ "--tids990-sector-count" }, | ||||
| 	"Number of sectors per track.", | ||||
| 	26); | ||||
|  | ||||
| static IntFlag clockRateKhz( | ||||
| 	{ "--tids990-clock-rate-khz" }, | ||||
| 	"Clock rate of data to write.", | ||||
| 	500); | ||||
|  | ||||
| static HexIntFlag am1Byte( | ||||
| 	{ "--tids990-am1-byte" }, | ||||
| 	"16-bit RAW bit pattern to use for the AM1 ID byte", | ||||
| 	0x2244); | ||||
|  | ||||
| static HexIntFlag am2Byte( | ||||
| 	{ "--tids990-am2-byte" }, | ||||
| 	"16-bit RAW bit pattern to use for the AM2 ID byte", | ||||
| 	0x2245); | ||||
|  | ||||
| static IntFlag gap1( | ||||
| 	{ "--tids990-gap1-bytes" }, | ||||
| 	"Size of gap 1 (the post-index gap).", | ||||
| 	80); | ||||
|  | ||||
| static IntFlag gap2( | ||||
| 	{ "--tids990-gap2-bytes" }, | ||||
| 	"Size of gap 2 (the post-ID gap).", | ||||
| 	21); | ||||
|  | ||||
| static IntFlag gap3( | ||||
| 	{ "--tids990-gap3-bytes" }, | ||||
| 	"Size of gap 3 (the post-data or format gap).", | ||||
| 	51); | ||||
|  | ||||
| static StringFlag sectorSkew( | ||||
| 	{ "--tids990-sector-skew" }, | ||||
| 	"Order to emit sectors.", | ||||
| 	"1mhc72nid83oje94pkfa50lgb6"); | ||||
|  | ||||
| static int charToInt(char c) | ||||
| { | ||||
| 	if (isdigit(c)) | ||||
| @@ -62,7 +16,7 @@ static int charToInt(char c) | ||||
| 	return 10 + tolower(c) - 'a'; | ||||
| } | ||||
|  | ||||
| void TiDs990Encoder::writeRawBits(uint32_t data, int width) | ||||
| void Tids990Encoder::writeRawBits(uint32_t data, int width) | ||||
| { | ||||
| 	_cursor += width; | ||||
| 	_lastBit = data & 1; | ||||
| @@ -75,12 +29,12 @@ void TiDs990Encoder::writeRawBits(uint32_t data, int width) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void TiDs990Encoder::writeBytes(const Bytes& bytes) | ||||
| void Tids990Encoder::writeBytes(const Bytes& bytes) | ||||
| { | ||||
| 	encodeMfm(_bits, _cursor, bytes, _lastBit); | ||||
| } | ||||
|  | ||||
| void TiDs990Encoder::writeBytes(int count, uint8_t byte) | ||||
| void Tids990Encoder::writeBytes(int count, uint8_t byte) | ||||
| { | ||||
| 	Bytes bytes = { byte }; | ||||
| 	for (int i=0; i<count; i++) | ||||
| @@ -95,25 +49,25 @@ static uint8_t decodeUint16(uint16_t raw) | ||||
| 	return decodeFmMfm(b.toBits())[0]; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> TiDs990Encoder::encode( | ||||
| std::unique_ptr<Fluxmap> Tids990Encoder::encode( | ||||
| 	int physicalTrack, int physicalSide, const SectorSet& allSectors) | ||||
| { | ||||
| 	double clockRateUs = 1e3 / clockRateKhz / 2.0; | ||||
| 	int bitsPerRevolution = (trackLengthMs * 1000.0) / clockRateUs; | ||||
| 	double clockRateUs = 1e3 / _config.clock_rate_khz() / 2.0; | ||||
| 	int bitsPerRevolution = (_config.track_length_ms() * 1000.0) / clockRateUs; | ||||
| 	_bits.resize(bitsPerRevolution); | ||||
| 	_cursor = 0; | ||||
|  | ||||
| 	uint8_t am1Unencoded = decodeUint16(am1Byte); | ||||
| 	uint8_t am2Unencoded = decodeUint16(am2Byte); | ||||
| 	uint8_t am1Unencoded = decodeUint16(_config.am1_byte()); | ||||
| 	uint8_t am2Unencoded = decodeUint16(_config.am2_byte()); | ||||
|  | ||||
| 	writeBytes(gap1, 0x55); | ||||
| 	writeBytes(_config.gap1_bytes(), 0x55); | ||||
|  | ||||
| 	bool first = true; | ||||
| 	for (char sectorChar : sectorSkew.get()) | ||||
| 	for (char sectorChar : _config.sector_skew()) | ||||
| 	{ | ||||
| 		int sectorId = charToInt(sectorChar); | ||||
| 		if (!first) | ||||
| 			writeBytes(gap3, 0x55); | ||||
| 			writeBytes(_config.gap3_bytes(), 0x55); | ||||
| 		first = false; | ||||
|  | ||||
| 		const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId); | ||||
| @@ -136,17 +90,17 @@ std::unique_ptr<Fluxmap> TiDs990Encoder::encode( | ||||
| 			bw.write_8(am1Unencoded); | ||||
| 			bw.write_8(sectorData->logicalSide << 3); | ||||
| 			bw.write_8(sectorData->logicalTrack); | ||||
| 			bw.write_8(sectorCount); | ||||
| 			bw.write_8(_config.sector_count()); | ||||
| 			bw.write_8(sectorData->logicalSector); | ||||
| 			bw.write_be16(sectorData->data.size()); | ||||
| 			uint16_t crc = crc16(CCITT_POLY, header); | ||||
| 			bw.write_be16(crc); | ||||
|  | ||||
| 			writeRawBits(am1Byte, 16); | ||||
| 			writeRawBits(_config.am1_byte(), 16); | ||||
| 			writeBytes(header.slice(1)); | ||||
| 		} | ||||
|  | ||||
| 		writeBytes(gap2, 0x55); | ||||
| 		writeBytes(_config.gap2_bytes(), 0x55); | ||||
|  | ||||
| 		{ | ||||
| 			Bytes data; | ||||
| @@ -159,7 +113,7 @@ std::unique_ptr<Fluxmap> TiDs990Encoder::encode( | ||||
| 			uint16_t crc = crc16(CCITT_POLY, data); | ||||
| 			bw.write_be16(crc); | ||||
|  | ||||
| 			writeRawBits(am2Byte, 16); | ||||
| 			writeRawBits(_config.am2_byte(), 16); | ||||
| 			writeBytes(data.slice(1)); | ||||
| 		} | ||||
|     } | ||||
|   | ||||
| @@ -9,21 +9,27 @@ class Sector; | ||||
| class SectorSet; | ||||
| class Fluxmap; | ||||
| class Track; | ||||
| class Tids990DecoderProto; | ||||
| class Tids990EncoderProto; | ||||
|  | ||||
| class TiDs990Decoder : public AbstractDecoder | ||||
| class Tids990Decoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
|     virtual ~TiDs990Decoder() {} | ||||
| 	Tids990Decoder(const Tids990DecoderProto&) {} | ||||
|     virtual ~Tids990Decoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|     void decodeSectorRecord(); | ||||
| 	void decodeDataRecord(); | ||||
| }; | ||||
|  | ||||
| class TiDs990Encoder : public AbstractEncoder | ||||
| class Tids990Encoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	virtual ~TiDs990Encoder() {} | ||||
| 	Tids990Encoder(const Tids990EncoderProto& config): | ||||
| 		_config(config) | ||||
| 	{} | ||||
| 	virtual ~Tids990Encoder() {} | ||||
|  | ||||
| private: | ||||
| 	void writeRawBits(uint32_t data, int width); | ||||
| @@ -35,6 +41,7 @@ public: | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors); | ||||
|  | ||||
| private: | ||||
| 	const Tids990EncoderProto& _config; | ||||
| 	std::vector<bool> _bits; | ||||
| 	unsigned _cursor; | ||||
| 	bool _lastBit; | ||||
|   | ||||
							
								
								
									
										26
									
								
								arch/tids990/tids990.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								arch/tids990/tids990.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message Tids990DecoderProto {} | ||||
| message Tids990EncoderProto { | ||||
| 	optional double track_length_ms = 1 [ default = 166, | ||||
| 		(help) = "length of a track" ]; | ||||
| 	optional int32 sector_count = 2 [ default = 26, | ||||
| 		(help) = "number of sectors per track" ]; | ||||
| 	optional double clock_rate_khz = 3 [ default = 500, | ||||
| 		(help) = "clock rate of data to write" ]; | ||||
| 	optional int32 am1_byte = 4 [ default = 0x2244, | ||||
| 		(help) = "16-bit RAW bit pattern to use for the AM1 ID byte" ]; | ||||
| 	optional int32 am2_byte = 5 [ default = 0x2245, | ||||
| 		(help) = "16-bit RAW bit pattern to use for the AM2 ID byte" ]; | ||||
| 	optional int32 gap1_bytes = 6 [ default = 80, | ||||
| 		(help) = "size of gap 1 (the post-index gap)" ]; | ||||
| 	optional int32 gap2_bytes = 7 [ default = 21, | ||||
| 		(help) = "size of gap 2 (the post-ID gap)" ]; | ||||
| 	optional int32 gap3_bytes = 8 [ default = 51, | ||||
| 		(help) = "size of gap 3 (the post-data or format gap)" ]; | ||||
| 	optional string sector_skew = 9 [ default = "1mhc72nid83oje94pkfa50lgb6", | ||||
| 		(help) = "order to emit sectors" ]; | ||||
| } | ||||
|  | ||||
| @@ -8,10 +8,12 @@ | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class Victor9kDecoderProto; | ||||
|  | ||||
| class Victor9kDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	Victor9kDecoder(const Victor9kDecoderProto&) {} | ||||
|     virtual ~Victor9kDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/victor9k/victor9k.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/victor9k/victor9k.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message Victor9kDecoderProto {} | ||||
|  | ||||
| @@ -3,10 +3,12 @@ | ||||
|  | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| class ZilogMczDecoderProto; | ||||
|  | ||||
| class ZilogMczDecoder : public AbstractDecoder | ||||
| { | ||||
| public: | ||||
| 	ZilogMczDecoder(const ZilogMczDecoderProto&) {} | ||||
|     virtual ~ZilogMczDecoder() {} | ||||
|  | ||||
|     RecordType advanceToNextRecord(); | ||||
|   | ||||
							
								
								
									
										4
									
								
								arch/zilogmcz/zilogmcz.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								arch/zilogmcz/zilogmcz.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| message ZilogMczDecoderProto {} | ||||
|  | ||||
| @@ -50,7 +50,7 @@ namespace agg | ||||
|         template<class FilterF> void calculate(const FilterF& filter, | ||||
|                                                bool normalization=true) | ||||
|         { | ||||
| 			filter; // prevent erroneous C4100 in MSVC | ||||
| 			(void)filter; // prevent erroneous C4100 in MSVC | ||||
|             double r = filter.radius(); | ||||
|             realloc_lut(r); | ||||
|             unsigned i; | ||||
|   | ||||
							
								
								
									
										49
									
								
								dep/snowhouse/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								dep/snowhouse/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| cmake_minimum_required(VERSION 3.1) | ||||
|  | ||||
| project(snowhouse) | ||||
|  | ||||
| option(SNOWHOUSE_BUILD_TESTS    "Build the Snowhouse tests"                 OFF) | ||||
| option(SNOWHOUSE_RUN_TESTS      "Run the Snowhouse tests"                   OFF) | ||||
| set(SNOWHOUSE_CXX_STANDARD "C++11" CACHE STRING "The C++ standard the examples are compiled with") | ||||
| set_property(CACHE SNOWHOUSE_CXX_STANDARD PROPERTY STRINGS "C++11" "C++14" "C++17") | ||||
|  | ||||
| add_library(snowhouse INTERFACE) | ||||
| target_include_directories(snowhouse INTERFACE include) | ||||
|  | ||||
| if(SNOWHOUSE_CXX_STANDARD STREQUAL "C++11") | ||||
|   set(CMAKE_CXX_STANDARD 11) | ||||
| elseif(SNOWHOUSE_CXX_STANDARD STREQUAL "C++14") | ||||
|   set(CMAKE_CXX_STANDARD 14) | ||||
| elseif(SNOWHOUSE_CXX_STANDARD STREQUAL "C++17") | ||||
|   set(CMAKE_CXX_STANDARD 17) | ||||
| else() | ||||
|   message(WARNING "C++ standard \"${SNOWHOUSE_CXX_STANDARD}\" not known, falling back to default") | ||||
| endif() | ||||
|  | ||||
| set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./bin) | ||||
|  | ||||
| if (MSVC) | ||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /MP ") | ||||
| else() | ||||
|   # Assume GCC-style arguments | ||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ | ||||
|     -Wall -Wextra -pedantic -Wdeprecated -Wdeprecated-declarations -Wnon-virtual-dtor \ | ||||
|     -Wshadow -Wfloat-equal -Wundef -Wendif-labels -Wno-error=unknown-pragmas") | ||||
| endif() | ||||
|  | ||||
| message(STATUS "C++ compiler flags: ${CMAKE_CXX_FLAGS}") | ||||
|  | ||||
| if (SNOWHOUSE_BUILD_TESTS) | ||||
|     FILE(GLOB SnowhouseSpecSourceFiles example/*.cpp) | ||||
|     add_executable(snowhouse-tests ${SnowhouseSpecSourceFiles}) | ||||
|     target_link_libraries(snowhouse-tests PRIVATE snowhouse) | ||||
| endif() | ||||
|  | ||||
| if (SNOWHOUSE_BUILD_TESTS AND SNOWHOUSE_RUN_TESTS) | ||||
|     add_custom_command(TARGET snowhouse-tests | ||||
|                        POST_BUILD | ||||
|                        COMMAND snowhouse-tests | ||||
|                        WORKING_DIRECTORY ./bin) | ||||
| elseif (SNOWHOUSE_RUN_TESTS) | ||||
|     message(WARNING "Unable to run snowhouse tests - set:\n  option(SNOWHOUSE_BUILD_TESTS, \"Build the Snowhouse tests\" ON)\nand clear your CMakeCache.txt") | ||||
| endif() | ||||
							
								
								
									
										23
									
								
								dep/snowhouse/LICENSE_1_0.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								dep/snowhouse/LICENSE_1_0.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| Boost Software License - Version 1.0 - August 17th, 2003 | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person or organization | ||||
| obtaining a copy of the software and accompanying documentation covered by | ||||
| this license (the "Software") to use, reproduce, display, distribute, | ||||
| execute, and transmit the Software, and to prepare derivative works of the | ||||
| Software, and to permit third-parties to whom the Software is furnished to | ||||
| do so, all subject to the following: | ||||
|  | ||||
| The copyright notices in the Software and this entire statement, including | ||||
| the above license grant, this restriction and the following disclaimer, | ||||
| must be included in all copies of the Software, in whole or in part, and | ||||
| all derivative works of the Software, unless such copies or derivative | ||||
| works are solely in the form of machine-executable object code generated by | ||||
| a source language processor. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||||
| SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||||
| FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||||
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||||
| DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										560
									
								
								dep/snowhouse/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										560
									
								
								dep/snowhouse/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,560 @@ | ||||
| snowhouse | ||||
| ========= | ||||
| [](https://travis-ci.org/banditcpp/snowhouse) | ||||
| [](https://ci.appveyor.com/project/banditcpp/snowhouse) | ||||
| [](https://github.com/banditcpp/snowhouse/actions?query=workflow%3ACI+branch%3Amaster) | ||||
| [](https://www.codacy.com/app/sbeyer/snowhouse?utm_source=github.com&utm_medium=referral&utm_content=banditcpp/snowhouse&utm_campaign=Badge_Grade) | ||||
|  | ||||
| An assertion library for C++ | ||||
|  | ||||
| Snowhouse is a stand-alone assertion framework for C++. | ||||
| It is a header-only library. | ||||
|  | ||||
| Snowhouse requires a C++11-compatible compiler since version 5.0.0. | ||||
| Feel free to use Snowhouse with major version 4 if you want to use it | ||||
| in a pre-C++11 setting. | ||||
| Major version 4 is still maintained in the `maint-v4` branch (bug fixes, etc.). | ||||
|  | ||||
| For inclusion in your projects, you have several options: | ||||
|  | ||||
| a) You can copy the code and just use it as the license allows. | ||||
|  | ||||
| b) You can use the `headers-only` branch as a submodule: | ||||
|  | ||||
| ```sh | ||||
| git submodule add -b headers-only https://github.com/banditcpp/snowhouse snowhouse | ||||
| git submodule update --init --recursive | ||||
| ``` | ||||
|  | ||||
| c) If you use CMake >= 3.1 in your project, | ||||
| you can use Snowhouse with the provided library target. | ||||
| Assuming you have cloned the `master` branch into a `snowhouse` subdirectory, | ||||
| your `CMakeLists.txt` might contain lines like the following: | ||||
|  | ||||
| ```cmake | ||||
| add_subdirectory(snowhouse) | ||||
| add_executable(app main.cpp) | ||||
| target_link_libraries(app snowhouse) | ||||
| ``` | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| ```C++ | ||||
| #include <snowhouse/snowhouse.h> | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   std::cout << "Testing that 23 is 23" << std::endl; | ||||
|   AssertThat(23, Is().EqualTo(23)); | ||||
|  | ||||
|   try | ||||
|   { | ||||
|     AssertThat(12, Is().LessThan(11).And().GreaterThan(99)); | ||||
|   } | ||||
|   catch (const AssertionException& ex) | ||||
|   { | ||||
|     std::cout << "Apparently this failed:" << std::endl; | ||||
|     std::cout << ex.what() << std::endl; | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### Assertions | ||||
|  | ||||
| Snowhouse uses a constraint-based assertion model that is heavily inspired by the | ||||
| model used in [NUnit](http://nunit.org/). An assertion in Snowhouse is written | ||||
| using the following format: | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(actual_value, <constraint expression>); | ||||
| ``` | ||||
|  | ||||
| where `<constraint expression>` is an expression that `actual_value` is | ||||
| evaluated against when the test is executed. | ||||
|  | ||||
| Constraint expressions come in two basic forms: composite and fluent expressions. | ||||
|  | ||||
| #### Composite Expressions | ||||
|  | ||||
| With composite expressions, you can create compact, powerful expressions that | ||||
| combine a set of predefined constraints with ones that you provide yourself. | ||||
|  | ||||
| Example: | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(length, IsGreaterThan(4) && !Equals(10)); | ||||
| ``` | ||||
|  | ||||
| Composite expressions can be any combination of constraints and the | ||||
| standard logical C++ operators. | ||||
|  | ||||
| You can also add your own constraints to be used within composite expressions. | ||||
|  | ||||
| #### Fluent Expressions | ||||
|  | ||||
| With fluent expressions, you can create assertions that better convey the intent | ||||
| of a test without exposing implementation-specific details. | ||||
| Fluent expressions aim to help you create tests that are not just by developers | ||||
| for developers, but rather can be read and understood by domain experts. | ||||
|  | ||||
| Fluent expressions also have the ability to make assertions on the elements in a | ||||
| container in a way you cannot achieve with composite expressions. | ||||
|  | ||||
| Example: | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(length, Is().GreaterThan(4).And().Not().EqualTo(10)); | ||||
| ``` | ||||
|  | ||||
| ### Basic Constraints | ||||
|  | ||||
| #### Equality Constraint | ||||
|  | ||||
| Used to verify equality between actual and expected. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(x, Equals(12)); | ||||
| AssertThat(x, Is().EqualTo(12)); | ||||
| ``` | ||||
|  | ||||
| #### EqualityWithDelta Constraint | ||||
|  | ||||
| Used to verify equality between actual and expected, | ||||
| allowing the two to differ by a delta. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(2.49, EqualsWithDelta(2.5, 0.1)); | ||||
| AssertThat(2.49, Is().EqualToWithDelta(2.5, 0.1)); | ||||
| ``` | ||||
|  | ||||
| #### GreaterThan Constraint | ||||
|  | ||||
| Used to verify that actual is greater than a value. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(x, IsGreaterThan(4)); | ||||
| AssertThat(x, Is().GreaterThan(4)); | ||||
| ``` | ||||
|  | ||||
| #### LessThan Constraint | ||||
|  | ||||
| Used to verify that actual is less than a value. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(x, IsLessThan(3)); | ||||
| AssertThat(x, Is().LessThan(3)); | ||||
| ``` | ||||
|  | ||||
| #### GreaterThanOrEqualTo Constraint | ||||
|  | ||||
| Used to verify that actual is greater than or equal to a value. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(x, IsGreaterThanOrEqualTo(5)); | ||||
| AssertThat(x, Is().GreaterThanOrEqualTo(5)); | ||||
| ``` | ||||
|  | ||||
| #### LessThanOrEqualTo Constraint | ||||
|  | ||||
| Used to verify that actual is less than or equal to a value. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(x, IsLessThanOrEqualTo(6)); | ||||
| AssertThat(x, Is().LessThanOrEqualTo(6)); | ||||
| ``` | ||||
|  | ||||
| ### Pointer Constraints | ||||
|  | ||||
| Used to check for `nullptr` equality. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(x, IsNull()); | ||||
| AssertThat(x, Is().Null()); | ||||
| ``` | ||||
|  | ||||
| ### String Constraints | ||||
|  | ||||
| String assertions in Snowhouse are used to verify the values of | ||||
| STL strings (`std::string`). | ||||
|  | ||||
| #### Equality Constraints | ||||
|  | ||||
| Used to verify that actual is equal to an expected value. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(actual_str, Equals("foo")); | ||||
| AssertThat(actual_str, Is().EqualTo("foo")); | ||||
| ``` | ||||
|  | ||||
| #### Contains Constraint | ||||
|  | ||||
| Used to verify that a string contains a substring. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(actual_str, Contains("foo")); | ||||
| AssertThat(actual_str, Is().Containing("foo")); | ||||
| ``` | ||||
|  | ||||
| #### EndsWith Constraint | ||||
|  | ||||
| Used to verify that a string ends with an expected substring. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(actual_str, EndsWith("foo")); | ||||
| AssertThat(actual_str, Is().EndingWith("foo")); | ||||
| ``` | ||||
|  | ||||
| #### StartsWith Constraint | ||||
|  | ||||
| Used to verify that a string starts with an expected substring. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(actual_str, StartsWith("foo")); | ||||
| AssertThat(actual_str, Is().StartingWith("foo")); | ||||
| ``` | ||||
|  | ||||
| #### HasLength Constraint | ||||
|  | ||||
| Used to verify that a string is of the expected length. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(actual_str, HasLength(5)); | ||||
| AssertThat(actual_str, Is().OfLength(5)); | ||||
| ``` | ||||
|  | ||||
| ### Constraints on Multiline Strings | ||||
|  | ||||
| If you have a string that contains multiple lines, you can use the collection | ||||
| constraints to make assertions on the content of that string. | ||||
| This may be handy if you have a string that, for instance, represents the | ||||
| resulting content of a file or a network transmission. | ||||
|  | ||||
| Snowhouse can handle both Windows (CR+LF) and Unix (LF) line endings. | ||||
|  | ||||
| ```cpp | ||||
| std::string lines = "First line\r\nSecond line\r\nThird line"; | ||||
| AssertThat(lines, Has().Exactly(1).StartingWith("Second")); | ||||
| ``` | ||||
|  | ||||
| ### Container Constraints | ||||
|  | ||||
| The following constraints can be applied to containers in the standard template library. | ||||
|  | ||||
| #### Contains Constraint | ||||
|  | ||||
| Used to verify that a container contains an expected value. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, Contains(12)); | ||||
| AssertThat(container, Is().Containing(12)); | ||||
| ``` | ||||
|  | ||||
| #### HasLength Constraint | ||||
|  | ||||
| Used to verify that a container has the expected length. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, HasLength(3)); | ||||
| AssertThat(container, Is().OfLength(3)); | ||||
| ``` | ||||
|  | ||||
| #### IsEmpty Constraint | ||||
|  | ||||
| Used to verify that a container is empty. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, IsEmpty()); | ||||
| AssertThat(container, Is().Empty()); | ||||
| ``` | ||||
|  | ||||
| #### All | ||||
|  | ||||
| Used to verify that all elements of a STL sequence container matches an expectation. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, Has().All().LessThan(5).Or().EqualTo(66)); | ||||
| ``` | ||||
|  | ||||
| #### AtLeast | ||||
|  | ||||
| Used to verify that at least a specified amount of elements in a STL sequence | ||||
| container matches an expectation. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, Has().AtLeast(3).StartingWith("foo")); | ||||
| ``` | ||||
|  | ||||
| #### AtMost | ||||
|  | ||||
| Used to verify that at most a specified amount of elements in a STL sequence | ||||
| container matches an expectation. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, Has().AtMost(2).Not().Containing("failed")); | ||||
| ``` | ||||
|  | ||||
| #### Exactly | ||||
|  | ||||
| Used to verify that a STL sequence container has exactly a specified amount | ||||
| of elements that matches an expectation. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container, Has().Exactly(3).GreaterThan(10).And().LessThan(20)); | ||||
| ``` | ||||
|  | ||||
| #### EqualsContainer | ||||
|  | ||||
| Used to verify that two STL sequence containers are equal. | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(container1, EqualsContainer(container2)); | ||||
| AssertThat(container1, Is().EqualToContainer(container2)); | ||||
| ``` | ||||
|  | ||||
| ##### Predicate functions | ||||
|  | ||||
| You can supply a predicate function or a functor to `EqualsContainer` to | ||||
| customize how to compare the elements in the two containers. | ||||
|  | ||||
| With a predicate function: | ||||
|  | ||||
| ```cpp | ||||
| static bool are_my_types_equal(const my_type& lhs, const my_type& rhs) | ||||
| { | ||||
|   return lhs.my_val_ == rhs.my_val_; | ||||
| } | ||||
|  | ||||
| AssertThat(container1, EqualsContainer(container2, are_my_types_equal)); | ||||
| ``` | ||||
|  | ||||
| With a functor as predicate: | ||||
|  | ||||
| ```cpp | ||||
| struct within_delta | ||||
| { | ||||
|   within_delta(int delta) : delta_(delta) {} | ||||
|  | ||||
|   bool operator()(const my_type& lhs, const my_type& rhs) const | ||||
|   { | ||||
|     return abs(lhs.my_val_ - rhs.my_val_) <= delta_; | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   int delta_; | ||||
| }; | ||||
|  | ||||
| AssertThat(container1, Is().EqualToContainer(container1, within_delta(1)); | ||||
| ``` | ||||
|  | ||||
| ### Exceptions | ||||
|  | ||||
| Exception constraints can be used to verify that your code throws the correct exceptions. | ||||
|  | ||||
| #### AssertThrows | ||||
|  | ||||
| `AssertThrows` succeeds if the exception thrown by the call is of the supplied | ||||
| type (or one of its subtypes). | ||||
|  | ||||
| ```cpp | ||||
| AssertThrows(std::logic_error, myObject.a_method(42)); | ||||
| ``` | ||||
|  | ||||
| #### Making Assertions on the Thrown Exceptions | ||||
|  | ||||
| If `AssertThrows` succeeds, it will store the thrown exception so that you can | ||||
| make more detailed assertions on it. | ||||
|  | ||||
| ```cpp | ||||
| AssertThrows(std::logic_error, myObject.a_method(42)); | ||||
| AssertThat(LastException<std::logic_error>().what(), Is().Containing("logic failure")); | ||||
| ``` | ||||
|  | ||||
| The `LastException<>` is available in the scope of the call to `AssertThrows`. | ||||
| An exception is not available between specs in order to avoid the result of | ||||
| one spec contaminating another. | ||||
|  | ||||
| ### Custom Constraints | ||||
|  | ||||
| You can add your own constraints to Snowhouse to create more expressive specifications. | ||||
|  | ||||
| #### Fulfills Constraints | ||||
|  | ||||
| By defining the following matcher | ||||
|  | ||||
| ```cpp | ||||
| struct IsEvenNumber | ||||
| { | ||||
|   bool Matches(const int actual) const | ||||
|   { | ||||
|     return (actual % 2) == 0; | ||||
|   } | ||||
|  | ||||
|   friend std::ostream& operator<<(std::ostream& stm, const IsEvenNumber& ); | ||||
| }; | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& stm, const IsEvenNumber& ) | ||||
| { | ||||
|   stm << "An even number"; | ||||
|   return stm; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| You can create the following constraints in Snowhouse: | ||||
|  | ||||
| ```cpp | ||||
| AssertThat(42, Fulfills(IsEvenNumber())); | ||||
| AssertThat(42, Is().Fulfilling(IsEvenNumber())); | ||||
| ``` | ||||
|  | ||||
| Your custom matcher should implement a method called `Matches()` that takes | ||||
| a parameter of the type you expect and returns true if the passed parameter | ||||
| fulfills the constraint. | ||||
|  | ||||
| To get more expressive failure messages, you should also implement the | ||||
| streaming operator as in the example above. | ||||
|  | ||||
| ## Getting better output for your types | ||||
|  | ||||
| Whenever Snowhouse prints an error message for a type, it will use the | ||||
| stream operator for that type, otherwise it will print "[unsupported type]" | ||||
| as a placeholder. | ||||
|  | ||||
| ```cpp | ||||
| struct MyType { int x; char c; }; | ||||
|  | ||||
| AssertThat(myType, Fulfills(MyConstraint()); | ||||
| ``` | ||||
|  | ||||
| Will output the following if the constraint fails: | ||||
|  | ||||
| ``` | ||||
| Expected: To fulfill my constraint | ||||
| Actual: [unsupported type] | ||||
| ``` | ||||
|  | ||||
| If we add a stream operator: | ||||
|  | ||||
| ```cpp | ||||
| std::ostream& operator<<(std::ostream& stream, const MyType& a) | ||||
| { | ||||
|   stream << a.c << a.x; | ||||
|   return stream; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| the output will be a bit more readable: | ||||
|  | ||||
| ``` | ||||
| Expected: To fulfill my constraint | ||||
| Actual: f23 | ||||
| ``` | ||||
|  | ||||
| If it is necessary to print an object in a different manner than the | ||||
| usual output stream operator provides, for example, to output more detailed | ||||
| information, we can use a specialization of the `Stringizer` class template: | ||||
|  | ||||
| ```cpp | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<> | ||||
|   struct Stringizer<MyType> | ||||
|   { | ||||
|     static std::string ToString(const MyType& a) | ||||
|     { | ||||
|       std::stringstream stream; | ||||
|       stream << "MyType(x = " << a.x << ", c = " << int(a.c) << "('" << a.c << "'))"; | ||||
|       return stream.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| with output: | ||||
|  | ||||
| ``` | ||||
| Expected: To fulfill my constraint | ||||
| Actual: MyType(x = 23, c = 102('f')) | ||||
| ``` | ||||
|  | ||||
| ## Configurable Failure Handlers | ||||
|  | ||||
| You can provide Snowhouse with custom failure handlers, for example to | ||||
| call `std::terminate` instead of throwing an exception. | ||||
| See `DefaultFailureHandler` for an example of a failure handler. | ||||
| You can derive your own macros with custom failure handlers using | ||||
| `SNOWHOUSE_ASSERT_THAT` and `SNOWHOUSE_ASSERT_THROWS`. | ||||
| See the definitions of `AssertThat` and `AssertThrows` for examples of these. | ||||
| Define `SNOWHOUSE_NO_MACROS` to disable the unprefixed macros `AssertThat` | ||||
| and `AssertThrows`. | ||||
|  | ||||
| ### Example Use Cases | ||||
|  | ||||
| #### Assert Program State | ||||
|  | ||||
| Log an error immediately as we may crash if we try to continue. | ||||
| Do not attempt to unwind the stack as we may be inside a destructor | ||||
| or `nothrow` function. | ||||
| We may want to call `std::terminate`, or attempt to muddle along | ||||
| with the rest of the program. | ||||
|  | ||||
| #### Assert Program State in Safe Builds | ||||
|  | ||||
| As above, but only in debug builds. | ||||
|  | ||||
| #### Test Assert | ||||
|  | ||||
| Assert that a test behaved as expected. | ||||
| Throw an exception and let our testing framework deal with the test failure. | ||||
|  | ||||
| ## Versioning | ||||
|  | ||||
| Snowhouse uses [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html) since | ||||
| version 3.0.0. | ||||
|  | ||||
| The macros `SNOWHOUSE_MAJOR`, `SNOWHOUSE_MINOR` and `SNOWHOUSE_PATCH` are defined | ||||
| accordingly and `SNOWHOUSE_VERSION` contains the version string. | ||||
| Note that in prior versions `SNOWHOUSE_VERSION` was the only defined macro. | ||||
|  | ||||
| Compatibility-breaking changes since version 3.0.0: | ||||
|  | ||||
|  * Since version 4.0.0, the display of booleans and strings has changed. | ||||
|    Booleans are now displayed as `true` or `false`. | ||||
|    Strings are put into quotation marks for improved readability. | ||||
|  | ||||
|  * Since version 5.0.0, the support for C++ versions prior to C++11 are dropped. | ||||
|    The definition of the macro `SNOWHOUSE_HAS_NULLPTR` is removed. | ||||
|    Our exceptions are now derived from the `std::exception` hierarchy, | ||||
|    thus their method names changed. | ||||
|  | ||||
| ## Contributing | ||||
|  | ||||
| The development of Snowhouse takes place on [GitHub](//github.com/banditcpp/snowhouse). | ||||
|  | ||||
| Snowhouse is licensed under the Boost Software License. | ||||
| See LICENSE_1_0.txt for further information. | ||||
|  | ||||
| By making available code for inclusion into Snowhouse (e.g., by opening a | ||||
| pull request on GitHub), you guarantee that the code is licensed under the | ||||
| same license as Snowhouse. | ||||
|  | ||||
| Please make sure to be consistent with the project's coding style. | ||||
| The `.clang-format` file allows easy checking and implementation of the | ||||
| coding style. | ||||
|  | ||||
| C++ code should comply to C++11. | ||||
| Please use `__cplusplus` guards if you want to use language features of | ||||
| a certain C++ version. | ||||
|  | ||||
| ## Responsibilities | ||||
|  | ||||
| Snowhouse was originally developed as part of the [Igloo](//github.com/joakimkarlsson/igloo) | ||||
| testing framework by [Joakim Karlsson](//github.com/joakimkarlsson). | ||||
| It has been extracted to be usable in other contexts, for example, | ||||
| [Bandit](//github.com/banditcpp/bandit). | ||||
|  | ||||
| Snowhouse is maintained by [Stephan Beyer](//github.com/sbeyer) since | ||||
| [October 2016](//twitter.com/JHKarlsson/status/789332548799332352). | ||||
							
								
								
									
										222
									
								
								dep/snowhouse/example/basic_assertions.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								dep/snowhouse/example/basic_assertions.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | ||||
| #include <stdexcept> | ||||
|  | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| static void throwRuntimeError() | ||||
| { | ||||
|   throw std::runtime_error("This is expected"); | ||||
| } | ||||
|  | ||||
| struct IgnoreErrors | ||||
| { | ||||
|   template<typename ExpectedType, typename ActualType> | ||||
|   static void Handle(const ExpectedType&, const ActualType&, const char*, int) | ||||
|   { | ||||
|   } | ||||
|  | ||||
|   static void Handle(const std::string&) | ||||
|   { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| void BasicAssertions() | ||||
| { | ||||
|   describe("Basic assertions"); | ||||
|  | ||||
|   it("handles integer equality"); | ||||
|   { | ||||
|     AssertThat(5, Is().EqualTo(5)); | ||||
|   } | ||||
|  | ||||
|   it("detects integer inequality"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, Is().EqualTo(4)), "equal to 4"); | ||||
|   } | ||||
|  | ||||
|   it("detects if Not() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, Is().Not().EqualTo(5)), "Expected: not equal to 5\nActual: 5\n"); | ||||
|   } | ||||
|  | ||||
|   it("handles strings"); | ||||
|   { | ||||
|     AssertThat(std::string("joakim"), Is().EqualTo(std::string("joakim"))); | ||||
|   } | ||||
|  | ||||
|   it("handles strings without explicit template specialization"); | ||||
|   { | ||||
|     AssertThat("kim", Is().EqualTo("kim")); | ||||
|   } | ||||
|  | ||||
|   it("handles GreaterThan()"); | ||||
|   { | ||||
|     AssertThat(5, Is().GreaterThan(4)); | ||||
|   } | ||||
|  | ||||
|   it("detects when GreaterThan() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, Is().GreaterThan(5)), | ||||
|         "Expected: greater than 5\nActual: 5\n"); | ||||
|   } | ||||
|  | ||||
|   it("handles LessThan()"); | ||||
|   { | ||||
|     AssertThat(5, Is().LessThan(6)); | ||||
|   } | ||||
|  | ||||
|   it("detects when LessThan() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(6, Is().LessThan(5)), | ||||
|         "Expected: less than 5\nActual: 6\n"); | ||||
|   } | ||||
|  | ||||
|   it("throws explicit failure message"); | ||||
|   { | ||||
|     AssertTestFails(Assert::Failure("foo"), "foo"); | ||||
|   } | ||||
|  | ||||
|   it("contains location information"); | ||||
|   { | ||||
|     int line; | ||||
|     std::string file; | ||||
|  | ||||
|     try | ||||
|     { | ||||
|       Assert::That(5, Equals(2), "filename", 32); | ||||
|     } | ||||
|     catch (const AssertionException& e) | ||||
|     { | ||||
|       line = e.line(); | ||||
|       file = e.file(); | ||||
|     } | ||||
|  | ||||
|     AssertThat(line, Equals(32)); | ||||
|     AssertThat(file, Equals("filename")); | ||||
|   } | ||||
|  | ||||
|   it("ensures exception is thrown"); | ||||
|   { | ||||
|     AssertThrows(std::runtime_error, throwRuntimeError()); | ||||
|   } | ||||
|  | ||||
|   it("ignores the error"); | ||||
|   { | ||||
|     ConfigurableAssert<IgnoreErrors>::That(1, Equals(2)); | ||||
|   } | ||||
|  | ||||
|   describe("Assertion expression templates"); | ||||
|  | ||||
|   it("handles integer equality"); | ||||
|   { | ||||
|     AssertThat(5, Equals(5)); | ||||
|   } | ||||
|  | ||||
|   it("detects integer inequality"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, Equals(4)), "equal to 4"); | ||||
|   } | ||||
|  | ||||
|   it("detects if !Equals() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, !Equals(5)), | ||||
|         "Expected: not equal to 5\nActual: 5\n"); | ||||
|   } | ||||
|  | ||||
|   it("handles strings"); | ||||
|   { | ||||
|     AssertThat(std::string("joakim"), Equals(std::string("joakim"))); | ||||
|   } | ||||
|  | ||||
|   it("handles strings without explicit template specialization"); | ||||
|   { | ||||
|     AssertThat("kim", Equals("kim")); | ||||
|   } | ||||
|  | ||||
|   it("handles IsGreaterThan()"); | ||||
|   { | ||||
|     AssertThat(5, IsGreaterThan(4)); | ||||
|   } | ||||
|  | ||||
|   it("handles IsGreaterThanOrEqualTo()"); | ||||
|   { | ||||
|     AssertThat(4, IsGreaterThanOrEqualTo(4)); | ||||
|     AssertThat(5, IsGreaterThanOrEqualTo(4)); | ||||
|   } | ||||
|  | ||||
|   it("detects when IsGreaterThan() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, IsGreaterThan(5)), | ||||
|         "Expected: greater than 5\nActual: 5\n"); | ||||
|   } | ||||
|  | ||||
|   it("detects when IsGreaterThanOrEqualTo() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(4, IsGreaterThanOrEqualTo(5)), | ||||
|         "Expected: greater than or equal to 5\nActual: 4\n"); | ||||
|   } | ||||
|  | ||||
|   it("handles IsLessThan()"); | ||||
|   { | ||||
|     AssertThat(5, IsLessThan(6)); | ||||
|   } | ||||
|  | ||||
|   it("handles IsLessThanOrEqualTo()"); | ||||
|   { | ||||
|     AssertThat(5, IsLessThanOrEqualTo(6)); | ||||
|     AssertThat(6, IsLessThanOrEqualTo(6)); | ||||
|   } | ||||
|  | ||||
|   it("detects when IsLessThan() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(6, IsLessThan(5)), | ||||
|         "Expected: less than 5\nActual: 6\n"); | ||||
|   } | ||||
|  | ||||
|   it("detects when IsLessThanOrEqualTo() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(6, IsLessThanOrEqualTo(5)), | ||||
|         "Expected: less than or equal to 5\nActual: 6\n"); | ||||
|   } | ||||
|  | ||||
|   it("handles IsNull()"); | ||||
|   { | ||||
|     AssertThat(nullptr, IsNull()); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().Null()"); | ||||
|   { | ||||
|     AssertThat(nullptr, Is().Null()); | ||||
|   } | ||||
|  | ||||
|   it("handles !IsNull()"); | ||||
|   { | ||||
|     int anInt = 0; | ||||
|     AssertThat(&anInt, !IsNull()); | ||||
|   } | ||||
|  | ||||
|   it("detects when IsNull() fails (real address)"); | ||||
|   { | ||||
|     int anInt = 0; | ||||
|     std::ostringstream message; | ||||
|     message << "Expected: equal to nullptr\nActual: " << &anInt << "\n"; | ||||
|     AssertTestFails(AssertThat(&anInt, IsNull()), message.str()); | ||||
|   } | ||||
|  | ||||
|   it("detects when Is().Null() fails"); | ||||
|   { | ||||
|     int anInt = 0; | ||||
|     std::ostringstream message; | ||||
|     message << "Expected: equal to nullptr\nActual: " << &anInt << "\n"; | ||||
|     AssertTestFails(AssertThat(&anInt, Is().Null()), message.str()); | ||||
|   } | ||||
|  | ||||
|   it("detects when !IsNull() fails (nullptr)"); | ||||
|   { | ||||
|     std::ostringstream message; | ||||
|     message << "Expected: not equal to nullptr\nActual: nullptr\n"; | ||||
|  | ||||
|     AssertTestFails(AssertThat(nullptr, !IsNull()), message.str()); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										45
									
								
								dep/snowhouse/example/boolean_operators.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								dep/snowhouse/example/boolean_operators.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void BooleanOperators() | ||||
| { | ||||
|   describe("Boolean operators"); | ||||
|  | ||||
|   it("handles IsFalse()"); | ||||
|   { | ||||
|     AssertThat(false, IsFalse()); | ||||
|   } | ||||
|  | ||||
|   it("handles failing IsFalse()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(true, IsFalse()), "Expected: false"); | ||||
|   } | ||||
|  | ||||
|   it("handles IsTrue()"); | ||||
|   { | ||||
|     AssertThat(true, IsTrue()); | ||||
|   } | ||||
|  | ||||
|   it("handles failing IsTrue()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(false, IsTrue()), "Expected: true"); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().True()"); | ||||
|   { | ||||
|     AssertThat(true, Is().True()); | ||||
|     AssertTestFails(AssertThat(false, Is().True()), "Expected: true"); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().False()"); | ||||
|   { | ||||
|     AssertThat(false, Is().False()); | ||||
|     AssertTestFails(AssertThat(true, Is().False()), "Expected: false"); | ||||
|   } | ||||
|  | ||||
|   it("treats assert without constraint as boolean constrains"); | ||||
|   { | ||||
|     Assert::That(true); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										85
									
								
								dep/snowhouse/example/container_spec.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								dep/snowhouse/example/container_spec.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2013. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include <list> | ||||
|  | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| struct my_type | ||||
| { | ||||
|   explicit my_type(int my_val) | ||||
|       : my_val_(my_val) | ||||
|   { | ||||
|   } | ||||
|  | ||||
|   friend bool operator==(const my_type&, const my_type&); | ||||
|   friend bool operator!=(const my_type&, const my_type&); | ||||
|   friend std::ostream& operator<<(std::ostream&, const my_type&); | ||||
|  | ||||
|   int my_val_; | ||||
| }; | ||||
|  | ||||
| bool operator==(const my_type& lhs, const my_type& rhs) | ||||
| { | ||||
|   return lhs.my_val_ == rhs.my_val_; | ||||
| } | ||||
|  | ||||
| bool operator!=(const my_type& lhs, const my_type& rhs) | ||||
| { | ||||
|   return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& stream, const my_type& item) | ||||
| { | ||||
|   stream << "(my_type: my_val_=" << item.my_val_ << " )"; | ||||
|   return stream; | ||||
| } | ||||
|  | ||||
| static bool are_my_types_equal(const my_type& lhs, const my_type& rhs) | ||||
| { | ||||
|   return lhs.my_val_ == rhs.my_val_; | ||||
| } | ||||
|  | ||||
| void ContainerConstraints() | ||||
| { | ||||
|   describe("Container constraints"); | ||||
|  | ||||
|   it("is able to compare containers of custom types"); | ||||
|   { | ||||
|     const my_type e[] = {my_type(1), my_type(3)}; | ||||
|     const std::list<my_type> expected(e, e + sizeof(e) / sizeof(e[0])); | ||||
|     std::list<my_type> my_container_; | ||||
|     my_container_.push_back(my_type(1)); | ||||
|     my_container_.push_back(my_type(3)); | ||||
|  | ||||
|     AssertThat(my_container_, EqualsContainer(expected)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing comparisons"); | ||||
|   { | ||||
|     const my_type e[] = {my_type(1), my_type(2)}; | ||||
|     const std::list<my_type> expected(e, e + sizeof(e) / sizeof(e[0])); | ||||
|     std::list<my_type> my_container_; | ||||
|     my_container_.push_back(my_type(1)); | ||||
|     my_container_.push_back(my_type(3)); | ||||
|  | ||||
|     AssertTestFails(AssertThat(my_container_, EqualsContainer(expected)), | ||||
|         "Expected: [ (my_type: my_val_=1 ), (my_type: my_val_=2 ) ]"); | ||||
|   } | ||||
|  | ||||
|   it("handles comparison with a predicate function"); | ||||
|   { | ||||
|     const my_type e[] = {my_type(1), my_type(3)}; | ||||
|     const std::list<my_type> expected(e, e + sizeof(e) / sizeof(e[0])); | ||||
|     std::list<my_type> my_container_; | ||||
|     my_container_.push_back(my_type(1)); | ||||
|     my_container_.push_back(my_type(3)); | ||||
|  | ||||
|     AssertThat(my_container_, EqualsContainer(expected, are_my_types_equal)); | ||||
|     AssertThat(my_container_, Is().EqualToContainer(expected, are_my_types_equal)); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										61
									
								
								dep/snowhouse/example/custom_matchers_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								dep/snowhouse/example/custom_matchers_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2013. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| struct IsEvenNumberNoStreamOperator | ||||
| { | ||||
|   bool Matches(const int actual) const | ||||
|   { | ||||
|     return (actual % 2) == 0; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct IsEvenNumberWithStreamOperator | ||||
| { | ||||
|   bool Matches(const int actual) const | ||||
|   { | ||||
|     return (actual % 2) == 0; | ||||
|   } | ||||
|  | ||||
|   friend std::ostream& operator<<(std::ostream& stm, | ||||
|       const IsEvenNumberWithStreamOperator&); | ||||
| }; | ||||
|  | ||||
| std::ostream& operator<<(std::ostream& stm, | ||||
|     const IsEvenNumberWithStreamOperator&) | ||||
| { | ||||
|   stm << "An even number"; | ||||
|   return stm; | ||||
| } | ||||
|  | ||||
| void CustomMatchers() | ||||
| { | ||||
|   describe("Custom matchers"); | ||||
|  | ||||
|   it("handles custom matcher"); | ||||
|   { | ||||
|     AssertThat(2, Fulfills(IsEvenNumberNoStreamOperator())); | ||||
|   } | ||||
|  | ||||
|   it("handles custom matcher with fluent"); | ||||
|   { | ||||
|     AssertThat(2, Is().Fulfilling(IsEvenNumberNoStreamOperator())); | ||||
|   } | ||||
|  | ||||
|   it("outputs correct message when fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(3, Fulfills(IsEvenNumberNoStreamOperator())), | ||||
|         "Expected: [unsupported type]\nActual: 3"); | ||||
|   } | ||||
|  | ||||
|   it("outputs correct message when custom stream operator is defined"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(3, Fulfills(IsEvenNumberWithStreamOperator())), | ||||
|         "Expected: An even number\nActual: 3"); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										105
									
								
								dep/snowhouse/example/exceptions_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								dep/snowhouse/example/exceptions_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2013. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include <stdexcept> | ||||
|  | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| struct ClassWithExceptions | ||||
| { | ||||
|   int LogicError() | ||||
|   { | ||||
|     throw std::logic_error("not logical!"); | ||||
|   } | ||||
|  | ||||
|   double RangeError() | ||||
|   { | ||||
|     throw std::range_error("range error!"); | ||||
|   } | ||||
|  | ||||
|   void NoError() | ||||
|   { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct ExpectedException : public std::exception | ||||
| { | ||||
|   const char* what() const noexcept override | ||||
|   { | ||||
|     return "Description of the exception we expected"; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| void ExceptionTests() | ||||
| { | ||||
|   ClassWithExceptions objectUnderTest; | ||||
|  | ||||
|   describe("Exceptions"); | ||||
|  | ||||
|   it("detects exceptions"); | ||||
|   { | ||||
|     AssertThrows(std::exception, objectUnderTest.LogicError()); | ||||
|   } | ||||
|  | ||||
|   it("asserts on LastException()"); | ||||
|   { | ||||
|     AssertThrows(std::logic_error, objectUnderTest.LogicError()); | ||||
|     AssertThat(LastException<std::logic_error>().what(), Contains("not logical!")); | ||||
|   } | ||||
|  | ||||
|   it("detects when wrong exception is thrown"); | ||||
|   { | ||||
|     AssertTestFails(AssertThrows(std::logic_error, objectUnderTest.RangeError()), "Wrong exception"); | ||||
|   } | ||||
|  | ||||
|   it("prints expected exception type when wrong exception is thrown"); | ||||
|   { | ||||
|     AssertTestFails(AssertThrows(std::logic_error, objectUnderTest.RangeError()), "Expected std::logic_error"); | ||||
|   } | ||||
|  | ||||
|   it("has several exception assertions in same spec"); | ||||
|   { | ||||
|     AssertThrows(std::logic_error, objectUnderTest.LogicError()); | ||||
|     AssertThat(LastException<std::logic_error>().what(), Contains("not logical!")); | ||||
|  | ||||
|     AssertThrows(std::range_error, objectUnderTest.RangeError()); | ||||
|     AssertThat(LastException<std::range_error>().what(), Contains("range error!")); | ||||
|   } | ||||
|  | ||||
|   it("has several exception assertion for the same exception in same spec"); | ||||
|   { | ||||
|     AssertThrows(std::logic_error, objectUnderTest.LogicError()); | ||||
|     AssertThat(LastException<std::logic_error>().what(), Contains("not logical!")); | ||||
|  | ||||
|     AssertThrows(std::logic_error, objectUnderTest.LogicError()); | ||||
|     AssertThat(LastException<std::logic_error>().what(), Contains("not logical!")); | ||||
|   } | ||||
|  | ||||
|   it("detects when no exception is thrown"); | ||||
|   { | ||||
|     AssertTestFails(AssertThrows(std::logic_error, objectUnderTest.NoError()), "No exception"); | ||||
|   } | ||||
|  | ||||
|   it("prints expected exception when no exception is thrown"); | ||||
|   { | ||||
|     AssertTestFails(AssertThrows(std::logic_error, objectUnderTest.NoError()), "Expected std::logic_error"); | ||||
|   } | ||||
|  | ||||
|   it("destroys exceptions when out-of-scope"); | ||||
|   { | ||||
|     { | ||||
|       AssertThrows(std::logic_error, objectUnderTest.LogicError()); | ||||
|     } | ||||
|     AssertThrows(AssertionException, LastException<std::logic_error>()); | ||||
|     AssertThat(LastException<AssertionException>().what(), Contains("No exception was stored")); | ||||
|   } | ||||
|  | ||||
|   it("prints description of unwanted exception"); | ||||
|   { | ||||
|     AssertTestFails(AssertThrows(ExpectedException, objectUnderTest.LogicError()), "Expected ExpectedException. Wrong exception was thrown. Description of unwanted exception: not logical!"); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										25
									
								
								dep/snowhouse/example/expression_error_handling.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								dep/snowhouse/example/expression_error_handling.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void ExpressionErrorHandling() | ||||
| { | ||||
|   describe("Expression error handling"); | ||||
|  | ||||
|   std::vector<int> collection; | ||||
|   collection.push_back(1); | ||||
|   collection.push_back(2); | ||||
|   collection.push_back(3); | ||||
|  | ||||
|   it("reports an invalid All() properly"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(collection, Has().All()), | ||||
|         "The expression after \"all\" operator does not yield any result"); | ||||
|   } | ||||
|  | ||||
|   it("reports an invalid AtLeast() properly"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(collection, Has().AtLeast(2)), | ||||
|         "The expression after \"at least 2\" operator does not yield any result"); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										45
									
								
								dep/snowhouse/example/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								dep/snowhouse/example/main.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void BooleanOperators(); | ||||
| void BasicAssertions(); | ||||
| void ContainerConstraints(); | ||||
| void CustomMatchers(); | ||||
| void ExceptionTests(); | ||||
| void ExpressionErrorHandling(); | ||||
| void MapTests(); | ||||
| void OperatorTests(); | ||||
| void SequenceContainerTests(); | ||||
| void StringLineTests(); | ||||
| void StringTests(); | ||||
| void StringizeTests(); | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   std::cout << "Spec for Snowhouse " SNOWHOUSE_VERSION << std::endl; | ||||
|  | ||||
|   try | ||||
|   { | ||||
|     BasicAssertions(); | ||||
|     BooleanOperators(); | ||||
|     ContainerConstraints(); | ||||
|     CustomMatchers(); | ||||
|     ExceptionTests(); | ||||
|     ExpressionErrorHandling(); | ||||
|     MapTests(); | ||||
|     OperatorTests(); | ||||
|     SequenceContainerTests(); | ||||
|     StringLineTests(); | ||||
|     StringTests(); | ||||
|     StringizeTests(); | ||||
|   } | ||||
|   catch (const AssertionException& e) | ||||
|   { | ||||
|     std::cout << "Tests failed!" << std::endl; | ||||
|     std::cout << e.what() << std::endl; | ||||
|     return 1; | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										36
									
								
								dep/snowhouse/example/map_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								dep/snowhouse/example/map_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void MapTests() | ||||
| { | ||||
|   describe("Containing (std::map)"); | ||||
|  | ||||
|   std::map<std::string, int> ages; | ||||
|   ages["joakim"] = 38; | ||||
|   ages["maria"] = 36; | ||||
|   ages["hanna"] = 6; | ||||
|   ages["moa"] = 4; | ||||
|  | ||||
|   it("determines if key exists"); | ||||
|   { | ||||
|     AssertThat(ages, Is().Containing("joakim")); | ||||
|   } | ||||
|  | ||||
|   it("gives a proper message when fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(ages, Is().Not().Containing("hanna")), | ||||
|         "Expected: not contains \"hanna\""); | ||||
|   } | ||||
|  | ||||
|   it("determines if key exists"); | ||||
|   { | ||||
|     AssertThat(ages, Contains("joakim")); | ||||
|   } | ||||
|  | ||||
|   it("gives a proper message when Contains() fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(ages, !Contains("hanna")), | ||||
|         "Expected: not contains \"hanna\""); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										132
									
								
								dep/snowhouse/example/operator_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								dep/snowhouse/example/operator_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void OperatorTests() | ||||
| { | ||||
|   describe("Operators"); | ||||
|  | ||||
|   it("handles &&"); | ||||
|   { | ||||
|     AssertThat(5, IsLessThan(6) && IsGreaterThan(4)); | ||||
|   } | ||||
|  | ||||
|   it("handles And()"); | ||||
|   { | ||||
|     AssertThat(5, Is().LessThan(6).And().GreaterThan(4)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing &&"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, IsLessThan(7) && IsGreaterThan(5)), | ||||
|         "less than 7 and greater than 5"); | ||||
|   } | ||||
|  | ||||
|   it("handles failing And()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(5, Is().LessThan(7).And().GreaterThan(5)), | ||||
|         "less than 7 and greater than 5"); | ||||
|   } | ||||
|  | ||||
|   it("handles Or()"); | ||||
|   { | ||||
|     AssertThat(12, Is().LessThan(7).Or().GreaterThan(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles ||"); | ||||
|   { | ||||
|     AssertThat(12, IsLessThan(7) || IsGreaterThan(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Or()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(67, Is().LessThan(12).Or().GreaterThan(99)), | ||||
|         "less than 12 or greater than 99"); | ||||
|   } | ||||
|  | ||||
|   it("handles failing ||"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(67, IsLessThan(12) || IsGreaterThan(99)), | ||||
|         "less than 12 or greater than 99"); | ||||
|   } | ||||
|  | ||||
|   it("handles Not()"); | ||||
|   { | ||||
|     AssertThat(5, Is().Not().EqualTo(4)); | ||||
|   } | ||||
|  | ||||
|   it("handles !"); | ||||
|   { | ||||
|     AssertThat(5, !Equals(4)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Not()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(12, Is().Not().EqualTo(12)), "not equal to 12"); | ||||
|   } | ||||
|  | ||||
|   it("handles failing !"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(12, !Equals(12)), "not equal to 12"); | ||||
|   } | ||||
|  | ||||
|   it("handles Not() for strings"); | ||||
|   { | ||||
|     AssertThat("joakim", Is().Not().EqualTo("harry")); | ||||
|   } | ||||
|  | ||||
|   it("handles failing ! for strings"); | ||||
|   { | ||||
|     AssertThat("joakim", !Equals("harry")); | ||||
|   } | ||||
|  | ||||
|   it("handles both left and right associative operators"); | ||||
|   { | ||||
|     AssertThat(5, Is().GreaterThan(4).And().Not().LessThan(3)); | ||||
|   } | ||||
|  | ||||
|   it("handles both left and right associative operators expression templates"); | ||||
|   { | ||||
|     AssertThat(5, IsGreaterThan(4) && !IsLessThan(3)); | ||||
|   } | ||||
|  | ||||
|   it("yields error on malformed expression"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(4, Is().Not()), | ||||
|         "The expression contains a \"not\" operator without any operand"); | ||||
|   } | ||||
|  | ||||
|   it("handles failing EqualsWithDelta() when larger than delta"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(3.9, EqualsWithDelta(3, 0.5)), | ||||
|         "Expected: equal to 3 (+/- 0.5)"); | ||||
|   } | ||||
|  | ||||
|   it("handles failing EqualsWithDelta() when less than delta"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(2.49, EqualsWithDelta(3, 0.5)), | ||||
|         "Expected: equal to 3 (+/- 0.5)"); | ||||
|   } | ||||
|  | ||||
|   it("handles EqualsWithDelta()"); | ||||
|   { | ||||
|     AssertThat(2, EqualsWithDelta(1.9, 0.1)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Is().EqualToWithDelta() when larger than delta"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(3.9, Is().EqualToWithDelta(3, 0.5)), | ||||
|         "Expected: equal to 3 (+/- 0.5)"); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Is().EqualToWithDelta() when less than delta"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(2.49, Is().EqualToWithDelta(3, 0.5)), | ||||
|         "Expected: equal to 3 (+/- 0.5)"); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().EqualToWithDelta()"); | ||||
|   { | ||||
|     AssertThat(2, Is().EqualToWithDelta(1.9, 0.1)); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										288
									
								
								dep/snowhouse/example/sequence_container_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								dep/snowhouse/example/sequence_container_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| #include <deque> | ||||
| #include <list> | ||||
| #include <set> | ||||
| #include <array> | ||||
| #include <forward_list> | ||||
|  | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| static const char* ExpectedActual = "\nActual: [ 1, 2, 3, 5, 8 ]"; | ||||
|  | ||||
| template<typename T> | ||||
| static void insert_numbers(T& container) | ||||
| { | ||||
|   container.push_back(1); | ||||
|   container.push_back(2); | ||||
|   container.push_back(3); | ||||
|   container.push_back(5); | ||||
|   container.push_back(8); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void insert_numbers(std::multiset<int>& container) | ||||
| { | ||||
|   container.insert(1); | ||||
|   container.insert(2); | ||||
|   container.insert(3); | ||||
|   container.insert(5); | ||||
|   container.insert(8); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void insert_numbers(std::set<int>& container) | ||||
| { | ||||
|   container.insert(1); | ||||
|   container.insert(2); | ||||
|   container.insert(3); | ||||
|   container.insert(5); | ||||
|   container.insert(8); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void insert_numbers(std::array<int, 5>& container) | ||||
| { | ||||
|   container[0] = 1; | ||||
|   container[1] = 2; | ||||
|   container[2] = 3; | ||||
|   container[3] = 5; | ||||
|   container[4] = 8; | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void insert_numbers(std::forward_list<int>& container) | ||||
| { | ||||
|   container.push_front(8); | ||||
|   container.push_front(5); | ||||
|   container.push_front(3); | ||||
|   container.push_front(2); | ||||
|   container.push_front(1); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| static void TestHasAll(const T& container) | ||||
| { | ||||
|   it("handles All()"); | ||||
|   { | ||||
|     AssertThat(container, Has().All().GreaterThan(1).Or().LessThan(4)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing All()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().All().GreaterThan(4)), std::string("Expected: all greater than 4") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles invalid expression after All()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().All().Not()), "The expression contains a \"not\" operator without any operand"); | ||||
|   } | ||||
|  | ||||
|   it("handles no expression after All()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().All()), "The expression after \"all\" operator does not yield any result"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void TestHasAll(const std::forward_list<int>&) | ||||
| { | ||||
|   // The constraint is size-based but there is no size() method available | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| static void TestLength(const T& container) | ||||
| { | ||||
|   it("handles HasLength()"); | ||||
|   { | ||||
|     AssertThat(container, HasLength(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing HasLength()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, HasLength(7)), std::string("of length 7") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().OfLength()"); | ||||
|   { | ||||
|     AssertThat(container, Is().OfLength(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Is().OfLength()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Is().OfLength(7)), std::string("of length 7") + ExpectedActual); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void TestLength(const std::forward_list<int>&) | ||||
| { | ||||
|   // There is no size() method available | ||||
| } | ||||
|  | ||||
| template<typename T, typename TEmpty> | ||||
| static void TestEmpty(const T& container, const TEmpty& is_empty) | ||||
| { | ||||
|   it("handles IsEmpty()"); | ||||
|   { | ||||
|     AssertThat(is_empty, IsEmpty()); | ||||
|   } | ||||
|  | ||||
|   it("handles failing IsEmpty()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, IsEmpty()), "empty"); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().Empty()"); | ||||
|   { | ||||
|     AssertThat(is_empty, Is().Empty()); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Is().Empty()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Is().Empty()), "empty"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| void TestEmpty(const T& container) | ||||
| { | ||||
|   T is_empty; | ||||
|   TestEmpty(container, is_empty); | ||||
| } | ||||
|  | ||||
| template<> | ||||
| void TestEmpty(const std::array<int, 5>& container) | ||||
| { | ||||
|   std::array<int, 0> is_empty; | ||||
|   TestEmpty(container, is_empty); | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| static void SequenceContainerActual() | ||||
| { | ||||
|   T container; | ||||
|   insert_numbers(container); | ||||
|  | ||||
|   TestHasAll(container); | ||||
|  | ||||
|   it("handles AtLeast()"); | ||||
|   { | ||||
|     AssertThat(container, Has().AtLeast(1).LessThan(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing AtLeast()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().AtLeast(2).LessThan(2)), std::string("Expected: at least 2 less than 2") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles Exactly()"); | ||||
|   { | ||||
|     AssertThat(container, Has().Exactly(1).EqualTo(3)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Exactly()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().Exactly(2).EqualTo(3)), std::string("Expected: exactly 2 equal to 3") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles AtMost()"); | ||||
|   { | ||||
|     AssertThat(container, Has().AtMost(1).EqualTo(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing AtMost()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().AtMost(1).EqualTo(3).Or().EqualTo(5)), std::string("Expected: at most 1 equal to 3 or equal to 5") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles None()"); | ||||
|   { | ||||
|     AssertThat(container, Has().None().EqualTo(666)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing None()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Has().None().EqualTo(5)), std::string("Expected: none equal to 5") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles Contains()"); | ||||
|   { | ||||
|     AssertThat(container, Contains(3)); | ||||
|   } | ||||
|  | ||||
|   it("detects failing Contains()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Contains(99)), std::string("contains 99") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().Containing()"); | ||||
|   { | ||||
|     AssertThat(container, Is().Containing(3)); | ||||
|   } | ||||
|  | ||||
|   it("detects failing Is().Containing()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(container, Is().Containing(99)), std::string("contains 99") + ExpectedActual); | ||||
|   } | ||||
|  | ||||
|   TestLength(container); | ||||
|  | ||||
|   TestEmpty(container); | ||||
|  | ||||
|   it("handles EqualsContainer()"); | ||||
|   { | ||||
|     std::list<int> expected; | ||||
|     expected.assign(container.begin(), container.end()); | ||||
|  | ||||
|     AssertThat(container, EqualsContainer(expected)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing EqualsContainer()"); | ||||
|   { | ||||
|     const int e[] = {4, 2, 4}; | ||||
|     std::list<int> expected(e, e + sizeof(e) / sizeof(e[0])); | ||||
|  | ||||
|     AssertTestFails(AssertThat(container, EqualsContainer(expected)), "Expected: [ 4, 2, 4 ]"); | ||||
|   } | ||||
|  | ||||
|   it("handles Is().EqualToContainer()"); | ||||
|   { | ||||
|     std::list<int> expected; | ||||
|     expected.assign(container.begin(), container.end()); | ||||
|  | ||||
|     AssertThat(container, Is().EqualToContainer(expected)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing Is().EqualToContainer()"); | ||||
|   { | ||||
|     const int e[] = {4, 2, 4}; | ||||
|     std::list<int> expected(e, e + sizeof(e) / sizeof(e[0])); | ||||
|  | ||||
|     AssertTestFails(AssertThat(container, Is().EqualToContainer(expected)), "Expected: [ 4, 2, 4 ]"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void SequenceContainerTests() | ||||
| { | ||||
|   describe("Sequence containers (std::vector)"); | ||||
|   SequenceContainerActual<std::vector<int>>(); | ||||
|  | ||||
|   describe("Sequence containers (std::list)"); | ||||
|   SequenceContainerActual<std::list<int>>(); | ||||
|  | ||||
|   describe("Sequence containers (std::deque)"); | ||||
|   SequenceContainerActual<std::deque<int>>(); | ||||
|  | ||||
|   describe("Sequence containers (std::set)"); | ||||
|   SequenceContainerActual<std::set<int>>(); | ||||
|  | ||||
|   describe("Sequence containers (std::multiset)"); | ||||
|   SequenceContainerActual<std::multiset<int>>(); | ||||
|  | ||||
|   describe("Sequence containers (std::array)"); | ||||
|   SequenceContainerActual<std::array<int, 5>>(); | ||||
|  | ||||
|   describe("Sequence containers (std::forward_list)"); | ||||
|   SequenceContainerActual<std::forward_list<int>>(); | ||||
| } | ||||
							
								
								
									
										173
									
								
								dep/snowhouse/example/string_line_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								dep/snowhouse/example/string_line_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void StringLineTests() | ||||
| { | ||||
|   describe("String lines"); | ||||
|  | ||||
|   it("asserts that at least one line in a stream matches"); | ||||
|   { | ||||
|     AssertThat("First line\n", Has().AtLeast(1).EqualTo("First line")); | ||||
|   } | ||||
|  | ||||
|   it("detects when assertion fails"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat("First line\n", Has().AtLeast(1).EqualTo("Second line")), "Expected: at least 1 equal to \"Second line\""); | ||||
|   } | ||||
|  | ||||
|   it("handles line missing newline"); | ||||
|   { | ||||
|     AssertThat("First line", Has().AtLeast(1).EqualTo("First line")); | ||||
|   } | ||||
|  | ||||
|   it("handles several lines"); | ||||
|   { | ||||
|     std::string lines = "First line\nSecond line"; | ||||
|     AssertThat(lines, Has().Exactly(2).EndingWith("line")); | ||||
|   } | ||||
|  | ||||
|   it("handles Windows line endings"); | ||||
|   { | ||||
|     std::string lines = "First line\r\nSecond line\r\nThird line"; | ||||
|     AssertThat(lines, Has().Exactly(3).EndingWith("line")); | ||||
|   } | ||||
|  | ||||
|   it("matches beginning of lines with Windows line endings"); | ||||
|   { | ||||
|     std::string lines = "First line\nSecond line\r\nThird line"; | ||||
|     AssertThat(lines, Has().Exactly(1).StartingWith("Second")); | ||||
|   } | ||||
|  | ||||
|   it("handles empty lines when using Windows line endings"); | ||||
|   { | ||||
|     std::string lines = "\r\nSecond line\r\n\r\n"; | ||||
|     AssertThat(lines, Has().Exactly(2).OfLength(0)); | ||||
|   } | ||||
|  | ||||
|   it("handles last line missing newline for Windows line endings"); | ||||
|   { | ||||
|     std::string lines = "First line\r\nSecond line"; | ||||
|     AssertThat(lines, Has().Exactly(2).EndingWith("line")); | ||||
|   } | ||||
|  | ||||
|   it("handles all empty lines"); | ||||
|   { | ||||
|     AssertThat("\n\n\n\n\n\n", Has().Exactly(6).OfLength(0)); | ||||
|   } | ||||
|  | ||||
|   it("handles all empty lines with Windows line endings"); | ||||
|   { | ||||
|     AssertThat("\r\n\r\n\r\n", Has().Exactly(3).OfLength(0)); | ||||
|   } | ||||
|  | ||||
|   describe("StringLineParser"); | ||||
|  | ||||
|   it("parses an empty string"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|  | ||||
|     StringLineParser::Parse("", res); | ||||
|  | ||||
|     AssertThat(res, HasLength(0)); | ||||
|   } | ||||
|  | ||||
|   it("parses a single line"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|  | ||||
|     StringLineParser::Parse("Simple line", res); | ||||
|  | ||||
|     AssertThat(res, HasLength(1)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Simple line")); | ||||
|   } | ||||
|  | ||||
|   it("parses two lines"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|  | ||||
|     StringLineParser::Parse("One line\nTwo lines", res); | ||||
|  | ||||
|     AssertThat(res, HasLength(2)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Two lines")); | ||||
|   } | ||||
|  | ||||
|   it("parses three lines"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|  | ||||
|     StringLineParser::Parse("One line\nTwo lines\nThree lines", res); | ||||
|  | ||||
|     AssertThat(res, HasLength(3)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Two lines")); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Three lines")); | ||||
|   } | ||||
|  | ||||
|   it("handles string ending with newline"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("One line\n", res); | ||||
|     AssertThat(res, HasLength(1)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|   } | ||||
|  | ||||
|   it("handles single line with Windows line ending"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("One line\r\n", res); | ||||
|     AssertThat(res, HasLength(1)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|   } | ||||
|  | ||||
|   it("handles two lines with Windows line endings"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("One line\r\nTwo lines", res); | ||||
|     AssertThat(res, HasLength(2)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Two lines")); | ||||
|   } | ||||
|  | ||||
|   it("handles empty line with newline"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("\n", res); | ||||
|     AssertThat(res, Is().OfLength(1).And().Exactly(1).OfLength(0)); | ||||
|   } | ||||
|  | ||||
|   it("handles two empty lines"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("\n\n", res); | ||||
|     AssertThat(res, HasLength(2)); | ||||
|     AssertThat(res, Has().Exactly(2).OfLength(0)); | ||||
|   } | ||||
|  | ||||
|   it("handles two empty lines with Windows line endings"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("\r\n\r\n", res); | ||||
|     AssertThat(res, HasLength(2)); | ||||
|     AssertThat(res, Has().Exactly(2).OfLength(0)); | ||||
|   } | ||||
|  | ||||
|   it("handles carriage return only"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("One line\rTwo lines", res); | ||||
|     AssertThat(res, HasLength(2)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Two lines")); | ||||
|   } | ||||
|  | ||||
|   it("handles carriage return only at end of string"); | ||||
|   { | ||||
|     std::vector<std::string> res; | ||||
|     StringLineParser::Parse("One line\r\nTwo lines\r", res); | ||||
|     AssertThat(res, HasLength(2)); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("One line")); | ||||
|     AssertThat(res, Has().Exactly(1).EqualTo("Two lines")); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										78
									
								
								dep/snowhouse/example/string_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								dep/snowhouse/example/string_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| void StringTests() | ||||
| { | ||||
|   describe("Strings"); | ||||
|  | ||||
|   it("handles string Contains()"); | ||||
|   { | ||||
|     AssertThat("abcdef", Contains("bcde")); | ||||
|   } | ||||
|  | ||||
|   it("handles match at beginning of string"); | ||||
|   { | ||||
|     AssertThat("abcdef", Contains("a")); | ||||
|   } | ||||
|  | ||||
|   it("detects failing Contains()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat("abcdef", Contains("hello")), "contains \"hello\""); | ||||
|   } | ||||
|  | ||||
|   it("handles string StartsWith()"); | ||||
|   { | ||||
|     AssertThat("abcdef", StartsWith("abc")); | ||||
|   } | ||||
|  | ||||
|   it("handles string EndsWith()"); | ||||
|   { | ||||
|     AssertThat("abcdef", EndsWith("def")); | ||||
|   } | ||||
|  | ||||
|   it("handles operators for strings"); | ||||
|   { | ||||
|     AssertThat("abcdef", StartsWith("ab") && EndsWith("ef")); | ||||
|   } | ||||
|  | ||||
|   it("handles strings with multiple operators"); | ||||
|   { | ||||
|     AssertThat("abcdef", StartsWith("ab") && !EndsWith("qwqw")); | ||||
|   } | ||||
|  | ||||
|   it("handles HasLength()"); | ||||
|   { | ||||
|     AssertThat("12345", HasLength(5)); | ||||
|   } | ||||
|  | ||||
|   it("handles failing HasLength()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat("1234", HasLength(5)), "of length 5"); | ||||
|   } | ||||
|  | ||||
|   it("handles IsEmpty()"); | ||||
|   { | ||||
|     AssertThat("", IsEmpty()); | ||||
|   } | ||||
|  | ||||
|   it("handles failing IsEmpty()"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat("not empty", IsEmpty()), "empty"); | ||||
|   } | ||||
|  | ||||
|   it("handles weird long expressions"); | ||||
|   { | ||||
|     AssertThat("12345", HasLength(5) && StartsWith("123") && !EndsWith("zyxxy")); | ||||
|   } | ||||
|  | ||||
|   it("handles std::string"); | ||||
|   { | ||||
|     AssertThat("12345", Contains(std::string("23"))); | ||||
|   } | ||||
|  | ||||
|   it("handles simple char"); | ||||
|   { | ||||
|     AssertThat("12345", StartsWith('1')); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										127
									
								
								dep/snowhouse/example/stringize_tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								dep/snowhouse/example/stringize_tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| #include "tests.h" | ||||
|  | ||||
| using namespace snowhouse; | ||||
|  | ||||
| namespace | ||||
| { | ||||
|   // No overload for operator<<(std::ostream&) or specialization of snowhouse::Stringizer | ||||
|   struct WithoutStreamOperator | ||||
|   { | ||||
|     explicit WithoutStreamOperator(int id) | ||||
|         : m_id(id) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     bool operator==(const WithoutStreamOperator& rhs) const | ||||
|     { | ||||
|       return m_id == rhs.m_id; | ||||
|     } | ||||
|  | ||||
|     int m_id; | ||||
|   }; | ||||
|  | ||||
|   // Has operator<<(std::ostream&) | ||||
|   struct WithStreamOperator : public WithoutStreamOperator | ||||
|   { | ||||
|     explicit WithStreamOperator(int id) | ||||
|         : WithoutStreamOperator(id) | ||||
|     { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   std::ostream& operator<<(std::ostream& stream, const WithStreamOperator& a) | ||||
|   { | ||||
|     stream << a.m_id; | ||||
|     return stream; | ||||
|   } | ||||
|  | ||||
|   // Has no operator<<(std::ostream&), but a specialization of snowhouse::Stringizer | ||||
|   struct WithoutStreamOperatorButWithStringizer : public WithoutStreamOperator | ||||
|   { | ||||
|     explicit WithoutStreamOperatorButWithStringizer(int id) | ||||
|         : WithoutStreamOperator(id) | ||||
|     { | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<> | ||||
|   struct Stringizer<WithoutStreamOperatorButWithStringizer> | ||||
|   { | ||||
|     static std::string ToString(const WithoutStreamOperatorButWithStringizer& value) | ||||
|     { | ||||
|       return snowhouse::Stringize(value.m_id); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| void StringizeTests() | ||||
| { | ||||
|   describe("Stringize"); | ||||
|  | ||||
|   it("handles types with stream operators"); | ||||
|   { | ||||
|     WithStreamOperator a(12); | ||||
|     WithStreamOperator b(13); | ||||
|     AssertTestFails(AssertThat(a, Is().EqualTo(b)), "Expected: equal to 13\nActual: 12"); | ||||
|   } | ||||
|  | ||||
|   it("handles types without stream operators"); | ||||
|   { | ||||
|     WithoutStreamOperator a(12); | ||||
|     WithoutStreamOperator b(13); | ||||
|     AssertTestFails(AssertThat(a, Is().EqualTo(b)), "Expected: equal to [unsupported type]\nActual: [unsupported type]"); | ||||
|   } | ||||
|  | ||||
|   it("handles types with traits"); | ||||
|   { | ||||
|     WithoutStreamOperatorButWithStringizer a(12); | ||||
|     WithoutStreamOperatorButWithStringizer b(13); | ||||
|     AssertTestFails(AssertThat(a, Is().EqualTo(b)), "Expected: equal to 13\nActual: 12"); | ||||
|   } | ||||
|  | ||||
|   it("provides bools as true or false"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(false, Is().True()), "Expected: true\nActual: false"); | ||||
|   } | ||||
|  | ||||
|   it("provides strings in quotation marks"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat("wrong", Is().EqualTo("right")), "Expected: equal to \"right\"\nActual: \"wrong\""); | ||||
|   } | ||||
|  | ||||
|   describe("Stringize expression templates"); | ||||
|  | ||||
|   it("handles types with stream operators"); | ||||
|   { | ||||
|     WithStreamOperator a(12); | ||||
|     WithStreamOperator b(13); | ||||
|     AssertTestFails(AssertThat(a, Equals(b)), "Expected: equal to 13\nActual: 12"); | ||||
|   } | ||||
|  | ||||
|   it("handles types without stream operators"); | ||||
|   { | ||||
|     WithoutStreamOperator a(12); | ||||
|     WithoutStreamOperator b(13); | ||||
|     AssertTestFails(AssertThat(a, Equals(b)), "Expected: equal to [unsupported type]\nActual: [unsupported type]"); | ||||
|   } | ||||
|  | ||||
|   it("handles types with traits"); | ||||
|   { | ||||
|     WithoutStreamOperatorButWithStringizer a(12); | ||||
|     WithoutStreamOperatorButWithStringizer b(13); | ||||
|     AssertTestFails(AssertThat(a, Equals(b)), "Expected: equal to 13\nActual: 12"); | ||||
|   } | ||||
|  | ||||
|   it("provides bools as true or false"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat(true, IsFalse()), "Expected: false\nActual: true"); | ||||
|   } | ||||
|  | ||||
|   it("provides strings in quotation marks"); | ||||
|   { | ||||
|     AssertTestFails(AssertThat("wrong", Equals("right")), "Expected: equal to \"right\"\nActual: \"wrong\""); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										31
									
								
								dep/snowhouse/example/tests.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								dep/snowhouse/example/tests.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| #ifndef SNOWHOUSE_EXAMPLES_TEST_H | ||||
| #define SNOWHOUSE_EXAMPLES_TEST_H | ||||
|  | ||||
| #include <snowhouse/snowhouse.h> | ||||
|  | ||||
| // clang-format off | ||||
| #define AssertTestFails(assertion, expected_error_text) \ | ||||
|   std::string SNOWHOUSE_INTERNAL_expected_error = "Test did not fail"; \ | ||||
|   try \ | ||||
|   { \ | ||||
|     assertion; \ | ||||
|   }  \ | ||||
|   catch (const AssertionException& exception_from_snowhouse_assertion)  \ | ||||
|   {  \ | ||||
|     SNOWHOUSE_INTERNAL_expected_error = exception_from_snowhouse_assertion.what();  \ | ||||
|   }  \ | ||||
|   AssertThat(SNOWHOUSE_INTERNAL_expected_error, Is().Containing(expected_error_text)); | ||||
| // clang-format on | ||||
|  | ||||
| inline void describe(const char* title) | ||||
| { | ||||
|   std::cout << std::endl | ||||
|             << title << ":" << std::endl; | ||||
| } | ||||
|  | ||||
| inline void it(const char* title) | ||||
| { | ||||
|   std::cout << " - " << title << std::endl; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										116
									
								
								dep/snowhouse/include/snowhouse/assert.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								dep/snowhouse/include/snowhouse/assert.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ASSERT_H | ||||
| #define SNOWHOUSE_ASSERT_H | ||||
|  | ||||
| #include "assertionexception.h" | ||||
| #include "fluent/expressionbuilder.h" | ||||
|  | ||||
| // clang-format off | ||||
| #define SNOWHOUSE_ASSERT_THAT(P1, P2, FAILURE_HANDLER) \ | ||||
|   ::snowhouse::ConfigurableAssert<FAILURE_HANDLER>::That((P1), (P2), __FILE__, __LINE__) | ||||
|  | ||||
| #ifndef SNOWHOUSE_NO_MACROS | ||||
| # define AssertThat(P1, P2) \ | ||||
|   SNOWHOUSE_ASSERT_THAT((P1), (P2), ::snowhouse::DefaultFailureHandler) | ||||
| #endif | ||||
| // clang-format on | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct DefaultFailureHandler | ||||
|   { | ||||
|     template<typename ExpectedType, typename ActualType> | ||||
|     static void Handle(const ExpectedType& expected, const ActualType& actual, const char* file_name, int line_number) | ||||
|     { | ||||
|       std::ostringstream str; | ||||
|  | ||||
|       str << "Expected: " << snowhouse::Stringize(expected) << std::endl; | ||||
|       str << "Actual: " << snowhouse::Stringize(actual) << std::endl; | ||||
|  | ||||
|       throw AssertionException(str.str(), file_name, line_number); | ||||
|     } | ||||
|  | ||||
|     static void Handle(const std::string& message) | ||||
|     { | ||||
|       throw AssertionException(message); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename FailureHandler> | ||||
|   struct ConfigurableAssert | ||||
|   { | ||||
|     template<typename ActualType, typename ConstraintListType> | ||||
|     static void That(const ActualType& actual, ExpressionBuilder<ConstraintListType> expression, const char* file_name = "", int line_number = 0) | ||||
|     { | ||||
|       try | ||||
|       { | ||||
|         ResultStack result; | ||||
|         OperatorStack operators; | ||||
|         expression.Evaluate(result, operators, actual); | ||||
|  | ||||
|         while (!operators.empty()) | ||||
|         { | ||||
|           ConstraintOperator* op = operators.top(); | ||||
|           op->PerformOperation(result); | ||||
|           operators.pop(); | ||||
|         } | ||||
|  | ||||
|         if (result.empty()) | ||||
|         { | ||||
|           throw InvalidExpressionException("The expression did not yield any result"); | ||||
|         } | ||||
|  | ||||
|         if (!result.top()) | ||||
|         { | ||||
|           FailureHandler::Handle(expression, actual, file_name, line_number); | ||||
|         } | ||||
|       } | ||||
|       catch (const InvalidExpressionException& e) | ||||
|       { | ||||
|         FailureHandler::Handle("Malformed expression: \"" + snowhouse::Stringize(expression) + "\"\n" + e.what()); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     template<typename ConstraintListType> | ||||
|     static void That(const char* actual, ExpressionBuilder<ConstraintListType> expression, const char* file_name = "", int line_number = 0) | ||||
|     { | ||||
|       return That(std::string(actual), expression, file_name, line_number); | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType, typename ExpressionType> | ||||
|     static void That(const ActualType& actual, const ExpressionType& expression, const char* file_name = "", int line_number = 0) | ||||
|     { | ||||
|       if (!expression(actual)) | ||||
|       { | ||||
|         FailureHandler::Handle(expression, actual, file_name, line_number); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     template<typename ExpressionType> | ||||
|     static void That(const char* actual, const ExpressionType& expression, const char* file_name = "", int line_number = 0) | ||||
|     { | ||||
|       return That(std::string(actual), expression, file_name, line_number); | ||||
|     } | ||||
|  | ||||
|     static void That(bool actual) | ||||
|     { | ||||
|       if (!actual) | ||||
|       { | ||||
|         FailureHandler::Handle("Expected: true\nActual: false"); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     static void Failure(const std::string& message) | ||||
|     { | ||||
|       FailureHandler::Handle(message); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   using Assert = ConfigurableAssert<DefaultFailureHandler>; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										44
									
								
								dep/snowhouse/include/snowhouse/assertionexception.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								dep/snowhouse/include/snowhouse/assertionexception.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ASSERTIONEXCEPTION_H | ||||
| #define SNOWHOUSE_ASSERTIONEXCEPTION_H | ||||
|  | ||||
| #include <stdexcept> | ||||
| #include <string> | ||||
|  | ||||
| #include "macros.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct AssertionException : public std::runtime_error | ||||
|   { | ||||
|     explicit AssertionException(const std::string& message, const std::string& filename, unsigned int line_number) | ||||
|         : std::runtime_error(message), m_file(filename), m_line(line_number) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     explicit AssertionException(const std::string& message) | ||||
|         : AssertionException(message, "", 0) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     std::string file() const | ||||
|     { | ||||
|       return m_file; | ||||
|     } | ||||
|  | ||||
|     unsigned int line() const | ||||
|     { | ||||
|       return m_line; | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     std::string m_file; | ||||
|     unsigned int m_line; | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										23
									
								
								dep/snowhouse/include/snowhouse/constraints/constraints.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								dep/snowhouse/include/snowhouse/constraints/constraints.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_CONSTRAINTS_H | ||||
| #define SNOWHOUSE_CONSTRAINTS_H | ||||
|  | ||||
| #include "containsconstraint.h" | ||||
| #include "endswithconstraint.h" | ||||
| #include "equalsconstraint.h" | ||||
| #include "haslengthconstraint.h" | ||||
| #include "isemptyconstraint.h" | ||||
| #include "isgreaterthanconstraint.h" | ||||
| #include "isgreaterthanorequaltoconstraint.h" | ||||
| #include "islessthanconstraint.h" | ||||
| #include "islessthanorequaltoconstraint.h" | ||||
| #include "startswithconstraint.h" | ||||
| #include "fulfillsconstraint.h" | ||||
| #include "equalswithdeltaconstraint.h" | ||||
| #include "equalscontainerconstraint.h" | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,82 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_CONTAINSCONSTRAINT_H | ||||
| #define SNOWHOUSE_CONTAINSCONSTRAINT_H | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <map> | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ContainerType> | ||||
|   struct find_in_container_traits | ||||
|   { | ||||
|     template<typename ExpectedType> | ||||
|     static bool find(const ContainerType& container, const ExpectedType& expected) | ||||
|     { | ||||
|       return std::find(container.begin(), container.end(), expected) != container.end(); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename KeyType, typename ValueType> | ||||
|   struct find_in_container_traits<std::map<KeyType, ValueType>> | ||||
|   { | ||||
|     template<typename ExpectedType> | ||||
|     static bool find(const std::map<KeyType, ValueType>& container, const ExpectedType& expected) | ||||
|     { | ||||
|       return container.find(expected) != container.end(); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct ContainsConstraint : Expression<ContainsConstraint<ExpectedType>> | ||||
|   { | ||||
|     ContainsConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return find_in_container_traits<ActualType>::find(actual, m_expected); | ||||
|     } | ||||
|  | ||||
|     bool operator()(const std::string& actual) const | ||||
|     { | ||||
|       return actual.find(m_expected) != std::string::npos; | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline ContainsConstraint<ExpectedType> Contains(const ExpectedType& expected) | ||||
|   { | ||||
|     return ContainsConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline ContainsConstraint<std::string> Contains(const char* expected) | ||||
|   { | ||||
|     return ContainsConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<ContainsConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const ContainsConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "contains " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,54 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ENDSWITHCONSTRAINT_H | ||||
| #define SNOWHOUSE_ENDSWITHCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct EndsWithConstraint : Expression<EndsWithConstraint<ExpectedType>> | ||||
|   { | ||||
|     EndsWithConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     bool operator()(const std::string& actual) const | ||||
|     { | ||||
|       size_t expectedPos = actual.length() - m_expected.length(); | ||||
|       return actual.find(m_expected) == expectedPos; | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline EndsWithConstraint<ExpectedType> EndsWith(const ExpectedType& expected) | ||||
|   { | ||||
|     return EndsWithConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline EndsWithConstraint<std::string> EndsWith(const char* expected) | ||||
|   { | ||||
|     return EndsWithConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<EndsWithConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const EndsWithConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "ends with " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,78 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EQUALSCONSTRAINT_H | ||||
| #define SNOWHOUSE_EQUALSCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct EqualsConstraint : Expression<EqualsConstraint<ExpectedType>> | ||||
|   { | ||||
|     EqualsConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (m_expected == actual); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline EqualsConstraint<ExpectedType> Equals(const ExpectedType& expected) | ||||
|   { | ||||
|     return EqualsConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline EqualsConstraint<std::string> Equals(const char* expected) | ||||
|   { | ||||
|     return EqualsConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   inline EqualsConstraint<bool> IsFalse() | ||||
|   { | ||||
|     return EqualsConstraint<bool>(false); | ||||
|   } | ||||
|  | ||||
|   inline EqualsConstraint<bool> IsTrue() | ||||
|   { | ||||
|     return EqualsConstraint<bool>(true); | ||||
|   } | ||||
|  | ||||
|   inline EqualsConstraint<std::nullptr_t> IsNull() | ||||
|   { | ||||
|     return EqualsConstraint<std::nullptr_t>(nullptr); | ||||
|   } | ||||
|  | ||||
|   template<> | ||||
|   struct Stringizer<EqualsConstraint<bool>> | ||||
|   { | ||||
|     static std::string ToString(const EqualsConstraint<bool>& constraint) | ||||
|     { | ||||
|       return constraint.m_expected ? "true" : "false"; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<EqualsConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const EqualsConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "equal to " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,75 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EQUALSCONTAINERCONSTRAINT_H | ||||
| #define SNOWHOUSE_EQUALSCONTAINERCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   namespace constraint_internal | ||||
|   { | ||||
|     template<typename T> | ||||
|     inline bool default_comparer(const T& lhs, const T& rhs) | ||||
|     { | ||||
|       return lhs == rhs; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType, typename BinaryPredicate> | ||||
|   struct EqualsContainerConstraint : Expression<EqualsContainerConstraint<ExpectedType, BinaryPredicate>> | ||||
|   { | ||||
|     EqualsContainerConstraint(const ExpectedType& expected, const BinaryPredicate predicate) | ||||
|         : m_expected(expected), m_predicate(predicate) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       typename ActualType::const_iterator actual_it; | ||||
|       typename ExpectedType::const_iterator expected_it; | ||||
|  | ||||
|       for (actual_it = actual.begin(), expected_it = m_expected.begin(); actual_it != actual.end() && expected_it != m_expected.end(); ++actual_it, ++expected_it) | ||||
|       { | ||||
|         if (!m_predicate(*actual_it, *expected_it)) | ||||
|         { | ||||
|           return false; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       return actual_it == actual.end() && expected_it == m_expected.end(); | ||||
|     } | ||||
|  | ||||
|     const ExpectedType m_expected; | ||||
|     const BinaryPredicate m_predicate; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline EqualsContainerConstraint<ExpectedType, bool (*)(const typename ExpectedType::value_type&, const typename ExpectedType::value_type&)> EqualsContainer(const ExpectedType& expected) | ||||
|   { | ||||
|     return EqualsContainerConstraint<ExpectedType, bool (*)(const typename ExpectedType::value_type&, const typename ExpectedType::value_type&)>(expected, constraint_internal::default_comparer); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType, typename BinaryPredicate> | ||||
|   inline EqualsContainerConstraint<ExpectedType, BinaryPredicate> EqualsContainer(const ExpectedType& expected, const BinaryPredicate predicate) | ||||
|   { | ||||
|     return EqualsContainerConstraint<ExpectedType, BinaryPredicate>(expected, predicate); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType, typename BinaryPredicate> | ||||
|   struct Stringizer<EqualsContainerConstraint<ExpectedType, BinaryPredicate>> | ||||
|   { | ||||
|     static std::string ToString(const EqualsContainerConstraint<ExpectedType, BinaryPredicate>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << snowhouse::Stringize(constraint.m_expected); | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,50 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EQUALSWITHDELTACONSTRAINT_H | ||||
| #define SNOWHOUSE_EQUALSWITHDELTACONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType, typename DeltaType> | ||||
|   struct EqualsWithDeltaConstraint : Expression<EqualsWithDeltaConstraint<ExpectedType, DeltaType>> | ||||
|   { | ||||
|     EqualsWithDeltaConstraint(const ExpectedType& expected, const DeltaType& delta) | ||||
|         : m_expected(expected), m_delta(delta) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return ((m_expected <= (actual + m_delta)) && (m_expected >= (actual - m_delta))); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|     DeltaType m_delta; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType, typename DeltaType> | ||||
|   inline EqualsWithDeltaConstraint<ExpectedType, DeltaType> EqualsWithDelta(const ExpectedType& expected, const DeltaType& delta) | ||||
|   { | ||||
|     return EqualsWithDeltaConstraint<ExpectedType, DeltaType>(expected, delta); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType, typename DeltaType> | ||||
|   struct Stringizer<EqualsWithDeltaConstraint<ExpectedType, DeltaType>> | ||||
|   { | ||||
|     static std::string ToString(const EqualsWithDeltaConstraint<ExpectedType, DeltaType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "equal to " << snowhouse::Stringize(constraint.m_expected) << " (+/- " << snowhouse::Stringize(constraint.m_delta) << ")"; | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,45 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ANDEXPRESSION_H | ||||
| #define SNOWHOUSE_ANDEXPRESSION_H | ||||
|  | ||||
| #include "../../stringize.h" | ||||
| #include "expression_fwd.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename LeftExpression, typename RightExpression> | ||||
|   struct AndExpression : Expression<AndExpression<LeftExpression, RightExpression>> | ||||
|   { | ||||
|     AndExpression(const LeftExpression& left, const RightExpression& right) | ||||
|         : m_left(left), m_right(right) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (m_left(actual) && m_right(actual)); | ||||
|     } | ||||
|  | ||||
|     LeftExpression m_left; | ||||
|     RightExpression m_right; | ||||
|   }; | ||||
|  | ||||
|   template<typename LeftExpression, typename RightExpression> | ||||
|   struct Stringizer<AndExpression<LeftExpression, RightExpression>> | ||||
|   { | ||||
|     static std::string ToString(const AndExpression<LeftExpression, RightExpression>& expression) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << Stringize(expression.m_left) << " and " << Stringize(expression.m_right); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,37 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EXPRESSION_H | ||||
| #define SNOWHOUSE_EXPRESSION_H | ||||
|  | ||||
| #include "notexpression.h" | ||||
| #include "andexpression.h" | ||||
| #include "orexpression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename T> | ||||
|   struct Expression | ||||
|   { | ||||
|     NotExpression<T> operator!() const | ||||
|     { | ||||
|       return NotExpression<T>(static_cast<const T&>(*this)); | ||||
|     } | ||||
|  | ||||
|     template<typename Right> | ||||
|     AndExpression<T, Right> operator&&(const Right& right) const | ||||
|     { | ||||
|       return AndExpression<T, Right>(static_cast<const T&>(*this), right); | ||||
|     } | ||||
|  | ||||
|     template<typename Right> | ||||
|     OrExpression<T, Right> operator||(const Right& right) const | ||||
|     { | ||||
|       return OrExpression<T, Right>(static_cast<const T&>(*this), right); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,15 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EXPRESSION_FWD_H | ||||
| #define SNOWHOUSE_EXPRESSION_FWD_H | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename T> | ||||
|   struct Expression; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,44 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_NOTEXPRESSION_H | ||||
| #define SNOWHOUSE_NOTEXPRESSION_H | ||||
|  | ||||
| #include "../../stringize.h" | ||||
| #include "expression_fwd.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpressionType> | ||||
|   struct NotExpression : Expression<NotExpression<ExpressionType>> | ||||
|   { | ||||
|     explicit NotExpression(const ExpressionType& expression) | ||||
|         : m_expression(expression) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return !m_expression(actual); | ||||
|     } | ||||
|  | ||||
|     ExpressionType m_expression; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpressionType> | ||||
|   struct Stringizer<NotExpression<ExpressionType>> | ||||
|   { | ||||
|     static std::string ToString(const NotExpression<ExpressionType>& expression) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "not " << snowhouse::Stringize(expression.m_expression); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,45 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_OREXPRESSION_H | ||||
| #define SNOWHOUSE_OREXPRESSION_H | ||||
|  | ||||
| #include "../../stringize.h" | ||||
| #include "expression_fwd.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename LeftExpression, typename RightExpression> | ||||
|   struct OrExpression : Expression<OrExpression<LeftExpression, RightExpression>> | ||||
|   { | ||||
|     OrExpression(const LeftExpression& left, const RightExpression& right) | ||||
|         : m_left(left), m_right(right) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (m_left(actual) || m_right(actual)); | ||||
|     } | ||||
|  | ||||
|     LeftExpression m_left; | ||||
|     RightExpression m_right; | ||||
|   }; | ||||
|  | ||||
|   template<typename LeftExpression, typename RightExpression> | ||||
|   struct Stringizer<OrExpression<LeftExpression, RightExpression>> | ||||
|   { | ||||
|     static std::string ToString(const OrExpression<LeftExpression, RightExpression>& expression) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << snowhouse::Stringize(expression.m_left) << " or " << snowhouse::Stringize(expression.m_right); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,49 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_FULFILLSCONSTRAINT_H | ||||
| #define SNOWHOUSE_FULFILLSCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename MatcherType> | ||||
|   struct FulfillsConstraint : Expression<FulfillsConstraint<MatcherType>> | ||||
|   { | ||||
|     FulfillsConstraint(const MatcherType& matcher) | ||||
|         : m_matcher(matcher) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return m_matcher.Matches(actual); | ||||
|     } | ||||
|  | ||||
|     MatcherType m_matcher; | ||||
|   }; | ||||
|  | ||||
|   template<typename MatcherType> | ||||
|   inline FulfillsConstraint<MatcherType> Fulfills(const MatcherType& matcher) | ||||
|   { | ||||
|     return FulfillsConstraint<MatcherType>(matcher); | ||||
|   } | ||||
|  | ||||
|   template<typename MatcherType> | ||||
|   struct Stringizer<FulfillsConstraint<MatcherType>> | ||||
|   { | ||||
|     static std::string ToString(const FulfillsConstraint<MatcherType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << snowhouse::Stringize(constraint.m_matcher); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,56 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_HASLENGTHCONSTRAINT_H | ||||
| #define SNOWHOUSE_HASLENGTHCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct HasLengthConstraint : Expression<HasLengthConstraint<ExpectedType>> | ||||
|   { | ||||
|     HasLengthConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       using SizeType = typename ActualType::size_type; | ||||
|       SizeType expectedSize = static_cast<SizeType>(m_expected); | ||||
|       return (actual.size() == expectedSize); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline HasLengthConstraint<ExpectedType> HasLength(const ExpectedType& expected) | ||||
|   { | ||||
|     return HasLengthConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline HasLengthConstraint<std::string> HasLength(const char* expected) | ||||
|   { | ||||
|     return HasLengthConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<HasLengthConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const HasLengthConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "of length " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,42 @@ | ||||
| // Copyright (C) 2017 Stephan Beyer | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ISEMPTYCONSTRAINT_H | ||||
| #define SNOWHOUSE_ISEMPTYCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct IsEmptyConstraint : Expression<IsEmptyConstraint> | ||||
|   { | ||||
|     // The ignored default argument is a workaround to make this class | ||||
|     // compatible to ConstraintAdapterType | ||||
|     IsEmptyConstraint(int = 0) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return actual.empty(); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   inline IsEmptyConstraint IsEmpty() | ||||
|   { | ||||
|     return IsEmptyConstraint(); | ||||
|   } | ||||
|  | ||||
|   template<> | ||||
|   struct Stringizer<IsEmptyConstraint> | ||||
|   { | ||||
|     static std::string ToString(const IsEmptyConstraint&) | ||||
|     { | ||||
|       return "empty"; | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,54 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ISGREATERTHANCONSTRAINT_H | ||||
| #define SNOWHOUSE_ISGREATERTHANCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct IsGreaterThanConstraint : Expression<IsGreaterThanConstraint<ExpectedType>> | ||||
|   { | ||||
|     IsGreaterThanConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (actual > m_expected); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline IsGreaterThanConstraint<ExpectedType> IsGreaterThan(const ExpectedType& expected) | ||||
|   { | ||||
|     return IsGreaterThanConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline IsGreaterThanConstraint<std::string> IsGreaterThan(const char* expected) | ||||
|   { | ||||
|     return IsGreaterThanConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<IsGreaterThanConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const IsGreaterThanConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "greater than " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,54 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ISGREATERTHANOREQUALTOCONSTRAINT_H | ||||
| #define SNOWHOUSE_ISGREATERTHANOREQUALTOCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct IsGreaterThanOrEqualToConstraint : Expression<IsGreaterThanOrEqualToConstraint<ExpectedType>> | ||||
|   { | ||||
|     IsGreaterThanOrEqualToConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (actual >= m_expected); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline IsGreaterThanOrEqualToConstraint<ExpectedType> IsGreaterThanOrEqualTo(const ExpectedType& expected) | ||||
|   { | ||||
|     return IsGreaterThanOrEqualToConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline IsGreaterThanOrEqualToConstraint<std::string> IsGreaterThanOrEqualTo(const char* expected) | ||||
|   { | ||||
|     return IsGreaterThanOrEqualToConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<IsGreaterThanOrEqualToConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const IsGreaterThanOrEqualToConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "greater than or equal to " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,53 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ISLESSTHANCONSTRAINT_H | ||||
| #define SNOWHOUSE_ISLESSTHANCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct IsLessThanConstraint : Expression<IsLessThanConstraint<ExpectedType>> | ||||
|   { | ||||
|     IsLessThanConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (actual < m_expected); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline IsLessThanConstraint<ExpectedType> IsLessThan(const ExpectedType& expected) | ||||
|   { | ||||
|     return IsLessThanConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline IsLessThanConstraint<std::string> IsLessThan(const char* expected) | ||||
|   { | ||||
|     return IsLessThanConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<IsLessThanConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const IsLessThanConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "less than " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
| #endif | ||||
| @@ -0,0 +1,54 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ISLESSTHANOREQUALTOCONSTRAINT_H | ||||
| #define SNOWHOUSE_ISLESSTHANOREQUALTOCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct IsLessThanOrEqualToConstraint : Expression<IsLessThanOrEqualToConstraint<ExpectedType>> | ||||
|   { | ||||
|     IsLessThanOrEqualToConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     bool operator()(const ActualType& actual) const | ||||
|     { | ||||
|       return (actual <= m_expected); | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline IsLessThanOrEqualToConstraint<ExpectedType> IsLessThanOrEqualTo(const ExpectedType& expected) | ||||
|   { | ||||
|     return IsLessThanOrEqualToConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline IsLessThanOrEqualToConstraint<std::string> IsLessThanOrEqualTo(const char* expected) | ||||
|   { | ||||
|     return IsLessThanOrEqualToConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<IsLessThanOrEqualToConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const IsLessThanOrEqualToConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "less than or equal to " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,53 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_STARTSWITHCONSTRAINT_H | ||||
| #define SNOWHOUSE_STARTSWITHCONSTRAINT_H | ||||
|  | ||||
| #include "expressions/expression.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExpectedType> | ||||
|   struct StartsWithConstraint : Expression<StartsWithConstraint<ExpectedType>> | ||||
|   { | ||||
|     StartsWithConstraint(const ExpectedType& expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     bool operator()(const std::string& actual) const | ||||
|     { | ||||
|       return actual.find(m_expected) == 0; | ||||
|     } | ||||
|  | ||||
|     ExpectedType m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   inline StartsWithConstraint<ExpectedType> StartsWith(const ExpectedType& expected) | ||||
|   { | ||||
|     return StartsWithConstraint<ExpectedType>(expected); | ||||
|   } | ||||
|  | ||||
|   inline StartsWithConstraint<std::string> StartsWith(const char* expected) | ||||
|   { | ||||
|     return StartsWithConstraint<std::string>(expected); | ||||
|   } | ||||
|  | ||||
|   template<typename ExpectedType> | ||||
|   struct Stringizer<StartsWithConstraint<ExpectedType>> | ||||
|   { | ||||
|     static std::string ToString(const StartsWithConstraint<ExpectedType>& constraint) | ||||
|     { | ||||
|       std::ostringstream builder; | ||||
|       builder << "starts with " << snowhouse::Stringize(constraint.m_expected); | ||||
|  | ||||
|       return builder.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										134
									
								
								dep/snowhouse/include/snowhouse/exceptions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								dep/snowhouse/include/snowhouse/exceptions.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,134 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EXCEPTIONS_H | ||||
| #define SNOWHOUSE_EXCEPTIONS_H | ||||
|  | ||||
| #include "assert.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ExceptionType> | ||||
|   struct ExceptionStorage | ||||
|   { | ||||
|     static void last_exception(ExceptionType*** e, bool clear = false) | ||||
|     { | ||||
|       static ExceptionType* last = nullptr; | ||||
|       if (clear && last) | ||||
|       { | ||||
|         delete last; | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|       *e = &last; | ||||
|       silly_warning_about_unused_arg(e); | ||||
|     } | ||||
|  | ||||
|     static ExceptionType*** silly_warning_about_unused_arg(ExceptionType*** e) | ||||
|     { | ||||
|       return e; | ||||
|     } | ||||
|  | ||||
|     static void store(const ExceptionType& e) | ||||
|     { | ||||
|       ExceptionType** last = nullptr; | ||||
|       last_exception(&last); | ||||
|       if (*last) | ||||
|       { | ||||
|         delete *last; | ||||
|         *last = nullptr; | ||||
|       } | ||||
|  | ||||
|       *last = new ExceptionType(e); | ||||
|     } | ||||
|  | ||||
|     void compiler_thinks_i_am_unused() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     ~ExceptionStorage() | ||||
|     { | ||||
|       ExceptionType** e = nullptr; | ||||
|       last_exception(&e); | ||||
|       if (*e) | ||||
|       { | ||||
|         delete *e; | ||||
|         *e = nullptr; | ||||
|       } | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename ExceptionType> | ||||
|   inline ExceptionType& LastException() | ||||
|   { | ||||
|     ExceptionType** e = nullptr; | ||||
|     ExceptionStorage<ExceptionType>::last_exception(&e); | ||||
|     if (*e == nullptr) | ||||
|     { | ||||
|       Assert::Failure("No exception was stored"); | ||||
|     } | ||||
|  | ||||
|     return **e; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // clang-format off | ||||
| #define SNOWHOUSE_CONCAT2(a, b) a##b | ||||
| #define SNOWHOUSE_CONCAT(a, b) SNOWHOUSE_CONCAT2(a, b) | ||||
| #define SNOWHOUSE_LINESUFFIX(a) SNOWHOUSE_CONCAT(a, __LINE__) | ||||
| #define SNOWHOUSE_TEMPVAR(a) SNOWHOUSE_CONCAT(SNOWHOUSE_, SNOWHOUSE_LINESUFFIX(a ## _)) | ||||
|  | ||||
| #define SNOWHOUSE_ASSERT_THROWS(EXCEPTION_TYPE, METHOD, FAILURE_HANDLER_TYPE) \ | ||||
|   ::snowhouse::ExceptionStorage<EXCEPTION_TYPE> SNOWHOUSE_TEMPVAR(storage); \ | ||||
|   SNOWHOUSE_TEMPVAR(storage).compiler_thinks_i_am_unused(); \ | ||||
|   bool SNOWHOUSE_TEMPVAR(wrong_exception) = false; \ | ||||
|   bool SNOWHOUSE_TEMPVAR(no_exception) = false; \ | ||||
|   bool SNOWHOUSE_TEMPVAR(more_info) = true; \ | ||||
|   std::string SNOWHOUSE_TEMPVAR(info_string); \ | ||||
|   try \ | ||||
|   { \ | ||||
|     METHOD; \ | ||||
|     SNOWHOUSE_TEMPVAR(no_exception) = true; \ | ||||
|   } \ | ||||
|   catch (const EXCEPTION_TYPE& SNOWHOUSE_TEMPVAR(catched_exception)) \ | ||||
|   { \ | ||||
|     ::snowhouse::ExceptionStorage<EXCEPTION_TYPE>::store(SNOWHOUSE_TEMPVAR(catched_exception)); \ | ||||
|   } \ | ||||
|   catch (...) \ | ||||
|   { \ | ||||
|     SNOWHOUSE_TEMPVAR(wrong_exception) = true; \ | ||||
|     if (auto eptr = std::current_exception()) { \ | ||||
|       try { \ | ||||
|         std::rethrow_exception(eptr); \ | ||||
|       } catch (const std::exception& e) { \ | ||||
|         SNOWHOUSE_TEMPVAR(more_info) = true; \ | ||||
|         SNOWHOUSE_TEMPVAR(info_string) = e.what(); \ | ||||
|       } catch (...) {} \ | ||||
|     } \ | ||||
|   } \ | ||||
|   if (SNOWHOUSE_TEMPVAR(no_exception)) \ | ||||
|   { \ | ||||
|     ::std::ostringstream SNOWHOUSE_TEMPVAR(stm); \ | ||||
|     SNOWHOUSE_TEMPVAR(stm) << "Expected " #EXCEPTION_TYPE ". No exception was thrown."; \ | ||||
|     ::snowhouse::ConfigurableAssert<FAILURE_HANDLER_TYPE>::Failure(SNOWHOUSE_TEMPVAR(stm).str()); \ | ||||
|   } \ | ||||
|   if (SNOWHOUSE_TEMPVAR(wrong_exception)) \ | ||||
|   { \ | ||||
|     ::std::ostringstream SNOWHOUSE_TEMPVAR(stm); \ | ||||
|     SNOWHOUSE_TEMPVAR(stm) << "Expected " #EXCEPTION_TYPE ". Wrong exception was thrown."; \ | ||||
|     if (SNOWHOUSE_TEMPVAR(more_info)) { \ | ||||
|       SNOWHOUSE_TEMPVAR(stm) << " Description of unwanted exception: " << SNOWHOUSE_TEMPVAR(info_string); \ | ||||
|     } \ | ||||
|     ::snowhouse::ConfigurableAssert<FAILURE_HANDLER_TYPE>::Failure(SNOWHOUSE_TEMPVAR(stm).str()); \ | ||||
|   } \ | ||||
|   do {} while (false) | ||||
|  | ||||
| #ifndef SNOWHOUSE_NO_MACROS | ||||
| # define AssertThrows(EXCEPTION_TYPE, METHOD) \ | ||||
|   SNOWHOUSE_ASSERT_THROWS(EXCEPTION_TYPE, (METHOD), ::snowhouse::DefaultFailureHandler) | ||||
| #endif | ||||
| // clang-format on | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										42
									
								
								dep/snowhouse/include/snowhouse/fluent/constraintadapter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								dep/snowhouse/include/snowhouse/fluent/constraintadapter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_CONSTRAINTADAPTER_H | ||||
| #define SNOWHOUSE_CONSTRAINTADAPTER_H | ||||
|  | ||||
| #include "../stringize.h" | ||||
| #include "constraintlist.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ConstraintType> | ||||
|   struct ConstraintAdapter | ||||
|   { | ||||
|     explicit ConstraintAdapter(const ConstraintType& constraint) | ||||
|         : m_constraint(constraint) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ConstraintListType, typename ActualType> | ||||
|     void Evaluate(ConstraintListType& list, ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       result.push(m_constraint(actual)); | ||||
|       EvaluateConstraintList(list.m_tail, result, operators, actual); | ||||
|     } | ||||
|  | ||||
|     ConstraintType m_constraint; | ||||
|   }; | ||||
|  | ||||
|   template<typename ConstraintType> | ||||
|   struct Stringizer<ConstraintAdapter<ConstraintType>> | ||||
|   { | ||||
|     static std::string ToString(const ConstraintAdapter<ConstraintType>& constraintAdapter) | ||||
|     { | ||||
|       return snowhouse::Stringize(constraintAdapter.m_constraint); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										102
									
								
								dep/snowhouse/include/snowhouse/fluent/constraintlist.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								dep/snowhouse/include/snowhouse/fluent/constraintlist.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_CONSTRAINTLIST_H | ||||
| #define SNOWHOUSE_CONSTRAINTLIST_H | ||||
|  | ||||
| #include <stack> | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct ConstraintOperator; | ||||
|   using ResultStack = std::stack<bool>; | ||||
|   using OperatorStack = std::stack<ConstraintOperator*>; | ||||
|  | ||||
|   template<typename HT, typename TT> | ||||
|   struct ConstraintList | ||||
|   { | ||||
|     using HeadType = HT; | ||||
|     using TailType = TT; | ||||
|  | ||||
|     ConstraintList(const HeadType& head, const TailType& tail) | ||||
|         : m_head(head), m_tail(tail) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     HeadType m_head; | ||||
|     TailType m_tail; | ||||
|   }; | ||||
|  | ||||
|   struct Nil | ||||
|   { | ||||
|     Nil() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     Nil(const Nil&) | ||||
|     { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   // ---- These structs defines the resulting types of list concatenation operations | ||||
|   template<typename L1, typename L2> | ||||
|   struct type_concat | ||||
|   { | ||||
|     using t = ConstraintList<typename L1::HeadType, typename type_concat<typename L1::TailType, L2>::t>; | ||||
|   }; | ||||
|  | ||||
|   template<typename L2> | ||||
|   struct type_concat<Nil, L2> | ||||
|   { | ||||
|     using t = L2; | ||||
|   }; | ||||
|  | ||||
|   template<typename L3> | ||||
|   inline L3 tr_concat(const Nil&, const Nil&) | ||||
|   { | ||||
|     return Nil(); | ||||
|   } | ||||
|  | ||||
|   // ---- These structs define the concatenation operations. | ||||
|  | ||||
|   template<typename LeftList, typename RightList, typename ResultList> | ||||
|   struct ListConcat | ||||
|   { | ||||
|     static ResultList Concatenate(const LeftList& left, const RightList& right) | ||||
|     { | ||||
|       return ResultList(left.m_head, ListConcat<typename LeftList::TailType, RightList, typename type_concat<typename LeftList::TailType, RightList>::t>::Concatenate(left.m_tail, right)); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   // Concatenating an empty list with a second list yields the second list | ||||
|   template<typename RightList, typename ResultList> | ||||
|   struct ListConcat<Nil, RightList, ResultList> | ||||
|   { | ||||
|     static ResultList Concatenate(const Nil&, const RightList& right) | ||||
|     { | ||||
|       return right; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   // Concatenating two empty lists yields an empty list | ||||
|   template<typename ResultList> | ||||
|   struct ListConcat<Nil, Nil, ResultList> | ||||
|   { | ||||
|     static ResultList Concatenate(const Nil&, const Nil&) | ||||
|     { | ||||
|       return Nil(); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   // ---- The concatenation operation | ||||
|  | ||||
|   template<typename L1, typename L2> | ||||
|   inline typename type_concat<L1, L2>::t Concatenate(const L1& list1, const L2& list2) | ||||
|   { | ||||
|     return ListConcat<L1, L2, typename type_concat<L1, L2>::t>::Concatenate(list1, list2); | ||||
|   } | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										365
									
								
								dep/snowhouse/include/snowhouse/fluent/expressionbuilder.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										365
									
								
								dep/snowhouse/include/snowhouse/fluent/expressionbuilder.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,365 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_EXPRESSIONBUILDER_H | ||||
| #define SNOWHOUSE_EXPRESSIONBUILDER_H | ||||
|  | ||||
| #include "../constraints/constraints.h" | ||||
| #include "constraintadapter.h" | ||||
| #include "operators/andoperator.h" | ||||
| #include "operators/notoperator.h" | ||||
| #include "operators/oroperator.h" | ||||
| #include "operators/collections/alloperator.h" | ||||
| #include "operators/collections/noneoperator.h" | ||||
| #include "operators/collections/atleastoperator.h" | ||||
| #include "operators/collections/exactlyoperator.h" | ||||
| #include "operators/collections/atmostoperator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   // ---- Evaluation of list of constraints | ||||
|  | ||||
|   template<typename ConstraintListType, typename ActualType> | ||||
|   inline void EvaluateConstraintList(ConstraintListType& constraint_list, ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|   { | ||||
|     constraint_list.m_head.Evaluate(constraint_list, result, operators, actual); | ||||
|   } | ||||
|  | ||||
|   template<typename ActualType> | ||||
|   inline void EvaluateConstraintList(Nil&, ResultStack&, OperatorStack&, const ActualType&) | ||||
|   { | ||||
|   } | ||||
|  | ||||
|   template<typename ConstraintListType> | ||||
|   struct ExpressionBuilder | ||||
|   { | ||||
|     explicit ExpressionBuilder(const ConstraintListType& list) | ||||
|         : m_constraint_list(list) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsConstraint<ExpectedType>>, Nil>>::t> | ||||
|     EqualTo(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<EqualsConstraint<ExpectedType>>; | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|  | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|  | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType, typename DeltaType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsWithDeltaConstraint<ExpectedType, DeltaType>>, Nil>>::t> | ||||
|     EqualToWithDelta(const ExpectedType& expected, const DeltaType& delta) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<EqualsWithDeltaConstraint<ExpectedType, DeltaType>>; | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|  | ||||
|       ConstraintAdapterType constraint(EqualsWithDeltaConstraint<ExpectedType, DeltaType>(expected, delta)); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|  | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename MatcherType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<FulfillsConstraint<MatcherType>>, Nil>>::t> | ||||
|     Fulfilling(const MatcherType& matcher) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<FulfillsConstraint<MatcherType>>; | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|  | ||||
|       ConstraintAdapterType constraint(matcher); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|  | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsConstraint<bool>>, Nil>>::t> | ||||
|     False() | ||||
|     { | ||||
|       return EqualTo<bool>(false); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsConstraint<bool>>, Nil>>::t> | ||||
|     True() | ||||
|     { | ||||
|       return EqualTo<bool>(true); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsConstraint<std::nullptr_t>>, Nil>>::t> | ||||
|     Null() | ||||
|     { | ||||
|       return EqualTo<std::nullptr_t>(nullptr); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsConstraint<std::string>>, Nil>>::t> | ||||
|     EqualTo(const char* expected) | ||||
|     { | ||||
|       return EqualTo<std::string>(std::string(expected)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<IsGreaterThanConstraint<ExpectedType>>, Nil>>::t> | ||||
|     GreaterThan(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<IsGreaterThanConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<IsGreaterThanOrEqualToConstraint<ExpectedType>>, Nil>>::t> | ||||
|     GreaterThanOrEqualTo(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<IsGreaterThanOrEqualToConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<IsLessThanConstraint<ExpectedType>>, Nil>>::t> | ||||
|     LessThan(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<IsLessThanConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<IsLessThanOrEqualToConstraint<ExpectedType>>, Nil>>::t> | ||||
|     LessThanOrEqualTo(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<IsLessThanOrEqualToConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<ContainsConstraint<ExpectedType>>, Nil>>::t> | ||||
|     Containing(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<ContainsConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<ContainsConstraint<std::string>>, Nil>>::t> | ||||
|     Containing(const char* expected) | ||||
|     { | ||||
|       return Containing<std::string>(std::string(expected)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EndsWithConstraint<ExpectedType>>, Nil>>::t> | ||||
|     EndingWith(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<EndsWithConstraint<ExpectedType>>; | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|  | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EndsWithConstraint<std::string>>, Nil>>::t> | ||||
|     EndingWith(const char* expected) | ||||
|     { | ||||
|       return EndingWith(std::string(expected)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<StartsWithConstraint<ExpectedType>>, Nil>>::t> | ||||
|     StartingWith(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<StartsWithConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<StartsWithConstraint<std::string>>, Nil>>::t> | ||||
|     StartingWith(const char* expected) | ||||
|     { | ||||
|       return StartingWith(std::string(expected)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<HasLengthConstraint<ExpectedType>>, Nil>>::t> | ||||
|     OfLength(const ExpectedType& expected) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<HasLengthConstraint<ExpectedType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(expected); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<IsEmptyConstraint>, Nil>>::t> | ||||
|     Empty() | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<IsEmptyConstraint>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(0); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsContainerConstraint<ExpectedType, bool (*)(const typename ExpectedType::value_type&, const typename ExpectedType::value_type&)>>, Nil>>::t> | ||||
|     EqualToContainer(const ExpectedType& expected) | ||||
|     { | ||||
|       using DefaultBinaryPredicateType = bool (*)(const typename ExpectedType::value_type&, const typename ExpectedType::value_type&); | ||||
|       using ConstraintAdapterType = ConstraintAdapter<EqualsContainerConstraint<ExpectedType, DefaultBinaryPredicateType>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(EqualsContainerConstraint<ExpectedType, DefaultBinaryPredicateType>(expected, constraint_internal::default_comparer<typename ExpectedType::value_type>)); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ExpectedType, typename BinaryPredicate> | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapter<EqualsContainerConstraint<ExpectedType, BinaryPredicate>>, Nil>>::t> | ||||
|     EqualToContainer(const ExpectedType& expected, const BinaryPredicate predicate) | ||||
|     { | ||||
|       using ConstraintAdapterType = ConstraintAdapter<EqualsContainerConstraint<ExpectedType, BinaryPredicate>>; | ||||
|  | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ConstraintList<ConstraintAdapterType, Nil>>::t>; | ||||
|       ConstraintAdapterType constraint(EqualsContainerConstraint<ExpectedType, BinaryPredicate>(expected, predicate)); | ||||
|       ConstraintList<ConstraintAdapterType, Nil> node(constraint, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     using AndOperatorNode = ConstraintList<AndOperator, Nil>; | ||||
|     using OrOperatorNode = ConstraintList<OrOperator, Nil>; | ||||
|     using NotOperatorNode = ConstraintList<NotOperator, Nil>; | ||||
|     using AllOperatorNode = ConstraintList<AllOperator, Nil>; | ||||
|     using AtLeastOperatorNode = ConstraintList<AtLeastOperator, Nil>; | ||||
|     using ExactlyOperatorNode = ConstraintList<ExactlyOperator, Nil>; | ||||
|     using AtMostOperatorNode = ConstraintList<AtMostOperator, Nil>; | ||||
|     using NoneOperatorNode = ConstraintList<NoneOperator, Nil>; | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, AllOperatorNode>::t> All() | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, AllOperatorNode>::t>; | ||||
|       AllOperator op; | ||||
|       AllOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, AtLeastOperatorNode>::t> AtLeast(unsigned int expected) | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, AtLeastOperatorNode>::t>; | ||||
|       AtLeastOperator op(expected); | ||||
|       AtLeastOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, ExactlyOperatorNode>::t> Exactly(unsigned int expected) | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, ExactlyOperatorNode>::t>; | ||||
|       ExactlyOperator op(expected); | ||||
|       ExactlyOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, AtMostOperatorNode>::t> AtMost(unsigned int expected) | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, AtMostOperatorNode>::t>; | ||||
|       AtMostOperator op(expected); | ||||
|       AtMostOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, NoneOperatorNode>::t> None() | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, NoneOperatorNode>::t>; | ||||
|       NoneOperator op; | ||||
|       NoneOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, AndOperatorNode>::t> And() | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, AndOperatorNode>::t>; | ||||
|       AndOperator op; | ||||
|       AndOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, OrOperatorNode>::t> Or() | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, OrOperatorNode>::t>; | ||||
|       OrOperator op; | ||||
|       OrOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     ExpressionBuilder<typename type_concat<ConstraintListType, NotOperatorNode>::t> Not() | ||||
|     { | ||||
|       using BuilderType = ExpressionBuilder<typename type_concat<ConstraintListType, NotOperatorNode>::t>; | ||||
|       NotOperator op; | ||||
|       NotOperatorNode node(op, Nil()); | ||||
|       return BuilderType(Concatenate(m_constraint_list, node)); | ||||
|     } | ||||
|  | ||||
|     template<typename ActualType> | ||||
|     void Evaluate(ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       EvaluateConstraintList(m_constraint_list, result, operators, actual); | ||||
|     } | ||||
|  | ||||
|     ConstraintListType m_constraint_list; | ||||
|   }; | ||||
|  | ||||
|   template<typename T> | ||||
|   inline void StringizeConstraintList(const T& list, std::ostringstream& stm) | ||||
|   { | ||||
|     if (stm.tellp() > 0) | ||||
|       stm << " "; | ||||
|  | ||||
|     stm << snowhouse::Stringize(list.m_head); | ||||
|     StringizeConstraintList(list.m_tail, stm); | ||||
|   } | ||||
|  | ||||
|   inline void StringizeConstraintList(const Nil&, std::ostringstream&) | ||||
|   { | ||||
|   } | ||||
|  | ||||
|   template<typename ConstraintListType> | ||||
|   struct Stringizer<ExpressionBuilder<ConstraintListType>> | ||||
|   { | ||||
|     static std::string ToString(const ExpressionBuilder<ConstraintListType>& builder) | ||||
|     { | ||||
|       std::ostringstream stm; | ||||
|       StringizeConstraintList(builder.m_constraint_list, stm); | ||||
|  | ||||
|       return stm.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										24
									
								
								dep/snowhouse/include/snowhouse/fluent/fluent.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								dep/snowhouse/include/snowhouse/fluent/fluent.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_FLUENT_H | ||||
| #define SNOWHOUSE_FLUENT_H | ||||
|  | ||||
| #include "expressionbuilder.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   inline ExpressionBuilder<Nil> Is() | ||||
|   { | ||||
|     return ExpressionBuilder<Nil>(Nil()); | ||||
|   } | ||||
|  | ||||
|   inline ExpressionBuilder<Nil> Has() | ||||
|   { | ||||
|     return ExpressionBuilder<Nil>(Nil()); | ||||
|   } | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,55 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ANDOPERATOR_H | ||||
| #define SNOWHOUSE_ANDOPERATOR_H | ||||
|  | ||||
| #include "constraintoperator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct AndOperator : public ConstraintOperator | ||||
|   { | ||||
|     template<typename ConstraintListType, typename ActualType> | ||||
|     void Evaluate(ConstraintListType& list, ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       EvaluateOperatorsWithLessOrEqualPrecedence(*this, operators, result); | ||||
|  | ||||
|       operators.push(this); | ||||
|  | ||||
|       EvaluateConstraintList(list.m_tail, result, operators, actual); | ||||
|     } | ||||
|  | ||||
|     void PerformOperation(ResultStack& result) override | ||||
|     { | ||||
|       if (result.size() < 2) | ||||
|       { | ||||
|         throw InvalidExpressionException("The expression contains an \"and\" operator with too few operands"); | ||||
|       } | ||||
|  | ||||
|       bool right = result.top(); | ||||
|       result.pop(); | ||||
|       bool left = result.top(); | ||||
|       result.pop(); | ||||
|  | ||||
|       result.push(left && right); | ||||
|     } | ||||
|  | ||||
|     int Precedence() const override | ||||
|     { | ||||
|       return 3; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<> | ||||
|   struct Stringizer<AndOperator> | ||||
|   { | ||||
|     static std::string ToString(const AndOperator&) | ||||
|     { | ||||
|       return "and"; | ||||
|     } | ||||
|   }; | ||||
| } | ||||
| #endif | ||||
| @@ -0,0 +1,35 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ALLOPERATOR_H | ||||
| #define SNOWHOUSE_ALLOPERATOR_H | ||||
|  | ||||
| #include "collectionoperator.h" | ||||
| #include "collectionconstraintevaluator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct AllOperator : public CollectionOperator | ||||
|   { | ||||
|     template<typename ConstraintListType, typename ActualType> | ||||
|     void Evaluate(ConstraintListType& list, ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       unsigned int passed_elements = CollectionConstraintEvaluator<ConstraintListType, ActualType>::Evaluate(*this, list, result, operators, actual); | ||||
|  | ||||
|       result.push(passed_elements == actual.size()); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<> | ||||
|   struct Stringizer<AllOperator> | ||||
|   { | ||||
|     static std::string ToString(const AllOperator&) | ||||
|     { | ||||
|       return "all"; | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,44 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ATLEASTOPERATOR_H | ||||
| #define SNOWHOUSE_ATLEASTOPERATOR_H | ||||
|  | ||||
| #include "collectionoperator.h" | ||||
| #include "collectionconstraintevaluator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct AtLeastOperator : public CollectionOperator | ||||
|   { | ||||
|     explicit AtLeastOperator(unsigned int expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ConstraintListType, typename ActualType> | ||||
|     void Evaluate(ConstraintListType& list, ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       unsigned int passed_elements = CollectionConstraintEvaluator<ConstraintListType, ActualType>::Evaluate(*this, list, result, operators, actual); | ||||
|  | ||||
|       result.push(passed_elements >= m_expected); | ||||
|     } | ||||
|  | ||||
|     unsigned int m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<> | ||||
|   struct Stringizer<AtLeastOperator> | ||||
|   { | ||||
|     static std::string ToString(const AtLeastOperator& op) | ||||
|     { | ||||
|       std::ostringstream stm; | ||||
|       stm << "at least " << op.m_expected; | ||||
|       return stm.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,44 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_ATMOSTOPERATOR_H | ||||
| #define SNOWHOUSE_ATMOSTOPERATOR_H | ||||
|  | ||||
| #include "collectionoperator.h" | ||||
| #include "collectionconstraintevaluator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct AtMostOperator : public CollectionOperator | ||||
|   { | ||||
|     explicit AtMostOperator(unsigned int expected) | ||||
|         : m_expected(expected) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<typename ConstraintListType, typename ActualType> | ||||
|     void Evaluate(ConstraintListType& list, ResultStack& result, OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       unsigned int passed_elements = CollectionConstraintEvaluator<ConstraintListType, ActualType>::Evaluate(*this, list, result, operators, actual); | ||||
|  | ||||
|       result.push(passed_elements <= m_expected); | ||||
|     } | ||||
|  | ||||
|     unsigned int m_expected; | ||||
|   }; | ||||
|  | ||||
|   template<> | ||||
|   struct Stringizer<AtMostOperator> | ||||
|   { | ||||
|     static std::string ToString(const AtMostOperator& op) | ||||
|     { | ||||
|       std::ostringstream stm; | ||||
|       stm << "at most " << op.m_expected; | ||||
|       return stm.str(); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,110 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_COLLECTIONCONSTRAINTEVALUATOR_H | ||||
| #define SNOWHOUSE_COLLECTIONCONSTRAINTEVALUATOR_H | ||||
|  | ||||
| #include <vector> | ||||
|  | ||||
| #include "../constraintoperator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   template<typename ConstraintListType, typename ActualType> | ||||
|   struct CollectionConstraintEvaluator | ||||
|   { | ||||
|     static unsigned int Evaluate(const ConstraintOperator& op, | ||||
|         ConstraintListType& expression, ResultStack& result, | ||||
|         OperatorStack& operators, const ActualType& actual) | ||||
|     { | ||||
|       ConstraintOperator::EvaluateOperatorsWithLessOrEqualPrecedence(op, | ||||
|           operators, result); | ||||
|  | ||||
|       unsigned int passed_elements = 0; | ||||
|       for (const auto& member : actual) | ||||
|       { | ||||
|         if (ConstraintOperator::EvaluateElementAgainstRestOfExpression(expression, member)) | ||||
|         { | ||||
|           ++passed_elements; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       return passed_elements; | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   struct StringLineParser | ||||
|   { | ||||
|     static void Parse(const std::string& str, std::vector<std::string>& res) | ||||
|     { | ||||
|       size_t start = 0; | ||||
|       size_t newline = FindNewline(str, start); | ||||
|  | ||||
|       while (newline != std::string::npos) | ||||
|       { | ||||
|         StoreLine(str, start, newline, res); | ||||
|         start = MoveToNextLine(str, newline); | ||||
|         newline = FindNewline(str, start); | ||||
|       } | ||||
|  | ||||
|       if (start < str.size()) | ||||
|       { | ||||
|         StoreLine(str, start, std::string::npos, res); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|   private: | ||||
|     static size_t FindNewline(const std::string& str, size_t start) | ||||
|     { | ||||
|       return str.find_first_of("\r\n", start); | ||||
|     } | ||||
|  | ||||
|     static void StoreLine(const std::string& str, size_t start, size_t end, | ||||
|         std::vector<std::string>& res) | ||||
|     { | ||||
|       std::string line = str.substr(start, end - start); | ||||
|       res.push_back(line); | ||||
|     } | ||||
|  | ||||
|     static size_t MoveToNextLine(const std::string& str, size_t newline) | ||||
|     { | ||||
|       if (str.find("\r\n", newline) == newline) | ||||
|       { | ||||
|         return newline + 2; | ||||
|       } | ||||
|  | ||||
|       if (str.find('\n', newline) == newline) | ||||
|       { | ||||
|         return newline + 1; | ||||
|       } | ||||
|  | ||||
|       if (str.find('\r', newline) == newline) | ||||
|       { | ||||
|         return newline + 1; | ||||
|       } | ||||
|  | ||||
|       std::ostringstream stm; | ||||
|       stm << "This string seems to contain an invalid line ending at position " | ||||
|           << newline << ":" << std::endl | ||||
|           << str << std::endl; | ||||
|       throw InvalidExpressionException(stm.str()); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   template<typename ConstraintListType> | ||||
|   struct CollectionConstraintEvaluator<ConstraintListType, std::string> | ||||
|   { | ||||
|     static unsigned int Evaluate(const ConstraintOperator& op, | ||||
|         ConstraintListType& expression, ResultStack& result, | ||||
|         OperatorStack& operators, const std::string& actual) | ||||
|     { | ||||
|       std::vector<std::string> lines; | ||||
|       StringLineParser::Parse(actual, lines); | ||||
|       return CollectionConstraintEvaluator<ConstraintListType, std::vector<std::string>>::Evaluate(op, expression, result, operators, lines); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,26 @@ | ||||
| //          Copyright Joakim Karlsson & Kim Gräsman 2010-2012. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| //    (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //          http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #ifndef SNOWHOUSE_COLLECTIONOPERATOR_H | ||||
| #define SNOWHOUSE_COLLECTIONOPERATOR_H | ||||
|  | ||||
| #include "../constraintoperator.h" | ||||
|  | ||||
| namespace snowhouse | ||||
| { | ||||
|   struct CollectionOperator : public ConstraintOperator | ||||
|   { | ||||
|     void PerformOperation(ResultStack&) override | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     int Precedence() const override | ||||
|     { | ||||
|       return 1; | ||||
|     } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| #endif | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user