Compare commits
658 Commits
release-2.
...
main
Author | SHA1 | Date |
---|---|---|
Ryan C. Gordon | 9266e773d3 | |
Ryan C. Gordon | fdd38a3f8a | |
Ryan C. Gordon | 6a7625cd77 | |
Ozkan Sezer | 49662cd826 | |
Ryan C. Gordon | 4d9bcc3d1a | |
Ryan C. Gordon | 496817a9e8 | |
Ozkan Sezer | 0d4e9aac45 | |
Ozkan Sezer | 65195f9c1a | |
Ozkan Sezer | fb0901b10f | |
Ryan C. Gordon | f0c7367b0f | |
Ozkan Sezer | e32221a104 | |
Ozkan Sezer | cfbbb255a2 | |
Anonymous Maarten | 2a90b1f469 | |
Anonymous Maarten | 88ef84c053 | |
Anonymous Maarten | 9bc66b6469 | |
Anonymous Maarten | aabb732caf | |
Ryan C. Gordon | 6925c1067d | |
Ryan C. Gordon | 64807353df | |
Ryan C. Gordon | ed4ab15524 | |
Ryan C. Gordon | 48e7c2e3af | |
Ryan C. Gordon | 497934818b | |
Ryan C. Gordon | 17b691b0ea | |
Ozkan Sezer | 14691399cd | |
Ozkan Sezer | 20e90ed3c4 | |
Ozkan Sezer | eec3f7f79a | |
Ryan C. Gordon | 3a3c552e50 | |
Ryan C. Gordon | b975bb679b | |
Ozkan Sezer | 0ae9467685 | |
Ozkan Sezer | cd2e055454 | |
Ozkan Sezer | 141dccb087 | |
Ozkan Sezer | 3abe069870 | |
Ozkan Sezer | 02b6a7f084 | |
Ryan C. Gordon | 045ee2cb7f | |
Ryan C. Gordon | a329a35993 | |
Semphris | 7305ee92a2 | |
past-due | a0dfe220ff | |
alfadur | b3cca6a026 | |
alfadur | 8eab55d173 | |
Arthur Brianville (Ybalrid) | 23690f316d | |
pastdue | b8fa8fdcac | |
pastdue | a9cb20772b | |
James Le Cuirot | d8ba1a935c | |
Ryan C. Gordon | 0145431345 | |
Ryan C. Gordon | b7410d673e | |
Ryan C. Gordon | fdf308fa88 | |
Matthew Albrecht | d24ce15922 | |
Ryan C. Gordon | 69a7428787 | |
Ryan C. Gordon | ebe02ceb02 | |
Ryan C. Gordon | 9b83066716 | |
Ryan C. Gordon | 13f00546a9 | |
Ryan C. Gordon | 5ea6ba7557 | |
Ryan C. Gordon | 009be5ab20 | |
Ryan C. Gordon | 55c3d9f9d8 | |
Ryan C. Gordon | 22297e7ea2 | |
Ryan C. Gordon | 00599b7dac | |
Ryan C. Gordon | 3169a5e9d3 | |
Ryan C. Gordon | 101ec3c831 | |
Ryan C. Gordon | e3231d1cb0 | |
Ryan C. Gordon | 9d61fadd3e | |
Ryan C. Gordon | 235e31c420 | |
Ryan C. Gordon | 291cad07b7 | |
Ryan C. Gordon | 0d1df744ba | |
Ryan C. Gordon | 08dc47a72b | |
Ryan C. Gordon | 1daf787fb2 | |
Ryan C. Gordon | 56aaae4949 | |
Ryan C. Gordon | 19ea59109d | |
Ryan C. Gordon | a8180f0e4c | |
Ryan C. Gordon | 9cb45dc6cb | |
Kevin d'Orange | 8791811909 | |
Ryan C. Gordon | f94ce0613d | |
Ryan C. Gordon | 6b0839051f | |
Ryan C. Gordon | 5cbb460bcd | |
Ryan C. Gordon | e549fe0e0f | |
Ryan C. Gordon | 736d0b371a | |
Ryan C. Gordon | 28ac5794b1 | |
Ryan C. Gordon | 500033f37d | |
Ryan C. Gordon | b57d8960e8 | |
Ryan C. Gordon | 5786a58628 | |
Ryan C. Gordon | 73d66441e3 | |
Ryan C. Gordon | 7d194a8a62 | |
Ryan C. Gordon | 8ce294a458 | |
Ryan C. Gordon | 15dd00659a | |
Ryan C. Gordon | 7394c07d6b | |
Ryan C. Gordon | 0bad12d401 | |
Ryan C. Gordon | 89d4809f28 | |
Ryan C. Gordon | ea90a92016 | |
Ryan C. Gordon | 3597a7b69a | |
Ryan C. Gordon | c86895264b | |
Ryan C. Gordon | 47b0e834dc | |
Ryan C. Gordon | 90dfc49f6d | |
Ryan C. Gordon | a45afc5d50 | |
Ryan C. Gordon | 62d24e228f | |
Ryan C. Gordon | 26db9376da | |
Ryan C. Gordon | 1c7945461d | |
Ryan C. Gordon | f5e5b586c7 | |
Ryan C. Gordon | fbb8ce7e2d | |
Ryan C. Gordon | 347bb7b6c8 | |
Ryan C. Gordon | 9e756312d5 | |
Ryan C. Gordon | 975b7a577b | |
R?mi Verschelde | 3167a48675 | |
Ryan C. Gordon | bb2c38cdea | |
Ryan C. Gordon | 9b42fe23fd | |
Ryan C. Gordon | 300beeda72 | |
Ryan C. Gordon | 1722e9ba92 | |
Ryan C. Gordon | 4ca60a090b | |
Ryan C. Gordon | 3d8817346d | |
Ryan C. Gordon | 425131ccda | |
Ryan C. Gordon | 2b78f64c11 | |
Ryan C. Gordon | 395b2b02dd | |
Ryan C. Gordon | 69d3df3286 | |
Ryan C. Gordon | 7a26b83733 | |
Francesco Bertolaccini | e728c65912 | |
Marty Plummer | db700fd327 | |
Ryan C. Gordon | 21b2fd39f2 | |
Ryan C. Gordon | bc2ddf0a53 | |
Ryan C. Gordon | 9f8ecb91cb | |
Ryan C. Gordon | eb75883226 | |
Ryan C. Gordon | 689333dc8f | |
Ryan C. Gordon | 6ad71878fe | |
Ryan C. Gordon | 4e0d3d55e9 | |
Ryan C. Gordon | 5fb9119ebc | |
Ryan C. Gordon | 7607eeeb00 | |
Ryan C. Gordon | e19422cc06 | |
Ryan C. Gordon | cd0ccf64ed | |
Ryan C. Gordon | 98278f787b | |
Ryan C. Gordon | 2270b3c3c2 | |
Ryan C. Gordon | b311ee44ad | |
Ryan C. Gordon | 735fd14ea4 | |
Ryan C. Gordon | 8dfd3cff8d | |
Ryan C. Gordon | 692d5e8219 | |
Ryan C. Gordon | a65a7ed7a5 | |
Ryan C. Gordon | 0d1a73fce4 | |
Ryan C. Gordon | 395ea71990 | |
Ryan C. Gordon | 660171f79f | |
Ryan C. Gordon | f425f051db | |
Ryan C. Gordon | 8db27a1236 | |
Ryan C. Gordon | cfe3f0180b | |
Ryan C. Gordon | 3b7ee3974c | |
Ryan C. Gordon | 63277e500c | |
Ryan C. Gordon | 3078acd1eb | |
Ryan C. Gordon | 2a6215394b | |
Ryan C. Gordon | 88e7f3eb0f | |
Ryan C. Gordon | 9c9325c2c5 | |
Ryan C. Gordon | dd68246737 | |
Ryan C. Gordon | 1364f6a915 | |
Ryan C. Gordon | 0d61295781 | |
Ryan C. Gordon | cc3ac9539e | |
Ryan C. Gordon | 7fcddfb741 | |
Ryan C. Gordon | 6da5bea804 | |
Ryan C. Gordon | f6a8533ba2 | |
Ryan C. Gordon | db2201e4e1 | |
Ryan C. Gordon | ee9687bca9 | |
Ryan C. Gordon | b082bc3432 | |
Ryan C. Gordon | 78c1a985ec | |
Ryan C. Gordon | 15048fbb1d | |
Ryan C. Gordon | d1f2637ca8 | |
Ryan C. Gordon | 587ec88a0d | |
Ryan C. Gordon | 1efdb62a8f | |
Ryan C. Gordon | 0e778b0b16 | |
Ryan C. Gordon | 961c0604dc | |
Ryan C. Gordon | c52be25d1e | |
Ryan C. Gordon | 982411ec8a | |
Ryan C. Gordon | 0a730433ae | |
Ryan C. Gordon | ca4d5be5f8 | |
Ryan C. Gordon | eb46d82500 | |
Ryan C. Gordon | af555317b9 | |
Ryan C. Gordon | f0eb5c0db9 | |
Ryan C. Gordon | 0287160f3c | |
Ryan C. Gordon | 1d6c519c5e | |
Ryan C. Gordon | 2176364a16 | |
Ryan C. Gordon | 36c51d40d1 | |
Ryan C. Gordon | 114bfd1b21 | |
Ryan C. Gordon | a7ce178eec | |
Ryan C. Gordon | 121ee38fde | |
Ryan C. Gordon | 61bdee4d78 | |
Ryan C. Gordon | 248167af40 | |
Ryan C. Gordon | be9bf023d0 | |
Ryan C. Gordon | befc894b1f | |
Ryan C. Gordon | b6e139fc22 | |
Ryan C. Gordon | 0d249cae36 | |
Ryan C. Gordon | cc2c29b207 | |
Ryan C. Gordon | 093dcb555b | |
Ryan C. Gordon | 3f9ffddc83 | |
Ryan C. Gordon | 1e850d32ea | |
Ryan C. Gordon | 007c2fc037 | |
Ryan C. Gordon | bea510def0 | |
Ryan C. Gordon | 02c2c4736e | |
Ryan C. Gordon | 5ab8df339d | |
Ryan C. Gordon | 32930ef41d | |
Ryan C. Gordon | 99992bb1d5 | |
Ryan C. Gordon | 0e7f3ee6a1 | |
Ryan C. Gordon | f578f85557 | |
Ryan C. Gordon | 1e2650b6fc | |
Ryan C. Gordon | c74f4cb007 | |
Ryan C. Gordon | a5461ddcd9 | |
Ryan C. Gordon | 8c13bd27d6 | |
Ryan C. Gordon | bc28fb74b4 | |
Ryan C. Gordon | e2750bff62 | |
Ryan C. Gordon | 6d91dde273 | |
Ryan C. Gordon | 1fa4be6f66 | |
Ryan C. Gordon | f10b861036 | |
Ryan C. Gordon | e75d38adf5 | |
Ryan C. Gordon | ea29339a8b | |
Ryan C. Gordon | db349bd067 | |
Ryan C. Gordon | 18c89c1cbc | |
Ryan C. Gordon | d9f040cb6a | |
Ryan C. Gordon | ace324cdc8 | |
Ryan C. Gordon | c1defd3ec4 | |
Ryan C. Gordon | eefc757398 | |
Ryan C. Gordon | 6ed2bf1478 | |
Ryan C. Gordon | 8ee7f5d351 | |
Ryan C. Gordon | a7616f3960 | |
Ryan C. Gordon | 03097332ca | |
Ryan C. Gordon | 3c9351c0ad | |
Ryan C. Gordon | 91a19982ca | |
Ryan C. Gordon | 2dd3d7c28a | |
Ryan C. Gordon | d3ac612b61 | |
Ryan C. Gordon | 32ed71db48 | |
Ryan C. Gordon | 7e30657f54 | |
Ryan C. Gordon | adb7ea4dfc | |
Ryan C. Gordon | 28f32ad240 | |
Ryan C. Gordon | 823061758b | |
Ryan C. Gordon | f130714e92 | |
Ryan C. Gordon | 0bda50c276 | |
Ryan C. Gordon | 1d616dcaf1 | |
Ryan C. Gordon | 4557dbf0f7 | |
Ryan C. Gordon | 7ab5cc52ce | |
Ryan C. Gordon | f6c830968c | |
Ryan C. Gordon | 3765efb652 | |
Ryan C. Gordon | 8ebecded22 | |
Ryan C. Gordon | a28a01c124 | |
Ryan C. Gordon | 8553113870 | |
Ryan C. Gordon | 7fed370cfd | |
Ryan C. Gordon | 43f8ffcd2d | |
Ryan C. Gordon | afacf0395e | |
Ryan C. Gordon | d38c10dea7 | |
Ryan C. Gordon | f83e36a8be | |
Ryan C. Gordon | c375504463 | |
Ryan C. Gordon | cdba81f5c4 | |
Ryan C. Gordon | 8c3501491c | |
Ryan C. Gordon | 6d42436270 | |
Ryan C. Gordon | 820109cc1d | |
Ryan C. Gordon | da1561a09f | |
Ryan C. Gordon | a5d3dd498e | |
Ryan C. Gordon | 63de092cb7 | |
Ryan C. Gordon | e84277a1df | |
Ryan C. Gordon | de444a9866 | |
Ryan C. Gordon | 62ad133862 | |
Ryan C. Gordon | ffa1836335 | |
Ryan C. Gordon | 56bddb0b78 | |
Ryan C. Gordon | 5afd9754e2 | |
Ryan C. Gordon | 9cec66be3e | |
Ryan C. Gordon | 53225ca62c | |
Ryan C. Gordon | 1bacc6d6af | |
Ryan C. Gordon | bf9999af2d | |
Ryan C. Gordon | 4438fe14cf | |
Ryan C. Gordon | a25569ba14 | |
Ryan C. Gordon | efd71e08f6 | |
Ryan C. Gordon | a681fe258d | |
Ryan C. Gordon | 187d04ae9e | |
Ryan C. Gordon | 46db289145 | |
Ryan C. Gordon | 19b15d34a1 | |
Ryan C. Gordon | 2cb1f73737 | |
Ryan C. Gordon | 9ae6fc9e87 | |
Ryan C. Gordon | 4b2180dd17 | |
Ryan C. Gordon | 5f5eca8d01 | |
Ryan C. Gordon | 0f514bbae3 | |
Ryan C. Gordon | 68ad1fa8c5 | |
Ryan C. Gordon | c2c1c7ac30 | |
Ryan C. Gordon | 0be0e3fd33 | |
Ryan C. Gordon | 73070339a4 | |
Ryan C. Gordon | fe55814681 | |
Ryan C. Gordon | 4ae17a5d60 | |
Ryan C. Gordon | 3b5091ba9f | |
Ryan C. Gordon | f2cbac7479 | |
Ryan C. Gordon | a7f5ebf684 | |
Ryan C. Gordon | ebb00f0520 | |
Ryan C. Gordon | 4015689068 | |
Ryan C. Gordon | 53c81e216a | |
Ryan C. Gordon | 2dbd784cc1 | |
Ryan C. Gordon | 3324ec88a9 | |
Ryan C. Gordon | f5c6383b4b | |
Ryan C. Gordon | cf11d2ec99 | |
Ryan C. Gordon | c057f2d7dd | |
Ryan C. Gordon | 083940aef1 | |
Ryan C. Gordon | ffdc55f1e5 | |
Ryan C. Gordon | f8ed5c6f7e | |
Ryan C. Gordon | e4c035a99f | |
Ryan C. Gordon | 7cb89ce454 | |
Ryan C. Gordon | bae1f440ba | |
Ryan C. Gordon | 84231feb0f | |
Ryan C. Gordon | 3e5f92d756 | |
Ryan C. Gordon | bbd1fd4b38 | |
Ryan C. Gordon | d1f8c9df35 | |
Ryan C. Gordon | e9e0ca81de | |
Ryan C. Gordon | fc1687cc2d | |
Ryan C. Gordon | 35ab010a7b | |
Ryan C. Gordon | 3776e50310 | |
Ryan C. Gordon | 16850b0a9c | |
Ryan C. Gordon | b2e9cbf004 | |
Ryan C. Gordon | 3346eb24c6 | |
Ryan C. Gordon | 59a07020a8 | |
Ryan C. Gordon | d3237eba1f | |
Ryan C. Gordon | 377b420a18 | |
Ryan C. Gordon | 4cbffd39e8 | |
Ryan C. Gordon | 683216def8 | |
Ryan C. Gordon | 9a19eba065 | |
Ryan C. Gordon | 2bd8c33fe5 | |
Ryan C. Gordon | 32da097a55 | |
Ryan C. Gordon | 9aebcff5ba | |
Ryan C. Gordon | 34009cf762 | |
Ryan C. Gordon | d1e40af4e3 | |
Ryan C. Gordon | 062bdc2c5b | |
Ryan C. Gordon | 9ca88e3794 | |
Ryan C. Gordon | 58bca6ae05 | |
Ryan C. Gordon | 15c18b0c04 | |
Francesco Bertolaccini | 4b80422a79 | |
Francesco Bertolaccini | dc5958ec71 | |
Ryan C. Gordon | 656a9b92c0 | |
Francesco Bertolaccini | e4206408e5 | |
Ryan C. Gordon | cf18d4f2c6 | |
Ryan C. Gordon | 468edd80eb | |
Ryan C. Gordon | 2777b5efe2 | |
Ryan C. Gordon | 66b7767cec | |
Ryan C. Gordon | ab7eb81a4a | |
Ryan C. Gordon | dfd658ff92 | |
Ryan C. Gordon | e05d1acc76 | |
Ryan C. Gordon | 84f27f8fb5 | |
Ryan C. Gordon | 8363d15439 | |
Ryan C. Gordon | b66b2d4563 | |
David Yip | 51f0807cb3 | |
David Yip | 9293c3dc8d | |
Ryan C. Gordon | c3cc732a70 | |
Ryan C. Gordon | 32d4f4541e | |
Ryan C. Gordon | b479c57bcb | |
Ryan C. Gordon | acd00dda94 | |
Ryan C. Gordon | e608c5c3de | |
Ryan C. Gordon | 0278c30776 | |
Ryan C. Gordon | ce85702893 | |
Ryan C. Gordon | cec3dad0aa | |
Ryan C. Gordon | 2b060f8127 | |
Ryan C. Gordon | c4deb67883 | |
Ryan C. Gordon | 57bbcc3eb3 | |
Ryan C. Gordon | 1ab2afda15 | |
Ryan C. Gordon | fb31167e11 | |
Ryan C. Gordon | 6cafcc4bc7 | |
Ryan C. Gordon | 3d38708088 | |
Ryan C. Gordon | e13803c101 | |
Ryan C. Gordon | 0c4d9ec68f | |
Martin Ahrnbom | 9d55f3f099 | |
Ryan C. Gordon | f6a62ecad1 | |
Ryan C. Gordon | c9f40346bc | |
Ryan C. Gordon | 53ef674270 | |
Ryan C. Gordon | 4b906c1e5f | |
Ryan C. Gordon | 628b88f112 | |
Willi Schinmeyer | 9df22f4bf5 | |
Ryan C. Gordon | 2091eccad3 | |
Ryan C. Gordon | 016394067c | |
Ryan C. Gordon | 8e065c08f7 | |
Ryan C. Gordon | 44fb6d5e2d | |
Ryan C. Gordon | 5aa0dae5e2 | |
Ryan C. Gordon | 5dd2cfce35 | |
Ryan C. Gordon | 61d931fecc | |
Ryan C. Gordon | 6d9923706d | |
Ryan C. Gordon | 4046759f61 | |
Ryan C. Gordon | 09baf99aa4 | |
Ryan C. Gordon | 26f5eb481e | |
Ryan C. Gordon | 7a42f7dd41 | |
Ryan C. Gordon | 4eafb44817 | |
Ryan C. Gordon | 2dd99ccbb2 | |
Ryan C. Gordon | f5c746967f | |
Ryan C. Gordon | 36b542ee7f | |
Ryan C. Gordon | 697c31e81b | |
Ryan C. Gordon | 7824a093fb | |
Ryan C. Gordon | ada24e9c5d | |
Ryan C. Gordon | 1ed8bc07c0 | |
Ryan C. Gordon | 16ee8355db | |
Ryan C. Gordon | 259399124a | |
Ryan C. Gordon | e40d80b00f | |
Ryan C. Gordon | 123313c3cd | |
Ryan C. Gordon | 9826c8b073 | |
Ryan C. Gordon | e61ade0062 | |
Ryan C. Gordon | 8156bd219c | |
Ryan C. Gordon | 06edd385fc | |
Ryan C. Gordon | 7be76515a5 | |
Aleksi Nurmi | fd137cba42 | |
Ryan C. Gordon | 7bd05972c7 | |
Ryan C. Gordon | 72430427c8 | |
Ryan C. Gordon | de59afc5a2 | |
Ryan C. Gordon | 1c48a28166 | |
Ryan C. Gordon | 3f212a8a44 | |
Sam Lantinga | 724b71a657 | |
Ryan C. Gordon | 13855849e6 | |
Ryan C. Gordon | 986c40ac6a | |
Ryan C. Gordon | e38b5e9cb7 | |
Ryan C. Gordon | e70c6847a9 | |
Ryan C. Gordon | c59105bd03 | |
Ryan C. Gordon | bbbbb17258 | |
Ryan C. Gordon | 2a4d891ac5 | |
Ryan C. Gordon | 9159717a27 | |
Ryan C. Gordon | 5c18db7fe9 | |
Ryan C. Gordon | 4d9f2534f2 | |
Ryan C. Gordon | 2b39e47fda | |
Ryan C. Gordon | a865b14bec | |
Ryan C. Gordon | 3e750a903f | |
Ryan C. Gordon | 758e5beedb | |
Ryan C. Gordon | 6222a4a92d | |
Ryan C. Gordon | a7383c295f | |
Ryan C. Gordon | 107f07da97 | |
Ryan C. Gordon | 4cfd7277f3 | |
Ryan C. Gordon | b3fbba7af0 | |
Ryan C. Gordon | 716ea0522f | |
Ryan C. Gordon | de54065b31 | |
Ryan C. Gordon | af4bf8419f | |
Ryan C. Gordon | d4a99cc204 | |
Ryan C. Gordon | fed8e331a5 | |
Ryan C. Gordon | 0de337eb75 | |
Ryan C. Gordon | 24aef83ead | |
Ryan C. Gordon | b2e6882f52 | |
Ryan C. Gordon | 14d723c316 | |
Ryan C. Gordon | dda627412c | |
Ryan C. Gordon | 2392ca1aa3 | |
Ryan C. Gordon | 9d01a645ed | |
Ryan C. Gordon | c306437ece | |
Ryan C. Gordon | a6ff95c6aa | |
Ryan C. Gordon | 0360899357 | |
Ryan C. Gordon | a688d5c686 | |
Ryan C. Gordon | 320b154a11 | |
Ryan C. Gordon | 0584117f85 | |
Ryan C. Gordon | cd5362cc57 | |
Ryan C. Gordon | 66fbf41bc0 | |
Ryan C. Gordon | 53fe6d360a | |
Ryan C. Gordon | 4aec77e618 | |
Ryan C. Gordon | 76fdd9cab6 | |
Ryan C. Gordon | b7f3e5bd1e | |
Ryan C. Gordon | 46125c95b3 | |
Ryan C. Gordon | 0d8bf3a129 | |
Ryan C. Gordon | a0af6bbb71 | |
Ryan C. Gordon | b1d4afcbd3 | |
Ryan C. Gordon | 59c6310e92 | |
Ryan C. Gordon | 60aa0e460c | |
Ryan C. Gordon | 43367c0c29 | |
Ryan C. Gordon | 629614838a | |
Ryan C. Gordon | 3a5a780988 | |
Ryan C. Gordon | 24d6a925d1 | |
Ryan C. Gordon | 584119a4a0 | |
Ryan C. Gordon | ba676b23e5 | |
Ryan C. Gordon | 8d7cf56651 | |
Ryan C. Gordon | f5923f5cea | |
Ryan C. Gordon | e34e67ff68 | |
Ryan C. Gordon | 803730884a | |
Ryan C. Gordon | 2486105f4f | |
Ryan C. Gordon | d67e2c9207 | |
Ryan C. Gordon | f49c122784 | |
Ryan C. Gordon | bb6c5e468c | |
Ryan C. Gordon | e5fa9ab9fc | |
Ryan C. Gordon | 52267fe380 | |
Ryan C. Gordon | 82a6ce0abf | |
Ryan C. Gordon | 1030e5d5ec | |
Ryan C. Gordon | 391f94681c | |
Ryan C. Gordon | be4ae4d401 | |
Ryan C. Gordon | 03dbc3f758 | |
Ryan C. Gordon | aaf8868c8d | |
Ryan C. Gordon | 466f538926 | |
Ryan C. Gordon | abd2624c59 | |
Ryan C. Gordon | 624d7f3a42 | |
Ryan C. Gordon | 519046db72 | |
Ryan C. Gordon | a42ada1380 | |
Ryan C. Gordon | c57bd94f84 | |
Ryan C. Gordon | 0ae446d970 | |
Ryan C. Gordon | 16ff5c8aca | |
Ryan C. Gordon | 5ad70036b2 | |
Ryan C. Gordon | 1d41608a64 | |
Ryan C. Gordon | 611aeec61b | |
Ryan C. Gordon | 2aa0c5a278 | |
Ryan C. Gordon | c94d70ec0a | |
Ryan C. Gordon | b7e0ec7391 | |
Ryan C. Gordon | 7a8e3de103 | |
Ryan C. Gordon | df3c281014 | |
Ryan C. Gordon | 700d94e577 | |
Ryan C. Gordon | c8fc8cf957 | |
Ryan C. Gordon | 6e4279e76a | |
Ryan C. Gordon | 9dceda3d9f | |
Ryan C. Gordon | a0b21c9ae9 | |
Ryan C. Gordon | 25224b0e7a | |
Ryan C. Gordon | eac0f11005 | |
Ryan C. Gordon | 86dbf54fc7 | |
Ryan C. Gordon | 54cc53349d | |
Ryan C. Gordon | de27c2a422 | |
Ryan C. Gordon | 9e2acfd8a6 | |
Ryan C. Gordon | 4d46d42f73 | |
Ryan C. Gordon | d1d0de3947 | |
Ryan C. Gordon | 608958b8ce | |
Sam Lantinga | 9fb20ec349 | |
Ryan C. Gordon | 9d11b991bc | |
Ryan C. Gordon | bbd356a27b | |
Ryan C. Gordon | b97ad1f366 | |
Ryan C. Gordon | 6d4d91414a | |
Ryan C. Gordon | 9d1ef087a9 | |
Ryan C. Gordon | 28007c9bae | |
Ryan C. Gordon | 025a02f4c0 | |
Ryan C. Gordon | 8258274a90 | |
Ryan C. Gordon | e4cc3fcd9b | |
Ryan C. Gordon | 65497160f7 | |
Ryan C. Gordon | 4075482826 | |
Ryan C. Gordon | f94d227945 | |
Ryan C. Gordon | 49a8ff3f86 | |
Ryan C. Gordon | b8c4942413 | |
Ryan C. Gordon | 6a1aca5db5 | |
Ryan C. Gordon | c6ca60eb20 | |
Ryan C. Gordon | 4446cfa613 | |
Ryan C. Gordon | 2939b26b7f | |
Ryan C. Gordon | 4298d85313 | |
Ryan C. Gordon | 014f0e2254 | |
Ryan C. Gordon | 794a3b3d90 | |
Ryan C. Gordon | 72f0e7f9b5 | |
Ryan C. Gordon | 67995ad0c5 | |
Ryan C. Gordon | 7dee41eb0c | |
Ryan C. Gordon | 8e4fb13617 | |
Ryan C. Gordon | 660c7f9823 | |
Ryan C. Gordon | 54f72a0b42 | |
Ryan C. Gordon | 855025c3e5 | |
Ryan C. Gordon | 706f50be0a | |
Ryan C. Gordon | 82b8546bc9 | |
Ryan C. Gordon | f5e0dbe78b | |
Ryan C. Gordon | 899517dc85 | |
Ryan C. Gordon | 5f5775c1ec | |
Ryan C. Gordon | 7d253b13ed | |
Ryan C. Gordon | 4d567a0d2f | |
Ryan C. Gordon | f871802f51 | |
Ryan C. Gordon | 3f02ce767f | |
Ryan C. Gordon | 9d900f8814 | |
Ryan C. Gordon | 125c170f7d | |
Ryan C. Gordon | 7f0e7105a7 | |
Ryan C. Gordon | 2219123cc5 | |
Ryan C. Gordon | 84c6e2242e | |
Ryan C. Gordon | d9e98704f7 | |
Ryan C. Gordon | 5ff1a2a12e | |
Ryan C. Gordon | bb9f5e5049 | |
Ryan C. Gordon | 8cd320b858 | |
Ryan C. Gordon | 4bc5ed1725 | |
Ryan C. Gordon | c2e77d7e35 | |
Ryan C. Gordon | 74f8cb4f91 | |
Ryan C. Gordon | b58e5f348c | |
Ryan C. Gordon | 8def2f8aaf | |
Ryan C. Gordon | fc680aa468 | |
Ryan C. Gordon | c92f3035f9 | |
Ryan C. Gordon | 2beafa790d | |
Ryan C. Gordon | c1969d0595 | |
Ryan C. Gordon | c306d73fdc | |
Ryan C. Gordon | f99f0ef9e7 | |
Ryan C. Gordon | 024784efbd | |
Ryan C. Gordon | f7a8d9292c | |
Ryan C. Gordon | b69dfedaf0 | |
Ryan C. Gordon | 8b0988a038 | |
Ryan C. Gordon | 51a22c576e | |
Ryan C. Gordon | 94c621c8fb | |
Ryan C. Gordon | 8546c9a202 | |
Ryan C. Gordon | 3dc77f8a54 | |
Ryan C. Gordon | d797ea7cd8 | |
Ryan C. Gordon | 4000b234c0 | |
Ryan C. Gordon | 68632d3c57 | |
Ryan C. Gordon | 11e2306c1c | |
Ryan C. Gordon | c88d2c3746 | |
Ryan C. Gordon | acdfcfca04 | |
Ryan C. Gordon | 77d16c2bed | |
Ryan C. Gordon | 9d979b21d0 | |
Ryan C. Gordon | f329f4ed0b | |
Ryan C. Gordon | 1fe05388ad | |
Ryan C. Gordon | 80713fb40e | |
Ryan C. Gordon | a9855949f0 | |
Ryan C. Gordon | a44e9669c1 | |
Ryan C. Gordon | e6f331f32d | |
Ryan C. Gordon | ddd82040f4 | |
Ryan C. Gordon | efa498fd5d | |
Ryan C. Gordon | 72b232d4f5 | |
Ryan C. Gordon | 4c7d25aebe | |
Ryan C. Gordon | ed989aa171 | |
Ryan C. Gordon | 47c3e8875c | |
Ryan C. Gordon | cd3587bbf3 | |
Ryan C. Gordon | 39e4da1929 | |
Ryan C. Gordon | 0fa35af2b9 | |
Ryan C. Gordon | c369e78296 | |
Ryan C. Gordon | 8d1cff2bdf | |
Ryan C. Gordon | 9141cd77a0 | |
Ryan C. Gordon | 71dd0f7a6c | |
Ryan C. Gordon | a4a72dfe8c | |
Ryan C. Gordon | a4a7f88db0 | |
Ryan C. Gordon | f1cd4d8f0d | |
Ryan C. Gordon | 8e78e4719d | |
Ryan C. Gordon | 7cc80bebc5 | |
Ryan C. Gordon | eafefbdfdc | |
Ryan C. Gordon | c08d722c2e | |
Ryan C. Gordon | 5a98fc83a8 | |
Ryan C. Gordon | 6d6fec87ad | |
Ryan C. Gordon | 68db1196be | |
Ryan C. Gordon | 13a9f9b2dd | |
Ryan C. Gordon | 8ce71e5924 | |
Ryan C. Gordon | a40d3e1e3b | |
Ryan C. Gordon | 12ad3828e7 | |
Ryan C. Gordon | 35ed8dd586 | |
Ryan C. Gordon | 282bf1b3ec | |
Ryan C. Gordon | bdd4d3ebe3 | |
Ryan C. Gordon | 6116683f5e | |
Ryan C. Gordon | c844a98be3 | |
Ryan C. Gordon | 8415f297f0 | |
Ryan C. Gordon | 319ff77100 | |
Ryan C. Gordon | 23d28cbe12 | |
Ryan C. Gordon | 392193ea0c | |
Ryan C. Gordon | 5720b168ca | |
Ryan C. Gordon | a09a54d0f2 | |
Ryan C. Gordon | aa7126619e | |
Ryan C. Gordon | 5629f8b8bc | |
Ryan C. Gordon | c2c1ba9cc5 | |
Ryan C. Gordon | 4cbe694020 | |
Ryan C. Gordon | 595ac1da39 | |
Ryan C. Gordon | 17b2640d71 | |
Ryan C. Gordon | cef8847a06 | |
Ryan C. Gordon | 5a26df8383 | |
Ryan C. Gordon | 88729ebff2 | |
Ryan C. Gordon | a69f97bb26 | |
Ryan C. Gordon | 71e0e6883d | |
Ryan C. Gordon | 44f6c8306d | |
Ryan C. Gordon | 43207273dd | |
Ryan C. Gordon | ff80fc8003 | |
Ryan C. Gordon | 71fc15fd19 | |
Ryan C. Gordon | 5323b6a532 | |
Ryan C. Gordon | 04b6388b68 | |
Ryan C. Gordon | d7945d5955 | |
Ryan C. Gordon | 94d1b71e49 | |
Ryan C. Gordon | cedcd95541 | |
Ryan C. Gordon | 652f0ec03c | |
Ryan C. Gordon | d26781a809 | |
Ryan C. Gordon | 57d908dca0 | |
Ryan C. Gordon | 0bc32891ba | |
Ryan C. Gordon | 3b91814f20 | |
Ryan C. Gordon | 05e3864db8 | |
Ryan C. Gordon | d8d296e8c6 | |
Ryan C. Gordon | 07e97a0166 | |
Ryan C. Gordon | e1dee8e56a | |
Ryan C. Gordon | 3f0cffcc50 | |
Ryan C. Gordon | 8d796488a2 | |
Ryan C. Gordon | ca244993e6 | |
Ryan C. Gordon | 3bc1f7d670 | |
Ryan C. Gordon | 47557ee2d4 | |
Ryan C. Gordon | 544f0f6185 | |
Ryan C. Gordon | 7eff1f1977 | |
Ryan C. Gordon | ec93cca7c7 | |
Ryan C. Gordon | 778f1987cf | |
Ryan C. Gordon | fb5e8d9cd2 | |
Ryan C. Gordon | b78da18657 | |
Ryan C. Gordon | d6ce63e912 | |
Ryan C. Gordon | 2a65060cde | |
Ryan C. Gordon | 60366b5b32 | |
Ryan C. Gordon | da35dbe448 | |
Ryan C. Gordon | 87558aad9d | |
Ryan C. Gordon | c32cd9d130 | |
Ryan C. Gordon | c021fa0613 |
|
@ -0,0 +1,2 @@
|
|||
github: [icculus]
|
||||
patreon: icculus
|
|
@ -0,0 +1,30 @@
|
|||
name: Build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
name: ${{ matrix.platform.name }}
|
||||
runs-on: ${{ matrix.platform.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
platform: # !!! FIXME: figure out an efficient way to get SDL2 on the Windows/Mac bots.
|
||||
- { name: Linux, os: ubuntu-20.04, flags: -GNinja }
|
||||
- { name: MinGW, os: windows-latest, flags: -GNinja -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc -DCMAKE_SYSTEM_NAME=Windows }
|
||||
- { name: Windows, os: windows-latest }
|
||||
- { name: MacOS, os: macos-latest }
|
||||
steps:
|
||||
- name: Setup Linux dependencies
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ninja-build
|
||||
- name: Setup MinGW dependencies
|
||||
if: contains(matrix.platform.name, 'MinGW')
|
||||
run: choco install ninja
|
||||
- name: Get PhysicsFS sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Configure CMake
|
||||
run: cmake -B build ${{ matrix.platform.flags }}
|
||||
- name: Build
|
||||
run: cmake --build build/
|
|
@ -0,0 +1,20 @@
|
|||
name: Build (OS/2)
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
os2:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: open-watcom/setup-watcom@v0
|
||||
- name: Build physfs.dll
|
||||
run: |
|
||||
cd src
|
||||
wmake -f Makefile.os2
|
||||
cd ..
|
||||
- name: distclean
|
||||
run: |
|
||||
cd src
|
||||
wmake -f Makefile.os2 distclean
|
||||
cd ..
|
|
@ -0,0 +1,2 @@
|
|||
cmake-build
|
||||
|
636
CMakeLists.txt
636
CMakeLists.txt
|
@ -1,381 +1,345 @@
|
|||
# PhysicsFS; a portable, flexible file i/o abstraction.
|
||||
# Copyright (C) 2007 Ryan C. Gordon.
|
||||
#
|
||||
# Please see the file LICENSE.txt in the source's root directory.
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
|
||||
# The CMake project file is meant to get this compiling on all sorts of
|
||||
# platforms quickly, and serve as the way Unix platforms and Linux distros
|
||||
# package up official builds, but you don't _need_ to use this; we have
|
||||
# built PhysicsFS to (hopefully) be able to drop into your project and
|
||||
# compile, using preprocessor checks for platform-specific bits instead of
|
||||
# testing in here.
|
||||
|
||||
PROJECT(PhysicsFS)
|
||||
SET(PHYSFS_VERSION 2.0.0)
|
||||
set(PHYSFS_VERSION 3.3.0)
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(PhysicsFS VERSION ${PHYSFS_VERSION} LANGUAGES C )
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Increment this if/when we break backwards compatibility.
|
||||
SET(PHYSFS_SOVERSION 1)
|
||||
set(PHYSFS_SOVERSION 1)
|
||||
|
||||
set(PHYSFS_M_SRCS)
|
||||
set(PHYSFS_CPP_SRCS)
|
||||
|
||||
# I hate that they define "WIN32" ... we're about to move to Win64...I hope!
|
||||
IF(WIN32 AND NOT WINDOWS)
|
||||
SET(WINDOWS TRUE)
|
||||
ENDIF(WIN32 AND NOT WINDOWS)
|
||||
|
||||
# Bleh, let's do it for "APPLE" too.
|
||||
IF(APPLE AND NOT MACOSX)
|
||||
SET(MACOSX TRUE)
|
||||
ENDIF(APPLE AND NOT MACOSX)
|
||||
if(APPLE)
|
||||
set(OTHER_LDFLAGS ${OTHER_LDFLAGS} "-framework IOKit -framework Foundation")
|
||||
list(APPEND PHYSFS_M_SRCS src/physfs_platform_apple.m)
|
||||
endif()
|
||||
|
||||
INCLUDE(CheckIncludeFile)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall)
|
||||
# Don't use -rpath.
|
||||
set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE)
|
||||
endif()
|
||||
|
||||
INCLUDE_DIRECTORIES(.)
|
||||
#INCLUDE_DIRECTORIES(platform)
|
||||
#INCLUDE_DIRECTORIES(archivers)
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "SunPro")
|
||||
add_definitions(-erroff=E_EMPTY_TRANSLATION_UNIT)
|
||||
add_definitions(-xldscope=hidden)
|
||||
endif()
|
||||
|
||||
IF(MACOSX)
|
||||
# Fallback to older OS X on PowerPC to support wider range of systems...
|
||||
IF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
||||
ADD_DEFINITIONS(-DMAC_OS_X_VERSION_MIN_REQUIRED=1020)
|
||||
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -mmacosx-version-min=10.2")
|
||||
ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES ppc)
|
||||
|
||||
# Need these everywhere...
|
||||
ADD_DEFINITIONS(-fno-common)
|
||||
SET(OTHER_LDFLAGS ${OTHER_LDFLAGS} " -framework Carbon -framework IOKit")
|
||||
ENDIF(MACOSX)
|
||||
|
||||
# Add some gcc-specific command lines.
|
||||
IF(CMAKE_COMPILER_IS_GNUCC)
|
||||
# Always build with debug symbols...you can strip it later.
|
||||
ADD_DEFINITIONS(-g -pipe -Werror -fsigned-char)
|
||||
|
||||
# Stupid BeOS generates warnings in the system headers.
|
||||
IF(NOT BEOS)
|
||||
ADD_DEFINITIONS(-Wall)
|
||||
ENDIF(NOT BEOS)
|
||||
|
||||
CHECK_C_SOURCE_COMPILES("
|
||||
#if ((defined(__GNUC__)) && (__GNUC__ >= 4))
|
||||
int main(int argc, char **argv) { int is_gcc4 = 1; return 0; }
|
||||
#else
|
||||
#error This is not gcc4.
|
||||
#endif
|
||||
" PHYSFS_IS_GCC4)
|
||||
|
||||
IF(PHYSFS_IS_GCC4)
|
||||
ADD_DEFINITIONS(-fvisibility=hidden)
|
||||
ENDIF(PHYSFS_IS_GCC4)
|
||||
ENDIF(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
IF(MSVC)
|
||||
# VS.NET 8.0 got really really anal about strcpy, etc, which even if we
|
||||
# cleaned up our code, zlib, etc still use...so disable the warning.
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS=1)
|
||||
ENDIF(MSVC)
|
||||
|
||||
# Basic chunks of source code ...
|
||||
|
||||
SET(ZLIB_SRCS
|
||||
zlib123/adler32.c
|
||||
zlib123/compress.c
|
||||
zlib123/crc32.c
|
||||
zlib123/deflate.c
|
||||
zlib123/gzio.c
|
||||
zlib123/infback.c
|
||||
zlib123/inffast.c
|
||||
zlib123/inflate.c
|
||||
zlib123/inftrees.c
|
||||
zlib123/trees.c
|
||||
zlib123/uncompr.c
|
||||
zlib123/zutil.c
|
||||
)
|
||||
|
||||
SET(LZMA_SRCS
|
||||
lzma/C/7zCrc.c
|
||||
lzma/C/Archive/7z/7zBuffer.c
|
||||
lzma/C/Archive/7z/7zDecode.c
|
||||
lzma/C/Archive/7z/7zExtract.c
|
||||
lzma/C/Archive/7z/7zHeader.c
|
||||
lzma/C/Archive/7z/7zIn.c
|
||||
lzma/C/Archive/7z/7zItem.c
|
||||
lzma/C/Archive/7z/7zMethodID.c
|
||||
lzma/C/Compress/Branch/BranchX86.c
|
||||
lzma/C/Compress/Branch/BranchX86_2.c
|
||||
lzma/C/Compress/Lzma/LzmaDecode.c
|
||||
)
|
||||
|
||||
IF(BEOS)
|
||||
if(HAIKU)
|
||||
# We add this explicitly, since we don't want CMake to think this
|
||||
# is a C++ project unless we're on BeOS.
|
||||
SET(PHYSFS_BEOS_SRCS platform/beos.cpp)
|
||||
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} be root)
|
||||
ENDIF(BEOS)
|
||||
# is a C++ project unless we're on Haiku.
|
||||
list(APPEND PHYSFS_CPP_SRCS src/physfs_platform_haiku.cpp)
|
||||
find_library(BE_LIBRARY be)
|
||||
find_library(ROOT_LIBRARY root)
|
||||
list(APPEND OPTIONAL_LIBRARY_LIBS ${BE_LIBRARY} ${ROOT_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" OR CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
|
||||
set(WINRT TRUE)
|
||||
endif()
|
||||
|
||||
if(WINRT)
|
||||
list(APPEND PHYSFS_CPP_SRCS src/physfs_platform_winrt.cpp)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT WIN32 AND NOT APPLE) # (MingW and such might be UNIX _and_ WINDOWS!)
|
||||
find_library(PTHREAD_LIBRARY pthread)
|
||||
if(PTHREAD_LIBRARY)
|
||||
set(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} ${PTHREAD_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(PHYSFS_CPP_SRCS)
|
||||
enable_language(CXX)
|
||||
endif()
|
||||
|
||||
# Almost everything is "compiled" here, but things that don't apply to the
|
||||
# build are #ifdef'd out. This is to make it easy to embed PhysicsFS into
|
||||
# another project or bring up a new build system: just compile all the source
|
||||
# code and #define the things you want.
|
||||
SET(PHYSFS_SRCS
|
||||
physfs.c
|
||||
physfs_byteorder.c
|
||||
physfs_unicode.c
|
||||
platform/os2.c
|
||||
platform/pocketpc.c
|
||||
platform/posix.c
|
||||
platform/unix.c
|
||||
platform/macosx.c
|
||||
platform/windows.c
|
||||
archivers/dir.c
|
||||
archivers/grp.c
|
||||
archivers/hog.c
|
||||
archivers/lzma.c
|
||||
archivers/mvl.c
|
||||
archivers/qpak.c
|
||||
archivers/wad.c
|
||||
archivers/zip.c
|
||||
${PHYSFS_BEOS_SRCS}
|
||||
set(PHYSFS_SRCS
|
||||
src/physfs.c
|
||||
src/physfs_byteorder.c
|
||||
src/physfs_unicode.c
|
||||
src/physfs_platform_posix.c
|
||||
src/physfs_platform_unix.c
|
||||
src/physfs_platform_windows.c
|
||||
src/physfs_platform_os2.c
|
||||
src/physfs_platform_qnx.c
|
||||
src/physfs_platform_android.c
|
||||
src/physfs_archiver_dir.c
|
||||
src/physfs_archiver_unpacked.c
|
||||
src/physfs_archiver_grp.c
|
||||
src/physfs_archiver_hog.c
|
||||
src/physfs_archiver_7z.c
|
||||
src/physfs_archiver_mvl.c
|
||||
src/physfs_archiver_qpak.c
|
||||
src/physfs_archiver_wad.c
|
||||
src/physfs_archiver_zip.c
|
||||
src/physfs_archiver_slb.c
|
||||
src/physfs_archiver_iso9660.c
|
||||
src/physfs_archiver_vdf.c
|
||||
${PHYSFS_CPP_SRCS}
|
||||
${PHYSFS_M_SRCS}
|
||||
)
|
||||
|
||||
|
||||
# platform layers ...
|
||||
|
||||
IF(UNIX)
|
||||
IF(BEOS)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
||||
SET(HAVE_PTHREAD_H TRUE)
|
||||
ELSE(BEOS)
|
||||
# !!! FIXME
|
||||
# AC_DEFINE([PHYSFS_HAVE_LLSEEK], 1, [define if we have llseek])
|
||||
CHECK_INCLUDE_FILE(sys/ucred.h HAVE_UCRED_H)
|
||||
IF(HAVE_UCRED_H)
|
||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_SYS_UCRED_H=1)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
ENDIF(HAVE_UCRED_H)
|
||||
|
||||
CHECK_INCLUDE_FILE(mntent.h HAVE_MNTENT_H)
|
||||
IF(HAVE_MNTENT_H)
|
||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_MNTENT_H=1)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
ENDIF(HAVE_MNTENT_H)
|
||||
|
||||
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
|
||||
IF(HAVE_PTHREAD_H)
|
||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
||||
ELSE(HAVE_PTHREAD_H)
|
||||
ADD_DEFINITIONS(-DPHYSFS_NO_PTHREADS_SUPPORT=1)
|
||||
ENDIF(HAVE_PTHREAD_H)
|
||||
ENDIF(BEOS)
|
||||
ENDIF(UNIX)
|
||||
|
||||
IF(WINDOWS)
|
||||
SET(PHYSFS_HAVE_CDROM_SUPPORT TRUE)
|
||||
SET(PHYSFS_HAVE_THREAD_SUPPORT TRUE)
|
||||
ENDIF(WINDOWS)
|
||||
|
||||
IF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
|
||||
ADD_DEFINITIONS(-DPHYSFS_NO_CDROM_SUPPORT=1)
|
||||
MESSAGE(WARNING " ***")
|
||||
MESSAGE(WARNING " *** There is no CD-ROM support in this build!")
|
||||
MESSAGE(WARNING " *** PhysicsFS will just pretend there are no discs.")
|
||||
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
|
||||
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
|
||||
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
|
||||
MESSAGE(WARNING " ***")
|
||||
ENDIF(NOT PHYSFS_HAVE_CDROM_SUPPORT)
|
||||
|
||||
IF(PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
ADD_DEFINITIONS(-D_REENTRANT -D_THREAD_SAFE)
|
||||
ELSE(PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
MESSAGE(WARNING " ***")
|
||||
MESSAGE(WARNING " *** There is no thread support in this build!")
|
||||
MESSAGE(WARNING " *** PhysicsFS will NOT be reentrant!")
|
||||
MESSAGE(WARNING " *** This may be fine, depending on how PhysicsFS is used,")
|
||||
MESSAGE(WARNING " *** but is this what you REALLY wanted?")
|
||||
MESSAGE(WARNING " *** (Maybe fix CMakeLists.txt, or write a platform driver?)")
|
||||
MESSAGE(WARNING " ***")
|
||||
ENDIF(PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
|
||||
CHECK_INCLUDE_FILE(assert.h HAVE_ASSERT_H)
|
||||
IF(HAVE_ASSERT_H)
|
||||
ADD_DEFINITIONS(-DHAVE_ASSERT_H=1)
|
||||
ENDIF(HAVE_ASSERT_H)
|
||||
|
||||
|
||||
|
||||
# Archivers ...
|
||||
# These are (mostly) on by default now, so these options are only useful for
|
||||
# disabling them.
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_ZIP)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_ZIP=1)
|
||||
SET(PHYSFS_NEED_ZLIB TRUE)
|
||||
ENDIF(PHYSFS_ARCHIVE_ZIP)
|
||||
option(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_ZIP)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_ZIP=0)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_7Z "Enable 7zip support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_7Z)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_7Z=1)
|
||||
# !!! FIXME: rename to 7z.c?
|
||||
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${LZMA_SRCS})
|
||||
ENDIF(PHYSFS_ARCHIVE_7Z)
|
||||
option(PHYSFS_ARCHIVE_7Z "Enable 7zip support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_7Z)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_7Z=0)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_GRP)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_GRP=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_GRP)
|
||||
option(PHYSFS_ARCHIVE_GRP "Enable Build Engine GRP support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_GRP)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_GRP=0)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_WAD)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_WAD=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_WAD)
|
||||
option(PHYSFS_ARCHIVE_WAD "Enable Doom WAD support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_WAD)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_WAD=0)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_HOG)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_HOG=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_HOG)
|
||||
option(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_HOG)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_HOG=0)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_MVL)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_MVL=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_MVL)
|
||||
option(PHYSFS_ARCHIVE_MVL "Enable Descent I/II MVL support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_MVL)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_MVL=0)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
|
||||
IF(PHYSFS_ARCHIVE_QPAK)
|
||||
ADD_DEFINITIONS(-DPHYSFS_SUPPORTS_QPAK=1)
|
||||
ENDIF(PHYSFS_ARCHIVE_QPAK)
|
||||
option(PHYSFS_ARCHIVE_QPAK "Enable Quake I/II QPAK support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_QPAK)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_QPAK=0)
|
||||
endif()
|
||||
|
||||
option(PHYSFS_ARCHIVE_SLB "Enable I-War / Independence War SLB support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_SLB)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_SLB=0)
|
||||
endif()
|
||||
|
||||
option(PHYSFS_ARCHIVE_ISO9660 "Enable ISO9660 support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_ISO9660)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_ISO9660=0)
|
||||
endif()
|
||||
|
||||
option(PHYSFS_ARCHIVE_VDF "Enable Gothic I/II VDF archive support" TRUE)
|
||||
if(NOT PHYSFS_ARCHIVE_VDF)
|
||||
add_definitions(-DPHYSFS_SUPPORTS_VDF=0)
|
||||
endif()
|
||||
|
||||
|
||||
# See if some archiver required zlib, and see about using system version.
|
||||
option(PHYSFS_BUILD_STATIC "Build static library" TRUE)
|
||||
if(PHYSFS_BUILD_STATIC)
|
||||
add_library(physfs-static STATIC ${PHYSFS_SRCS})
|
||||
add_library(PhysFS::PhysFS-static ALIAS physfs-static)
|
||||
set_target_properties(physfs-static PROPERTIES EXPORT_NAME PhysFS-static)
|
||||
# Don't rename this on Windows, since DLLs will also produce an import
|
||||
# library named "physfs.lib" which would conflict; Unix tend to like the
|
||||
# same library name with a different extension for static libs, but
|
||||
# Windows can just have a separate name.
|
||||
if(NOT MSVC)
|
||||
set_target_properties(physfs-static PROPERTIES OUTPUT_NAME "physfs")
|
||||
endif()
|
||||
if(WINRT)
|
||||
# Ignore LNK4264 warnings; we don't author any WinRT components, just consume them, so we're okay in a static library.
|
||||
set_target_properties(physfs-static PROPERTIES VS_WINRT_COMPONENT True)
|
||||
set_target_properties(physfs-static PROPERTIES STATIC_LIBRARY_FLAGS "/ignore:4264")
|
||||
endif()
|
||||
if(WIN32 OR WINRT OR OS2)
|
||||
# no dll exports from the static library
|
||||
target_compile_definitions(physfs-static PRIVATE "PHYSFS_STATIC")
|
||||
endif()
|
||||
target_include_directories(physfs-static PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
|
||||
target_link_libraries(physfs-static PRIVATE ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
|
||||
set(PHYSFS_LIB_TARGET physfs-static)
|
||||
list(APPEND PHYSFS_INSTALL_TARGETS "physfs-static")
|
||||
endif()
|
||||
|
||||
IF(PHYSFS_NEED_ZLIB)
|
||||
CHECK_INCLUDE_FILE(zlib.h HAVE_ZLIB_H)
|
||||
IF(HAVE_ZLIB_H)
|
||||
CHECK_LIBRARY_EXISTS("z" "inflate" "" HAVE_LIBZ)
|
||||
IF(HAVE_LIBZ)
|
||||
SET(HAVE_SYSTEM_ZLIB TRUE)
|
||||
ENDIF(HAVE_LIBZ)
|
||||
ENDIF(HAVE_ZLIB_H)
|
||||
option(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
|
||||
if(PHYSFS_BUILD_SHARED)
|
||||
add_library(physfs SHARED ${PHYSFS_SRCS})
|
||||
add_library(PhysFS::PhysFS ALIAS physfs)
|
||||
set_target_properties(physfs PROPERTIES MACOSX_RPATH 1)
|
||||
set_target_properties(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
|
||||
set_target_properties(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
|
||||
set_target_properties(physfs PROPERTIES EXPORT_NAME PhysFS)
|
||||
if(WINRT)
|
||||
set_target_properties(physfs PROPERTIES VS_WINRT_COMPONENT True)
|
||||
endif()
|
||||
if(OS2) # OS/2 does not support a DLL name longer than 8 characters.
|
||||
set_target_properties(physfs PROPERTIES OUTPUT_NAME "physfs")
|
||||
endif()
|
||||
target_include_directories(physfs PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>")
|
||||
target_link_libraries(physfs PRIVATE ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
|
||||
set(PHYSFS_LIB_TARGET physfs)
|
||||
list(APPEND PHYSFS_INSTALL_TARGETS "physfs")
|
||||
endif()
|
||||
|
||||
IF(HAVE_SYSTEM_ZLIB)
|
||||
OPTION(PHYSFS_INTERNAL_ZLIB "Link own zlib instead of system library" FALSE)
|
||||
ELSE(HAVE_SYSTEM_ZLIB)
|
||||
SET(PHYSFS_INTERNAL_ZLIB TRUE)
|
||||
ENDIF(HAVE_SYSTEM_ZLIB)
|
||||
|
||||
IF(PHYSFS_INTERNAL_ZLIB)
|
||||
INCLUDE_DIRECTORIES(zlib123)
|
||||
ADD_DEFINITIONS(-DZ_PREFIX=1)
|
||||
SET(PHYSFS_SRCS ${PHYSFS_SRCS} ${ZLIB_SRCS})
|
||||
ELSE(PHYSFS_INTERNAL_ZLIB)
|
||||
SET(OPTIONAL_LIBRARY_LIBS ${OPTIONAL_LIBRARY_LIBS} z)
|
||||
ENDIF(PHYSFS_INTERNAL_ZLIB)
|
||||
ENDIF(PHYSFS_NEED_ZLIB)
|
||||
|
||||
OPTION(PHYSFS_BUILD_STATIC "Build static library" TRUE)
|
||||
IF(PHYSFS_BUILD_STATIC)
|
||||
ADD_LIBRARY(physfs-static STATIC ${PHYSFS_SRCS})
|
||||
SET_TARGET_PROPERTIES(physfs-static PROPERTIES OUTPUT_NAME "physfs")
|
||||
SET(PHYSFS_LIB_TARGET physfs-static)
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs-static")
|
||||
ENDIF(PHYSFS_BUILD_STATIC)
|
||||
|
||||
OPTION(PHYSFS_BUILD_SHARED "Build shared library" TRUE)
|
||||
IF(PHYSFS_BUILD_SHARED)
|
||||
ADD_LIBRARY(physfs SHARED ${PHYSFS_SRCS})
|
||||
SET_TARGET_PROPERTIES(physfs PROPERTIES VERSION ${PHYSFS_VERSION})
|
||||
SET_TARGET_PROPERTIES(physfs PROPERTIES SOVERSION ${PHYSFS_SOVERSION})
|
||||
TARGET_LINK_LIBRARIES(physfs ${OPTIONAL_LIBRARY_LIBS} ${OTHER_LDFLAGS})
|
||||
SET(PHYSFS_LIB_TARGET physfs)
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";physfs")
|
||||
ENDIF(PHYSFS_BUILD_SHARED)
|
||||
|
||||
IF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
||||
MESSAGE(FATAL "Both shared and static libraries are disabled!")
|
||||
ENDIF(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
||||
if(NOT PHYSFS_BUILD_SHARED AND NOT PHYSFS_BUILD_STATIC)
|
||||
message(FATAL "Both shared and static libraries are disabled!")
|
||||
endif()
|
||||
|
||||
# CMake FAQ says I need this...
|
||||
IF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
|
||||
SET_TARGET_PROPERTIES(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
SET_TARGET_PROPERTIES(physfs-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
ENDIF(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC)
|
||||
if(PHYSFS_BUILD_SHARED AND PHYSFS_BUILD_STATIC AND NOT WIN32)
|
||||
set_target_properties(physfs PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
set_target_properties(physfs-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_BUILD_TEST "Build stdio test program." TRUE)
|
||||
MARK_AS_ADVANCED(PHYSFS_BUILD_TEST)
|
||||
IF(PHYSFS_BUILD_TEST)
|
||||
CHECK_INCLUDE_FILE(readline/readline.h HAVE_READLINE_H)
|
||||
CHECK_INCLUDE_FILE(readline/history.h HAVE_HISTORY_H)
|
||||
IF(HAVE_READLINE_H AND HAVE_HISTORY_H)
|
||||
SET(CMAKE_REQUIRED_LIBRARIES curses)
|
||||
CHECK_LIBRARY_EXISTS("readline" "readline" "" HAVE_LIBREADLINE)
|
||||
CHECK_LIBRARY_EXISTS("readline" "history" "" HAVE_LIBHISTORY)
|
||||
IF(HAVE_LIBREADLINE AND HAVE_LIBHISTORY)
|
||||
SET(HAVE_SYSTEM_READLINE TRUE)
|
||||
SET(TEST_PHYSFS_LIBS ${TEST_PHYSFS_LIBS} " " readline curses)
|
||||
ADD_DEFINITIONS(-DPHYSFS_HAVE_READLINE=1)
|
||||
ENDIF(HAVE_LIBREADLINE AND HAVE_LIBHISTORY)
|
||||
ENDIF(HAVE_READLINE_H AND HAVE_HISTORY_H)
|
||||
ADD_EXECUTABLE(test_physfs test/test_physfs.c)
|
||||
TARGET_LINK_LIBRARIES(test_physfs ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";test_physfs")
|
||||
ENDIF(PHYSFS_BUILD_TEST)
|
||||
option(PHYSFS_BUILD_TEST "Build stdio test program." TRUE)
|
||||
mark_as_advanced(PHYSFS_BUILD_TEST)
|
||||
if(PHYSFS_BUILD_TEST)
|
||||
find_path(READLINE_H readline/readline.h)
|
||||
find_path(HISTORY_H readline/history.h)
|
||||
if(READLINE_H AND HISTORY_H)
|
||||
find_library(CURSES_LIBRARY NAMES curses ncurses)
|
||||
if(CURSES_LIBRARY)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
|
||||
find_library(READLINE_LIBRARY readline)
|
||||
if(READLINE_LIBRARY)
|
||||
set(HAVE_SYSTEM_READLINE TRUE)
|
||||
list(APPEND TEST_PHYSFS_LIBS ${READLINE_LIBRARY} ${CURSES_LIBRARY})
|
||||
include_directories(SYSTEM ${READLINE_H} ${HISTORY_H})
|
||||
add_definitions(-DPHYSFS_HAVE_READLINE=1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
add_executable(test_physfs test/test_physfs.c)
|
||||
target_link_libraries(test_physfs PRIVATE ${PHYSFS_LIB_TARGET} ${TEST_PHYSFS_LIBS} ${OTHER_LDFLAGS})
|
||||
list(APPEND PHYSFS_INSTALL_TARGETS test_physfs)
|
||||
endif()
|
||||
|
||||
OPTION(PHYSFS_BUILD_WX_TEST "Build wxWidgets test program." TRUE)
|
||||
MARK_AS_ADVANCED(PHYSFS_BUILD_WX_TEST)
|
||||
IF(PHYSFS_BUILD_WX_TEST)
|
||||
SET(wxWidgets_USE_LIBS base core adv)
|
||||
SET(wxWidgets_INCLUDE_DIRS_NO_SYSTEM 1)
|
||||
FIND_PACKAGE(wxWidgets)
|
||||
IF(wxWidgets_FOUND)
|
||||
INCLUDE(${wxWidgets_USE_FILE})
|
||||
ADD_EXECUTABLE(wxtest_physfs test/wxtest_physfs.cpp)
|
||||
SET_SOURCE_FILES_PROPERTIES(test/wxtest_physfs.cpp COMPILE_FLAGS ${wxWidgets_CXX_FLAGS})
|
||||
TARGET_LINK_LIBRARIES(wxtest_physfs ${PHYSFS_LIB_TARGET} ${wxWidgets_LIBRARIES} ${OTHER_LDFLAGS})
|
||||
SET(PHYSFS_INSTALL_TARGETS ${PHYSFS_INSTALL_TARGETS} ";wxtest_physfs")
|
||||
ELSE(wxWidgets_FOUND)
|
||||
MESSAGE(STATUS "wxWidgets not found. Disabling wx test app.")
|
||||
SET(PHYSFS_BUILD_WX_TEST FALSE)
|
||||
ENDIF(wxWidgets_FOUND)
|
||||
ENDIF(PHYSFS_BUILD_WX_TEST)
|
||||
option(PHYSFS_DISABLE_INSTALL "Disable installing PhysFS" OFF)
|
||||
if(NOT PHYSFS_DISABLE_INSTALL)
|
||||
|
||||
INSTALL(TARGETS ${PHYSFS_INSTALL_TARGETS}
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
INSTALL(FILES physfs.h DESTINATION include)
|
||||
install(TARGETS ${PHYSFS_INSTALL_TARGETS} EXPORT PhysFSExport
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES src/physfs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
FIND_PACKAGE(Doxygen)
|
||||
IF(DOXYGEN_FOUND)
|
||||
ADD_CUSTOM_TARGET(docs ${DOXYGEN_EXECUTABLE} COMMENT "Building documentation")
|
||||
ELSE(DOXYGEN_FOUND)
|
||||
MESSAGE(STATUS "Doxygen not found. You won't be able to build documentation.")
|
||||
ENDIF(DOXYGEN_FOUND)
|
||||
install(EXPORT PhysFSExport
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/PhysFS"
|
||||
FILE PhysFSConfig.cmake
|
||||
NAMESPACE PhysFS::
|
||||
)
|
||||
|
||||
IF(UNIX)
|
||||
ADD_CUSTOM_TARGET(dist ./extras/makedist.sh ${PHYSFS_VERSION} COMMENT "Building source tarball")
|
||||
ENDIF(UNIX)
|
||||
if(NOT MSVC)
|
||||
configure_file(
|
||||
"extras/physfs.pc.in"
|
||||
"extras/physfs.pc"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
MACRO(MESSAGE_BOOL_OPTION _NAME _VALUE)
|
||||
IF(${_VALUE})
|
||||
MESSAGE(STATUS " ${_NAME}: enabled")
|
||||
ELSE(${_VALUE})
|
||||
MESSAGE(STATUS " ${_NAME}: disabled")
|
||||
ENDIF(${_VALUE})
|
||||
ENDMACRO(MESSAGE_BOOL_OPTION)
|
||||
install(
|
||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/extras/physfs.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
MESSAGE(STATUS "PhysicsFS will build with the following options:")
|
||||
MESSAGE_BOOL_OPTION("ZIP support" PHYSFS_ARCHIVE_ZIP)
|
||||
MESSAGE_BOOL_OPTION("7zip support" PHYSFS_ARCHIVE_7Z)
|
||||
MESSAGE_BOOL_OPTION("GRP support" PHYSFS_ARCHIVE_GRP)
|
||||
MESSAGE_BOOL_OPTION("WAD support" PHYSFS_ARCHIVE_WAD)
|
||||
MESSAGE_BOOL_OPTION("HOG support" PHYSFS_ARCHIVE_HOG)
|
||||
MESSAGE_BOOL_OPTION("MVL support" PHYSFS_ARCHIVE_MVL)
|
||||
MESSAGE_BOOL_OPTION("QPAK support" PHYSFS_ARCHIVE_QPAK)
|
||||
MESSAGE_BOOL_OPTION("CD-ROM drive support" PHYSFS_HAVE_CDROM_SUPPORT)
|
||||
MESSAGE_BOOL_OPTION("Thread safety" PHYSFS_HAVE_THREAD_SUPPORT)
|
||||
MESSAGE_BOOL_OPTION("Build own zlib" PHYSFS_INTERNAL_ZLIB)
|
||||
MESSAGE_BOOL_OPTION("Build static library" PHYSFS_BUILD_STATIC)
|
||||
MESSAGE_BOOL_OPTION("Build shared library" PHYSFS_BUILD_SHARED)
|
||||
MESSAGE_BOOL_OPTION("Build wxWidgets test program" PHYSFS_BUILD_WX_TEST)
|
||||
MESSAGE_BOOL_OPTION("Build stdio test program" PHYSFS_BUILD_TEST)
|
||||
IF(PHYSFS_BUILD_TEST)
|
||||
MESSAGE_BOOL_OPTION(" Use readline in test program" HAVE_SYSTEM_READLINE)
|
||||
ENDIF(PHYSFS_BUILD_TEST)
|
||||
option(PHYSFS_BUILD_DOCS "Build doxygen based documentation" TRUE)
|
||||
if(PHYSFS_BUILD_DOCS)
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
set(PHYSFS_OUTPUT_DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile"
|
||||
"${PHYSFS_OUTPUT_DOXYFILE}"
|
||||
COPYONLY
|
||||
)
|
||||
file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n\n# Below auto-generated by cmake...\n\n")
|
||||
file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "PROJECT_NUMBER = \"${PHYSFS_VERSION}\"\n")
|
||||
file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "OUTPUT_DIRECTORY = \"${CMAKE_CURRENT_BINARY_DIR}/docs\"\n")
|
||||
file(APPEND "${PHYSFS_OUTPUT_DOXYFILE}" "\n# End auto-generated section.\n\n")
|
||||
|
||||
set(PHYSFS_TARGETNAME_DOCS "docs" CACHE STRING "Name of 'docs' build target")
|
||||
|
||||
add_custom_target(
|
||||
${PHYSFS_TARGETNAME_DOCS}
|
||||
${DOXYGEN_EXECUTABLE} "${PHYSFS_OUTPUT_DOXYFILE}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Building documentation in 'docs' directory..."
|
||||
)
|
||||
|
||||
else()
|
||||
message(STATUS "Doxygen not found. You won't be able to build documentation.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
set(PHYSFS_TARBALL "${CMAKE_CURRENT_SOURCE_DIR}/../physfs-${PHYSFS_VERSION}.tar.gz")
|
||||
|
||||
set(PHYSFS_TARGETNAME_DIST "dist" CACHE STRING "Name of 'dist' build target")
|
||||
add_custom_target(
|
||||
${PHYSFS_TARGETNAME_DIST}
|
||||
git archive --prefix="physfs-${PHYSFS_VERSION}/" --output="${PHYSFS_TARBALL}" HEAD
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
COMMENT "Building source tarball '${PHYSFS_TARBALL}'..."
|
||||
)
|
||||
|
||||
set(PHYSFS_TARGETNAME_UNINSTALL "uninstall" CACHE STRING "Name of 'uninstall' build target")
|
||||
add_custom_target(
|
||||
${PHYSFS_TARGETNAME_UNINSTALL}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/extras/uninstall.sh"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
COMMENT "Uninstall the project..."
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
macro(message_bool_option _NAME _VALUE)
|
||||
if(${_VALUE})
|
||||
message(STATUS " ${_NAME}: enabled")
|
||||
else()
|
||||
message(STATUS " ${_NAME}: disabled")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
message(STATUS "PhysicsFS will build with the following options:")
|
||||
message_bool_option("ZIP support" PHYSFS_ARCHIVE_ZIP)
|
||||
message_bool_option("7zip support" PHYSFS_ARCHIVE_7Z)
|
||||
message_bool_option("GRP support" PHYSFS_ARCHIVE_GRP)
|
||||
message_bool_option("WAD support" PHYSFS_ARCHIVE_WAD)
|
||||
message_bool_option("HOG support" PHYSFS_ARCHIVE_HOG)
|
||||
message_bool_option("MVL support" PHYSFS_ARCHIVE_MVL)
|
||||
message_bool_option("QPAK support" PHYSFS_ARCHIVE_QPAK)
|
||||
message_bool_option("SLB support" PHYSFS_ARCHIVE_SLB)
|
||||
message_bool_option("VDF support" PHYSFS_ARCHIVE_VDF)
|
||||
message_bool_option("ISO9660 support" PHYSFS_ARCHIVE_ISO9660)
|
||||
message_bool_option("Build static library" PHYSFS_BUILD_STATIC)
|
||||
message_bool_option("Build shared library" PHYSFS_BUILD_SHARED)
|
||||
message_bool_option("Build stdio test program" PHYSFS_BUILD_TEST)
|
||||
message_bool_option("Build Doxygen documentation" PHYSFS_BUILD_DOCS)
|
||||
if(PHYSFS_BUILD_TEST)
|
||||
message_bool_option(" Use readline in test program" HAVE_SYSTEM_READLINE)
|
||||
endif()
|
||||
|
||||
# end of CMakeLists.txt ...
|
||||
|
||||
|
|
153
INSTALL.txt
153
INSTALL.txt
|
@ -1,153 +0,0 @@
|
|||
|
||||
The latest PhysicsFS information and releases can be found at:
|
||||
http://icculus.org/physfs/
|
||||
|
||||
Building is (ahem) very easy.
|
||||
|
||||
|
||||
ALL PLATFORMS:
|
||||
|
||||
Please understand your rights and mine: read the text file LICENSE.txt in the
|
||||
root of the source tree. If you can't abide by it, delete this source tree
|
||||
now. The license is extremely liberal, even to closed-source, commercial
|
||||
applications.
|
||||
|
||||
If you've got Doxygen (http://www.doxygen.org/) installed, you can run it
|
||||
without any command line arguments in the root of the source tree to generate
|
||||
the API reference (or build the "docs" target from your build system). This
|
||||
is optional. You can browse the API docs online here:
|
||||
|
||||
http://icculus.org/physfs/docs/
|
||||
|
||||
|
||||
|
||||
|
||||
UNIX:
|
||||
|
||||
You will need CMake (http://www.cmake.org/) 2.4 or later installed.
|
||||
|
||||
Make a directory, wherever you like. This will be your build directory.
|
||||
|
||||
Chdir to your build directory. Run "cmake /where/i/unpacked/physfs" to
|
||||
generate Makefiles. You can then run "ccmake ." and customize the build,
|
||||
but the defaults are probably okay. You can have CMake generate KDevelop
|
||||
project files if you prefer these.
|
||||
|
||||
Run "make". PhysicsFS will now build.
|
||||
|
||||
As root, run "make install".
|
||||
If you get sick of the library, run "xargs rm < install_manifest.txt" as root
|
||||
and it will remove all traces of the library from the system paths.
|
||||
|
||||
Once you are satisfied, you can delete the build directory.
|
||||
|
||||
Primary Unix development is done with GNU/Linux, but PhysicsFS is known to
|
||||
work out of the box with several flavors of Unix. It it doesn't work, patches
|
||||
to get it running can be sent to icculus@icculus.org.
|
||||
|
||||
|
||||
|
||||
BeOS, Zeta, and Haiku:
|
||||
|
||||
Use the "Unix" instructions, above. The CMake port to BeOS is fairly new at
|
||||
the time of this writing, but it works. You can get a build of CMake from
|
||||
bebits.com or build it yourself from source from cmake.org.
|
||||
|
||||
|
||||
|
||||
Windows:
|
||||
|
||||
If building with Cygwin, mingw32, MSYS, or something else that uses the GNU
|
||||
toolchain, follow the Unix instructions, above.
|
||||
|
||||
If you want to use Visual Studio, nmake, or the Platform SDK, you will need
|
||||
CMake (http://www.cmake.org/) 2.4 or later installed. Point CMake at the
|
||||
CMakeLists.txt file in the root of the source directory and hit the
|
||||
"Configure" button. After telling it what type of compiler you are targeting
|
||||
(Borland, Visual Studio, etc), CMake will process for while and then give you
|
||||
a list of options you can change (what archivers you want to support, etc).
|
||||
If you aren't sure, the defaults are probably fine. Hit the "Configure"
|
||||
button again, then "OK" once configuration has completed with options that
|
||||
match your liking. Now project files for your favorite programming
|
||||
environment will be generated for you in the directory you specified.
|
||||
Go there and use them to build PhysicsFS.
|
||||
|
||||
PhysicsFS will only link directly against system libraries that have existed
|
||||
since Windows 95 and Windows NT 3.51. If there's a newer API we want to use,
|
||||
we try to dynamically load it at runtime and fallback to a reasonable
|
||||
behaviour when we can't find it...this is used for Unicode support and
|
||||
locating user-specific directories, etc.
|
||||
|
||||
PhysicsFS has not been tested on 64-bit Windows, but probably works. There is
|
||||
no 16-bit Windows support at all. Reports of success and problems can go to
|
||||
Ryan at icculus@icculus.org ...
|
||||
|
||||
If someone is willing to maintain prebuilt PhysicsFS DLLs, I'd like to hear
|
||||
from you; send an email to icculus@icculus.org ...
|
||||
|
||||
|
||||
|
||||
PocketPC/WindowsCE:
|
||||
|
||||
Code exists for PocketPC support, and there are shipping titles that used
|
||||
PhysicsFS 1.0 on PocketPC...but it isn't tested in 2.0, and is probably
|
||||
broken with the new build system. Please send patches.
|
||||
|
||||
|
||||
|
||||
MAC OS 8/9:
|
||||
|
||||
Classic Mac OS support has been dropped in PhysicsFS 2.0. Apple hasn't updated
|
||||
pre-OSX versions in more than a decade at this point, none of the hardware
|
||||
they've shipped will boot it for almost as many years, and finding
|
||||
developer tools for it is becoming almost impossible. As the switch to Intel
|
||||
hardware has removed the "Classic" emulation environment, it was time to
|
||||
remove support from PhysicsFS. That being said, the PhysicsFS 1.0 branch can
|
||||
still target back to Mac OS 8.5, so you can use that if you need support for
|
||||
this legacy OS. We still very much support Mac OS X, though: see below.
|
||||
|
||||
|
||||
|
||||
MAC OS X:
|
||||
|
||||
You will need CMake (http://www.cmake.org/) 2.4 or later installed.
|
||||
|
||||
You can either generate a Unix makefile with CMake, or generate an Xcode
|
||||
project, whichever makes you more comfortable.
|
||||
|
||||
PowerPC and Intel Macs should both be supported.
|
||||
|
||||
If someone is willing to maintain prebuilt PhysicsFS Shared Libraries for
|
||||
Mac OS X, I'd like to hear from you; send an email to icculus@icculus.org.
|
||||
|
||||
|
||||
|
||||
OS/2:
|
||||
|
||||
You need Innotek GCC and libc installed (or kLIBC). I tried this on a stock
|
||||
Warp 4 install, no fixpaks. You need to install link386.exe (Selective
|
||||
Install, "link object modules" option). Once klibc and GCC are installed
|
||||
correctly, unpack the source to PhysicsFS and run the script
|
||||
file "makeos2.cmd". I know this isn't ideal, but I wanted to have this build
|
||||
without users having to hunt down a "make" program.
|
||||
|
||||
Someone please port CMake to OS/2. Ideally I'd like to be able to target
|
||||
Innotek GCC and OpenWatcom with CMake.
|
||||
|
||||
If someone is willing to maintain prebuilt PhysicsFS Shared Libraries for
|
||||
OS/2, I'd like to hear from you; send an email to icculus@icculus.org.
|
||||
|
||||
|
||||
|
||||
OTHER PLATFORMS:
|
||||
|
||||
Many Unix-like platforms might "just work" with CMake. Some of these platforms
|
||||
are known to have worked at one time, but have not been heavily tested, if
|
||||
tested at all. PhysicsFS is, as far as we know, 64-bit and byteorder clean,
|
||||
and is known to compile on several compilers across many platforms. To
|
||||
implement a new platform or archiver, please read the heavily-commented
|
||||
physfs_internal.h and look in the platform/ and archiver/ directories for
|
||||
examples.
|
||||
|
||||
--ryan. (icculus@icculus.org)
|
||||
|
51
LICENSE.txt
51
LICENSE.txt
|
@ -1,44 +1,17 @@
|
|||
Copyright (c) 2001-2022 Ryan C. Gordon <icculus@icculus.org> and others.
|
||||
|
||||
Copyright (c) 2003-2009 Ryan C. Gordon and others.
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event will the authors be held liable for any damages arising from
|
||||
the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software in a
|
||||
product, an acknowledgment in the product documentation would be
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Ryan C. Gordon <icculus@icculus.org>
|
||||
|
||||
|
||||
|
||||
|
||||
Notes, separate from the license. This is not legal advice.
|
||||
|
||||
Versions of PhysicsFS prior to 0.1.9 are licensed under the GNU Lesser General
|
||||
Public License, which restricts you significantly more. For your own safety,
|
||||
please make sure you've got 0.1.9 or later if you plan to use physfs in a
|
||||
commercial or closed-source project.
|
||||
|
||||
Optional pieces of PhysicsFS may fall under other licenses, please consult
|
||||
your lawyer for legal advice, which this is not...
|
||||
|
||||
zlib: if you enable ZIP archive support, PhysicsFS uses zlib. Its license
|
||||
requirements are identical to PhysicsFS.
|
||||
Please see zlib123/README for details.
|
||||
|
||||
lzma: if you enable LZMA (7zip) support, PhysicsFS uses the lzma sdk.
|
||||
It uses the LGPL license, with exceptions for closed-source programs.
|
||||
Please see lzma/lzma.txt for details.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
PhysicsFS; a portable, flexible file i/o abstraction.
|
||||
|
||||
https://icculus.org/physfs/
|
||||
|
||||
Please see the docs directory for documentation.
|
||||
|
||||
Please see LICENSE.txt for licensing information.
|
||||
|
45
TODO.txt
45
TODO.txt
|
@ -1,45 +0,0 @@
|
|||
Stuff that needs to be done and wishlist:
|
||||
|
||||
These are in no particular order.
|
||||
Some might be dupes, some might be done already.
|
||||
|
||||
UNICODE:
|
||||
- OS/2: Codepages. No full Unicode in the filesystem, but we can probably make
|
||||
a conversion effort.
|
||||
|
||||
|
||||
Stuff:
|
||||
- Other archivers: perhaps tar(.gz|.bz2), RPM, ARJ, etc. These are less
|
||||
important, since streaming archives aren't of much value to games (which
|
||||
is why zipfiles are king: random access), but it could have uses for, say,
|
||||
an installer/updater.
|
||||
- Reduce malloc() pressure all over the place. We fragment memory like mad.
|
||||
- profile string list interpolation.
|
||||
- We have two different ways to find dir entries in zip.c.
|
||||
- Do symlinks in zip archiver work when they point to dirs?
|
||||
- Enable more warnings?
|
||||
- Use __cdecl in physfs.h?
|
||||
- Look for FIXMEs (many marked with "!!!" in comments).
|
||||
- Find some way to relax or remove the security model for external tools.
|
||||
- OSX shouldn't use ~/.app for userdir.
|
||||
- fscanf and fprintf support in extras dir.
|
||||
- Why do we call it openArchive and dirClose?
|
||||
- Sanity check byte order at runtime.
|
||||
- Memory locking?
|
||||
- Find a better name than dvoid and fvoid.
|
||||
- Can windows.c and pocketpc.c get merged?
|
||||
- There's so much cut-and-paste between archivers...can this be reduced?
|
||||
- General code audit.
|
||||
- Multiple write dirs with mount points?
|
||||
- Deprecate PHYSFS_setSaneConfig and move it to extras?
|
||||
- Why is physfsrwops.c cut-and-pasted into the ruby bindings?
|
||||
- Replace code from SDL...
|
||||
- Should file enumeration return an error or set error state?
|
||||
- Need "getmountpoint" command in test_physfs.c ...
|
||||
- Look for calloc() calls that aren't going through the allocation hooks.
|
||||
- Write up a simple HOWTO on embedding physicsfs in another project.
|
||||
- Archivers need abstracted i/o to read from memory or files (archives in archives?)
|
||||
- Probably other stuff. Requests and recommendations are welcome.
|
||||
|
||||
// end of TODO.txt ...
|
||||
|
283
archivers/dir.c
283
archivers/dir.c
|
@ -1,283 +0,0 @@
|
|||
/*
|
||||
* Standard directory I/O support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
static PHYSFS_sint64 DIR_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
PHYSFS_sint64 retval;
|
||||
retval = __PHYSFS_platformRead(opaque, buffer, objSize, objCount);
|
||||
return(retval);
|
||||
} /* DIR_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
PHYSFS_sint64 retval;
|
||||
retval = __PHYSFS_platformWrite(opaque, buffer, objSize, objCount);
|
||||
return(retval);
|
||||
} /* DIR_write */
|
||||
|
||||
|
||||
static int DIR_eof(fvoid *opaque)
|
||||
{
|
||||
return(__PHYSFS_platformEOF(opaque));
|
||||
} /* DIR_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_tell(fvoid *opaque)
|
||||
{
|
||||
return(__PHYSFS_platformTell(opaque));
|
||||
} /* DIR_tell */
|
||||
|
||||
|
||||
static int DIR_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
return(__PHYSFS_platformSeek(opaque, offset));
|
||||
} /* DIR_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_fileLength(fvoid *opaque)
|
||||
{
|
||||
return(__PHYSFS_platformFileLength(opaque));
|
||||
} /* DIR_fileLength */
|
||||
|
||||
|
||||
static int DIR_fileClose(fvoid *opaque)
|
||||
{
|
||||
/*
|
||||
* we manually flush the buffer, since that's the place a close will
|
||||
* most likely fail, but that will leave the file handle in an undefined
|
||||
* state if it fails. Flush failures we can recover from.
|
||||
*/
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformFlush(opaque), NULL, 0);
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(opaque), NULL, 0);
|
||||
return(1);
|
||||
} /* DIR_fileClose */
|
||||
|
||||
|
||||
static int DIR_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
/* directories ARE archives in this driver... */
|
||||
return(__PHYSFS_platformIsDirectory(filename));
|
||||
} /* DIR_isArchive */
|
||||
|
||||
|
||||
static void *DIR_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
const char *dirsep = PHYSFS_getDirSeparator();
|
||||
char *retval = NULL;
|
||||
size_t namelen = strlen(name);
|
||||
size_t seplen = strlen(dirsep);
|
||||
|
||||
/* !!! FIXME: when is this not called right before openArchive? */
|
||||
BAIL_IF_MACRO(!DIR_isArchive(name, forWriting),
|
||||
ERR_UNSUPPORTED_ARCHIVE, 0);
|
||||
|
||||
retval = allocator.Malloc(namelen + seplen + 1);
|
||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
/* make sure there's a dir separator at the end of the string */
|
||||
strcpy(retval, name);
|
||||
if (strcmp((name + namelen) - seplen, dirsep) != 0)
|
||||
strcat(retval, dirsep);
|
||||
|
||||
return(retval);
|
||||
} /* DIR_openArchive */
|
||||
|
||||
|
||||
static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *)opaque, dname, NULL);
|
||||
if (d != NULL)
|
||||
{
|
||||
__PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
|
||||
origdir, callbackdata);
|
||||
allocator.Free(d);
|
||||
} /* if */
|
||||
} /* DIR_enumerateFiles */
|
||||
|
||||
|
||||
static int DIR_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
retval = __PHYSFS_platformExists(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_exists */
|
||||
|
||||
|
||||
static int DIR_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval = 0;
|
||||
|
||||
BAIL_IF_MACRO(d == NULL, NULL, 0);
|
||||
*fileExists = __PHYSFS_platformExists(d);
|
||||
if (*fileExists)
|
||||
retval = __PHYSFS_platformIsDirectory(d);
|
||||
allocator.Free(d);
|
||||
return(retval);
|
||||
} /* DIR_isDirectory */
|
||||
|
||||
|
||||
static int DIR_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval = 0;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
*fileExists = __PHYSFS_platformExists(f);
|
||||
if (*fileExists)
|
||||
retval = __PHYSFS_platformIsSymLink(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 DIR_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
char *d = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
BAIL_IF_MACRO(d == NULL, NULL, 0);
|
||||
*fileExists = __PHYSFS_platformExists(d);
|
||||
if (*fileExists)
|
||||
retval = __PHYSFS_platformGetLastModTime(d);
|
||||
allocator.Free(d);
|
||||
return(retval);
|
||||
} /* DIR_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *doOpen(dvoid *opaque, const char *name,
|
||||
void *(*openFunc)(const char *filename),
|
||||
int *fileExists)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
void *rc = NULL;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, NULL);
|
||||
|
||||
if (fileExists != NULL)
|
||||
{
|
||||
*fileExists = __PHYSFS_platformExists(f);
|
||||
if (!(*fileExists))
|
||||
{
|
||||
allocator.Free(f);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
rc = openFunc(f);
|
||||
allocator.Free(f);
|
||||
|
||||
return((fvoid *) rc);
|
||||
} /* doOpen */
|
||||
|
||||
|
||||
static fvoid *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
|
||||
{
|
||||
return(doOpen(opaque, fnm, __PHYSFS_platformOpenRead, exist));
|
||||
} /* DIR_openRead */
|
||||
|
||||
|
||||
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
|
||||
{
|
||||
return(doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL));
|
||||
} /* DIR_openWrite */
|
||||
|
||||
|
||||
static fvoid *DIR_openAppend(dvoid *opaque, const char *filename)
|
||||
{
|
||||
return(doOpen(opaque, filename, __PHYSFS_platformOpenAppend, NULL));
|
||||
} /* DIR_openAppend */
|
||||
|
||||
|
||||
static int DIR_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
retval = __PHYSFS_platformDelete(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_remove */
|
||||
|
||||
|
||||
static int DIR_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
char *f = __PHYSFS_platformCvtToDependent((char *) opaque, name, NULL);
|
||||
int retval;
|
||||
|
||||
BAIL_IF_MACRO(f == NULL, NULL, 0);
|
||||
retval = __PHYSFS_platformMkDir(f);
|
||||
allocator.Free(f);
|
||||
return(retval);
|
||||
} /* DIR_mkdir */
|
||||
|
||||
|
||||
static void DIR_dirClose(dvoid *opaque)
|
||||
{
|
||||
allocator.Free(opaque);
|
||||
} /* DIR_dirClose */
|
||||
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
|
||||
{
|
||||
"",
|
||||
DIR_ARCHIVE_DESCRIPTION,
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_DIR,
|
||||
DIR_isArchive, /* isArchive() method */
|
||||
DIR_openArchive, /* openArchive() method */
|
||||
DIR_enumerateFiles, /* enumerateFiles() method */
|
||||
DIR_exists, /* exists() method */
|
||||
DIR_isDirectory, /* isDirectory() method */
|
||||
DIR_isSymLink, /* isSymLink() method */
|
||||
DIR_getLastModTime, /* getLastModTime() method */
|
||||
DIR_openRead, /* openRead() method */
|
||||
DIR_openWrite, /* openWrite() method */
|
||||
DIR_openAppend, /* openAppend() method */
|
||||
DIR_remove, /* remove() method */
|
||||
DIR_mkdir, /* mkdir() method */
|
||||
DIR_dirClose, /* dirClose() method */
|
||||
DIR_read, /* read() method */
|
||||
DIR_write, /* write() method */
|
||||
DIR_eof, /* eof() method */
|
||||
DIR_tell, /* tell() method */
|
||||
DIR_seek, /* seek() method */
|
||||
DIR_fileLength, /* fileLength() method */
|
||||
DIR_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
/* end of dir.c ... */
|
||||
|
475
archivers/grp.c
475
archivers/grp.c
|
@ -1,475 +0,0 @@
|
|||
/*
|
||||
* GRP support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles BUILD engine archives ("groupfiles"). This format
|
||||
* (but not this driver) was put together by Ken Silverman.
|
||||
*
|
||||
* The format is simple enough. In Ken's words:
|
||||
*
|
||||
* What's the .GRP file format?
|
||||
*
|
||||
* The ".grp" file format is just a collection of a lot of files stored
|
||||
* into 1 big one. I tried to make the format as simple as possible: The
|
||||
* first 12 bytes contains my name, "KenSilverman". The next 4 bytes is
|
||||
* the number of files that were compacted into the group file. Then for
|
||||
* each file, there is a 16 byte structure, where the first 12 bytes are
|
||||
* the filename, and the last 4 bytes are the file's size. The rest of
|
||||
* the group file is just the raw data packed one after the other in the
|
||||
* same order as the list of files.
|
||||
*
|
||||
* (That info is from http://www.advsys.net/ken/build.htm ...)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_GRP)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[13];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} GRPentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
GRPentry *entries;
|
||||
} GRPinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
GRPentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} GRPfileinfo;
|
||||
|
||||
|
||||
static void GRP_dirClose(dvoid *opaque)
|
||||
{
|
||||
GRPinfo *info = ((GRPinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* GRP_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
GRPentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* GRP_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* GRP_write */
|
||||
|
||||
|
||||
static int GRP_eof(fvoid *opaque)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
GRPentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* GRP_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_tell(fvoid *opaque)
|
||||
{
|
||||
return(((GRPfileinfo *) opaque)->curPos);
|
||||
} /* GRP_tell */
|
||||
|
||||
|
||||
static int GRP_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
GRPentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* GRP_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_fileLength(fvoid *opaque)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* GRP_fileLength */
|
||||
|
||||
|
||||
static int GRP_fileClose(fvoid *opaque)
|
||||
{
|
||||
GRPfileinfo *finfo = (GRPfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* GRP_fileClose */
|
||||
|
||||
|
||||
static int grp_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint8 buf[12];
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 12, 1) != 1)
|
||||
goto openGrp_failed;
|
||||
|
||||
if (memcmp(buf, "KenSilverman", 12) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openGrp_failed;
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openGrp_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
return(1);
|
||||
|
||||
openGrp_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* grp_open */
|
||||
|
||||
|
||||
static int GRP_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = grp_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* GRP_isArchive */
|
||||
|
||||
|
||||
static int grp_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const GRPentry *a = (const GRPentry *) _a;
|
||||
return(strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* grp_entry_cmp */
|
||||
|
||||
|
||||
static void grp_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
GRPentry tmp;
|
||||
GRPentry *first = &(((GRPentry *) _a)[one]);
|
||||
GRPentry *second = &(((GRPentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (GRPentry));
|
||||
memcpy(first, second, sizeof (GRPentry));
|
||||
memcpy(second, &tmp, sizeof (GRPentry));
|
||||
} /* if */
|
||||
} /* grp_entry_swap */
|
||||
|
||||
|
||||
static int grp_load_entries(const char *name, int forWriting, GRPinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
PHYSFS_uint32 location = 16; /* sizeof sig. */
|
||||
GRPentry *entry;
|
||||
char *ptr;
|
||||
|
||||
BAIL_IF_MACRO(!grp_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (GRPentry *) allocator.Malloc(sizeof(GRPentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
location += (16 * fileCount);
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 12, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->name[12] = '\0'; /* name isn't null-terminated in file. */
|
||||
if ((ptr = strchr(entry->name, ' ')) != NULL)
|
||||
*ptr = '\0'; /* trim extra spaces. */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = location;
|
||||
location += entry->size;
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
grp_entry_cmp, grp_entry_swap);
|
||||
return(1);
|
||||
} /* grp_load_entries */
|
||||
|
||||
|
||||
static void *GRP_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
GRPinfo *info = (GRPinfo *) allocator.Malloc(sizeof (GRPinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
|
||||
memset(info, '\0', sizeof (GRPinfo));
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, GRP_openArchive_failed);
|
||||
|
||||
if (!grp_load_entries(name, forWriting, info))
|
||||
goto GRP_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
|
||||
return(info);
|
||||
|
||||
GRP_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* GRP_openArchive */
|
||||
|
||||
|
||||
static void GRP_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
/* no directories in GRP files. */
|
||||
if (*dname == '\0')
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
GRPentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
cb(callbackdata, origdir, entry->name);
|
||||
} /* if */
|
||||
} /* GRP_enumerateFiles */
|
||||
|
||||
|
||||
static GRPentry *grp_find_entry(GRPinfo *info, const char *name)
|
||||
{
|
||||
char *ptr = strchr(name, '.');
|
||||
GRPentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
||||
* big filenames, or extensions > 3 chars.
|
||||
*/
|
||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = strcmp(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* grp_find_entry */
|
||||
|
||||
|
||||
static int GRP_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(grp_find_entry((GRPinfo *) opaque, name) != NULL);
|
||||
} /* GRP_exists */
|
||||
|
||||
|
||||
static int GRP_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = GRP_exists(opaque, name);
|
||||
return(0); /* never directories in a groupfile. */
|
||||
} /* GRP_isDirectory */
|
||||
|
||||
|
||||
static int GRP_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = GRP_exists(opaque, name);
|
||||
return(0); /* never symlinks in a groupfile. */
|
||||
} /* GRP_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 GRP_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (grp_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of GRP itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* GRP_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *GRP_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
GRPinfo *info = (GRPinfo *) opaque;
|
||||
GRPfileinfo *finfo;
|
||||
GRPentry *entry;
|
||||
|
||||
entry = grp_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (GRPfileinfo *) allocator.Malloc(sizeof (GRPfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* GRP_openRead */
|
||||
|
||||
|
||||
static fvoid *GRP_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* GRP_openWrite */
|
||||
|
||||
|
||||
static fvoid *GRP_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* GRP_openAppend */
|
||||
|
||||
|
||||
static int GRP_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* GRP_remove */
|
||||
|
||||
|
||||
static int GRP_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* GRP_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP =
|
||||
{
|
||||
"GRP",
|
||||
GRP_ARCHIVE_DESCRIPTION,
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_GRP,
|
||||
GRP_isArchive, /* isArchive() method */
|
||||
GRP_openArchive, /* openArchive() method */
|
||||
GRP_enumerateFiles, /* enumerateFiles() method */
|
||||
GRP_exists, /* exists() method */
|
||||
GRP_isDirectory, /* isDirectory() method */
|
||||
GRP_isSymLink, /* isSymLink() method */
|
||||
GRP_getLastModTime, /* getLastModTime() method */
|
||||
GRP_openRead, /* openRead() method */
|
||||
GRP_openWrite, /* openWrite() method */
|
||||
GRP_openAppend, /* openAppend() method */
|
||||
GRP_remove, /* remove() method */
|
||||
GRP_mkdir, /* mkdir() method */
|
||||
GRP_dirClose, /* dirClose() method */
|
||||
GRP_read, /* read() method */
|
||||
GRP_write, /* write() method */
|
||||
GRP_eof, /* eof() method */
|
||||
GRP_tell, /* tell() method */
|
||||
GRP_seek, /* seek() method */
|
||||
GRP_fileLength, /* fileLength() method */
|
||||
GRP_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_GRP */
|
||||
|
||||
/* end of grp.c ... */
|
||||
|
514
archivers/hog.c
514
archivers/hog.c
|
@ -1,514 +0,0 @@
|
|||
/*
|
||||
* HOG support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles Descent I/II HOG archives.
|
||||
*
|
||||
* The format is very simple:
|
||||
*
|
||||
* The file always starts with the 3-byte signature "DHF" (Descent
|
||||
* HOG file). After that the files of a HOG are just attached after
|
||||
* another, divided by a 17 bytes header, which specifies the name
|
||||
* and length (in bytes) of the forthcoming file! So you just read
|
||||
* the header with its information of how big the following file is,
|
||||
* and then skip exact that number of bytes to get to the next file
|
||||
* in that HOG.
|
||||
*
|
||||
* char sig[3] = {'D', 'H', 'F'}; // "DHF"=Descent HOG File
|
||||
*
|
||||
* struct {
|
||||
* char file_name[13]; // Filename, padded to 13 bytes with 0s
|
||||
* int file_size; // filesize in bytes
|
||||
* char data[file_size]; // The file data
|
||||
* } FILE_STRUCT; // Repeated until the end of the file.
|
||||
*
|
||||
* (That info is from http://www.descent2.com/ddn/specs/hog/)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Bradley Bell.
|
||||
* Based on grp.c by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_HOG)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
/*
|
||||
* One HOGentry is kept for each file in an open HOG archive.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char name[13];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} HOGentry;
|
||||
|
||||
/*
|
||||
* One HOGinfo is kept for each open HOG archive.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
HOGentry *entries;
|
||||
} HOGinfo;
|
||||
|
||||
/*
|
||||
* One HOGfileinfo is kept for each open file in a HOG archive.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
HOGentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} HOGfileinfo;
|
||||
|
||||
|
||||
static void HOG_dirClose(dvoid *opaque)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* HOG_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
HOGentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* HOG_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* HOG_write */
|
||||
|
||||
|
||||
static int HOG_eof(fvoid *opaque)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
HOGentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* HOG_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_tell(fvoid *opaque)
|
||||
{
|
||||
return(((HOGfileinfo *) opaque)->curPos);
|
||||
} /* HOG_tell */
|
||||
|
||||
|
||||
static int HOG_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
HOGentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* HOG_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_fileLength(fvoid *opaque)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* HOG_fileLength */
|
||||
|
||||
|
||||
static int HOG_fileClose(fvoid *opaque)
|
||||
{
|
||||
HOGfileinfo *finfo = (HOGfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* HOG_fileClose */
|
||||
|
||||
|
||||
static int hog_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint8 buf[13];
|
||||
PHYSFS_uint32 size;
|
||||
PHYSFS_sint64 pos;
|
||||
|
||||
*count = 0;
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 3, 1) != 1)
|
||||
goto openHog_failed;
|
||||
|
||||
if (memcmp(buf, "DHF", 3) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openHog_failed;
|
||||
} /* if */
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (__PHYSFS_platformRead(*fh, buf, 13, 1) != 1)
|
||||
break; /* eof here is ok */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, &size, 4, 1) != 1)
|
||||
goto openHog_failed;
|
||||
|
||||
size = PHYSFS_swapULE32(size);
|
||||
|
||||
(*count)++;
|
||||
|
||||
/* Skip over entry... */
|
||||
pos = __PHYSFS_platformTell(*fh);
|
||||
if (pos == -1)
|
||||
goto openHog_failed;
|
||||
if (!__PHYSFS_platformSeek(*fh, pos + size))
|
||||
goto openHog_failed;
|
||||
} /* while */
|
||||
|
||||
/* Rewind to start of entries... */
|
||||
if (!__PHYSFS_platformSeek(*fh, 3))
|
||||
goto openHog_failed;
|
||||
|
||||
return(1);
|
||||
|
||||
openHog_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* hog_open */
|
||||
|
||||
|
||||
static int HOG_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = hog_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* HOG_isArchive */
|
||||
|
||||
|
||||
static int hog_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const HOGentry *a = (const HOGentry *) _a;
|
||||
return(__PHYSFS_stricmpASCII(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* hog_entry_cmp */
|
||||
|
||||
|
||||
static void hog_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
HOGentry tmp;
|
||||
HOGentry *first = &(((HOGentry *) _a)[one]);
|
||||
HOGentry *second = &(((HOGentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (HOGentry));
|
||||
memcpy(first, second, sizeof (HOGentry));
|
||||
memcpy(second, &tmp, sizeof (HOGentry));
|
||||
} /* if */
|
||||
} /* hog_entry_swap */
|
||||
|
||||
|
||||
static int hog_load_entries(const char *name, int forWriting, HOGinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
HOGentry *entry;
|
||||
|
||||
BAIL_IF_MACRO(!hog_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (HOGentry *) allocator.Malloc(sizeof(HOGentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = (unsigned int) __PHYSFS_platformTell(fh);
|
||||
if (entry->startPos == -1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Skip over entry */
|
||||
if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size))
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
}
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
hog_entry_cmp, hog_entry_swap);
|
||||
return(1);
|
||||
} /* hog_load_entries */
|
||||
|
||||
|
||||
static void *HOG_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
HOGinfo *info = (HOGinfo *) allocator.Malloc(sizeof (HOGinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||
memset(info, '\0', sizeof (HOGinfo));
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, HOG_openArchive_failed);
|
||||
|
||||
if (!hog_load_entries(name, forWriting, info))
|
||||
goto HOG_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
|
||||
return(info);
|
||||
|
||||
HOG_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* HOG_openArchive */
|
||||
|
||||
|
||||
static void HOG_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
/* no directories in HOG files. */
|
||||
if (*dname == '\0')
|
||||
{
|
||||
HOGinfo *info = (HOGinfo *) opaque;
|
||||
HOGentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
cb(callbackdata, origdir, entry->name);
|
||||
} /* if */
|
||||
} /* HOG_enumerateFiles */
|
||||
|
||||
|
||||
static HOGentry *hog_find_entry(HOGinfo *info, const char *name)
|
||||
{
|
||||
char *ptr = strchr(name, '.');
|
||||
HOGentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
||||
* big filenames, or extensions > 3 chars.
|
||||
*/
|
||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* hog_find_entry */
|
||||
|
||||
|
||||
static int HOG_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(hog_find_entry(((HOGinfo *) opaque), name) != NULL);
|
||||
} /* HOG_exists */
|
||||
|
||||
|
||||
static int HOG_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = HOG_exists(opaque, name);
|
||||
return(0); /* never directories in a groupfile. */
|
||||
} /* HOG_isDirectory */
|
||||
|
||||
|
||||
static int HOG_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = HOG_exists(opaque, name);
|
||||
return(0); /* never symlinks in a groupfile. */
|
||||
} /* HOG_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 HOG_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (hog_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of HOG itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* HOG_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *HOG_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
HOGinfo *info = ((HOGinfo *) opaque);
|
||||
HOGfileinfo *finfo;
|
||||
HOGentry *entry;
|
||||
|
||||
entry = hog_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (HOGfileinfo *) allocator.Malloc(sizeof (HOGfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* HOG_openRead */
|
||||
|
||||
|
||||
static fvoid *HOG_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* HOG_openWrite */
|
||||
|
||||
|
||||
static fvoid *HOG_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* HOG_openAppend */
|
||||
|
||||
|
||||
static int HOG_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* HOG_remove */
|
||||
|
||||
|
||||
static int HOG_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* HOG_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_HOG =
|
||||
{
|
||||
"HOG",
|
||||
HOG_ARCHIVE_DESCRIPTION,
|
||||
"Bradley Bell <btb@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_HOG,
|
||||
HOG_isArchive, /* isArchive() method */
|
||||
HOG_openArchive, /* openArchive() method */
|
||||
HOG_enumerateFiles, /* enumerateFiles() method */
|
||||
HOG_exists, /* exists() method */
|
||||
HOG_isDirectory, /* isDirectory() method */
|
||||
HOG_isSymLink, /* isSymLink() method */
|
||||
HOG_getLastModTime, /* getLastModTime() method */
|
||||
HOG_openRead, /* openRead() method */
|
||||
HOG_openWrite, /* openWrite() method */
|
||||
HOG_openAppend, /* openAppend() method */
|
||||
HOG_remove, /* remove() method */
|
||||
HOG_mkdir, /* mkdir() method */
|
||||
HOG_dirClose, /* dirClose() method */
|
||||
HOG_read, /* read() method */
|
||||
HOG_write, /* write() method */
|
||||
HOG_eof, /* eof() method */
|
||||
HOG_tell, /* tell() method */
|
||||
HOG_seek, /* seek() method */
|
||||
HOG_fileLength, /* fileLength() method */
|
||||
HOG_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_HOG */
|
||||
|
||||
/* end of hog.c ... */
|
||||
|
735
archivers/lzma.c
735
archivers/lzma.c
|
@ -1,735 +0,0 @@
|
|||
/*
|
||||
* LZMA support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file lzma.txt in the lzma/ directory.
|
||||
*
|
||||
* This file was written by Dennis Schridde, with some peeking at "7zMain.c"
|
||||
* by Igor Pavlov.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_7Z)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#include "lzma/C/7zCrc.h"
|
||||
#include "lzma/C/Archive/7z/7zIn.h"
|
||||
#include "lzma/C/Archive/7z/7zExtract.h"
|
||||
|
||||
|
||||
/* 7z internal from 7zIn.c */
|
||||
extern int TestSignatureCandidate(Byte *testBytes);
|
||||
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
# define BUFFER_SIZE (1 << 12)
|
||||
#endif /* _LZMA_IN_CB */
|
||||
|
||||
|
||||
/*
|
||||
* Carries filestream metadata through 7z
|
||||
*/
|
||||
typedef struct _FileInputStream
|
||||
{
|
||||
ISzAlloc allocImp; /* Allocation implementation, used by 7z */
|
||||
ISzAlloc allocTempImp; /* Temporary allocation implementation, used by 7z */
|
||||
ISzInStream inStream; /* Input stream with read callbacks, used by 7z */
|
||||
void *file; /* Filehandle, used by read implementation */
|
||||
#ifdef _LZMA_IN_CB
|
||||
Byte buffer[BUFFER_SIZE]; /* Buffer, used by read implementation */
|
||||
#endif /* _LZMA_IN_CB */
|
||||
} FileInputStream;
|
||||
|
||||
/*
|
||||
* In the 7z format archives are splited into blocks, those are called folders
|
||||
* Set by LZMA_read()
|
||||
*/
|
||||
typedef struct _LZMAfolder
|
||||
{
|
||||
PHYSFS_uint32 index; /* Index of folder in archive */
|
||||
PHYSFS_uint32 references; /* Number of files using this block */
|
||||
PHYSFS_uint8 *cache; /* Cached folder */
|
||||
size_t size; /* Size of folder */
|
||||
} LZMAfolder;
|
||||
|
||||
/*
|
||||
* Set by LZMA_openArchive(), except folder which gets it's values
|
||||
* in LZMA_read()
|
||||
*/
|
||||
typedef struct _LZMAarchive
|
||||
{
|
||||
struct _LZMAfile *files; /* Array of files, size == archive->db.Database.NumFiles */
|
||||
LZMAfolder *folders; /* Array of folders, size == archive->db.Database.NumFolders */
|
||||
CArchiveDatabaseEx db; /* For 7z: Database */
|
||||
FileInputStream stream; /* For 7z: Input file incl. read and seek callbacks */
|
||||
} LZMAarchive;
|
||||
|
||||
/* Set by LZMA_openArchive(), except offset which is set by LZMA_read() */
|
||||
typedef struct _LZMAfile
|
||||
{
|
||||
PHYSFS_uint32 index; /* Index of file in archive */
|
||||
LZMAarchive *archive; /* Link to corresponding archive */
|
||||
LZMAfolder *folder; /* Link to corresponding folder */
|
||||
CFileItem *item; /* For 7z: File info, eg. name, size */
|
||||
size_t offset; /* Offset in folder */
|
||||
size_t position; /* Current "virtual" position in file */
|
||||
} LZMAfile;
|
||||
|
||||
|
||||
/* Memory management implementations to be passed to 7z */
|
||||
|
||||
static void *SzAllocPhysicsFS(size_t size)
|
||||
{
|
||||
return ((size == 0) ? NULL : allocator.Malloc(size));
|
||||
} /* SzAllocPhysicsFS */
|
||||
|
||||
|
||||
static void SzFreePhysicsFS(void *address)
|
||||
{
|
||||
if (address != NULL)
|
||||
allocator.Free(address);
|
||||
} /* SzFreePhysicsFS */
|
||||
|
||||
|
||||
/* Filesystem implementations to be passed to 7z */
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
|
||||
/*
|
||||
* Read implementation, to be passed to 7z
|
||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
||||
*/
|
||||
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxReqSize,
|
||||
size_t *processedSize)
|
||||
{
|
||||
FileInputStream *s = (FileInputStream *)(object - offsetof(FileInputStream, inStream)); // HACK!
|
||||
PHYSFS_sint64 processedSizeLoc = 0;
|
||||
|
||||
if (maxReqSize > BUFFER_SIZE)
|
||||
maxReqSize = BUFFER_SIZE;
|
||||
processedSizeLoc = __PHYSFS_platformRead(s->file, s->buffer, 1, maxReqSize);
|
||||
*buffer = s->buffer;
|
||||
if (processedSize != NULL)
|
||||
*processedSize = (size_t) processedSizeLoc;
|
||||
|
||||
return SZ_OK;
|
||||
} /* SzFileReadImp */
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Read implementation, to be passed to 7z
|
||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
||||
*/
|
||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size,
|
||||
size_t *processedSize)
|
||||
{
|
||||
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); // HACK!
|
||||
size_t processedSizeLoc = __PHYSFS_platformRead(s->file, buffer, 1, size);
|
||||
if (processedSize != 0)
|
||||
*processedSize = processedSizeLoc;
|
||||
return SZ_OK;
|
||||
} /* SzFileReadImp */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Seek implementation, to be passed to 7z
|
||||
* WARNING: If the ISzInStream in 'object' is not contained in a valid FileInputStream this _will_ break horribly!
|
||||
*/
|
||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
||||
{
|
||||
FileInputStream *s = (FileInputStream *)((unsigned long)object - offsetof(FileInputStream, inStream)); // HACK!
|
||||
if (__PHYSFS_platformSeek(s->file, (PHYSFS_uint64) pos))
|
||||
return SZ_OK;
|
||||
return SZE_FAIL;
|
||||
} /* SzFileSeekImp */
|
||||
|
||||
|
||||
/*
|
||||
* Translate Microsoft FILETIME (used by 7zip) into UNIX timestamp
|
||||
*/
|
||||
static PHYSFS_sint64 lzma_filetime_to_unix_timestamp(CArchiveFileTime *ft)
|
||||
{
|
||||
/* MS counts in nanoseconds ... */
|
||||
const PHYSFS_uint64 FILETIME_NANOTICKS_PER_SECOND = __PHYSFS_UI64(10000000);
|
||||
/* MS likes to count seconds since 01.01.1601 ... */
|
||||
const PHYSFS_uint64 FILETIME_UNIX_DIFF = __PHYSFS_UI64(11644473600);
|
||||
|
||||
PHYSFS_uint64 filetime = ft->Low | ((PHYSFS_uint64)ft->High << 32);
|
||||
return filetime/FILETIME_NANOTICKS_PER_SECOND - FILETIME_UNIX_DIFF;
|
||||
} /* lzma_filetime_to_unix_timestamp */
|
||||
|
||||
|
||||
/*
|
||||
* Compare a file with a given name, C89 stdlib variant
|
||||
* Used for sorting
|
||||
*/
|
||||
static int lzma_file_cmp_stdlib(const void *key, const void *object)
|
||||
{
|
||||
const char *name = (const char *) key;
|
||||
LZMAfile *file = (LZMAfile *) object;
|
||||
return(strcmp(name, file->item->Name));
|
||||
} /* lzma_file_cmp_posix */
|
||||
|
||||
|
||||
/*
|
||||
* Compare two files with each other based on the name
|
||||
* Used for sorting
|
||||
*/
|
||||
static int lzma_file_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
LZMAfile *files = (LZMAfile *) _a;
|
||||
return(strcmp(files[one].item->Name, files[two].item->Name));
|
||||
} /* lzma_file_cmp */
|
||||
|
||||
|
||||
/*
|
||||
* Swap two entries in the file array
|
||||
*/
|
||||
static void lzma_file_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
LZMAfile tmp;
|
||||
LZMAfile *first = &(((LZMAfile *) _a)[one]);
|
||||
LZMAfile *second = &(((LZMAfile *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (LZMAfile));
|
||||
memcpy(first, second, sizeof (LZMAfile));
|
||||
memcpy(second, &tmp, sizeof (LZMAfile));
|
||||
} /* lzma_file_swap */
|
||||
|
||||
|
||||
/*
|
||||
* Find entry 'name' in 'archive'
|
||||
*/
|
||||
static LZMAfile * lzma_find_file(LZMAarchive *archive, const char *name)
|
||||
{
|
||||
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); // FIXME: Should become __PHYSFS_search!!!
|
||||
|
||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
return(file);
|
||||
} /* lzma_find_file */
|
||||
|
||||
|
||||
/*
|
||||
* Load metadata for the file at given index
|
||||
*/
|
||||
static int lzma_file_init(LZMAarchive *archive, PHYSFS_uint32 fileIndex)
|
||||
{
|
||||
LZMAfile *file = &archive->files[fileIndex];
|
||||
PHYSFS_uint32 folderIndex = archive->db.FileIndexToFolderIndexMap[fileIndex];
|
||||
|
||||
file->index = fileIndex; // Store index into 7z array, since we sort our own.
|
||||
file->archive = archive;
|
||||
file->folder = (folderIndex != (PHYSFS_uint32)-1 ? &archive->folders[folderIndex] : NULL); // Directories don't have a folder (they contain no own data...)
|
||||
file->item = &archive->db.Database.Files[fileIndex]; // Holds crucial data and is often referenced -> Store link
|
||||
file->position = 0;
|
||||
file->offset = 0; /* Offset will be set by LZMA_read() */
|
||||
|
||||
return(1);
|
||||
} /* lzma_load_file */
|
||||
|
||||
|
||||
/*
|
||||
* Load metadata for all files
|
||||
*/
|
||||
static int lzma_files_init(LZMAarchive *archive)
|
||||
{
|
||||
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
|
||||
|
||||
for (fileIndex = 0; fileIndex < numFiles; fileIndex++ )
|
||||
{
|
||||
if (!lzma_file_init(archive, fileIndex))
|
||||
{
|
||||
return(0); // FALSE on failure
|
||||
}
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_sort(archive->files, numFiles, lzma_file_cmp, lzma_file_swap);
|
||||
|
||||
return(1);
|
||||
} /* lzma_load_files */
|
||||
|
||||
|
||||
/*
|
||||
* Initialise specified archive
|
||||
*/
|
||||
static void lzma_archive_init(LZMAarchive *archive)
|
||||
{
|
||||
memset(archive, 0, sizeof(*archive));
|
||||
|
||||
/* Prepare callbacks for 7z */
|
||||
archive->stream.inStream.Read = SzFileReadImp;
|
||||
archive->stream.inStream.Seek = SzFileSeekImp;
|
||||
|
||||
archive->stream.allocImp.Alloc = SzAllocPhysicsFS;
|
||||
archive->stream.allocImp.Free = SzFreePhysicsFS;
|
||||
|
||||
archive->stream.allocTempImp.Alloc = SzAllocPhysicsFS;
|
||||
archive->stream.allocTempImp.Free = SzFreePhysicsFS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Deinitialise archive
|
||||
*/
|
||||
static void lzma_archive_exit(LZMAarchive *archive)
|
||||
{
|
||||
/* Free arrays */
|
||||
allocator.Free(archive->folders);
|
||||
allocator.Free(archive->files);
|
||||
allocator.Free(archive);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrap all 7z calls in this, so the physfs error state is set appropriately.
|
||||
*/
|
||||
static int lzma_err(SZ_RESULT rc)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case SZ_OK: /* Same as LZMA_RESULT_OK */
|
||||
break;
|
||||
case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */
|
||||
__PHYSFS_setError(ERR_DATA_ERROR);
|
||||
break;
|
||||
case SZE_OUTOFMEMORY:
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
break;
|
||||
case SZE_CRC_ERROR:
|
||||
__PHYSFS_setError(ERR_CORRUPTED);
|
||||
break;
|
||||
case SZE_NOTIMPL:
|
||||
__PHYSFS_setError(ERR_NOT_IMPLEMENTED);
|
||||
break;
|
||||
case SZE_FAIL:
|
||||
__PHYSFS_setError(ERR_UNKNOWN_ERROR); /* !!! FIXME: right? */
|
||||
break;
|
||||
case SZE_ARCHIVE_ERROR:
|
||||
__PHYSFS_setError(ERR_CORRUPTED); /* !!! FIXME: right? */
|
||||
break;
|
||||
default:
|
||||
__PHYSFS_setError(ERR_UNKNOWN_ERROR);
|
||||
} /* switch */
|
||||
|
||||
return(rc);
|
||||
} /* lzma_err */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
|
||||
size_t wantedSize = objSize*objCount;
|
||||
size_t remainingSize = file->item->Size - file->position;
|
||||
size_t fileSize = 0;
|
||||
|
||||
BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */
|
||||
BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0);
|
||||
|
||||
if (remainingSize < wantedSize)
|
||||
{
|
||||
wantedSize = remainingSize - (remainingSize % objSize);
|
||||
objCount = (PHYSFS_uint32) (remainingSize / objSize);
|
||||
BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */
|
||||
__PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */
|
||||
} /* if */
|
||||
|
||||
/* Only decompress the folder if it is not allready cached */
|
||||
if (file->folder->cache == NULL)
|
||||
{
|
||||
int rc = lzma_err(SzExtract(
|
||||
&file->archive->stream.inStream, /* compressed data */
|
||||
&file->archive->db, /* 7z's database, containing everything */
|
||||
file->index, /* Index into database arrays */
|
||||
/* Index of cached folder, will be changed by SzExtract */
|
||||
&file->folder->index,
|
||||
/* Cache for decompressed folder, allocated/freed by SzExtract */
|
||||
&file->folder->cache,
|
||||
/* Size of cache, will be changed by SzExtract */
|
||||
&file->folder->size,
|
||||
/* Offset of this file inside the cache, set by SzExtract */
|
||||
&file->offset,
|
||||
&fileSize, /* Size of this file */
|
||||
&file->archive->stream.allocImp,
|
||||
&file->archive->stream.allocTempImp));
|
||||
|
||||
if (rc != SZ_OK)
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
/* Copy wanted bytes over from cache to outBuffer */
|
||||
memcpy(outBuffer,
|
||||
(file->folder->cache +
|
||||
file->offset + file->position),
|
||||
wantedSize);
|
||||
file->position += wantedSize; /* Increase virtual position */
|
||||
|
||||
return objCount;
|
||||
} /* LZMA_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_write(fvoid *opaque, const void *buf,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* LZMA_write */
|
||||
|
||||
|
||||
static int LZMA_eof(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
return (file->position >= file->item->Size);
|
||||
} /* LZMA_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_tell(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
return (file->position);
|
||||
} /* LZMA_tell */
|
||||
|
||||
|
||||
static int LZMA_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_SEEK_OUT_OF_RANGE, 0);
|
||||
BAIL_IF_MACRO(offset > file->item->Size, ERR_PAST_EOF, 0);
|
||||
|
||||
file->position = offset; /* We only use a virtual position... */
|
||||
|
||||
return 1;
|
||||
} /* LZMA_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_fileLength(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
return (file->item->Size);
|
||||
} /* LZMA_fileLength */
|
||||
|
||||
|
||||
static int LZMA_fileClose(fvoid *opaque)
|
||||
{
|
||||
LZMAfile *file = (LZMAfile *) opaque;
|
||||
|
||||
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, 0);
|
||||
|
||||
/* Only decrease refcount if someone actually requested this file... Prevents from overflows and close-on-open... */
|
||||
if (file->folder->references > 0)
|
||||
file->folder->references--;
|
||||
if (file->folder->references == 0)
|
||||
{
|
||||
/* Free the cache which might have been allocated by LZMA_read() */
|
||||
allocator.Free(file->folder->cache);
|
||||
file->folder->cache = NULL;
|
||||
}
|
||||
|
||||
return(1);
|
||||
} /* LZMA_fileClose */
|
||||
|
||||
|
||||
static int LZMA_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
PHYSFS_uint8 sig[k7zSignatureSize];
|
||||
void *in;
|
||||
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
in = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(in == NULL, NULL, 0);
|
||||
|
||||
/* Read signature bytes */
|
||||
if (__PHYSFS_platformRead(in, sig, k7zSignatureSize, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(in); // Don't forget to close the file before returning...
|
||||
BAIL_MACRO(NULL, 0);
|
||||
}
|
||||
|
||||
__PHYSFS_platformClose(in);
|
||||
|
||||
/* Test whether sig is the 7z signature */
|
||||
return(TestSignatureCandidate(sig));
|
||||
} /* LZMA_isArchive */
|
||||
|
||||
|
||||
static void *LZMA_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
size_t len = 0;
|
||||
LZMAarchive *archive = NULL;
|
||||
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
|
||||
BAIL_IF_MACRO(!LZMA_isArchive(name,forWriting), ERR_UNSUPPORTED_ARCHIVE, 0);
|
||||
|
||||
archive = (LZMAarchive *) allocator.Malloc(sizeof (LZMAarchive));
|
||||
BAIL_IF_MACRO(archive == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
lzma_archive_init(archive);
|
||||
|
||||
if ( (archive->stream.file = __PHYSFS_platformOpenRead(name)) == NULL )
|
||||
{
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
return(NULL); // Error is set by platformOpenRead!
|
||||
}
|
||||
|
||||
CrcGenerateTable();
|
||||
SzArDbExInit(&archive->db);
|
||||
if (lzma_err(SzArchiveOpen(&archive->stream.inStream,
|
||||
&archive->db,
|
||||
&archive->stream.allocImp,
|
||||
&archive->stream.allocTempImp)) != SZ_OK)
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
return NULL; // Error is set by lzma_err!
|
||||
} /* if */
|
||||
|
||||
len = archive->db.Database.NumFiles * sizeof (LZMAfile);
|
||||
archive->files = (LZMAfile *) allocator.Malloc(len);
|
||||
if (archive->files == NULL)
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init with 0 so we know when a folder is already cached
|
||||
* Values will be set by LZMA_openRead()
|
||||
*/
|
||||
memset(archive->files, 0, len);
|
||||
|
||||
len = archive->db.Database.NumFolders * sizeof (LZMAfolder);
|
||||
archive->folders = (LZMAfolder *) allocator.Malloc(len);
|
||||
if (archive->folders == NULL)
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Init with 0 so we know when a folder is already cached
|
||||
* Values will be set by LZMA_read()
|
||||
*/
|
||||
memset(archive->folders, 0, len);
|
||||
|
||||
if(!lzma_files_init(archive))
|
||||
{
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
BAIL_MACRO(ERR_UNKNOWN_ERROR, NULL);
|
||||
}
|
||||
|
||||
return(archive);
|
||||
} /* LZMA_openArchive */
|
||||
|
||||
|
||||
/*
|
||||
* Moved to seperate function so we can use alloca then immediately throw
|
||||
* away the allocated stack space...
|
||||
*/
|
||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||
const char *odir, const char *str, size_t flen)
|
||||
{
|
||||
char *newstr = __PHYSFS_smallAlloc(flen + 1);
|
||||
if (newstr == NULL)
|
||||
return;
|
||||
|
||||
memcpy(newstr, str, flen);
|
||||
newstr[flen] = '\0';
|
||||
cb(callbackdata, odir, newstr);
|
||||
__PHYSFS_smallFree(newstr);
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
static void LZMA_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
size_t dlen = strlen(dname),
|
||||
dlen_inc = dlen + ((dlen > 0) ? 1 : 0);
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = NULL,
|
||||
*lastFile = &archive->files[archive->db.Database.NumFiles];
|
||||
if (dlen)
|
||||
{
|
||||
file = lzma_find_file(archive, dname);
|
||||
if (file != NULL) // if 'file' is NULL it should stay so, otherwise errors will not be handled
|
||||
file += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
file = archive->files;
|
||||
}
|
||||
|
||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, );
|
||||
|
||||
while (file < lastFile)
|
||||
{
|
||||
const char * fname = file->item->Name;
|
||||
const char * dirNameEnd = fname + dlen_inc;
|
||||
|
||||
if (strncmp(dname, fname, dlen) != 0) /* Stop after mismatch, archive->files is sorted */
|
||||
break;
|
||||
|
||||
if (strchr(dirNameEnd, '/')) /* Skip subdirs */
|
||||
{
|
||||
file++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do the actual callback... */
|
||||
doEnumCallback(cb, callbackdata, origdir, dirNameEnd, strlen(dirNameEnd));
|
||||
|
||||
file++;
|
||||
}
|
||||
} /* LZMA_enumerateFiles */
|
||||
|
||||
|
||||
static int LZMA_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
return(lzma_find_file(archive, name) != NULL);
|
||||
} /* LZMA_exists */
|
||||
|
||||
|
||||
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = lzma_find_file(archive, name);
|
||||
|
||||
*fileExists = (file != NULL);
|
||||
|
||||
BAIL_IF_MACRO(file == NULL, NULL, -1);
|
||||
BAIL_IF_MACRO(!file->item->IsLastWriteTimeDefined, NULL, -1); // write-time may not be defined for every file
|
||||
|
||||
return(lzma_filetime_to_unix_timestamp(&file->item->LastWriteTime));
|
||||
} /* LZMA_getLastModTime */
|
||||
|
||||
|
||||
static int LZMA_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = lzma_find_file(archive, name);
|
||||
|
||||
*fileExists = (file != NULL);
|
||||
|
||||
return(file == NULL ? 0 : file->item->IsDirectory);
|
||||
} /* LZMA_isDirectory */
|
||||
|
||||
|
||||
static int LZMA_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* LZMA_isSymLink */
|
||||
|
||||
|
||||
static fvoid *LZMA_openRead(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
LZMAfile *file = lzma_find_file(archive, name);
|
||||
|
||||
*fileExists = (file != NULL);
|
||||
BAIL_IF_MACRO(file == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(file->folder == NULL, ERR_NOT_A_FILE, NULL);
|
||||
|
||||
file->folder->references++; // Increase refcount for automatic cleanup...
|
||||
|
||||
return(file);
|
||||
} /* LZMA_openRead */
|
||||
|
||||
|
||||
static fvoid *LZMA_openWrite(dvoid *opaque, const char *filename)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* LZMA_openWrite */
|
||||
|
||||
|
||||
static fvoid *LZMA_openAppend(dvoid *opaque, const char *filename)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* LZMA_openAppend */
|
||||
|
||||
|
||||
static void LZMA_dirClose(dvoid *opaque)
|
||||
{
|
||||
LZMAarchive *archive = (LZMAarchive *) opaque;
|
||||
PHYSFS_uint32 fileIndex = 0, numFiles = archive->db.Database.NumFiles;
|
||||
|
||||
for (fileIndex = 0; fileIndex < numFiles; fileIndex++)
|
||||
{
|
||||
LZMA_fileClose(&archive->files[fileIndex]);
|
||||
} /* for */
|
||||
|
||||
SzArDbExFree(&archive->db, SzFreePhysicsFS);
|
||||
__PHYSFS_platformClose(archive->stream.file);
|
||||
lzma_archive_exit(archive);
|
||||
} /* LZMA_dirClose */
|
||||
|
||||
|
||||
static int LZMA_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* LZMA_remove */
|
||||
|
||||
|
||||
static int LZMA_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* LZMA_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_LZMA =
|
||||
{
|
||||
"7Z",
|
||||
LZMA_ARCHIVE_DESCRIPTION,
|
||||
"Dennis Schridde <devurandom@gmx.net>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_LZMA,
|
||||
LZMA_isArchive, /* isArchive() method */
|
||||
LZMA_openArchive, /* openArchive() method */
|
||||
LZMA_enumerateFiles, /* enumerateFiles() method */
|
||||
LZMA_exists, /* exists() method */
|
||||
LZMA_isDirectory, /* isDirectory() method */
|
||||
LZMA_isSymLink, /* isSymLink() method */
|
||||
LZMA_getLastModTime, /* getLastModTime() method */
|
||||
LZMA_openRead, /* openRead() method */
|
||||
LZMA_openWrite, /* openWrite() method */
|
||||
LZMA_openAppend, /* openAppend() method */
|
||||
LZMA_remove, /* remove() method */
|
||||
LZMA_mkdir, /* mkdir() method */
|
||||
LZMA_dirClose, /* dirClose() method */
|
||||
LZMA_read, /* read() method */
|
||||
LZMA_write, /* write() method */
|
||||
LZMA_eof, /* eof() method */
|
||||
LZMA_tell, /* tell() method */
|
||||
LZMA_seek, /* seek() method */
|
||||
LZMA_fileLength, /* fileLength() method */
|
||||
LZMA_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_7Z */
|
||||
|
||||
/* end of lzma.c ... */
|
||||
|
471
archivers/mvl.c
471
archivers/mvl.c
|
@ -1,471 +0,0 @@
|
|||
/*
|
||||
* MVL support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles Descent II Movielib archives.
|
||||
*
|
||||
* The file format of MVL is quite easy...
|
||||
*
|
||||
* //MVL File format - Written by Heiko Herrmann
|
||||
* char sig[4] = {'D','M', 'V', 'L'}; // "DMVL"=Descent MoVie Library
|
||||
*
|
||||
* int num_files; // the number of files in this MVL
|
||||
*
|
||||
* struct {
|
||||
* char file_name[13]; // Filename, padded to 13 bytes with 0s
|
||||
* int file_size; // filesize in bytes
|
||||
* }DIR_STRUCT[num_files];
|
||||
*
|
||||
* struct {
|
||||
* char data[file_size]; // The file data
|
||||
* }FILE_STRUCT[num_files];
|
||||
*
|
||||
* (That info is from http://www.descent2.com/ddn/specs/mvl/)
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Bradley Bell.
|
||||
* Based on grp.c by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_MVL)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[13];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} MVLentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
MVLentry *entries;
|
||||
} MVLinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
MVLentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} MVLfileinfo;
|
||||
|
||||
|
||||
static void MVL_dirClose(dvoid *opaque)
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* MVL_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
MVLentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* MVL_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* MVL_write */
|
||||
|
||||
|
||||
static int MVL_eof(fvoid *opaque)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
MVLentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* MVL_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_tell(fvoid *opaque)
|
||||
{
|
||||
return(((MVLfileinfo *) opaque)->curPos);
|
||||
} /* MVL_tell */
|
||||
|
||||
|
||||
static int MVL_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
MVLentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* MVL_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_fileLength(fvoid *opaque)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* MVL_fileLength */
|
||||
|
||||
|
||||
static int MVL_fileClose(fvoid *opaque)
|
||||
{
|
||||
MVLfileinfo *finfo = (MVLfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* MVL_fileClose */
|
||||
|
||||
|
||||
static int mvl_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint8 buf[4];
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
|
||||
goto openMvl_failed;
|
||||
|
||||
if (memcmp(buf, "DMVL", 4) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openMvl_failed;
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openMvl_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
return(1);
|
||||
|
||||
openMvl_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* mvl_open */
|
||||
|
||||
|
||||
static int MVL_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = mvl_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* MVL_isArchive */
|
||||
|
||||
|
||||
static int mvl_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const MVLentry *a = (const MVLentry *) _a;
|
||||
return(strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* mvl_entry_cmp */
|
||||
|
||||
|
||||
static void mvl_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
MVLentry tmp;
|
||||
MVLentry *first = &(((MVLentry *) _a)[one]);
|
||||
MVLentry *second = &(((MVLentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (MVLentry));
|
||||
memcpy(first, second, sizeof (MVLentry));
|
||||
memcpy(second, &tmp, sizeof (MVLentry));
|
||||
} /* if */
|
||||
} /* mvl_entry_swap */
|
||||
|
||||
|
||||
static int mvl_load_entries(const char *name, int forWriting, MVLinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
PHYSFS_uint32 location = 8; /* sizeof sig. */
|
||||
MVLentry *entry;
|
||||
|
||||
BAIL_IF_MACRO(!mvl_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (MVLentry *) allocator.Malloc(sizeof(MVLentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
location += (17 * fileCount);
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = location;
|
||||
location += entry->size;
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
mvl_entry_cmp, mvl_entry_swap);
|
||||
return(1);
|
||||
} /* mvl_load_entries */
|
||||
|
||||
|
||||
static void *MVL_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
MVLinfo *info = (MVLinfo *) allocator.Malloc(sizeof (MVLinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (MVLinfo));
|
||||
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, MVL_openArchive_failed);
|
||||
if (!mvl_load_entries(name, forWriting, info))
|
||||
goto MVL_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
return(info);
|
||||
|
||||
MVL_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* MVL_openArchive */
|
||||
|
||||
|
||||
static void MVL_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
/* no directories in MVL files. */
|
||||
if (*dname == '\0')
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
MVLentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
cb(callbackdata, origdir, entry->name);
|
||||
} /* if */
|
||||
} /* MVL_enumerateFiles */
|
||||
|
||||
|
||||
static MVLentry *mvl_find_entry(MVLinfo *info, const char *name)
|
||||
{
|
||||
char *ptr = strchr(name, '.');
|
||||
MVLentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Rule out filenames to avoid unneeded processing...no dirs,
|
||||
* big filenames, or extensions > 3 chars.
|
||||
*/
|
||||
BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL);
|
||||
BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = __PHYSFS_stricmpASCII(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* mvl_find_entry */
|
||||
|
||||
|
||||
static int MVL_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(mvl_find_entry(((MVLinfo *) opaque), name) != NULL);
|
||||
} /* MVL_exists */
|
||||
|
||||
|
||||
static int MVL_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = MVL_exists(opaque, name);
|
||||
return(0); /* never directories in a groupfile. */
|
||||
} /* MVL_isDirectory */
|
||||
|
||||
|
||||
static int MVL_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = MVL_exists(opaque, name);
|
||||
return(0); /* never symlinks in a groupfile. */
|
||||
} /* MVL_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 MVL_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (mvl_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of MVL itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* MVL_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *MVL_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
MVLinfo *info = ((MVLinfo *) opaque);
|
||||
MVLfileinfo *finfo;
|
||||
MVLentry *entry;
|
||||
|
||||
entry = mvl_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (MVLfileinfo *) allocator.Malloc(sizeof (MVLfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* MVL_openRead */
|
||||
|
||||
|
||||
static fvoid *MVL_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* MVL_openWrite */
|
||||
|
||||
|
||||
static fvoid *MVL_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* MVL_openAppend */
|
||||
|
||||
|
||||
static int MVL_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* MVL_remove */
|
||||
|
||||
|
||||
static int MVL_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* MVL_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_MVL =
|
||||
{
|
||||
"MVL",
|
||||
MVL_ARCHIVE_DESCRIPTION,
|
||||
"Bradley Bell <btb@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_MVL,
|
||||
MVL_isArchive, /* isArchive() method */
|
||||
MVL_openArchive, /* openArchive() method */
|
||||
MVL_enumerateFiles, /* enumerateFiles() method */
|
||||
MVL_exists, /* exists() method */
|
||||
MVL_isDirectory, /* isDirectory() method */
|
||||
MVL_isSymLink, /* isSymLink() method */
|
||||
MVL_getLastModTime, /* getLastModTime() method */
|
||||
MVL_openRead, /* openRead() method */
|
||||
MVL_openWrite, /* openWrite() method */
|
||||
MVL_openAppend, /* openAppend() method */
|
||||
MVL_remove, /* remove() method */
|
||||
MVL_mkdir, /* mkdir() method */
|
||||
MVL_dirClose, /* dirClose() method */
|
||||
MVL_read, /* read() method */
|
||||
MVL_write, /* write() method */
|
||||
MVL_eof, /* eof() method */
|
||||
MVL_tell, /* tell() method */
|
||||
MVL_seek, /* seek() method */
|
||||
MVL_fileLength, /* fileLength() method */
|
||||
MVL_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_MVL */
|
||||
|
||||
/* end of mvl.c ... */
|
||||
|
630
archivers/qpak.c
630
archivers/qpak.c
|
@ -1,630 +0,0 @@
|
|||
/*
|
||||
* QPAK support routines for PhysicsFS.
|
||||
*
|
||||
* This archiver handles the archive format utilized by Quake 1 and 2.
|
||||
* Quake3-based games use the PkZip/Info-Zip format (which our zip.c
|
||||
* archiver handles).
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This format info (in more detail) comes from:
|
||||
* http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/pak.txt
|
||||
*
|
||||
* Quake PAK Format
|
||||
*
|
||||
* Header
|
||||
* (4 bytes) signature = 'PACK'
|
||||
* (4 bytes) directory offset
|
||||
* (4 bytes) directory length
|
||||
*
|
||||
* Directory
|
||||
* (56 bytes) file name
|
||||
* (4 bytes) file position
|
||||
* (4 bytes) file length
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_QPAK)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#if 1 /* Make this case insensitive? */
|
||||
#define QPAK_strcmp(x, y) __PHYSFS_stricmpASCII(x, y)
|
||||
#define QPAK_strncmp(x, y, z) __PHYSFS_strnicmpASCII(x, y, z)
|
||||
#else
|
||||
#define QPAK_strcmp(x, y) strcmp(x, y)
|
||||
#define QPAK_strncmp(x, y, z) strncmp(x, y, z)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[56];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} QPAKentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
QPAKentry *entries;
|
||||
} QPAKinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
QPAKentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} QPAKfileinfo;
|
||||
|
||||
/* Magic numbers... */
|
||||
#define QPAK_SIG 0x4b434150 /* "PACK" in ASCII. */
|
||||
|
||||
|
||||
static void QPAK_dirClose(dvoid *opaque)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* QPAK_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
QPAKentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* QPAK_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* QPAK_write */
|
||||
|
||||
|
||||
static int QPAK_eof(fvoid *opaque)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
QPAKentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* QPAK_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_tell(fvoid *opaque)
|
||||
{
|
||||
return(((QPAKfileinfo *) opaque)->curPos);
|
||||
} /* QPAK_tell */
|
||||
|
||||
|
||||
static int QPAK_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
QPAKentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* QPAK_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_fileLength(fvoid *opaque)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* QPAK_fileLength */
|
||||
|
||||
|
||||
static int QPAK_fileClose(fvoid *opaque)
|
||||
{
|
||||
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* QPAK_fileClose */
|
||||
|
||||
|
||||
static int qpak_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count)
|
||||
{
|
||||
PHYSFS_uint32 buf;
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openQpak_failed;
|
||||
|
||||
buf = PHYSFS_swapULE32(buf);
|
||||
GOTO_IF_MACRO(buf != QPAK_SIG, ERR_UNSUPPORTED_ARCHIVE, openQpak_failed);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, &buf, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openQpak_failed;
|
||||
|
||||
buf = PHYSFS_swapULE32(buf); /* directory table offset. */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openQpak_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
/* corrupted archive? */
|
||||
GOTO_IF_MACRO((*count % 64) != 0, ERR_CORRUPTED, openQpak_failed);
|
||||
|
||||
if (!__PHYSFS_platformSeek(*fh, buf))
|
||||
goto openQpak_failed;
|
||||
|
||||
*count /= 64;
|
||||
return(1);
|
||||
|
||||
openQpak_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* qpak_open */
|
||||
|
||||
|
||||
static int QPAK_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount;
|
||||
int retval = qpak_open(filename, forWriting, &fh, &fileCount);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* QPAK_isArchive */
|
||||
|
||||
|
||||
static int qpak_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const QPAKentry *a = (const QPAKentry *) _a;
|
||||
return(QPAK_strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* qpak_entry_cmp */
|
||||
|
||||
|
||||
static void qpak_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
QPAKentry tmp;
|
||||
QPAKentry *first = &(((QPAKentry *) _a)[one]);
|
||||
QPAKentry *second = &(((QPAKentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (QPAKentry));
|
||||
memcpy(first, second, sizeof (QPAKentry));
|
||||
memcpy(second, &tmp, sizeof (QPAKentry));
|
||||
} /* if */
|
||||
} /* qpak_entry_swap */
|
||||
|
||||
|
||||
static int qpak_load_entries(const char *name, int forWriting, QPAKinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
QPAKentry *entry;
|
||||
|
||||
BAIL_IF_MACRO(!qpak_open(name, forWriting, &fh, &fileCount), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (QPAKentry*) allocator.Malloc(sizeof(QPAKentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
PHYSFS_uint32 loc;
|
||||
|
||||
if (__PHYSFS_platformRead(fh,&entry->name,sizeof(entry->name),1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh,&loc,sizeof(loc),1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh,&entry->size,sizeof(entry->size),1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = PHYSFS_swapULE32(loc);
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
qpak_entry_cmp, qpak_entry_swap);
|
||||
return(1);
|
||||
} /* qpak_load_entries */
|
||||
|
||||
|
||||
static void *QPAK_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
QPAKinfo *info = (QPAKinfo *) allocator.Malloc(sizeof (QPAKinfo));
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (QPAKinfo));
|
||||
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
if (info->filename == NULL)
|
||||
{
|
||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
||||
goto QPAK_openArchive_failed;
|
||||
} /* if */
|
||||
|
||||
if (!qpak_load_entries(name, forWriting, info))
|
||||
goto QPAK_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
return(info);
|
||||
|
||||
QPAK_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* QPAK_openArchive */
|
||||
|
||||
|
||||
static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
|
||||
int stop_on_first_find)
|
||||
{
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
PHYSFS_uint32 dlen = strlen(path);
|
||||
PHYSFS_sint32 retval = -1;
|
||||
const char *name;
|
||||
int rc;
|
||||
|
||||
if (*path == '\0') /* root dir? */
|
||||
return(0);
|
||||
|
||||
if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen--;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
name = info->entries[middle].name;
|
||||
rc = QPAK_strncmp(path, name, dlen);
|
||||
if (rc == 0)
|
||||
{
|
||||
char ch = name[dlen];
|
||||
if (ch < '/') /* make sure this isn't just a substr match. */
|
||||
rc = -1;
|
||||
else if (ch > '/')
|
||||
rc = 1;
|
||||
else
|
||||
{
|
||||
if (stop_on_first_find) /* Just checking dir's existance? */
|
||||
return(middle);
|
||||
|
||||
if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
|
||||
return(middle + 1);
|
||||
|
||||
/* there might be more entries earlier in the list. */
|
||||
retval = middle;
|
||||
hi = middle - 1;
|
||||
} /* else */
|
||||
} /* if */
|
||||
|
||||
if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
return(retval);
|
||||
} /* qpak_find_start_of_dir */
|
||||
|
||||
|
||||
/*
|
||||
* Moved to seperate function so we can use alloca then immediately throw
|
||||
* away the allocated stack space...
|
||||
*/
|
||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||
const char *odir, const char *str, PHYSFS_sint32 ln)
|
||||
{
|
||||
char *newstr = __PHYSFS_smallAlloc(ln + 1);
|
||||
if (newstr == NULL)
|
||||
return;
|
||||
|
||||
memcpy(newstr, str, ln);
|
||||
newstr[ln] = '\0';
|
||||
cb(callbackdata, odir, newstr);
|
||||
__PHYSFS_smallFree(newstr);
|
||||
} /* doEnumCallback */
|
||||
|
||||
|
||||
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
PHYSFS_sint32 dlen, dlen_inc, max, i;
|
||||
|
||||
i = qpak_find_start_of_dir(info, dname, 0);
|
||||
if (i == -1) /* no such directory. */
|
||||
return;
|
||||
|
||||
dlen = strlen(dname);
|
||||
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
|
||||
dlen--;
|
||||
|
||||
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
|
||||
max = (PHYSFS_sint32) info->entryCount;
|
||||
while (i < max)
|
||||
{
|
||||
char *add;
|
||||
char *ptr;
|
||||
PHYSFS_sint32 ln;
|
||||
char *e = info->entries[i].name;
|
||||
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
|
||||
break; /* past end of this dir; we're done. */
|
||||
|
||||
add = e + dlen_inc;
|
||||
ptr = strchr(add, '/');
|
||||
ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
|
||||
doEnumCallback(cb, callbackdata, origdir, add, ln);
|
||||
ln += dlen_inc; /* point past entry to children... */
|
||||
|
||||
/* increment counter and skip children of subdirs... */
|
||||
while ((++i < max) && (ptr != NULL))
|
||||
{
|
||||
char *e_new = info->entries[i].name;
|
||||
if ((QPAK_strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
|
||||
break;
|
||||
} /* while */
|
||||
} /* while */
|
||||
} /* QPAK_enumerateFiles */
|
||||
|
||||
|
||||
/*
|
||||
* This will find the QPAKentry associated with a path in platform-independent
|
||||
* notation. Directories don't have QPAKentries associated with them, but
|
||||
* (*isDir) will be set to non-zero if a dir was hit.
|
||||
*/
|
||||
static QPAKentry *qpak_find_entry(QPAKinfo *info, const char *path, int *isDir)
|
||||
{
|
||||
QPAKentry *a = info->entries;
|
||||
PHYSFS_sint32 pathlen = strlen(path);
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
const char *thispath = NULL;
|
||||
int rc;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
thispath = a[middle].name;
|
||||
rc = QPAK_strncmp(path, thispath, pathlen);
|
||||
|
||||
if (rc > 0)
|
||||
lo = middle + 1;
|
||||
|
||||
else if (rc < 0)
|
||||
hi = middle - 1;
|
||||
|
||||
else /* substring match...might be dir or entry or nothing. */
|
||||
{
|
||||
if (isDir != NULL)
|
||||
{
|
||||
*isDir = (thispath[pathlen] == '/');
|
||||
if (*isDir)
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
if (thispath[pathlen] == '\0') /* found entry? */
|
||||
return(&a[middle]);
|
||||
else
|
||||
hi = middle - 1; /* adjust search params, try again. */
|
||||
} /* if */
|
||||
} /* while */
|
||||
|
||||
if (isDir != NULL)
|
||||
*isDir = 0;
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* qpak_find_entry */
|
||||
|
||||
|
||||
static int QPAK_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
int isDir;
|
||||
QPAKinfo *info = (QPAKinfo *) opaque;
|
||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
||||
return((entry != NULL) || (isDir));
|
||||
} /* QPAK_exists */
|
||||
|
||||
|
||||
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
QPAKinfo *info = (QPAKinfo *) opaque;
|
||||
int isDir;
|
||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
||||
|
||||
*fileExists = ((isDir) || (entry != NULL));
|
||||
if (isDir)
|
||||
return(1); /* definitely a dir. */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
|
||||
} /* QPAK_isDirectory */
|
||||
|
||||
|
||||
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = QPAK_exists(opaque, name);
|
||||
return(0); /* never symlinks in a quake pak. */
|
||||
} /* QPAK_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 QPAK_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
int isDir;
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
|
||||
|
||||
*fileExists = ((isDir) || (entry != NULL));
|
||||
if (*fileExists) /* use time of QPAK itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* QPAK_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
QPAKinfo *info = ((QPAKinfo *) opaque);
|
||||
QPAKfileinfo *finfo;
|
||||
QPAKentry *entry;
|
||||
int isDir;
|
||||
|
||||
entry = qpak_find_entry(info, fnm, &isDir);
|
||||
*fileExists = ((entry != NULL) || (isDir));
|
||||
BAIL_IF_MACRO(isDir, ERR_NOT_A_FILE, NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, NULL);
|
||||
|
||||
finfo = (QPAKfileinfo *) allocator.Malloc(sizeof (QPAKfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* QPAK_openRead */
|
||||
|
||||
|
||||
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* QPAK_openWrite */
|
||||
|
||||
|
||||
static fvoid *QPAK_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* QPAK_openAppend */
|
||||
|
||||
|
||||
static int QPAK_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* QPAK_remove */
|
||||
|
||||
|
||||
static int QPAK_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* QPAK_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
|
||||
{
|
||||
"PAK",
|
||||
QPAK_ARCHIVE_DESCRIPTION,
|
||||
"Ryan C. Gordon <icculus@icculus.org>",
|
||||
"http://icculus.org/physfs/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_QPAK,
|
||||
QPAK_isArchive, /* isArchive() method */
|
||||
QPAK_openArchive, /* openArchive() method */
|
||||
QPAK_enumerateFiles, /* enumerateFiles() method */
|
||||
QPAK_exists, /* exists() method */
|
||||
QPAK_isDirectory, /* isDirectory() method */
|
||||
QPAK_isSymLink, /* isSymLink() method */
|
||||
QPAK_getLastModTime, /* getLastModTime() method */
|
||||
QPAK_openRead, /* openRead() method */
|
||||
QPAK_openWrite, /* openWrite() method */
|
||||
QPAK_openAppend, /* openAppend() method */
|
||||
QPAK_remove, /* remove() method */
|
||||
QPAK_mkdir, /* mkdir() method */
|
||||
QPAK_dirClose, /* dirClose() method */
|
||||
QPAK_read, /* read() method */
|
||||
QPAK_write, /* write() method */
|
||||
QPAK_eof, /* eof() method */
|
||||
QPAK_tell, /* tell() method */
|
||||
QPAK_seek, /* seek() method */
|
||||
QPAK_fileLength, /* fileLength() method */
|
||||
QPAK_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_QPAK */
|
||||
|
||||
/* end of qpak.c ... */
|
||||
|
534
archivers/wad.c
534
archivers/wad.c
|
@ -1,534 +0,0 @@
|
|||
/*
|
||||
* WAD support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles DOOM engine archives ("wads").
|
||||
* This format (but not this driver) was designed by id Software for use
|
||||
* with the DOOM engine.
|
||||
* The specs of the format are from the unofficial doom specs v1.666
|
||||
* found here: http://www.gamers.org/dhs/helpdocs/dmsp1666.html
|
||||
* The format of the archive: (from the specs)
|
||||
*
|
||||
* A WAD file has three parts:
|
||||
* (1) a twelve-byte header
|
||||
* (2) one or more "lumps"
|
||||
* (3) a directory or "info table" that contains the names, offsets, and
|
||||
* sizes of all the lumps in the WAD
|
||||
*
|
||||
* The header consists of three four-byte parts:
|
||||
* (a) an ASCII string which must be either "IWAD" or "PWAD"
|
||||
* (b) a 4-byte (long) integer which is the number of lumps in the wad
|
||||
* (c) a long integer which is the file offset to the start of
|
||||
* the directory
|
||||
*
|
||||
* The directory has one 16-byte entry for every lump. Each entry consists
|
||||
* of three parts:
|
||||
*
|
||||
* (a) a long integer, the file offset to the start of the lump
|
||||
* (b) a long integer, the size of the lump in bytes
|
||||
* (c) an 8-byte ASCII string, the name of the lump, padded with zeros.
|
||||
* For example, the "DEMO1" entry in hexadecimal would be
|
||||
* (44 45 4D 4F 31 00 00 00)
|
||||
*
|
||||
* Note that there is no way to tell if an opened WAD archive is a
|
||||
* IWAD or PWAD with this archiver.
|
||||
* I couldn't think of a way to provide that information, without being too
|
||||
* hacky.
|
||||
* I don't think it's really that important though.
|
||||
*
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Travis Wells, based on the GRP archiver by
|
||||
* Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#if (defined PHYSFS_SUPPORTS_WAD)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "physfs.h"
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_internal.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[18];
|
||||
PHYSFS_uint32 startPos;
|
||||
PHYSFS_uint32 size;
|
||||
} WADentry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename;
|
||||
PHYSFS_sint64 last_mod_time;
|
||||
PHYSFS_uint32 entryCount;
|
||||
PHYSFS_uint32 entryOffset;
|
||||
WADentry *entries;
|
||||
} WADinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *handle;
|
||||
WADentry *entry;
|
||||
PHYSFS_uint32 curPos;
|
||||
} WADfileinfo;
|
||||
|
||||
|
||||
static void WAD_dirClose(dvoid *opaque)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
allocator.Free(info->filename);
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* WAD_dirClose */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_read(fvoid *opaque, void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
WADentry *entry = finfo->entry;
|
||||
PHYSFS_uint32 bytesLeft = entry->size - finfo->curPos;
|
||||
PHYSFS_uint32 objsLeft = (bytesLeft / objSize);
|
||||
PHYSFS_sint64 rc;
|
||||
|
||||
if (objsLeft < objCount)
|
||||
objCount = objsLeft;
|
||||
|
||||
rc = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount);
|
||||
if (rc > 0)
|
||||
finfo->curPos += (PHYSFS_uint32) (rc * objSize);
|
||||
|
||||
return(rc);
|
||||
} /* WAD_read */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_write(fvoid *opaque, const void *buffer,
|
||||
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
|
||||
} /* WAD_write */
|
||||
|
||||
|
||||
static int WAD_eof(fvoid *opaque)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
WADentry *entry = finfo->entry;
|
||||
return(finfo->curPos >= entry->size);
|
||||
} /* WAD_eof */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_tell(fvoid *opaque)
|
||||
{
|
||||
return(((WADfileinfo *) opaque)->curPos);
|
||||
} /* WAD_tell */
|
||||
|
||||
|
||||
static int WAD_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
WADentry *entry = finfo->entry;
|
||||
int rc;
|
||||
|
||||
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
|
||||
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
|
||||
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
|
||||
if (rc)
|
||||
finfo->curPos = (PHYSFS_uint32) offset;
|
||||
|
||||
return(rc);
|
||||
} /* WAD_seek */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_fileLength(fvoid *opaque)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
return((PHYSFS_sint64) finfo->entry->size);
|
||||
} /* WAD_fileLength */
|
||||
|
||||
|
||||
static int WAD_fileClose(fvoid *opaque)
|
||||
{
|
||||
WADfileinfo *finfo = (WADfileinfo *) opaque;
|
||||
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
|
||||
allocator.Free(finfo);
|
||||
return(1);
|
||||
} /* WAD_fileClose */
|
||||
|
||||
|
||||
static int wad_open(const char *filename, int forWriting,
|
||||
void **fh, PHYSFS_uint32 *count,PHYSFS_uint32 *offset)
|
||||
{
|
||||
PHYSFS_uint8 buf[4];
|
||||
|
||||
*fh = NULL;
|
||||
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
|
||||
|
||||
*fh = __PHYSFS_platformOpenRead(filename);
|
||||
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1)
|
||||
goto openWad_failed;
|
||||
|
||||
if (memcmp(buf, "IWAD", 4) != 0 && memcmp(buf, "PWAD", 4) != 0)
|
||||
{
|
||||
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
||||
goto openWad_failed;
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openWad_failed;
|
||||
|
||||
*count = PHYSFS_swapULE32(*count);
|
||||
|
||||
if (__PHYSFS_platformRead(*fh, offset, sizeof (PHYSFS_uint32), 1) != 1)
|
||||
goto openWad_failed;
|
||||
|
||||
*offset = PHYSFS_swapULE32(*offset);
|
||||
|
||||
return(1);
|
||||
|
||||
openWad_failed:
|
||||
if (*fh != NULL)
|
||||
__PHYSFS_platformClose(*fh);
|
||||
|
||||
*count = -1;
|
||||
*fh = NULL;
|
||||
return(0);
|
||||
} /* wad_open */
|
||||
|
||||
|
||||
static int WAD_isArchive(const char *filename, int forWriting)
|
||||
{
|
||||
void *fh;
|
||||
PHYSFS_uint32 fileCount,offset;
|
||||
int retval = wad_open(filename, forWriting, &fh, &fileCount,&offset);
|
||||
|
||||
if (fh != NULL)
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
return(retval);
|
||||
} /* WAD_isArchive */
|
||||
|
||||
|
||||
static int wad_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
const WADentry *a = (const WADentry *) _a;
|
||||
return(strcmp(a[one].name, a[two].name));
|
||||
} /* if */
|
||||
|
||||
return 0;
|
||||
} /* wad_entry_cmp */
|
||||
|
||||
|
||||
static void wad_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
|
||||
{
|
||||
if (one != two)
|
||||
{
|
||||
WADentry tmp;
|
||||
WADentry *first = &(((WADentry *) _a)[one]);
|
||||
WADentry *second = &(((WADentry *) _a)[two]);
|
||||
memcpy(&tmp, first, sizeof (WADentry));
|
||||
memcpy(first, second, sizeof (WADentry));
|
||||
memcpy(second, &tmp, sizeof (WADentry));
|
||||
} /* if */
|
||||
} /* wad_entry_swap */
|
||||
|
||||
|
||||
static int wad_load_entries(const char *name, int forWriting, WADinfo *info)
|
||||
{
|
||||
void *fh = NULL;
|
||||
PHYSFS_uint32 fileCount;
|
||||
PHYSFS_uint32 directoryOffset;
|
||||
WADentry *entry;
|
||||
char lastDirectory[9];
|
||||
|
||||
lastDirectory[8] = 0; /* Make sure lastDirectory stays null-terminated. */
|
||||
|
||||
BAIL_IF_MACRO(!wad_open(name, forWriting, &fh, &fileCount,&directoryOffset), NULL, 0);
|
||||
info->entryCount = fileCount;
|
||||
info->entries = (WADentry *) allocator.Malloc(sizeof(WADentry)*fileCount);
|
||||
if (info->entries == NULL)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||
} /* if */
|
||||
|
||||
__PHYSFS_platformSeek(fh,directoryOffset);
|
||||
|
||||
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
|
||||
{
|
||||
if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1)
|
||||
{
|
||||
__PHYSFS_platformClose(fh);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
entry->name[8] = '\0'; /* name might not be null-terminated in file. */
|
||||
entry->size = PHYSFS_swapULE32(entry->size);
|
||||
entry->startPos = PHYSFS_swapULE32(entry->startPos);
|
||||
} /* for */
|
||||
|
||||
__PHYSFS_platformClose(fh);
|
||||
|
||||
__PHYSFS_sort(info->entries, info->entryCount,
|
||||
wad_entry_cmp, wad_entry_swap);
|
||||
return(1);
|
||||
} /* wad_load_entries */
|
||||
|
||||
|
||||
static void *WAD_openArchive(const char *name, int forWriting)
|
||||
{
|
||||
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
|
||||
WADinfo *info = (WADinfo *) allocator.Malloc(sizeof (WADinfo));
|
||||
|
||||
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (WADinfo));
|
||||
|
||||
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
|
||||
GOTO_IF_MACRO(!info->filename, ERR_OUT_OF_MEMORY, WAD_openArchive_failed);
|
||||
|
||||
if (!wad_load_entries(name, forWriting, info))
|
||||
goto WAD_openArchive_failed;
|
||||
|
||||
strcpy(info->filename, name);
|
||||
info->last_mod_time = modtime;
|
||||
return(info);
|
||||
|
||||
WAD_openArchive_failed:
|
||||
if (info != NULL)
|
||||
{
|
||||
if (info->filename != NULL)
|
||||
allocator.Free(info->filename);
|
||||
if (info->entries != NULL)
|
||||
allocator.Free(info->entries);
|
||||
allocator.Free(info);
|
||||
} /* if */
|
||||
|
||||
return(NULL);
|
||||
} /* WAD_openArchive */
|
||||
|
||||
|
||||
static void WAD_enumerateFiles(dvoid *opaque, const char *dname,
|
||||
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
||||
const char *origdir, void *callbackdata)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
WADentry *entry = info->entries;
|
||||
PHYSFS_uint32 max = info->entryCount;
|
||||
PHYSFS_uint32 i;
|
||||
const char *name;
|
||||
char *sep;
|
||||
|
||||
if (*dname == '\0') /* root directory enumeration? */
|
||||
{
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
{
|
||||
name = entry->name;
|
||||
if (strchr(name, '/') == NULL)
|
||||
cb(callbackdata, origdir, name);
|
||||
} /* for */
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < max; i++, entry++)
|
||||
{
|
||||
name = entry->name;
|
||||
sep = strchr(name, '/');
|
||||
if (sep != NULL)
|
||||
{
|
||||
if (strncmp(dname, name, (sep - name)) == 0)
|
||||
cb(callbackdata, origdir, sep + 1);
|
||||
} /* if */
|
||||
} /* for */
|
||||
} /* else */
|
||||
} /* WAD_enumerateFiles */
|
||||
|
||||
|
||||
static WADentry *wad_find_entry(WADinfo *info, const char *name)
|
||||
{
|
||||
WADentry *a = info->entries;
|
||||
PHYSFS_sint32 lo = 0;
|
||||
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
|
||||
PHYSFS_sint32 middle;
|
||||
int rc;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
middle = lo + ((hi - lo) / 2);
|
||||
rc = strcmp(name, a[middle].name);
|
||||
if (rc == 0) /* found it! */
|
||||
return(&a[middle]);
|
||||
else if (rc > 0)
|
||||
lo = middle + 1;
|
||||
else
|
||||
hi = middle - 1;
|
||||
} /* while */
|
||||
|
||||
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
|
||||
} /* wad_find_entry */
|
||||
|
||||
|
||||
static int WAD_exists(dvoid *opaque, const char *name)
|
||||
{
|
||||
return(wad_find_entry(((WADinfo *) opaque), name) != NULL);
|
||||
} /* WAD_exists */
|
||||
|
||||
|
||||
static int WAD_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
WADentry *entry = wad_find_entry(((WADinfo *) opaque), name);
|
||||
if (entry != NULL)
|
||||
{
|
||||
char *n;
|
||||
|
||||
*fileExists = 1;
|
||||
|
||||
/* Can't be a directory if it's a subdirectory. */
|
||||
if (strchr(entry->name, '/') != NULL)
|
||||
return(0);
|
||||
|
||||
/* Check if it matches "MAP??" or "E?M?" ... */
|
||||
n = entry->name;
|
||||
if ((n[0] == 'E' && n[2] == 'M') ||
|
||||
(n[0] == 'M' && n[1] == 'A' && n[2] == 'P' && n[6] == 0))
|
||||
{
|
||||
return(1);
|
||||
} /* if */
|
||||
return(0);
|
||||
} /* if */
|
||||
else
|
||||
{
|
||||
*fileExists = 0;
|
||||
return(0);
|
||||
} /* else */
|
||||
} /* WAD_isDirectory */
|
||||
|
||||
|
||||
static int WAD_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
||||
{
|
||||
*fileExists = WAD_exists(opaque, name);
|
||||
return(0); /* never symlinks in a wad. */
|
||||
} /* WAD_isSymLink */
|
||||
|
||||
|
||||
static PHYSFS_sint64 WAD_getLastModTime(dvoid *opaque,
|
||||
const char *name,
|
||||
int *fileExists)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
PHYSFS_sint64 retval = -1;
|
||||
|
||||
*fileExists = (wad_find_entry(info, name) != NULL);
|
||||
if (*fileExists) /* use time of WAD itself in the physical filesystem. */
|
||||
retval = info->last_mod_time;
|
||||
|
||||
return(retval);
|
||||
} /* WAD_getLastModTime */
|
||||
|
||||
|
||||
static fvoid *WAD_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
||||
{
|
||||
WADinfo *info = ((WADinfo *) opaque);
|
||||
WADfileinfo *finfo;
|
||||
WADentry *entry;
|
||||
|
||||
entry = wad_find_entry(info, fnm);
|
||||
*fileExists = (entry != NULL);
|
||||
BAIL_IF_MACRO(entry == NULL, NULL, NULL);
|
||||
|
||||
finfo = (WADfileinfo *) allocator.Malloc(sizeof (WADfileinfo));
|
||||
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
|
||||
if ( (finfo->handle == NULL) ||
|
||||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
|
||||
{
|
||||
allocator.Free(finfo);
|
||||
return(NULL);
|
||||
} /* if */
|
||||
|
||||
finfo->curPos = 0;
|
||||
finfo->entry = entry;
|
||||
return(finfo);
|
||||
} /* WAD_openRead */
|
||||
|
||||
|
||||
static fvoid *WAD_openWrite(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* WAD_openWrite */
|
||||
|
||||
|
||||
static fvoid *WAD_openAppend(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
||||
} /* WAD_openAppend */
|
||||
|
||||
|
||||
static int WAD_remove(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* WAD_remove */
|
||||
|
||||
|
||||
static int WAD_mkdir(dvoid *opaque, const char *name)
|
||||
{
|
||||
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
||||
} /* WAD_mkdir */
|
||||
|
||||
|
||||
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD =
|
||||
{
|
||||
"WAD",
|
||||
WAD_ARCHIVE_DESCRIPTION,
|
||||
"Travis Wells <traviswells@mchsi.com>",
|
||||
"http://www.3dmm2.com/doom/",
|
||||
};
|
||||
|
||||
|
||||
const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
|
||||
{
|
||||
&__PHYSFS_ArchiveInfo_WAD,
|
||||
WAD_isArchive, /* isArchive() method */
|
||||
WAD_openArchive, /* openArchive() method */
|
||||
WAD_enumerateFiles, /* enumerateFiles() method */
|
||||
WAD_exists, /* exists() method */
|
||||
WAD_isDirectory, /* isDirectory() method */
|
||||
WAD_isSymLink, /* isSymLink() method */
|
||||
WAD_getLastModTime, /* getLastModTime() method */
|
||||
WAD_openRead, /* openRead() method */
|
||||
WAD_openWrite, /* openWrite() method */
|
||||
WAD_openAppend, /* openAppend() method */
|
||||
WAD_remove, /* remove() method */
|
||||
WAD_mkdir, /* mkdir() method */
|
||||
WAD_dirClose, /* dirClose() method */
|
||||
WAD_read, /* read() method */
|
||||
WAD_write, /* write() method */
|
||||
WAD_eof, /* eof() method */
|
||||
WAD_tell, /* tell() method */
|
||||
WAD_seek, /* seek() method */
|
||||
WAD_fileLength, /* fileLength() method */
|
||||
WAD_fileClose /* fileClose() method */
|
||||
};
|
||||
|
||||
#endif /* defined PHYSFS_SUPPORTS_WAD */
|
||||
|
||||
/* end of wad.c ... */
|
||||
|
1451
archivers/zip.c
1451
archivers/zip.c
File diff suppressed because it is too large
Load Diff
|
@ -6,6 +6,6 @@ The changelog is no longer maintained by hand. It made sense to have a single
|
|||
If you want a list of changes, updated in real time, just point your web
|
||||
browser here:
|
||||
|
||||
http://hg.icculus.org/icculus/physfs/
|
||||
https://github.com/icculus/physfs/commits/
|
||||
|
||||
|
|
@ -27,7 +27,6 @@ Various support, fixes and suggestions:
|
|||
Alexander Pipelka
|
||||
|
||||
Russian translation,
|
||||
Ruby bindings,
|
||||
QPAK archiver:
|
||||
Ed Sinjiashvili
|
||||
|
||||
|
@ -53,6 +52,9 @@ Mac OS X improvements:
|
|||
iPhone support:
|
||||
Christian Gmeiner
|
||||
|
||||
WinRT support:
|
||||
Martin Ahrnbom
|
||||
|
||||
HOG archiver,
|
||||
MVL archiver:
|
||||
Bradley Bell
|
||||
|
@ -90,6 +92,12 @@ Bug fixes:
|
|||
Bug fixes:
|
||||
Olivier Boudeville
|
||||
|
||||
Bug fixes:
|
||||
Henk Boom
|
||||
|
||||
Build system fixes:
|
||||
Marc Kleine-Budde
|
||||
|
||||
Windows .rc file,
|
||||
7zip/lzma archiver:
|
||||
Dennis Schridde
|
||||
|
@ -97,6 +105,68 @@ Windows .rc file,
|
|||
OS/2 updates:
|
||||
Dave Yeo
|
||||
|
||||
Bug fixes:
|
||||
Patrice Mandin
|
||||
|
||||
PHYSFS_stat() API:
|
||||
Christoph Nelles
|
||||
Indy Sams
|
||||
|
||||
ISO9660 archiver:
|
||||
Christoph Nelles
|
||||
|
||||
Bug fixes:
|
||||
Steven Fuller
|
||||
|
||||
Bug fixes:
|
||||
Tolga Dalman
|
||||
|
||||
Bug fixes:
|
||||
Frank Becker
|
||||
|
||||
Bug fixes:
|
||||
Norfanin
|
||||
|
||||
Bug fixes:
|
||||
Evgeny Podjachev
|
||||
|
||||
Haiku fixes:
|
||||
Chris Roberts
|
||||
|
||||
SLB archiver:
|
||||
Aleksi Nurmi
|
||||
|
||||
Bug fixes:
|
||||
Dmitry Marakasov
|
||||
|
||||
Bug fixes:
|
||||
Andreas Karlsson
|
||||
|
||||
Bug fixes:
|
||||
Michael Bacon
|
||||
|
||||
Bug fixes:
|
||||
Xian Nox
|
||||
|
||||
Bug fixes:
|
||||
Reto Schneider
|
||||
|
||||
pkg-config support:
|
||||
Jonas Kulla
|
||||
|
||||
Bug fixes,
|
||||
VDF archiver:
|
||||
Francesco Bertolaccini
|
||||
|
||||
CMake fixes:
|
||||
Tobias Markus
|
||||
|
||||
Bug fixes,
|
||||
Rémi Verschelde
|
||||
|
||||
Bug fixes:
|
||||
Rob Loach
|
||||
|
||||
Other stuff:
|
||||
Your name here! Patches go to icculus@icculus.org ...
|
||||
|
|
@ -23,7 +23,8 @@ PROJECT_NAME = physfs
|
|||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 2.0.0
|
||||
# (CMake will set this properly at build time. --ryan.)
|
||||
PROJECT_NUMBER = "unknown version (build with 'make docs' next time!)"
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
@ -361,7 +362,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = physfs.h
|
||||
INPUT = src/physfs.h
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
@ -876,7 +877,8 @@ INCLUDE_FILE_PATTERNS =
|
|||
# omitted =1 is assumed.
|
||||
|
||||
PREDEFINED = DOXYGEN_SHOULD_IGNORE_THIS=1 \
|
||||
__EXPORT__=
|
||||
PHYSFS_DECL= \
|
||||
PHYSFS_DEPRECATED=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
|
@ -0,0 +1,173 @@
|
|||
|
||||
The latest PhysicsFS information and releases can be found at:
|
||||
https://icculus.org/physfs/
|
||||
|
||||
Building is (ahem) very easy.
|
||||
|
||||
|
||||
ALL PLATFORMS:
|
||||
|
||||
Please read the text file LICENSE.txt in the root of the source tree.
|
||||
The license is extremely liberal, even to closed-source, commercial
|
||||
applications.
|
||||
|
||||
If you've got Doxygen (http://www.doxygen.org/) installed, you can run it
|
||||
without any command line arguments in the root of the source tree to generate
|
||||
the API reference (or build the "docs" target from your build system). This
|
||||
is optional. You can browse the API docs online here:
|
||||
|
||||
https://icculus.org/physfs/docs/
|
||||
|
||||
|
||||
|
||||
BUILD IT WITH YOUR OWN PROGRAM:
|
||||
|
||||
If you don't care about formal packaging: just add everything in the "src"
|
||||
directory to whatever you use to build your program and compile it along with
|
||||
everything else, and you're done. It should compile with any reasonable
|
||||
ANSI C compiler, should build cleanly even with excessive compiler warnings
|
||||
enabled, needs no extra configuration, and allows static linking.
|
||||
WinRT and Haiku need C++ compilers for their system APIs, but if you aren't on
|
||||
these platforms and don't have a C++ compiler, don't build the .cpp files.
|
||||
Likewise: Apple platforms (macOS, iOS, etc) need an Objective-C compiler, but
|
||||
if you aren't on these platforms and don't have a Objective-C compiler, don't
|
||||
build the .m file. Everything you need is in the .c sources.
|
||||
|
||||
If this all worked for your specific project, you can stop reading now.
|
||||
|
||||
|
||||
|
||||
Unix:
|
||||
|
||||
You will need CMake (https://www.cmake.org/) 2.4 or later installed.
|
||||
|
||||
Make a directory, wherever you like. This will be your build directory.
|
||||
|
||||
Chdir to your build directory. Run "cmake /where/i/unpacked/physfs" to
|
||||
generate Makefiles. You can then run "ccmake ." and customize the build,
|
||||
but the defaults are probably okay. You can have CMake generate KDevelop
|
||||
or Ninja project files or whatever, if you prefer these.
|
||||
|
||||
Run "make". PhysicsFS will now build.
|
||||
|
||||
As root, run "make install".
|
||||
If you get sick of the library, run "make uninstall" as root
|
||||
and it will remove all traces of the library from the system paths.
|
||||
|
||||
Once you are satisfied, you can delete the build directory.
|
||||
|
||||
Primary Unix development is done with GNU/Linux, but PhysicsFS is known to
|
||||
work out of the box with several flavors of Unix. It it doesn't work, patches
|
||||
to get it running can be sent to icculus@icculus.org.
|
||||
|
||||
|
||||
Windows:
|
||||
|
||||
If building with Cygwin, mingw32, MSYS, or something else that uses the GNU
|
||||
toolchain, follow the Unix instructions, above.
|
||||
|
||||
If you want to use Visual Studio, nmake, or the Platform SDK, you will need
|
||||
CMake (https://www.cmake.org/) 2.4 or later installed. Point CMake at the
|
||||
CMakeLists.txt file in the root of the source directory and hit the
|
||||
"Configure" button. After telling it what type of compiler you are targeting
|
||||
(Borland, Visual Studio, etc), CMake will process for while and then give you
|
||||
a list of options you can change (what archivers you want to support, etc).
|
||||
If you aren't sure, the defaults are probably fine. Hit the "Configure"
|
||||
button again, then "OK" once configuration has completed with options that
|
||||
match your liking. Now project files for your favorite programming
|
||||
environment will be generated for you in the directory you specified.
|
||||
Go there and use them to build PhysicsFS.
|
||||
|
||||
PhysicsFS will only link directly against system libraries that have existed
|
||||
since Windows NT 3.51. If there's a newer API we want to use, we try to
|
||||
dynamically load it at runtime and fallback to a reasonable behaviour when
|
||||
we can't find it. Note that Windows 98 and later _should_
|
||||
work if you use the Microsoft Layer for Unicode (UNICOWS.DLL) to provide
|
||||
some missing system APIs, but this is no longer tested as of PhysicsFS 2.1.0.
|
||||
PhysicsFS 2.0.x is known to work with Windows 95 without UNICOWS.DLL.
|
||||
|
||||
PhysicsFS works on 32-bit and 64-bit Windows. There is no 16-bit Windows
|
||||
support at all. Windows RT is covered below.
|
||||
|
||||
|
||||
Windows RT:
|
||||
|
||||
Windows RT (Windows Phone, Windows Store, UWP) 8.0 and later are supported.
|
||||
Make sure you include both physfs_platform_windows.c _and_
|
||||
physfs_platform_winrt.cpp in your build, and that the C++ file has
|
||||
"Consume Windows Runtime Extension" set to "Yes" in its Visual Studio
|
||||
properties (from the command line, you want to compile this file with the
|
||||
"/ZW" compiler switch). CMake can, in theory, generate a project file for
|
||||
WinRT if you pick a recent Visual Studio target, choose manual cross-compile
|
||||
options, and set the system name to "WindowsPhone" or "WindowsStore" and the
|
||||
correct OS version (8.0 or later).
|
||||
|
||||
|
||||
PocketPC/WindowsCE:
|
||||
|
||||
Support for PocketPC was removed in PhysicsFS 2.1.0. This was known to work
|
||||
in the 1.0 releases, but wasn't tested in 2.0 and later. PhysicsFS should
|
||||
work on modern Windows Phones (see "Windows RT" section).
|
||||
|
||||
|
||||
macOS:
|
||||
|
||||
You will need CMake (https://www.cmake.org/) 2.4 or later installed.
|
||||
|
||||
You can either generate a Unix makefile with CMake, or generate an Xcode
|
||||
project, whichever makes you more comfortable.
|
||||
|
||||
PowerPC and Intel Macs should both be supported.
|
||||
|
||||
|
||||
MAC OS 8/9 ("Mac OS Classic"):
|
||||
|
||||
Classic Mac OS support has been dropped in PhysicsFS 2.0. Apple hasn't updated
|
||||
pre-OSX versions in more than a decade at this point, none of the hardware
|
||||
they've shipped will boot it for almost as many years, and finding
|
||||
developer tools for it is becoming almost impossible. As the switch to Intel
|
||||
hardware has removed the "Classic" emulation environment, it was time to
|
||||
remove support from PhysicsFS. That being said, the PhysicsFS 1.0 branch can
|
||||
still target back to Mac OS 8.5, so you can use that if you need support for
|
||||
this legacy OS. We still very much support modern macOS, though: see above.
|
||||
|
||||
|
||||
Emscripten:
|
||||
|
||||
Use the "Unix" instructions, above. You can install the Emscripten SDK and use
|
||||
the extras/buildbot-emscripten.sh script to automate this for you.
|
||||
|
||||
|
||||
BeOS, Zeta, YellowTab:
|
||||
|
||||
BeOS support was dropped in PhysicsFS 2.1.0. Consider installing Haiku, which
|
||||
we still support.
|
||||
|
||||
|
||||
Haiku:
|
||||
|
||||
Use the "Unix" instructions, above.
|
||||
|
||||
|
||||
OS/2:
|
||||
|
||||
OS/2 is known to work with OpenWatcom and GCC-based compilers. I couldn't get
|
||||
an OS/2 port of CMake to generate OpenWatcom project files (although it should
|
||||
be able to do that in theory), it should be able to do Unix Makefiles with
|
||||
GCC. It might be easier to just compile PhysicsFS along with the rest of
|
||||
your project on this platform.
|
||||
|
||||
|
||||
|
||||
OTHER PLATFORMS:
|
||||
|
||||
Many Unix-like platforms might "just work" with CMake. Some of these platforms
|
||||
are known to have worked at one time, but have not been heavily tested, if
|
||||
tested at all. PhysicsFS is, as far as we know, 64-bit and byteorder clean,
|
||||
and is known to compile on several compilers across many platforms. To
|
||||
implement a new platform or archiver, please read the heavily-commented
|
||||
physfs_internal.h and look at the physfs_platform_* and physfs_archiver_*
|
||||
source files for examples.
|
||||
|
||||
--ryan. (icculus@icculus.org)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
The API documentation is readable in a few ways:
|
||||
|
||||
- Read physfs.h; it's _heavily_ documented and the primary source of reference
|
||||
documentation for the library.
|
||||
- Run Doxygen over the header, which produces nicer-to-browse documentation in
|
||||
HTML, LaTeX, manpage, etc formats. This is done for you if Doxygen is
|
||||
installed and you build the "docs" target in whatever project files CMake
|
||||
generated for you.
|
||||
- Too much trouble? We generated the HTML reference for you, online here:
|
||||
|
||||
https://icculus.org/physfs/docs/
|
||||
|
||||
- We would love well-written tutorials for the latest version of PhysicsFS!
|
||||
If you write one, we would love to list it here. Drop me a line about it:
|
||||
icculus@icculus.org ... Thanks!
|
||||
|
||||
--ryan.
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
Stuff that needs to be done and wishlist:
|
||||
|
||||
These are in no particular order.
|
||||
Some might be dupes, some might be done already, some might be bad ideas.
|
||||
|
||||
|
||||
From https://icculus.org/pipermail/physfs/2009-March/000698.html ...
|
||||
|
||||
- Write support for various archives. I haven't decided how to do this yet,
|
||||
but I'd like to.
|
||||
- Add an API to expose a file's extended attributes to the application?
|
||||
- Deprecate PHYSFS_setSaneConfig(). It really should have been in the extras
|
||||
directory.
|
||||
- Clean up the sources to match my ever-changing coding style. :)
|
||||
|
||||
|
||||
|
||||
From https://icculus.org/pipermail/physfs/2010-January/000826.html ...
|
||||
|
||||
- Lua bindings
|
||||
|
||||
|
||||
From https://icculus.org/pipermail/physfs/2010-January/000833.html ...
|
||||
|
||||
- SWIG bindings
|
||||
|
||||
|
||||
|
||||
From old TODO.txt...
|
||||
|
||||
- Other archivers: perhaps tar(.gz|.bz2), RPM, ARJ, etc. These are less
|
||||
important, since streaming archives aren't of much value to games (which
|
||||
is why zipfiles are king: random access), but it could have uses for, say,
|
||||
an installer/updater.
|
||||
- Do symlinks in zip archiver work when they point to dirs?
|
||||
- Enable more warnings?
|
||||
- Use __cdecl in physfs.h?
|
||||
- Look for FIXMEs (many marked with "!!!" in comments).
|
||||
- fscanf and fprintf support in extras dir.
|
||||
- Sanity check byte order at runtime.
|
||||
- Memory locking?
|
||||
- General code audit.
|
||||
- Multiple write dirs with mount points?
|
||||
|
||||
|
||||
Other stuff I thought of...
|
||||
- moar asserts!
|
||||
- constify!
|
||||
- Does iPhone work?
|
||||
- Fix CMake vs Doxygen.
|
||||
- Doxygen replacement? (manpages suck.)
|
||||
- Fix coding standards to match.
|
||||
- See if we can ditch some #include lines...
|
||||
- LZMA support in zip archiver?
|
||||
- bzip2 support in zip archiver?
|
||||
- Reduce the BAIL and GOTO macro use. A lot of these don't add anything.
|
||||
- Change the term "search path" to something less confusing.
|
||||
|
||||
Probably other stuff. Requests and recommendations are welcome.
|
||||
|
||||
// end of TODO.txt ...
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("PhysFS.NET")]
|
||||
[assembly: AssemblyDescription("PhysFS Bindings for .NET")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PhysFS.NET")]
|
||||
[assembly: AssemblyCopyright("(c)2003 Gregory S. Read")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
|
@ -1,113 +0,0 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.0.9466"
|
||||
SchemaVersion = "1.0"
|
||||
ProjectGuid = "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = ""
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "PhysFS.NET"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "Library"
|
||||
RootNamespace = "PhysFS.NET"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "true"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "true"
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "true"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Drawing"
|
||||
AssemblyName = "System.Drawing"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Windows.Forms"
|
||||
AssemblyName = "System.Windows.Forms"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysFS.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysFS_DLL.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "PhysFSFileStream.cs"
|
||||
SubType = "Code"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysFS.NET", "PhysFS.NET.csproj", "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.ActiveCfg = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.Build.0 = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.ActiveCfg = Release|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,189 +0,0 @@
|
|||
/* PhysFS.cs - (c)2003 Gregory S. Read
|
||||
* Provides access to PhysFS API calls not specific to file handle access.
|
||||
*/
|
||||
using System;
|
||||
|
||||
namespace PhysFS_NET
|
||||
{
|
||||
public class PhysFS
|
||||
{
|
||||
/* Initialize
|
||||
* Inits the PhysFS API. This normally does not need to be called unless
|
||||
* the API has been manually deinitialized since the PhysFS_DLL class
|
||||
* initializes just before the first call is made into the DLL.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* none
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API
|
||||
*/
|
||||
public static void Initialize()
|
||||
{
|
||||
// Initialize the physfs library, raise an exception if error
|
||||
if(PhysFS_DLL.PHYSFS_init("") == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
/* Deinitialize
|
||||
* Deinits the PhysFS API. It is recommended that this method be called
|
||||
* by the application before exiting in order to gracefully deallocate
|
||||
* resources and close all filehandles, etc.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* none
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API
|
||||
*/
|
||||
public static void Deinitialize()
|
||||
{
|
||||
// Deinit, raise an exception if an error occured
|
||||
if(PhysFS_DLL.PHYSFS_deinit() == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
/* BaseDir
|
||||
* Gets the base directory configured for PhysFS. See the PhysFS API
|
||||
* documentation for more information.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* A string value representing the Base Directory
|
||||
* Exceptions
|
||||
* none
|
||||
*/
|
||||
public static string BaseDir
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return the current base directory
|
||||
return PhysFS_DLL.PHYSFS_getBaseDir();
|
||||
}
|
||||
}
|
||||
|
||||
/* WriteDir
|
||||
* Gets or sets the write directory configured for PhysFS. See the PhysFS API
|
||||
* documentation for more information.
|
||||
* Parameters
|
||||
* set - Path to set the WriteDir property to
|
||||
* Returns
|
||||
* A string value representing the Write Directory
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API when
|
||||
* settings the write directory.
|
||||
*/
|
||||
public static string WriteDir
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return the current write directory
|
||||
return PhysFS_DLL.PHYSFS_getWriteDir();
|
||||
}
|
||||
set
|
||||
{
|
||||
// Set the write directory and raise an exception if an error occured
|
||||
if(PhysFS_DLL.PHYSFS_setWriteDir(value) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
}
|
||||
|
||||
/* UserDir
|
||||
* Gets or sets the write directory configured for PhysFS. See the PhysFS API
|
||||
* documentation for more information.
|
||||
* Parameters
|
||||
* set - Path to set the WriteDir property to
|
||||
* Returns
|
||||
* A string value representing the Write Directory
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API when
|
||||
* settings the write directory.
|
||||
*/
|
||||
public static string UserDir
|
||||
{
|
||||
get
|
||||
{
|
||||
// Return the current user directory
|
||||
return PhysFS_DLL.PHYSFS_getUserDir();
|
||||
}
|
||||
}
|
||||
public static void AddToSearchPath(string NewDir, bool Append)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_addToSearchPath(NewDir, Append?1:0) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public static void RemoveFromSearchPath(string OldDir)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_removeFromSearchPath(OldDir) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public unsafe static string[] GetSearchPath()
|
||||
{
|
||||
byte** p; // Searchpath list from PhysFS dll
|
||||
string[] pathlist; // List converted to an array
|
||||
|
||||
// Get the CDROM drive listing
|
||||
p = PhysFS_DLL.PHYSFS_getSearchPath();
|
||||
// Convert the C-style array to a .NET style array
|
||||
pathlist = PhysFS_DLL.BytePPToArray(p);
|
||||
// Free the original list since we're done with it
|
||||
PhysFS_DLL.PHYSFS_freeList(p);
|
||||
|
||||
return pathlist;
|
||||
}
|
||||
public unsafe static string[] GetCDROMDrives()
|
||||
{
|
||||
byte** p; // CDROM list from PhysFS dll
|
||||
string[] cdromlist; // List converted to an array
|
||||
|
||||
// Get the CDROM drive listing
|
||||
p = PhysFS_DLL.PHYSFS_getCdRomDirs();
|
||||
// Convert the C-style array to a .NET style array
|
||||
cdromlist = PhysFS_DLL.BytePPToArray(p);
|
||||
// Free the original list since we're done with it
|
||||
PhysFS_DLL.PHYSFS_freeList(p);
|
||||
|
||||
return cdromlist;
|
||||
}
|
||||
public static void MkDir(string Dirname)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_mkdir(Dirname) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public static void Delete(string Filename)
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_delete(Filename) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
public static string GetRealDir(string Filename)
|
||||
{
|
||||
string RetValue;
|
||||
|
||||
RetValue = PhysFS_DLL.PHYSFS_getRealDir(Filename);
|
||||
if(RetValue == null)
|
||||
throw new PhysFSException("File not found in search path.");
|
||||
|
||||
// Return the real file path of the specified filename
|
||||
return RetValue;
|
||||
}
|
||||
public unsafe static string[] EnumerateFiles(string Dirname)
|
||||
{
|
||||
byte** p; // File list from PhysFS dll
|
||||
string[] filelist; // List converted to an array
|
||||
|
||||
// Get the CDROM drive listing
|
||||
p = PhysFS_DLL.PHYSFS_enumerateFiles(Dirname);
|
||||
// Convert the C-style array to a .NET style array
|
||||
filelist = PhysFS_DLL.BytePPToArray(p);
|
||||
// Free the original list since we're done with it
|
||||
PhysFS_DLL.PHYSFS_freeList(p);
|
||||
|
||||
return filelist;
|
||||
}
|
||||
public static bool IsDirectory(string Filename)
|
||||
{
|
||||
// Return true if non-zero, otherwise return false
|
||||
return (PhysFS_DLL.PHYSFS_isDirectory(Filename) == 0)?false:true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/* PhysFSFileStream.cs - (c)2003 Gregory S. Read */
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace PhysFS_NET
|
||||
{
|
||||
public enum PhysFSFileMode {Read, Write, Append};
|
||||
|
||||
// Our exception class we'll use for throwing all PhysFS API related exception
|
||||
public class PhysFSException : IOException
|
||||
{
|
||||
public PhysFSException(string Message) : base(Message) {}
|
||||
public PhysFSException() : base(PhysFS_DLL.PHYSFS_getLastError()) {}
|
||||
}
|
||||
|
||||
public unsafe class PhysFSFileStream : Stream
|
||||
{
|
||||
// ***Public properties***
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
{
|
||||
// Reading is supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get
|
||||
{
|
||||
// Seek is supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get
|
||||
{
|
||||
// Writing is supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
long TempLength;
|
||||
TempLength = PhysFS_DLL.PHYSFS_fileLength(pHandle);
|
||||
|
||||
// If call returned an error, throw an exception
|
||||
if(TempLength == -1)
|
||||
throw new PhysFSException();
|
||||
|
||||
return TempLength;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
long TempPosition;
|
||||
TempPosition = PhysFS_DLL.PHYSFS_tell(pHandle);
|
||||
|
||||
// If call returned an error, throw an exception
|
||||
if(TempPosition == -1)
|
||||
throw new PhysFSException();
|
||||
|
||||
return TempPosition;
|
||||
}
|
||||
set
|
||||
{
|
||||
// Seek from beginning of file using the position value
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
// ***Public methods***
|
||||
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode, ulong BufferSize)
|
||||
{
|
||||
// Open the specified file with the appropriate file access
|
||||
switch(FileMode)
|
||||
{
|
||||
case PhysFSFileMode.Read:
|
||||
pHandle = PhysFS_DLL.PHYSFS_openRead(FileName);
|
||||
break;
|
||||
case PhysFSFileMode.Write:
|
||||
pHandle = PhysFS_DLL.PHYSFS_openWrite(FileName);
|
||||
break;
|
||||
case PhysFSFileMode.Append:
|
||||
pHandle = PhysFS_DLL.PHYSFS_openAppend(FileName);
|
||||
break;
|
||||
default:
|
||||
throw new PhysFSException("Invalid FileMode specified");
|
||||
}
|
||||
|
||||
// If handle is null, an error occured, so raise an exception
|
||||
//!!! Does object get created if exception is thrown?
|
||||
if(pHandle == null)
|
||||
throw new PhysFSException();
|
||||
|
||||
// Set buffer size, raise an exception if an error occured
|
||||
if(PhysFS_DLL.PHYSFS_setBuffer(pHandle, BufferSize) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
// This constructor sets the buffer size to 0 if not specified
|
||||
public PhysFSFileStream(string FileName, PhysFSFileMode FileMode) : this(FileName, FileMode, 0) {}
|
||||
|
||||
~PhysFSFileStream()
|
||||
{
|
||||
// Don't close the handle if they've specifically closed it already
|
||||
if(!Closed)
|
||||
Close();
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
if(PhysFS_DLL.PHYSFS_flush(pHandle) == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
long RetValue;
|
||||
|
||||
fixed(byte *pbytes = &buffer[offset])
|
||||
{
|
||||
// Read into our allocated pointer
|
||||
RetValue = PhysFS_DLL.PHYSFS_read(pHandle, pbytes, sizeof(byte), (uint)count);
|
||||
}
|
||||
|
||||
if(RetValue == -1)
|
||||
throw new PhysFSException();
|
||||
|
||||
// Return number of bytes read
|
||||
// Note: This cast should be safe since we are only reading 'count' items, which
|
||||
// is of type 'int'.
|
||||
return (int)RetValue;
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
long RetValue;
|
||||
|
||||
fixed(byte* pbytes = &buffer[offset])
|
||||
{
|
||||
// Write buffer
|
||||
RetValue = PhysFS_DLL.PHYSFS_write(pHandle, pbytes, sizeof(byte), (uint)count);
|
||||
}
|
||||
|
||||
if(RetValue == -1)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
// Only seeking from beginning is supported by PhysFS API
|
||||
if(origin != SeekOrigin.Begin)
|
||||
throw new PhysFSException("Only seek origin of \"Begin\" is supported");
|
||||
|
||||
// Seek to specified offset, raise an exception if error occured
|
||||
if(PhysFS_DLL.PHYSFS_seek(pHandle, (ulong)offset) == 0)
|
||||
throw new PhysFSException();
|
||||
|
||||
// Since we always seek from beginning, the offset is always
|
||||
// the absolute position.
|
||||
return offset;
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException("SetLength method not supported in PhysFSFileStream objects.");
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
// Close the handle
|
||||
if(PhysFS_DLL.PHYSFS_close(pHandle) == 0)
|
||||
throw new PhysFSException();
|
||||
|
||||
// File has been closed. Rock.
|
||||
Closed = true;
|
||||
}
|
||||
|
||||
// ***Private variables***
|
||||
private void *pHandle;
|
||||
private bool Closed = false;
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/* PhysFS_DLL - (c)2003 Gregory S. Read
|
||||
* Internal class that provides direct access to the PhysFS DLL. It is
|
||||
* not accessible outside of the PhysFS.NET assembly.
|
||||
*/
|
||||
using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PhysFS_NET
|
||||
{
|
||||
internal class PhysFS_DLL
|
||||
{
|
||||
/* Static constructor
|
||||
* Initializes the PhysFS API before any method is called in this class. This
|
||||
* relieves the user from having to explicitly initialize the API.
|
||||
* Parameters
|
||||
* none
|
||||
* Returns
|
||||
* none
|
||||
* Exceptions
|
||||
* PhysFSException - An error occured in the PhysFS API
|
||||
*/
|
||||
static PhysFS_DLL()
|
||||
{
|
||||
if(PHYSFS_init("") == 0)
|
||||
throw new PhysFSException();
|
||||
}
|
||||
|
||||
/* BytePPToArray
|
||||
* Converts a C-style string array into a .NET managed string array
|
||||
* Parameters
|
||||
* C-style string array pointer returned from PhysFS
|
||||
* Returns
|
||||
* .NET managed string array
|
||||
* Exceptions
|
||||
* none
|
||||
*/
|
||||
public unsafe static string[] BytePPToArray(byte **bytearray)
|
||||
{
|
||||
byte** ptr;
|
||||
byte* c;
|
||||
string tempstr;
|
||||
ArrayList MyArrayList = new ArrayList();
|
||||
string[] RetArray;
|
||||
|
||||
for(ptr = bytearray; *ptr != null; ptr++)
|
||||
{
|
||||
tempstr = "";
|
||||
for(c = *ptr; *c != 0; c++)
|
||||
{
|
||||
tempstr += (char)*c;
|
||||
}
|
||||
|
||||
// Add string to our list
|
||||
MyArrayList.Add(tempstr);
|
||||
}
|
||||
|
||||
// Return a normal array of the list
|
||||
RetArray = new string[MyArrayList.Count];
|
||||
MyArrayList.CopyTo(RetArray, 0);
|
||||
return RetArray;
|
||||
}
|
||||
|
||||
// Name of DLL to import
|
||||
private const string PHYSFS_DLLNAME = "physfs.dll";
|
||||
|
||||
// DLL import declarations
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_init(string argv0);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_deinit();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void PHYSFS_freeList(void *listVar);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getLastError();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getDirSeparator();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern void PHYSFS_permitSymbolicLinks(int allow);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_getCdRomDirs();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getBaseDir();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getUserDir();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getWriteDir();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_setWriteDir(string newDir);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_addToSearchPath(string newDir, int appendToPath);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_removeFromSearchPath(string oldDir);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_getSearchPath();
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_setSaneConfig(string organization,
|
||||
string appName,
|
||||
string archiveExt,
|
||||
int includeCdRoms,
|
||||
int archivesFirst);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_mkdir(string dirName);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_delete(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern string PHYSFS_getRealDir(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe byte** PHYSFS_enumerateFiles(string dir);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_exists(string fname);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_isDirectory(string fname);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern int PHYSFS_isSymbolicLink(string fname);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openWrite(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openAppend(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe void* PHYSFS_openRead(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_close(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_getLastModTime(string filename);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_read(void* handle,
|
||||
void *buffer,
|
||||
uint objSize,
|
||||
uint objCount);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_write(void* handle,
|
||||
void *buffer,
|
||||
uint objSize,
|
||||
uint objCount);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_eof(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_tell(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_seek(void* handle, ulong pos);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe long PHYSFS_fileLength(void* handle);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_setBuffer(void* handle, ulong bufsize);
|
||||
[DllImport(PHYSFS_DLLNAME)] public static extern unsafe int PHYSFS_flush(void* handle);
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
PhysFS.NET is a library that encapsulates the PhysFS API into a .NET assembly.
|
||||
|
||||
There are two class objects that are exposed in the assembly:
|
||||
PhysFS.cs
|
||||
This class exposes any non-filehandle specific functionality contained in
|
||||
the PhysFS library.
|
||||
PhysFSFileStream.cs
|
||||
A System.IO.Stream derived class which provides file access via the
|
||||
PhysFS API. Usage of this object is identical to a standard stream
|
||||
object.
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1,58 +0,0 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
|
@ -1,116 +0,0 @@
|
|||
<VisualStudioProject>
|
||||
<CSHARP
|
||||
ProjectType = "Local"
|
||||
ProductVersion = "7.0.9466"
|
||||
SchemaVersion = "1.0"
|
||||
ProjectGuid = "{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}"
|
||||
>
|
||||
<Build>
|
||||
<Settings
|
||||
ApplicationIcon = "App.ico"
|
||||
AssemblyKeyContainerName = ""
|
||||
AssemblyName = "TestApp"
|
||||
AssemblyOriginatorKeyFile = ""
|
||||
DefaultClientScript = "JScript"
|
||||
DefaultHTMLPageLayout = "Grid"
|
||||
DefaultTargetSchema = "IE50"
|
||||
DelaySign = "false"
|
||||
OutputType = "WinExe"
|
||||
RootNamespace = "TestApp"
|
||||
StartupObject = ""
|
||||
>
|
||||
<Config
|
||||
Name = "Debug"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "DEBUG;TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "true"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "true"
|
||||
Optimize = "false"
|
||||
OutputPath = "bin\Debug\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
<Config
|
||||
Name = "Release"
|
||||
AllowUnsafeBlocks = "false"
|
||||
BaseAddress = "285212672"
|
||||
CheckForOverflowUnderflow = "false"
|
||||
ConfigurationOverrideFile = ""
|
||||
DefineConstants = "TRACE"
|
||||
DocumentationFile = ""
|
||||
DebugSymbols = "false"
|
||||
FileAlignment = "4096"
|
||||
IncrementalBuild = "false"
|
||||
Optimize = "true"
|
||||
OutputPath = "bin\Release\"
|
||||
RegisterForComInterop = "false"
|
||||
RemoveIntegerChecks = "false"
|
||||
TreatWarningsAsErrors = "false"
|
||||
WarningLevel = "4"
|
||||
/>
|
||||
</Settings>
|
||||
<References>
|
||||
<Reference
|
||||
Name = "System"
|
||||
AssemblyName = "System"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Data"
|
||||
AssemblyName = "System.Data"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Drawing"
|
||||
AssemblyName = "System.Drawing"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.Windows.Forms"
|
||||
AssemblyName = "System.Windows.Forms"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "System.XML"
|
||||
AssemblyName = "System.Xml"
|
||||
HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
|
||||
/>
|
||||
<Reference
|
||||
Name = "PhysFS.NET"
|
||||
Project = "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
|
||||
/>
|
||||
</References>
|
||||
</Build>
|
||||
<Files>
|
||||
<Include>
|
||||
<File
|
||||
RelPath = "App.ico"
|
||||
BuildAction = "Content"
|
||||
/>
|
||||
<File
|
||||
RelPath = "AssemblyInfo.cs"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestAppForm.cs"
|
||||
SubType = "Form"
|
||||
BuildAction = "Compile"
|
||||
/>
|
||||
<File
|
||||
RelPath = "TestAppForm.resx"
|
||||
DependentUpon = "TestAppForm.cs"
|
||||
BuildAction = "EmbeddedResource"
|
||||
/>
|
||||
</Include>
|
||||
</Files>
|
||||
</CSHARP>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApp", "TestApp.csproj", "{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PhysFS.NET", "..\PhysFS.NET.csproj", "{C6205A43-3D4D-41E6-872C-96CD7BE55230}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Debug.ActiveCfg = Debug|.NET
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Debug.Build.0 = Debug|.NET
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Release.ActiveCfg = Release|.NET
|
||||
{9C1ECC6B-16C7-42B3-BF7C-8BA8D81BA980}.Release.Build.0 = Release|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.ActiveCfg = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Debug.Build.0 = Debug|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.ActiveCfg = Release|.NET
|
||||
{C6205A43-3D4D-41E6-872C-96CD7BE55230}.Release.Build.0 = Release|.NET
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,274 +0,0 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Collections;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using PhysFS_NET;
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Form1.
|
||||
/// </summary>
|
||||
public class TestAppForm : System.Windows.Forms.Form
|
||||
{
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Button RefreshCDsButton;
|
||||
private System.Windows.Forms.ListBox CDDrivesList;
|
||||
private System.Windows.Forms.ListBox SearchPathList;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox EnumFilesPath;
|
||||
private System.Windows.Forms.ListBox EnumList;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.TextBox NewSearchPathText;
|
||||
private System.Windows.Forms.Button AddSearchPathButton;
|
||||
private System.Windows.Forms.Button RemovePathButton;
|
||||
private System.Windows.Forms.Button RefreshEnumList;
|
||||
private System.Windows.Forms.Button RefreshSearchPathButton;
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.Container components = null;
|
||||
|
||||
public TestAppForm()
|
||||
{
|
||||
//
|
||||
// Required for Windows Form Designer support
|
||||
//
|
||||
InitializeComponent();
|
||||
|
||||
//
|
||||
// TODO: Add any constructor code after InitializeComponent call
|
||||
//
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
protected override void Dispose( bool disposing )
|
||||
{
|
||||
if( disposing )
|
||||
{
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose( disposing );
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.RefreshCDsButton = new System.Windows.Forms.Button();
|
||||
this.CDDrivesList = new System.Windows.Forms.ListBox();
|
||||
this.SearchPathList = new System.Windows.Forms.ListBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.EnumFilesPath = new System.Windows.Forms.TextBox();
|
||||
this.EnumList = new System.Windows.Forms.ListBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.RefreshEnumList = new System.Windows.Forms.Button();
|
||||
this.NewSearchPathText = new System.Windows.Forms.TextBox();
|
||||
this.AddSearchPathButton = new System.Windows.Forms.Button();
|
||||
this.RemovePathButton = new System.Windows.Forms.Button();
|
||||
this.RefreshSearchPathButton = new System.Windows.Forms.Button();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.Location = new System.Drawing.Point(8, 8);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(136, 16);
|
||||
this.label2.TabIndex = 2;
|
||||
this.label2.Text = "Available CD-ROM Drives";
|
||||
//
|
||||
// RefreshCDsButton
|
||||
//
|
||||
this.RefreshCDsButton.Location = new System.Drawing.Point(8, 152);
|
||||
this.RefreshCDsButton.Name = "RefreshCDsButton";
|
||||
this.RefreshCDsButton.Size = new System.Drawing.Size(72, 24);
|
||||
this.RefreshCDsButton.TabIndex = 4;
|
||||
this.RefreshCDsButton.Text = "Refresh";
|
||||
this.RefreshCDsButton.Click += new System.EventHandler(this.RefreshCDsButton_Click);
|
||||
//
|
||||
// CDDrivesList
|
||||
//
|
||||
this.CDDrivesList.Location = new System.Drawing.Point(8, 24);
|
||||
this.CDDrivesList.Name = "CDDrivesList";
|
||||
this.CDDrivesList.Size = new System.Drawing.Size(136, 121);
|
||||
this.CDDrivesList.TabIndex = 7;
|
||||
//
|
||||
// SearchPathList
|
||||
//
|
||||
this.SearchPathList.Location = new System.Drawing.Point(152, 24);
|
||||
this.SearchPathList.Name = "SearchPathList";
|
||||
this.SearchPathList.Size = new System.Drawing.Size(248, 95);
|
||||
this.SearchPathList.TabIndex = 8;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.Location = new System.Drawing.Point(152, 8);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(136, 16);
|
||||
this.label1.TabIndex = 10;
|
||||
this.label1.Text = "Search Path";
|
||||
//
|
||||
// EnumFilesPath
|
||||
//
|
||||
this.EnumFilesPath.Location = new System.Drawing.Point(408, 128);
|
||||
this.EnumFilesPath.Name = "EnumFilesPath";
|
||||
this.EnumFilesPath.Size = new System.Drawing.Size(208, 20);
|
||||
this.EnumFilesPath.TabIndex = 11;
|
||||
this.EnumFilesPath.Text = "";
|
||||
//
|
||||
// EnumList
|
||||
//
|
||||
this.EnumList.Location = new System.Drawing.Point(408, 24);
|
||||
this.EnumList.Name = "EnumList";
|
||||
this.EnumList.Size = new System.Drawing.Size(208, 95);
|
||||
this.EnumList.TabIndex = 12;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.Location = new System.Drawing.Point(408, 8);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(136, 16);
|
||||
this.label3.TabIndex = 13;
|
||||
this.label3.Text = "Enumerate Files";
|
||||
//
|
||||
// RefreshEnumList
|
||||
//
|
||||
this.RefreshEnumList.Location = new System.Drawing.Point(544, 152);
|
||||
this.RefreshEnumList.Name = "RefreshEnumList";
|
||||
this.RefreshEnumList.Size = new System.Drawing.Size(72, 24);
|
||||
this.RefreshEnumList.TabIndex = 14;
|
||||
this.RefreshEnumList.Text = "Refresh";
|
||||
this.RefreshEnumList.Click += new System.EventHandler(this.RefreshEnumList_Click);
|
||||
//
|
||||
// NewSearchPathText
|
||||
//
|
||||
this.NewSearchPathText.Location = new System.Drawing.Point(152, 128);
|
||||
this.NewSearchPathText.Name = "NewSearchPathText";
|
||||
this.NewSearchPathText.Size = new System.Drawing.Size(248, 20);
|
||||
this.NewSearchPathText.TabIndex = 15;
|
||||
this.NewSearchPathText.Text = "";
|
||||
//
|
||||
// AddSearchPathButton
|
||||
//
|
||||
this.AddSearchPathButton.Location = new System.Drawing.Point(152, 152);
|
||||
this.AddSearchPathButton.Name = "AddSearchPathButton";
|
||||
this.AddSearchPathButton.Size = new System.Drawing.Size(72, 24);
|
||||
this.AddSearchPathButton.TabIndex = 9;
|
||||
this.AddSearchPathButton.Text = "Add Path";
|
||||
this.AddSearchPathButton.Click += new System.EventHandler(this.AddSearchPathButton_Click);
|
||||
//
|
||||
// RemovePathButton
|
||||
//
|
||||
this.RemovePathButton.Location = new System.Drawing.Point(232, 152);
|
||||
this.RemovePathButton.Name = "RemovePathButton";
|
||||
this.RemovePathButton.Size = new System.Drawing.Size(88, 24);
|
||||
this.RemovePathButton.TabIndex = 16;
|
||||
this.RemovePathButton.Text = "Remove Path";
|
||||
this.RemovePathButton.Click += new System.EventHandler(this.RemovePathButton_Click);
|
||||
//
|
||||
// RefreshSearchPathButton
|
||||
//
|
||||
this.RefreshSearchPathButton.Location = new System.Drawing.Point(328, 152);
|
||||
this.RefreshSearchPathButton.Name = "RefreshSearchPathButton";
|
||||
this.RefreshSearchPathButton.Size = new System.Drawing.Size(72, 24);
|
||||
this.RefreshSearchPathButton.TabIndex = 17;
|
||||
this.RefreshSearchPathButton.Text = "Refresh";
|
||||
this.RefreshSearchPathButton.Click += new System.EventHandler(this.RefreshSearchPathButton_Click);
|
||||
//
|
||||
// TestAppForm
|
||||
//
|
||||
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
|
||||
this.ClientSize = new System.Drawing.Size(624, 309);
|
||||
this.Controls.AddRange(new System.Windows.Forms.Control[] {
|
||||
this.RefreshSearchPathButton,
|
||||
this.RemovePathButton,
|
||||
this.NewSearchPathText,
|
||||
this.RefreshEnumList,
|
||||
this.label3,
|
||||
this.EnumList,
|
||||
this.EnumFilesPath,
|
||||
this.label1,
|
||||
this.SearchPathList,
|
||||
this.CDDrivesList,
|
||||
this.RefreshCDsButton,
|
||||
this.label2,
|
||||
this.AddSearchPathButton});
|
||||
this.Name = "TestAppForm";
|
||||
this.Text = "PhysFS Test Application";
|
||||
this.Load += new System.EventHandler(this.TestAppForm_Load);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// The main entry point for the application.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.Run(new TestAppForm());
|
||||
}
|
||||
|
||||
private void TestAppForm_Load(object sender, System.EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void RefreshCDsButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
// Clear ths listbox if it contains any items
|
||||
CDDrivesList.Items.Clear();
|
||||
// Add the items to the list
|
||||
CDDrivesList.Items.AddRange(PhysFS.GetCDROMDrives());
|
||||
}
|
||||
|
||||
private void RefreshSearchPathButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
// Clear ths listbox if it contains any items
|
||||
SearchPathList.Items.Clear();
|
||||
// Add the items to the list
|
||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
||||
}
|
||||
|
||||
private void AddSearchPathButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
// Add search path
|
||||
PhysFS.AddToSearchPath(NewSearchPathText.Text, false);
|
||||
// Clear ths listbox if it contains any items
|
||||
SearchPathList.Items.Clear();
|
||||
// Add the items to the list
|
||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
||||
}
|
||||
|
||||
private void RemovePathButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
if(SearchPathList.SelectedItem != null)
|
||||
{
|
||||
PhysFS.RemoveFromSearchPath(SearchPathList.SelectedItem.ToString());
|
||||
// Clear ths listbox if it contains any items
|
||||
SearchPathList.Items.Clear();
|
||||
// Add the items to the list
|
||||
SearchPathList.Items.AddRange(PhysFS.GetSearchPath());
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshEnumList_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
EnumList.Items.Clear();
|
||||
EnumList.Items.AddRange(PhysFS.EnumerateFiles(EnumFilesPath.Text));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 1.3
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">1.3</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1">this is my long string</data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
[base64 mime encoded serialized .NET Framework object]
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
[base64 mime encoded string representing a byte array form of the .NET Framework object]
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>1.3</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="$this.Name">
|
||||
<value>TestAppForm</value>
|
||||
</data>
|
||||
</root>
|
|
@ -0,0 +1,11 @@
|
|||
There used to be C# bindings in this directory, but they have been
|
||||
unmaintained for many years.
|
||||
|
||||
Instead, there is a more modern PhysicsFS wrapper for .NET available.
|
||||
|
||||
You can find it at https://github.com/frabert/SharpPhysFS
|
||||
|
||||
Thanks to Francesco Bertolaccini for his efforts on that project!
|
||||
|
||||
--ryan.
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is a script used by some Buildbot workers to push the project
|
||||
# through Clang's static analyzer and prepare the output to be uploaded
|
||||
# back to the buildmaster. You might find it useful too.
|
||||
|
||||
# Install Clang (you already have it on Mac OS X, apt-get install clang
|
||||
# on Ubuntu, etc), Make sure "scan-build" is in your $PATH.
|
||||
|
||||
FINALDIR="$1"
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
cd `dirname "$0"`
|
||||
cd ..
|
||||
|
||||
rm -rf checker-buildbot analysis
|
||||
if [ ! -z "$FINALDIR" ]; then
|
||||
rm -rf "$FINALDIR"
|
||||
fi
|
||||
|
||||
mkdir checker-buildbot
|
||||
cd checker-buildbot
|
||||
|
||||
# We turn off deprecated declarations, because we don't care about these warnings during static analysis.
|
||||
# The -Wno-liblto is new since our checker-279 upgrade, I think; checker otherwise warns "libLTO.dylib relative to clang installed dir not found"
|
||||
|
||||
# You might want to do this for CMake-backed builds instead...
|
||||
scan-build -o analysis cmake -G Ninja -Wno-dev -DPHYSFS_BUILD_SHARED=False -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_FLAGS="-Wno-deprecated-declarations" -DCMAKE_EXE_LINKER_FLAGS="-Wno-liblto" ..
|
||||
|
||||
rm -rf analysis
|
||||
scan-build -o analysis cmake --build . --config Debug
|
||||
|
||||
if [ `ls -A analysis |wc -l` == 0 ] ; then
|
||||
mkdir analysis/zarro
|
||||
echo '<html><head><title>Zarro boogs</title></head><body>Static analysis: no issues to report.</body></html>' >analysis/zarro/index.html
|
||||
fi
|
||||
|
||||
mv analysis/* ../analysis
|
||||
rmdir analysis # Make sure this is empty.
|
||||
cd ..
|
||||
chmod -R a+r analysis
|
||||
chmod -R go-w analysis
|
||||
find analysis -type d -exec chmod a+x {} \;
|
||||
if [ -x /usr/bin/xattr ]; then find analysis -exec /usr/bin/xattr -d com.apple.quarantine {} \; 2>/dev/null ; fi
|
||||
|
||||
if [ ! -z "$FINALDIR" ]; then
|
||||
mv analysis "$FINALDIR"
|
||||
else
|
||||
FINALDIR=analysis
|
||||
fi
|
||||
|
||||
rm -rf checker-buildbot
|
||||
|
||||
echo "Done. Final output is in '$FINALDIR' ..."
|
||||
|
||||
# end of checker-buildbot.sh ...
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ -z "$SDKDIR" ]; then
|
||||
SDKDIR="/emsdk"
|
||||
fi
|
||||
|
||||
ENVSCRIPT="$SDKDIR/emsdk_env.sh"
|
||||
if [ ! -f "$ENVSCRIPT" ]; then
|
||||
echo "ERROR: This script expects the Emscripten SDK to be in '$SDKDIR'." 1>&2
|
||||
echo "ERROR: Set the \$SDKDIR environment variable to override this." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARBALL="$1"
|
||||
if [ -z $1 ]; then
|
||||
TARBALL=physfs-emscripten.tar.xz
|
||||
fi
|
||||
|
||||
cd `dirname "$0"`
|
||||
cd ..
|
||||
PHYSFSBASE=`pwd`
|
||||
|
||||
echo "Setting up Emscripten SDK environment..."
|
||||
source "$ENVSCRIPT"
|
||||
|
||||
echo "Setting up..."
|
||||
cd "$PHYSFSBASE"
|
||||
rm -rf buildbot
|
||||
mkdir buildbot
|
||||
cd buildbot
|
||||
|
||||
echo "Configuring..."
|
||||
emcmake cmake -G "Ninja" -DPHYSFS_BUILD_SHARED=False -DCMAKE_BUILD_TYPE=MinSizeRel .. || exit $?
|
||||
|
||||
echo "Building..."
|
||||
emmake cmake --build . --config MinSizeRel || exit $?
|
||||
|
||||
set -e
|
||||
rm -rf "$TARBALL" physfs-emscripten
|
||||
mkdir -p physfs-emscripten
|
||||
echo "Archiving to '$TARBALL' ..."
|
||||
cp ../src/physfs.h libphysfs.a physfs-emscripten
|
||||
chmod -R a+r physfs-emscripten
|
||||
chmod a+x physfs-emscripten
|
||||
chmod -R go-w physfs-emscripten
|
||||
tar -cJvvf "$TARBALL" physfs-emscripten
|
||||
echo "Done."
|
||||
|
||||
exit 0
|
||||
|
||||
# end of emscripten-buildbot.sh ...
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is used by the buildbot to cross-compile for OS/2 from Linux, using
|
||||
# OpenWatcom. In an ideal world, we wouldn't need this, but we need a few
|
||||
# things to do this "properly" ...
|
||||
#
|
||||
# - OS/2 running as a VMware guest on the build machine
|
||||
# - Buildbot-worker running on that OS/2 guest
|
||||
# - CMake for OS/2 that...
|
||||
# - ... has Open Watcom compiler support and...
|
||||
# - ... a Watcom WMake project generator.
|
||||
#
|
||||
# Some of these things are doable (there is a CMake port for OS/2, you can
|
||||
# use GCC with it), but since OpenWatcom will just target OS/2 on Linux just
|
||||
# like it could on OS/2, it's easier and more efficient to just have a
|
||||
# buildbot script compile it here.
|
||||
#
|
||||
# Note that we just blast all the C files through the wcc386 compiler and
|
||||
# skip CMake entirely. We should fix this at some point.
|
||||
|
||||
set -e
|
||||
|
||||
ZIPFILE="$1"
|
||||
if [ -z $ZIPFILE ]; then
|
||||
ZIPFILE=physfs-os2.zip
|
||||
fi
|
||||
|
||||
export WATCOM="/usr/local/share/watcom"
|
||||
export PATH="$PATH:$WATCOM/binl"
|
||||
|
||||
CFLAGS="-i=\"$WATCOM/h;$WATCOM/h/os2;../src\" -wx -d0 -otexan -6r -zq -bt=os2 -fo=.obj -mf"
|
||||
WLIBFLAGS="-b -c -n -q -p=512"
|
||||
|
||||
cd `dirname "$0"`
|
||||
cd ..
|
||||
mkdir -p buildbot
|
||||
cd buildbot
|
||||
|
||||
rm -f test_physfs.obj
|
||||
|
||||
OKAY="1"
|
||||
for src in ../src/*.c ; do
|
||||
echo wcc386 $src $CFLAGS
|
||||
wcc386 $src $CFLAGS || OKAY="0"
|
||||
done
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
echo wlib $WLIBFLAGS physfs.lib *.obj
|
||||
wlib $WLIBFLAGS physfs.lib *.obj || OKAY="0"
|
||||
fi
|
||||
|
||||
echo wcc386 ../test/test_physfs.c $CFLAGS
|
||||
wcc386 ../test/test_physfs.c $CFLAGS || OKAY="0"
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
LDFLAGS="name test_physfs d all sys os2v2 op m libr physfs op q op symf FIL test_physfs.obj"
|
||||
echo wlink $LDFLAGS
|
||||
wlink $LDFLAGS || OKAY="0"
|
||||
fi
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
F=`file test_physfs.exe`
|
||||
echo "$F"
|
||||
if [ "$F" != 'test_physfs.exe: MS-DOS executable, LX for OS/2 (console) i80386' ]; then
|
||||
echo 1>&2 "ERROR: final binary doesn't appear to be OS/2 executable."
|
||||
OKAY=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$OKAY" == "1" ]; then
|
||||
echo 1>&2 "Build succeeded."
|
||||
set -e
|
||||
rm -rf "$ZIPFILE" physfs-os2
|
||||
mkdir -p physfs-os2
|
||||
echo "Zipping to '$ZIPFILE' ..."
|
||||
cp ../src/physfs.h physfs.lib physfs-os2
|
||||
chmod -R a+r physfs-os2
|
||||
chmod a+x physfs-os2
|
||||
chmod -R go-w physfs-os2
|
||||
zip -9r "$ZIPFILE" physfs-os2
|
||||
echo "Done."
|
||||
exit 0
|
||||
else
|
||||
echo 1>&2 "Build failed."
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This is the script physfs-buildbot.icculus.org uses to cross-compile
|
||||
# PhysicsFS from x86 Linux to Raspberry Pi. This script was originally from
|
||||
# Simple Directmedia Layer ( https://www.libsdl.org/ ).
|
||||
|
||||
# The final tarball can be unpacked in the root directory of a RPi,
|
||||
# so the PhysicsFS install lands in /usr/local. Run ldconfig, and then
|
||||
# you should be able to build and run PhysicsFS-based software on your
|
||||
# Pi. Standard configure scripts should be able to find PhysicsFS and
|
||||
# build against it.
|
||||
|
||||
TARBALL="$1"
|
||||
if [ -z $1 ]; then
|
||||
TARBALL=physfs-raspberrypi.tar.xz
|
||||
fi
|
||||
|
||||
BUILDBOTDIR="buildbot"
|
||||
PARENTDIR="$PWD"
|
||||
|
||||
set -e
|
||||
set -x
|
||||
rm -f $TARBALL
|
||||
rm -rf $BUILDBOTDIR
|
||||
mkdir -p $BUILDBOTDIR
|
||||
pushd $BUILDBOTDIR
|
||||
|
||||
# the '-G "Ninja"' can be '-G "Unix Makefiles"' if you prefer to use GNU Make.
|
||||
SYSROOT="/opt/rpi-sysroot"
|
||||
cmake -G "Ninja" \
|
||||
-DCMAKE_C_COMPILER="/opt/rpi-tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc" \
|
||||
-DCMAKE_BUILD_TYPE=MinSizeRel \
|
||||
-DCMAKE_SYSROOT="$SYSROOT" \
|
||||
-DCMAKE_FIND_ROOT_PATH="$SYSROOT" \
|
||||
-DCMAKE_SYSTEM_NAME="Linux" \
|
||||
-DCMAKE_SYSTEM_VERSION=1 \
|
||||
-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \
|
||||
-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \
|
||||
-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \
|
||||
..
|
||||
|
||||
cmake --build . --config MinSizeRel
|
||||
|
||||
rm -rf "$TARBALL" physfs-raspberrypi
|
||||
mkdir -p physfs-raspberrypi
|
||||
echo "Archiving to '$TARBALL' ..."
|
||||
cp -a ../src/physfs.h libphysfs.a libphysfs.so* physfs-raspberrypi
|
||||
chmod -R a+r physfs-raspberrypi
|
||||
chmod a+x physfs-raspberrypi physfs-raspberrypi/*.so*
|
||||
chmod -R go-w physfs-raspberrypi
|
||||
tar -cJvvf "$TARBALL" physfs-raspberrypi
|
||||
|
||||
set +x
|
||||
echo "Done."
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
# CaseFolding-4.1.0.txt
|
||||
# Date: 2005-03-26, 00:24:43 GMT [MD]
|
||||
# CaseFolding-8.0.0.txt
|
||||
# Date: 2015-01-13, 18:16:36 GMT [MD]
|
||||
#
|
||||
# Unicode Character Database
|
||||
# Copyright (c) 1991-2005 Unicode, Inc.
|
||||
# Copyright (c) 1991-2015 Unicode, Inc.
|
||||
# For terms of use, see http://www.unicode.org/terms_of_use.html
|
||||
# For documentation, see UCD.html
|
||||
# For documentation, see http://www.unicode.org/reports/tr44/
|
||||
#
|
||||
# Case Folding Properties
|
||||
#
|
||||
|
@ -23,8 +23,9 @@
|
|||
#
|
||||
# NOTE: case folding does not preserve normalization formats!
|
||||
#
|
||||
# For information on case folding, see
|
||||
# UTR #21 Case Mappings, at http://www.unicode.org/unicode/reports/tr21/
|
||||
# For information on case folding, including how to have case folding
|
||||
# preserve normalization formats, see Section 3.13 Default Case Algorithms in
|
||||
# The Unicode Standard.
|
||||
#
|
||||
# ================================================================================
|
||||
# Format
|
||||
|
@ -52,6 +53,12 @@
|
|||
#
|
||||
# =================================================================
|
||||
|
||||
# Property: Case_Folding
|
||||
|
||||
# All code points not explicitly listed for Case_Folding
|
||||
# have the value C for the status field, and the code point itself for the mapping field.
|
||||
|
||||
# =================================================================
|
||||
0041; C; 0061; # LATIN CAPITAL LETTER A
|
||||
0042; C; 0062; # LATIN CAPITAL LETTER B
|
||||
0043; C; 0063; # LATIN CAPITAL LETTER C
|
||||
|
@ -272,10 +279,24 @@
|
|||
022E; C; 022F; # LATIN CAPITAL LETTER O WITH DOT ABOVE
|
||||
0230; C; 0231; # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON
|
||||
0232; C; 0233; # LATIN CAPITAL LETTER Y WITH MACRON
|
||||
023A; C; 2C65; # LATIN CAPITAL LETTER A WITH STROKE
|
||||
023B; C; 023C; # LATIN CAPITAL LETTER C WITH STROKE
|
||||
023D; C; 019A; # LATIN CAPITAL LETTER L WITH BAR
|
||||
0241; C; 0294; # LATIN CAPITAL LETTER GLOTTAL STOP
|
||||
023E; C; 2C66; # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
|
||||
0241; C; 0242; # LATIN CAPITAL LETTER GLOTTAL STOP
|
||||
0243; C; 0180; # LATIN CAPITAL LETTER B WITH STROKE
|
||||
0244; C; 0289; # LATIN CAPITAL LETTER U BAR
|
||||
0245; C; 028C; # LATIN CAPITAL LETTER TURNED V
|
||||
0246; C; 0247; # LATIN CAPITAL LETTER E WITH STROKE
|
||||
0248; C; 0249; # LATIN CAPITAL LETTER J WITH STROKE
|
||||
024A; C; 024B; # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
|
||||
024C; C; 024D; # LATIN CAPITAL LETTER R WITH STROKE
|
||||
024E; C; 024F; # LATIN CAPITAL LETTER Y WITH STROKE
|
||||
0345; C; 03B9; # COMBINING GREEK YPOGEGRAMMENI
|
||||
0370; C; 0371; # GREEK CAPITAL LETTER HETA
|
||||
0372; C; 0373; # GREEK CAPITAL LETTER ARCHAIC SAMPI
|
||||
0376; C; 0377; # GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA
|
||||
037F; C; 03F3; # GREEK CAPITAL LETTER YOT
|
||||
0386; C; 03AC; # GREEK CAPITAL LETTER ALPHA WITH TONOS
|
||||
0388; C; 03AD; # GREEK CAPITAL LETTER EPSILON WITH TONOS
|
||||
0389; C; 03AE; # GREEK CAPITAL LETTER ETA WITH TONOS
|
||||
|
@ -312,6 +333,7 @@
|
|||
03AB; C; 03CB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
|
||||
03B0; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
|
||||
03C2; C; 03C3; # GREEK SMALL LETTER FINAL SIGMA
|
||||
03CF; C; 03D7; # GREEK CAPITAL KAI SYMBOL
|
||||
03D0; C; 03B2; # GREEK BETA SYMBOL
|
||||
03D1; C; 03B8; # GREEK THETA SYMBOL
|
||||
03D5; C; 03C6; # GREEK PHI SYMBOL
|
||||
|
@ -335,6 +357,9 @@
|
|||
03F7; C; 03F8; # GREEK CAPITAL LETTER SHO
|
||||
03F9; C; 03F2; # GREEK CAPITAL LUNATE SIGMA SYMBOL
|
||||
03FA; C; 03FB; # GREEK CAPITAL LETTER SAN
|
||||
03FD; C; 037B; # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL
|
||||
03FE; C; 037C; # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL
|
||||
03FF; C; 037D; # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
|
||||
0400; C; 0450; # CYRILLIC CAPITAL LETTER IE WITH GRAVE
|
||||
0401; C; 0451; # CYRILLIC CAPITAL LETTER IO
|
||||
0402; C; 0452; # CYRILLIC CAPITAL LETTER DJE
|
||||
|
@ -427,6 +452,7 @@
|
|||
04BA; C; 04BB; # CYRILLIC CAPITAL LETTER SHHA
|
||||
04BC; C; 04BD; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE
|
||||
04BE; C; 04BF; # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
|
||||
04C0; C; 04CF; # CYRILLIC LETTER PALOCHKA
|
||||
04C1; C; 04C2; # CYRILLIC CAPITAL LETTER ZHE WITH BREVE
|
||||
04C3; C; 04C4; # CYRILLIC CAPITAL LETTER KA WITH HOOK
|
||||
04C5; C; 04C6; # CYRILLIC CAPITAL LETTER EL WITH TAIL
|
||||
|
@ -455,6 +481,9 @@
|
|||
04F4; C; 04F5; # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
|
||||
04F6; C; 04F7; # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
|
||||
04F8; C; 04F9; # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
|
||||
04FA; C; 04FB; # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
|
||||
04FC; C; 04FD; # CYRILLIC CAPITAL LETTER HA WITH HOOK
|
||||
04FE; C; 04FF; # CYRILLIC CAPITAL LETTER HA WITH STROKE
|
||||
0500; C; 0501; # CYRILLIC CAPITAL LETTER KOMI DE
|
||||
0502; C; 0503; # CYRILLIC CAPITAL LETTER KOMI DJE
|
||||
0504; C; 0505; # CYRILLIC CAPITAL LETTER KOMI ZJE
|
||||
|
@ -463,6 +492,22 @@
|
|||
050A; C; 050B; # CYRILLIC CAPITAL LETTER KOMI NJE
|
||||
050C; C; 050D; # CYRILLIC CAPITAL LETTER KOMI SJE
|
||||
050E; C; 050F; # CYRILLIC CAPITAL LETTER KOMI TJE
|
||||
0510; C; 0511; # CYRILLIC CAPITAL LETTER REVERSED ZE
|
||||
0512; C; 0513; # CYRILLIC CAPITAL LETTER EL WITH HOOK
|
||||
0514; C; 0515; # CYRILLIC CAPITAL LETTER LHA
|
||||
0516; C; 0517; # CYRILLIC CAPITAL LETTER RHA
|
||||
0518; C; 0519; # CYRILLIC CAPITAL LETTER YAE
|
||||
051A; C; 051B; # CYRILLIC CAPITAL LETTER QA
|
||||
051C; C; 051D; # CYRILLIC CAPITAL LETTER WE
|
||||
051E; C; 051F; # CYRILLIC CAPITAL LETTER ALEUT KA
|
||||
0520; C; 0521; # CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK
|
||||
0522; C; 0523; # CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK
|
||||
0524; C; 0525; # CYRILLIC CAPITAL LETTER PE WITH DESCENDER
|
||||
0526; C; 0527; # CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER
|
||||
0528; C; 0529; # CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK
|
||||
052A; C; 052B; # CYRILLIC CAPITAL LETTER DZZHE
|
||||
052C; C; 052D; # CYRILLIC CAPITAL LETTER DCHE
|
||||
052E; C; 052F; # CYRILLIC CAPITAL LETTER EL WITH DESCENDER
|
||||
0531; C; 0561; # ARMENIAN CAPITAL LETTER AYB
|
||||
0532; C; 0562; # ARMENIAN CAPITAL LETTER BEN
|
||||
0533; C; 0563; # ARMENIAN CAPITAL LETTER GIM
|
||||
|
@ -540,6 +585,14 @@
|
|||
10C3; C; 2D23; # GEORGIAN CAPITAL LETTER WE
|
||||
10C4; C; 2D24; # GEORGIAN CAPITAL LETTER HAR
|
||||
10C5; C; 2D25; # GEORGIAN CAPITAL LETTER HOE
|
||||
10C7; C; 2D27; # GEORGIAN CAPITAL LETTER YN
|
||||
10CD; C; 2D2D; # GEORGIAN CAPITAL LETTER AEN
|
||||
13F8; C; 13F0; # CHEROKEE SMALL LETTER YE
|
||||
13F9; C; 13F1; # CHEROKEE SMALL LETTER YI
|
||||
13FA; C; 13F2; # CHEROKEE SMALL LETTER YO
|
||||
13FB; C; 13F3; # CHEROKEE SMALL LETTER YU
|
||||
13FC; C; 13F4; # CHEROKEE SMALL LETTER YV
|
||||
13FD; C; 13F5; # CHEROKEE SMALL LETTER MV
|
||||
1E00; C; 1E01; # LATIN CAPITAL LETTER A WITH RING BELOW
|
||||
1E02; C; 1E03; # LATIN CAPITAL LETTER B WITH DOT ABOVE
|
||||
1E04; C; 1E05; # LATIN CAPITAL LETTER B WITH DOT BELOW
|
||||
|
@ -621,6 +674,8 @@
|
|||
1E99; F; 0079 030A; # LATIN SMALL LETTER Y WITH RING ABOVE
|
||||
1E9A; F; 0061 02BE; # LATIN SMALL LETTER A WITH RIGHT HALF RING
|
||||
1E9B; C; 1E61; # LATIN SMALL LETTER LONG S WITH DOT ABOVE
|
||||
1E9E; F; 0073 0073; # LATIN CAPITAL LETTER SHARP S
|
||||
1E9E; S; 00DF; # LATIN CAPITAL LETTER SHARP S
|
||||
1EA0; C; 1EA1; # LATIN CAPITAL LETTER A WITH DOT BELOW
|
||||
1EA2; C; 1EA3; # LATIN CAPITAL LETTER A WITH HOOK ABOVE
|
||||
1EA4; C; 1EA5; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE
|
||||
|
@ -666,6 +721,9 @@
|
|||
1EF4; C; 1EF5; # LATIN CAPITAL LETTER Y WITH DOT BELOW
|
||||
1EF6; C; 1EF7; # LATIN CAPITAL LETTER Y WITH HOOK ABOVE
|
||||
1EF8; C; 1EF9; # LATIN CAPITAL LETTER Y WITH TILDE
|
||||
1EFA; C; 1EFB; # LATIN CAPITAL LETTER MIDDLE-WELSH LL
|
||||
1EFC; C; 1EFD; # LATIN CAPITAL LETTER MIDDLE-WELSH V
|
||||
1EFE; C; 1EFF; # LATIN CAPITAL LETTER Y WITH LOOP
|
||||
1F08; C; 1F00; # GREEK CAPITAL LETTER ALPHA WITH PSILI
|
||||
1F09; C; 1F01; # GREEK CAPITAL LETTER ALPHA WITH DASIA
|
||||
1F0A; C; 1F02; # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA
|
||||
|
@ -845,6 +903,7 @@
|
|||
2126; C; 03C9; # OHM SIGN
|
||||
212A; C; 006B; # KELVIN SIGN
|
||||
212B; C; 00E5; # ANGSTROM SIGN
|
||||
2132; C; 214E; # TURNED CAPITAL F
|
||||
2160; C; 2170; # ROMAN NUMERAL ONE
|
||||
2161; C; 2171; # ROMAN NUMERAL TWO
|
||||
2162; C; 2172; # ROMAN NUMERAL THREE
|
||||
|
@ -861,6 +920,7 @@
|
|||
216D; C; 217D; # ROMAN NUMERAL ONE HUNDRED
|
||||
216E; C; 217E; # ROMAN NUMERAL FIVE HUNDRED
|
||||
216F; C; 217F; # ROMAN NUMERAL ONE THOUSAND
|
||||
2183; C; 2184; # ROMAN NUMERAL REVERSED ONE HUNDRED
|
||||
24B6; C; 24D0; # CIRCLED LATIN CAPITAL LETTER A
|
||||
24B7; C; 24D1; # CIRCLED LATIN CAPITAL LETTER B
|
||||
24B8; C; 24D2; # CIRCLED LATIN CAPITAL LETTER C
|
||||
|
@ -934,6 +994,21 @@
|
|||
2C2C; C; 2C5C; # GLAGOLITIC CAPITAL LETTER SHTAPIC
|
||||
2C2D; C; 2C5D; # GLAGOLITIC CAPITAL LETTER TROKUTASTI A
|
||||
2C2E; C; 2C5E; # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
|
||||
2C60; C; 2C61; # LATIN CAPITAL LETTER L WITH DOUBLE BAR
|
||||
2C62; C; 026B; # LATIN CAPITAL LETTER L WITH MIDDLE TILDE
|
||||
2C63; C; 1D7D; # LATIN CAPITAL LETTER P WITH STROKE
|
||||
2C64; C; 027D; # LATIN CAPITAL LETTER R WITH TAIL
|
||||
2C67; C; 2C68; # LATIN CAPITAL LETTER H WITH DESCENDER
|
||||
2C69; C; 2C6A; # LATIN CAPITAL LETTER K WITH DESCENDER
|
||||
2C6B; C; 2C6C; # LATIN CAPITAL LETTER Z WITH DESCENDER
|
||||
2C6D; C; 0251; # LATIN CAPITAL LETTER ALPHA
|
||||
2C6E; C; 0271; # LATIN CAPITAL LETTER M WITH HOOK
|
||||
2C6F; C; 0250; # LATIN CAPITAL LETTER TURNED A
|
||||
2C70; C; 0252; # LATIN CAPITAL LETTER TURNED ALPHA
|
||||
2C72; C; 2C73; # LATIN CAPITAL LETTER W WITH HOOK
|
||||
2C75; C; 2C76; # LATIN CAPITAL LETTER HALF H
|
||||
2C7E; C; 023F; # LATIN CAPITAL LETTER S WITH SWASH TAIL
|
||||
2C7F; C; 0240; # LATIN CAPITAL LETTER Z WITH SWASH TAIL
|
||||
2C80; C; 2C81; # COPTIC CAPITAL LETTER ALFA
|
||||
2C82; C; 2C83; # COPTIC CAPITAL LETTER VIDA
|
||||
2C84; C; 2C85; # COPTIC CAPITAL LETTER GAMMA
|
||||
|
@ -984,6 +1059,196 @@
|
|||
2CDE; C; 2CDF; # COPTIC CAPITAL LETTER OLD NUBIAN NGI
|
||||
2CE0; C; 2CE1; # COPTIC CAPITAL LETTER OLD NUBIAN NYI
|
||||
2CE2; C; 2CE3; # COPTIC CAPITAL LETTER OLD NUBIAN WAU
|
||||
2CEB; C; 2CEC; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI
|
||||
2CED; C; 2CEE; # COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA
|
||||
2CF2; C; 2CF3; # COPTIC CAPITAL LETTER BOHAIRIC KHEI
|
||||
A640; C; A641; # CYRILLIC CAPITAL LETTER ZEMLYA
|
||||
A642; C; A643; # CYRILLIC CAPITAL LETTER DZELO
|
||||
A644; C; A645; # CYRILLIC CAPITAL LETTER REVERSED DZE
|
||||
A646; C; A647; # CYRILLIC CAPITAL LETTER IOTA
|
||||
A648; C; A649; # CYRILLIC CAPITAL LETTER DJERV
|
||||
A64A; C; A64B; # CYRILLIC CAPITAL LETTER MONOGRAPH UK
|
||||
A64C; C; A64D; # CYRILLIC CAPITAL LETTER BROAD OMEGA
|
||||
A64E; C; A64F; # CYRILLIC CAPITAL LETTER NEUTRAL YER
|
||||
A650; C; A651; # CYRILLIC CAPITAL LETTER YERU WITH BACK YER
|
||||
A652; C; A653; # CYRILLIC CAPITAL LETTER IOTIFIED YAT
|
||||
A654; C; A655; # CYRILLIC CAPITAL LETTER REVERSED YU
|
||||
A656; C; A657; # CYRILLIC CAPITAL LETTER IOTIFIED A
|
||||
A658; C; A659; # CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS
|
||||
A65A; C; A65B; # CYRILLIC CAPITAL LETTER BLENDED YUS
|
||||
A65C; C; A65D; # CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS
|
||||
A65E; C; A65F; # CYRILLIC CAPITAL LETTER YN
|
||||
A660; C; A661; # CYRILLIC CAPITAL LETTER REVERSED TSE
|
||||
A662; C; A663; # CYRILLIC CAPITAL LETTER SOFT DE
|
||||
A664; C; A665; # CYRILLIC CAPITAL LETTER SOFT EL
|
||||
A666; C; A667; # CYRILLIC CAPITAL LETTER SOFT EM
|
||||
A668; C; A669; # CYRILLIC CAPITAL LETTER MONOCULAR O
|
||||
A66A; C; A66B; # CYRILLIC CAPITAL LETTER BINOCULAR O
|
||||
A66C; C; A66D; # CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O
|
||||
A680; C; A681; # CYRILLIC CAPITAL LETTER DWE
|
||||
A682; C; A683; # CYRILLIC CAPITAL LETTER DZWE
|
||||
A684; C; A685; # CYRILLIC CAPITAL LETTER ZHWE
|
||||
A686; C; A687; # CYRILLIC CAPITAL LETTER CCHE
|
||||
A688; C; A689; # CYRILLIC CAPITAL LETTER DZZE
|
||||
A68A; C; A68B; # CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK
|
||||
A68C; C; A68D; # CYRILLIC CAPITAL LETTER TWE
|
||||
A68E; C; A68F; # CYRILLIC CAPITAL LETTER TSWE
|
||||
A690; C; A691; # CYRILLIC CAPITAL LETTER TSSE
|
||||
A692; C; A693; # CYRILLIC CAPITAL LETTER TCHE
|
||||
A694; C; A695; # CYRILLIC CAPITAL LETTER HWE
|
||||
A696; C; A697; # CYRILLIC CAPITAL LETTER SHWE
|
||||
A698; C; A699; # CYRILLIC CAPITAL LETTER DOUBLE O
|
||||
A69A; C; A69B; # CYRILLIC CAPITAL LETTER CROSSED O
|
||||
A722; C; A723; # LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF
|
||||
A724; C; A725; # LATIN CAPITAL LETTER EGYPTOLOGICAL AIN
|
||||
A726; C; A727; # LATIN CAPITAL LETTER HENG
|
||||
A728; C; A729; # LATIN CAPITAL LETTER TZ
|
||||
A72A; C; A72B; # LATIN CAPITAL LETTER TRESILLO
|
||||
A72C; C; A72D; # LATIN CAPITAL LETTER CUATRILLO
|
||||
A72E; C; A72F; # LATIN CAPITAL LETTER CUATRILLO WITH COMMA
|
||||
A732; C; A733; # LATIN CAPITAL LETTER AA
|
||||
A734; C; A735; # LATIN CAPITAL LETTER AO
|
||||
A736; C; A737; # LATIN CAPITAL LETTER AU
|
||||
A738; C; A739; # LATIN CAPITAL LETTER AV
|
||||
A73A; C; A73B; # LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR
|
||||
A73C; C; A73D; # LATIN CAPITAL LETTER AY
|
||||
A73E; C; A73F; # LATIN CAPITAL LETTER REVERSED C WITH DOT
|
||||
A740; C; A741; # LATIN CAPITAL LETTER K WITH STROKE
|
||||
A742; C; A743; # LATIN CAPITAL LETTER K WITH DIAGONAL STROKE
|
||||
A744; C; A745; # LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE
|
||||
A746; C; A747; # LATIN CAPITAL LETTER BROKEN L
|
||||
A748; C; A749; # LATIN CAPITAL LETTER L WITH HIGH STROKE
|
||||
A74A; C; A74B; # LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY
|
||||
A74C; C; A74D; # LATIN CAPITAL LETTER O WITH LOOP
|
||||
A74E; C; A74F; # LATIN CAPITAL LETTER OO
|
||||
A750; C; A751; # LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER
|
||||
A752; C; A753; # LATIN CAPITAL LETTER P WITH FLOURISH
|
||||
A754; C; A755; # LATIN CAPITAL LETTER P WITH SQUIRREL TAIL
|
||||
A756; C; A757; # LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER
|
||||
A758; C; A759; # LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE
|
||||
A75A; C; A75B; # LATIN CAPITAL LETTER R ROTUNDA
|
||||
A75C; C; A75D; # LATIN CAPITAL LETTER RUM ROTUNDA
|
||||
A75E; C; A75F; # LATIN CAPITAL LETTER V WITH DIAGONAL STROKE
|
||||
A760; C; A761; # LATIN CAPITAL LETTER VY
|
||||
A762; C; A763; # LATIN CAPITAL LETTER VISIGOTHIC Z
|
||||
A764; C; A765; # LATIN CAPITAL LETTER THORN WITH STROKE
|
||||
A766; C; A767; # LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER
|
||||
A768; C; A769; # LATIN CAPITAL LETTER VEND
|
||||
A76A; C; A76B; # LATIN CAPITAL LETTER ET
|
||||
A76C; C; A76D; # LATIN CAPITAL LETTER IS
|
||||
A76E; C; A76F; # LATIN CAPITAL LETTER CON
|
||||
A779; C; A77A; # LATIN CAPITAL LETTER INSULAR D
|
||||
A77B; C; A77C; # LATIN CAPITAL LETTER INSULAR F
|
||||
A77D; C; 1D79; # LATIN CAPITAL LETTER INSULAR G
|
||||
A77E; C; A77F; # LATIN CAPITAL LETTER TURNED INSULAR G
|
||||
A780; C; A781; # LATIN CAPITAL LETTER TURNED L
|
||||
A782; C; A783; # LATIN CAPITAL LETTER INSULAR R
|
||||
A784; C; A785; # LATIN CAPITAL LETTER INSULAR S
|
||||
A786; C; A787; # LATIN CAPITAL LETTER INSULAR T
|
||||
A78B; C; A78C; # LATIN CAPITAL LETTER SALTILLO
|
||||
A78D; C; 0265; # LATIN CAPITAL LETTER TURNED H
|
||||
A790; C; A791; # LATIN CAPITAL LETTER N WITH DESCENDER
|
||||
A792; C; A793; # LATIN CAPITAL LETTER C WITH BAR
|
||||
A796; C; A797; # LATIN CAPITAL LETTER B WITH FLOURISH
|
||||
A798; C; A799; # LATIN CAPITAL LETTER F WITH STROKE
|
||||
A79A; C; A79B; # LATIN CAPITAL LETTER VOLAPUK AE
|
||||
A79C; C; A79D; # LATIN CAPITAL LETTER VOLAPUK OE
|
||||
A79E; C; A79F; # LATIN CAPITAL LETTER VOLAPUK UE
|
||||
A7A0; C; A7A1; # LATIN CAPITAL LETTER G WITH OBLIQUE STROKE
|
||||
A7A2; C; A7A3; # LATIN CAPITAL LETTER K WITH OBLIQUE STROKE
|
||||
A7A4; C; A7A5; # LATIN CAPITAL LETTER N WITH OBLIQUE STROKE
|
||||
A7A6; C; A7A7; # LATIN CAPITAL LETTER R WITH OBLIQUE STROKE
|
||||
A7A8; C; A7A9; # LATIN CAPITAL LETTER S WITH OBLIQUE STROKE
|
||||
A7AA; C; 0266; # LATIN CAPITAL LETTER H WITH HOOK
|
||||
A7AB; C; 025C; # LATIN CAPITAL LETTER REVERSED OPEN E
|
||||
A7AC; C; 0261; # LATIN CAPITAL LETTER SCRIPT G
|
||||
A7AD; C; 026C; # LATIN CAPITAL LETTER L WITH BELT
|
||||
A7B0; C; 029E; # LATIN CAPITAL LETTER TURNED K
|
||||
A7B1; C; 0287; # LATIN CAPITAL LETTER TURNED T
|
||||
A7B2; C; 029D; # LATIN CAPITAL LETTER J WITH CROSSED-TAIL
|
||||
A7B3; C; AB53; # LATIN CAPITAL LETTER CHI
|
||||
A7B4; C; A7B5; # LATIN CAPITAL LETTER BETA
|
||||
A7B6; C; A7B7; # LATIN CAPITAL LETTER OMEGA
|
||||
AB70; C; 13A0; # CHEROKEE SMALL LETTER A
|
||||
AB71; C; 13A1; # CHEROKEE SMALL LETTER E
|
||||
AB72; C; 13A2; # CHEROKEE SMALL LETTER I
|
||||
AB73; C; 13A3; # CHEROKEE SMALL LETTER O
|
||||
AB74; C; 13A4; # CHEROKEE SMALL LETTER U
|
||||
AB75; C; 13A5; # CHEROKEE SMALL LETTER V
|
||||
AB76; C; 13A6; # CHEROKEE SMALL LETTER GA
|
||||
AB77; C; 13A7; # CHEROKEE SMALL LETTER KA
|
||||
AB78; C; 13A8; # CHEROKEE SMALL LETTER GE
|
||||
AB79; C; 13A9; # CHEROKEE SMALL LETTER GI
|
||||
AB7A; C; 13AA; # CHEROKEE SMALL LETTER GO
|
||||
AB7B; C; 13AB; # CHEROKEE SMALL LETTER GU
|
||||
AB7C; C; 13AC; # CHEROKEE SMALL LETTER GV
|
||||
AB7D; C; 13AD; # CHEROKEE SMALL LETTER HA
|
||||
AB7E; C; 13AE; # CHEROKEE SMALL LETTER HE
|
||||
AB7F; C; 13AF; # CHEROKEE SMALL LETTER HI
|
||||
AB80; C; 13B0; # CHEROKEE SMALL LETTER HO
|
||||
AB81; C; 13B1; # CHEROKEE SMALL LETTER HU
|
||||
AB82; C; 13B2; # CHEROKEE SMALL LETTER HV
|
||||
AB83; C; 13B3; # CHEROKEE SMALL LETTER LA
|
||||
AB84; C; 13B4; # CHEROKEE SMALL LETTER LE
|
||||
AB85; C; 13B5; # CHEROKEE SMALL LETTER LI
|
||||
AB86; C; 13B6; # CHEROKEE SMALL LETTER LO
|
||||
AB87; C; 13B7; # CHEROKEE SMALL LETTER LU
|
||||
AB88; C; 13B8; # CHEROKEE SMALL LETTER LV
|
||||
AB89; C; 13B9; # CHEROKEE SMALL LETTER MA
|
||||
AB8A; C; 13BA; # CHEROKEE SMALL LETTER ME
|
||||
AB8B; C; 13BB; # CHEROKEE SMALL LETTER MI
|
||||
AB8C; C; 13BC; # CHEROKEE SMALL LETTER MO
|
||||
AB8D; C; 13BD; # CHEROKEE SMALL LETTER MU
|
||||
AB8E; C; 13BE; # CHEROKEE SMALL LETTER NA
|
||||
AB8F; C; 13BF; # CHEROKEE SMALL LETTER HNA
|
||||
AB90; C; 13C0; # CHEROKEE SMALL LETTER NAH
|
||||
AB91; C; 13C1; # CHEROKEE SMALL LETTER NE
|
||||
AB92; C; 13C2; # CHEROKEE SMALL LETTER NI
|
||||
AB93; C; 13C3; # CHEROKEE SMALL LETTER NO
|
||||
AB94; C; 13C4; # CHEROKEE SMALL LETTER NU
|
||||
AB95; C; 13C5; # CHEROKEE SMALL LETTER NV
|
||||
AB96; C; 13C6; # CHEROKEE SMALL LETTER QUA
|
||||
AB97; C; 13C7; # CHEROKEE SMALL LETTER QUE
|
||||
AB98; C; 13C8; # CHEROKEE SMALL LETTER QUI
|
||||
AB99; C; 13C9; # CHEROKEE SMALL LETTER QUO
|
||||
AB9A; C; 13CA; # CHEROKEE SMALL LETTER QUU
|
||||
AB9B; C; 13CB; # CHEROKEE SMALL LETTER QUV
|
||||
AB9C; C; 13CC; # CHEROKEE SMALL LETTER SA
|
||||
AB9D; C; 13CD; # CHEROKEE SMALL LETTER S
|
||||
AB9E; C; 13CE; # CHEROKEE SMALL LETTER SE
|
||||
AB9F; C; 13CF; # CHEROKEE SMALL LETTER SI
|
||||
ABA0; C; 13D0; # CHEROKEE SMALL LETTER SO
|
||||
ABA1; C; 13D1; # CHEROKEE SMALL LETTER SU
|
||||
ABA2; C; 13D2; # CHEROKEE SMALL LETTER SV
|
||||
ABA3; C; 13D3; # CHEROKEE SMALL LETTER DA
|
||||
ABA4; C; 13D4; # CHEROKEE SMALL LETTER TA
|
||||
ABA5; C; 13D5; # CHEROKEE SMALL LETTER DE
|
||||
ABA6; C; 13D6; # CHEROKEE SMALL LETTER TE
|
||||
ABA7; C; 13D7; # CHEROKEE SMALL LETTER DI
|
||||
ABA8; C; 13D8; # CHEROKEE SMALL LETTER TI
|
||||
ABA9; C; 13D9; # CHEROKEE SMALL LETTER DO
|
||||
ABAA; C; 13DA; # CHEROKEE SMALL LETTER DU
|
||||
ABAB; C; 13DB; # CHEROKEE SMALL LETTER DV
|
||||
ABAC; C; 13DC; # CHEROKEE SMALL LETTER DLA
|
||||
ABAD; C; 13DD; # CHEROKEE SMALL LETTER TLA
|
||||
ABAE; C; 13DE; # CHEROKEE SMALL LETTER TLE
|
||||
ABAF; C; 13DF; # CHEROKEE SMALL LETTER TLI
|
||||
ABB0; C; 13E0; # CHEROKEE SMALL LETTER TLO
|
||||
ABB1; C; 13E1; # CHEROKEE SMALL LETTER TLU
|
||||
ABB2; C; 13E2; # CHEROKEE SMALL LETTER TLV
|
||||
ABB3; C; 13E3; # CHEROKEE SMALL LETTER TSA
|
||||
ABB4; C; 13E4; # CHEROKEE SMALL LETTER TSE
|
||||
ABB5; C; 13E5; # CHEROKEE SMALL LETTER TSI
|
||||
ABB6; C; 13E6; # CHEROKEE SMALL LETTER TSO
|
||||
ABB7; C; 13E7; # CHEROKEE SMALL LETTER TSU
|
||||
ABB8; C; 13E8; # CHEROKEE SMALL LETTER TSV
|
||||
ABB9; C; 13E9; # CHEROKEE SMALL LETTER WA
|
||||
ABBA; C; 13EA; # CHEROKEE SMALL LETTER WE
|
||||
ABBB; C; 13EB; # CHEROKEE SMALL LETTER WI
|
||||
ABBC; C; 13EC; # CHEROKEE SMALL LETTER WO
|
||||
ABBD; C; 13ED; # CHEROKEE SMALL LETTER WU
|
||||
ABBE; C; 13EE; # CHEROKEE SMALL LETTER WV
|
||||
ABBF; C; 13EF; # CHEROKEE SMALL LETTER YA
|
||||
FB00; F; 0066 0066; # LATIN SMALL LIGATURE FF
|
||||
FB01; F; 0066 0069; # LATIN SMALL LIGATURE FI
|
||||
FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL
|
||||
|
@ -1062,3 +1327,88 @@ FF3A; C; FF5A; # FULLWIDTH LATIN CAPITAL LETTER Z
|
|||
10425; C; 1044D; # DESERET CAPITAL LETTER ENG
|
||||
10426; C; 1044E; # DESERET CAPITAL LETTER OI
|
||||
10427; C; 1044F; # DESERET CAPITAL LETTER EW
|
||||
10C80; C; 10CC0; # OLD HUNGARIAN CAPITAL LETTER A
|
||||
10C81; C; 10CC1; # OLD HUNGARIAN CAPITAL LETTER AA
|
||||
10C82; C; 10CC2; # OLD HUNGARIAN CAPITAL LETTER EB
|
||||
10C83; C; 10CC3; # OLD HUNGARIAN CAPITAL LETTER AMB
|
||||
10C84; C; 10CC4; # OLD HUNGARIAN CAPITAL LETTER EC
|
||||
10C85; C; 10CC5; # OLD HUNGARIAN CAPITAL LETTER ENC
|
||||
10C86; C; 10CC6; # OLD HUNGARIAN CAPITAL LETTER ECS
|
||||
10C87; C; 10CC7; # OLD HUNGARIAN CAPITAL LETTER ED
|
||||
10C88; C; 10CC8; # OLD HUNGARIAN CAPITAL LETTER AND
|
||||
10C89; C; 10CC9; # OLD HUNGARIAN CAPITAL LETTER E
|
||||
10C8A; C; 10CCA; # OLD HUNGARIAN CAPITAL LETTER CLOSE E
|
||||
10C8B; C; 10CCB; # OLD HUNGARIAN CAPITAL LETTER EE
|
||||
10C8C; C; 10CCC; # OLD HUNGARIAN CAPITAL LETTER EF
|
||||
10C8D; C; 10CCD; # OLD HUNGARIAN CAPITAL LETTER EG
|
||||
10C8E; C; 10CCE; # OLD HUNGARIAN CAPITAL LETTER EGY
|
||||
10C8F; C; 10CCF; # OLD HUNGARIAN CAPITAL LETTER EH
|
||||
10C90; C; 10CD0; # OLD HUNGARIAN CAPITAL LETTER I
|
||||
10C91; C; 10CD1; # OLD HUNGARIAN CAPITAL LETTER II
|
||||
10C92; C; 10CD2; # OLD HUNGARIAN CAPITAL LETTER EJ
|
||||
10C93; C; 10CD3; # OLD HUNGARIAN CAPITAL LETTER EK
|
||||
10C94; C; 10CD4; # OLD HUNGARIAN CAPITAL LETTER AK
|
||||
10C95; C; 10CD5; # OLD HUNGARIAN CAPITAL LETTER UNK
|
||||
10C96; C; 10CD6; # OLD HUNGARIAN CAPITAL LETTER EL
|
||||
10C97; C; 10CD7; # OLD HUNGARIAN CAPITAL LETTER ELY
|
||||
10C98; C; 10CD8; # OLD HUNGARIAN CAPITAL LETTER EM
|
||||
10C99; C; 10CD9; # OLD HUNGARIAN CAPITAL LETTER EN
|
||||
10C9A; C; 10CDA; # OLD HUNGARIAN CAPITAL LETTER ENY
|
||||
10C9B; C; 10CDB; # OLD HUNGARIAN CAPITAL LETTER O
|
||||
10C9C; C; 10CDC; # OLD HUNGARIAN CAPITAL LETTER OO
|
||||
10C9D; C; 10CDD; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE
|
||||
10C9E; C; 10CDE; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE
|
||||
10C9F; C; 10CDF; # OLD HUNGARIAN CAPITAL LETTER OEE
|
||||
10CA0; C; 10CE0; # OLD HUNGARIAN CAPITAL LETTER EP
|
||||
10CA1; C; 10CE1; # OLD HUNGARIAN CAPITAL LETTER EMP
|
||||
10CA2; C; 10CE2; # OLD HUNGARIAN CAPITAL LETTER ER
|
||||
10CA3; C; 10CE3; # OLD HUNGARIAN CAPITAL LETTER SHORT ER
|
||||
10CA4; C; 10CE4; # OLD HUNGARIAN CAPITAL LETTER ES
|
||||
10CA5; C; 10CE5; # OLD HUNGARIAN CAPITAL LETTER ESZ
|
||||
10CA6; C; 10CE6; # OLD HUNGARIAN CAPITAL LETTER ET
|
||||
10CA7; C; 10CE7; # OLD HUNGARIAN CAPITAL LETTER ENT
|
||||
10CA8; C; 10CE8; # OLD HUNGARIAN CAPITAL LETTER ETY
|
||||
10CA9; C; 10CE9; # OLD HUNGARIAN CAPITAL LETTER ECH
|
||||
10CAA; C; 10CEA; # OLD HUNGARIAN CAPITAL LETTER U
|
||||
10CAB; C; 10CEB; # OLD HUNGARIAN CAPITAL LETTER UU
|
||||
10CAC; C; 10CEC; # OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE
|
||||
10CAD; C; 10CED; # OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE
|
||||
10CAE; C; 10CEE; # OLD HUNGARIAN CAPITAL LETTER EV
|
||||
10CAF; C; 10CEF; # OLD HUNGARIAN CAPITAL LETTER EZ
|
||||
10CB0; C; 10CF0; # OLD HUNGARIAN CAPITAL LETTER EZS
|
||||
10CB1; C; 10CF1; # OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN
|
||||
10CB2; C; 10CF2; # OLD HUNGARIAN CAPITAL LETTER US
|
||||
118A0; C; 118C0; # WARANG CITI CAPITAL LETTER NGAA
|
||||
118A1; C; 118C1; # WARANG CITI CAPITAL LETTER A
|
||||
118A2; C; 118C2; # WARANG CITI CAPITAL LETTER WI
|
||||
118A3; C; 118C3; # WARANG CITI CAPITAL LETTER YU
|
||||
118A4; C; 118C4; # WARANG CITI CAPITAL LETTER YA
|
||||
118A5; C; 118C5; # WARANG CITI CAPITAL LETTER YO
|
||||
118A6; C; 118C6; # WARANG CITI CAPITAL LETTER II
|
||||
118A7; C; 118C7; # WARANG CITI CAPITAL LETTER UU
|
||||
118A8; C; 118C8; # WARANG CITI CAPITAL LETTER E
|
||||
118A9; C; 118C9; # WARANG CITI CAPITAL LETTER O
|
||||
118AA; C; 118CA; # WARANG CITI CAPITAL LETTER ANG
|
||||
118AB; C; 118CB; # WARANG CITI CAPITAL LETTER GA
|
||||
118AC; C; 118CC; # WARANG CITI CAPITAL LETTER KO
|
||||
118AD; C; 118CD; # WARANG CITI CAPITAL LETTER ENY
|
||||
118AE; C; 118CE; # WARANG CITI CAPITAL LETTER YUJ
|
||||
118AF; C; 118CF; # WARANG CITI CAPITAL LETTER UC
|
||||
118B0; C; 118D0; # WARANG CITI CAPITAL LETTER ENN
|
||||
118B1; C; 118D1; # WARANG CITI CAPITAL LETTER ODD
|
||||
118B2; C; 118D2; # WARANG CITI CAPITAL LETTER TTE
|
||||
118B3; C; 118D3; # WARANG CITI CAPITAL LETTER NUNG
|
||||
118B4; C; 118D4; # WARANG CITI CAPITAL LETTER DA
|
||||
118B5; C; 118D5; # WARANG CITI CAPITAL LETTER AT
|
||||
118B6; C; 118D6; # WARANG CITI CAPITAL LETTER AM
|
||||
118B7; C; 118D7; # WARANG CITI CAPITAL LETTER BU
|
||||
118B8; C; 118D8; # WARANG CITI CAPITAL LETTER PU
|
||||
118B9; C; 118D9; # WARANG CITI CAPITAL LETTER HIYO
|
||||
118BA; C; 118DA; # WARANG CITI CAPITAL LETTER HOLO
|
||||
118BB; C; 118DB; # WARANG CITI CAPITAL LETTER HORR
|
||||
118BC; C; 118DC; # WARANG CITI CAPITAL LETTER HAR
|
||||
118BD; C; 118DD; # WARANG CITI CAPITAL LETTER SSUU
|
||||
118BE; C; 118DE; # WARANG CITI CAPITAL LETTER SII
|
||||
118BF; C; 118DF; # WARANG CITI CAPITAL LETTER VIYO
|
||||
#
|
||||
# EOF
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "physfs.h"
|
||||
#include "globbing.h"
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@
|
|||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
@ -77,38 +77,118 @@ static int matchesPattern(const char *fname, const char *wildcard,
|
|||
fnameptr++;
|
||||
|
||||
if (x != y)
|
||||
return(0);
|
||||
return 0;
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
while (*wildptr == '*')
|
||||
wildptr++;
|
||||
|
||||
return(*fnameptr == *wildptr);
|
||||
return (*fnameptr == *wildptr);
|
||||
} /* matchesPattern */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const PHYSFS_Allocator *allocator;
|
||||
const char *wildcard;
|
||||
int caseSensitive;
|
||||
PHYSFS_EnumFilesCallback callback;
|
||||
void *origData;
|
||||
} WildcardCallbackData;
|
||||
|
||||
|
||||
/*
|
||||
* This callback sits between the enumerator and the enduser callback,
|
||||
* filtering out files that don't match the wildcard pattern.
|
||||
*/
|
||||
static void wildcardCallback(void *_d, const char *origdir, const char *fname)
|
||||
{
|
||||
const WildcardCallbackData *data = (const WildcardCallbackData *) _d;
|
||||
if (matchesPattern(fname, data->wildcard, data->caseSensitive))
|
||||
data->callback(data->origData, origdir, fname);
|
||||
} /* wildcardCallback */
|
||||
|
||||
|
||||
void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive,
|
||||
PHYSFS_EnumFilesCallback c,
|
||||
void *d)
|
||||
{
|
||||
WildcardCallbackData data;
|
||||
data.allocator = PHYSFS_getAllocator();
|
||||
data.wildcard = wildcard;
|
||||
data.caseSensitive = caseSensitive;
|
||||
data.callback = c;
|
||||
data.origData = d;
|
||||
PHYSFS_enumerateFilesCallback(dir, wildcardCallback, &data);
|
||||
} /* PHYSFSEXT_enumerateFilesCallbackWildcard */
|
||||
|
||||
|
||||
void PHYSFSEXT_freeEnumeration(char **list)
|
||||
{
|
||||
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||
int i;
|
||||
if (list != NULL)
|
||||
{
|
||||
for (i = 0; list[i] != NULL; i++)
|
||||
allocator->Free(list[i]);
|
||||
allocator->Free(list);
|
||||
} /* if */
|
||||
} /* PHYSFSEXT_freeEnumeration */
|
||||
|
||||
|
||||
char **PHYSFSEXT_enumerateFilesWildcard(const char *dir, const char *wildcard,
|
||||
int caseSensitive)
|
||||
{
|
||||
char **rc = PHYSFS_enumerateFiles(dir);
|
||||
char **i = rc;
|
||||
char **j;
|
||||
const PHYSFS_Allocator *allocator = PHYSFS_getAllocator();
|
||||
char **list = PHYSFS_enumerateFiles(dir);
|
||||
char **retval = NULL;
|
||||
int totalmatches = 0;
|
||||
int matches = 0;
|
||||
char **i;
|
||||
|
||||
while (*i != NULL)
|
||||
for (i = list; *i != NULL; i++)
|
||||
{
|
||||
#if 0
|
||||
printf("matchesPattern: '%s' vs '%s' (%s) ... %s\n", *i, wildcard,
|
||||
caseSensitive ? "case" : "nocase",
|
||||
matchesPattern(*i, wildcard, caseSensitive) ? "true" : "false");
|
||||
#endif
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
i++;
|
||||
else
|
||||
{
|
||||
/* FIXME: This counts on physfs's allocation method not changing! */
|
||||
free(*i);
|
||||
for (j = i; *j != NULL; j++)
|
||||
j[0] = j[1];
|
||||
} /* else */
|
||||
totalmatches++;
|
||||
} /* for */
|
||||
|
||||
return(rc);
|
||||
retval = (char **) allocator->Malloc(sizeof (char *) * (totalmatches+1));
|
||||
if (retval != NULL)
|
||||
{
|
||||
for (i = list; ((matches < totalmatches) && (*i != NULL)); i++)
|
||||
{
|
||||
if (matchesPattern(*i, wildcard, caseSensitive))
|
||||
{
|
||||
retval[matches] = (char *) allocator->Malloc(strlen(*i) + 1);
|
||||
if (retval[matches] == NULL)
|
||||
{
|
||||
while (matches--)
|
||||
allocator->Free(retval[matches]);
|
||||
allocator->Free(retval);
|
||||
retval = NULL;
|
||||
break;
|
||||
} /* if */
|
||||
strcpy(retval[matches], *i);
|
||||
matches++;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
assert(totalmatches == matches);
|
||||
retval[matches] = NULL;
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
PHYSFS_freeList(list);
|
||||
return retval;
|
||||
} /* PHYSFSEXT_enumerateFilesWildcard */
|
||||
|
||||
|
||||
|
@ -123,20 +203,20 @@ int main(int argc, char **argv)
|
|||
{
|
||||
printf("USAGE: %s <pattern> <caseSen>\n"
|
||||
" where <caseSen> is 1 or 0.\n", argv[0]);
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
|
||||
return(1);
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_addToSearchPath(".", 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
flist = PHYSFSEXT_enumerateFilesWildcard("/", argv[1], atoi(argv[2]));
|
||||
|
@ -148,10 +228,10 @@ int main(int argc, char **argv)
|
|||
} /* for */
|
||||
printf("\n total %d files.\n\n", rc);
|
||||
|
||||
PHYSFS_freeList(flist);
|
||||
PHYSFSEXT_freeEnumeration(flist);
|
||||
PHYSFS_deinit();
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#ifndef INCL_PHYSFSEXT_GLOBBING_H
|
||||
#define INCL_PHYSFSEXT_GLOBBING_H
|
||||
|
||||
/** \file globbing.h */
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
/**
|
||||
* \mainpage PhysicsFS globbing
|
||||
*
|
||||
|
@ -9,10 +14,10 @@
|
|||
* locating matching entries.
|
||||
*
|
||||
* Usage: Set up PhysicsFS as you normally would, then use
|
||||
* PHYSFSEXT_enumerateFilesPattern() when enumerating files. This is just
|
||||
* PHYSFSEXT_enumerateFilesWildcard() when enumerating files. This is just
|
||||
* like PHYSFS_enumerateFiles(), but it returns a subset that matches your
|
||||
* wildcard pattern. You must call PHYSFS_freeList() on the results, just
|
||||
* like you would with PHYSFS_enumerateFiles().
|
||||
* wildcard pattern. You must call PHYSFSEXT_freeEnumeration() on the results,
|
||||
* just PHYSFS_enumerateFiles() would do with PHYSFS_freeList().
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
|
@ -25,15 +30,18 @@
|
|||
* NO WARRANTY.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
* Please see LICENSE.txt in the source's "docs" directory.
|
||||
*
|
||||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn char **PHYSFS_enumerateFilesWildcard(const char *dir, const char *wildcard, int caseSensitive)
|
||||
* \brief Get a file listing of a search path's directory.
|
||||
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern.
|
||||
*
|
||||
* Matching directories are interpolated. That is, if "C:\mydir" is in the
|
||||
* search path and contains a directory "savegames" that contains "x.sav",
|
||||
|
@ -63,15 +71,95 @@
|
|||
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||
*
|
||||
* Don't forget to call PHYSFS_freeList() with the return value from this
|
||||
* function when you are done with it.
|
||||
* Don't forget to call PHYSFSEXT_freeEnumerator() with the return value from
|
||||
* this function when you are done with it. As we use PhysicsFS's allocator
|
||||
* for this list, you must free it before calling PHYSFS_deinit().
|
||||
* Do not use PHYSFS_freeList() on the returned value!
|
||||
*
|
||||
* \param dir directory in platform-independent notation to enumerate.
|
||||
* \param wildcard Wildcard pattern to use for filtering.
|
||||
* \param caseSensitive Zero for case-insensitive matching,
|
||||
* non-zero for case-sensitive.
|
||||
* \return Null-terminated array of null-terminated strings.
|
||||
*
|
||||
* \sa PHYSFSEXT_freeEnumeration
|
||||
*/
|
||||
__EXPORT__ char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
||||
PHYSFS_DECL char **PHYSFSEXT_enumerateFilesWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive);
|
||||
|
||||
/**
|
||||
* \fn void PHYSFSEXT_freeEnumeration(char **list)
|
||||
* \brief Free data returned by PHYSFSEXT_enumerateFilesWildcard
|
||||
*
|
||||
* Conceptually, this works like PHYSFS_freeList(), but is used with data
|
||||
* returned by PHYSFSEXT_enumerateFilesWildcard() only. Be sure to call this
|
||||
* on any returned data from that function before
|
||||
*
|
||||
* \param list Pointer previously returned by
|
||||
* PHYSFSEXT_enumerateFilesWildcard(). It is safe to pass a
|
||||
* NULL here.
|
||||
*
|
||||
* \sa PHYSFSEXT_enumerateFilesWildcard
|
||||
*/
|
||||
PHYSFS_DECL void PHYSFSEXT_freeEnumeration(char **list);
|
||||
|
||||
|
||||
/**
|
||||
* \fn void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir, const char *wildcard, int caseSensitive, PHYSFS_EnumFilesCallback c, void *d);
|
||||
* \brief Get a file listing of a search path's directory, filtered with a wildcard pattern, using an application-defined callback.
|
||||
*
|
||||
* This function is equivalent to PHYSFSEXT_enumerateFilesWildcard(). It
|
||||
* reports file listings, filtered by a wildcard pattern.
|
||||
*
|
||||
* Unlike PHYSFS_enumerateFiles(), this function does not return an array.
|
||||
* Rather, it calls a function specified by the application once per
|
||||
* element of the search path:
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* static void printDir(void *data, const char *origdir, const char *fname)
|
||||
* {
|
||||
* printf(" * We've got [%s] in [%s].\n", fname, origdir);
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* PHYSFS_enumerateFilesCallbackWildcard("savegames","*.sav",0,printDir,NULL);
|
||||
* \endcode
|
||||
*
|
||||
* Items sent to the callback are not guaranteed to be in any order whatsoever.
|
||||
* There is no sorting done at this level, and if you need that, you should
|
||||
* probably use PHYSFS_enumerateFilesWildcard() instead, which guarantees
|
||||
* alphabetical sorting. This form reports whatever is discovered in each
|
||||
* archive before moving on to the next. Even within one archive, we can't
|
||||
* guarantee what order it will discover data. <em>Any sorting you find in
|
||||
* these callbacks is just pure luck. Do not rely on it.</em> As this walks
|
||||
* the entire list of archives, you may receive duplicate filenames.
|
||||
*
|
||||
* Wildcard strings can use the '*' and '?' characters, currently.
|
||||
* Matches can be case-insensitive if you pass a zero for argument 3.
|
||||
*
|
||||
* \param dir Directory, in platform-independent notation, to enumerate.
|
||||
* \param wildcard Wildcard pattern to use for filtering.
|
||||
* \param caseSensitive Zero for case-insensitive matching,
|
||||
* non-zero for case-sensitive.
|
||||
* \param c Callback function to notify about search path elements.
|
||||
* \param d Application-defined data passed to callback. Can be NULL.
|
||||
*
|
||||
* \sa PHYSFS_EnumFilesCallback
|
||||
* \sa PHYSFS_enumerateFiles
|
||||
*/
|
||||
PHYSFS_DECL void PHYSFSEXT_enumerateFilesCallbackWildcard(const char *dir,
|
||||
const char *wildcard,
|
||||
int caseSensitive,
|
||||
PHYSFS_EnumFilesCallback c,
|
||||
void *d);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
/* end of globbing.h ... */
|
||||
|
||||
|
|
|
@ -27,25 +27,6 @@
|
|||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
/* I'm not screwing around with stricmp vs. strcasecmp... */
|
||||
/* !!! FIXME: this will NOT work with UTF-8 strings in physfs2.0 */
|
||||
static int caseInsensitiveStringCompare(const char *x, const char *y)
|
||||
{
|
||||
int ux, uy;
|
||||
do
|
||||
{
|
||||
ux = toupper((int) *x);
|
||||
uy = toupper((int) *y);
|
||||
if (ux != uy)
|
||||
return((ux > uy) ? 1 : -1);
|
||||
x++;
|
||||
y++;
|
||||
} while ((ux) && (uy));
|
||||
|
||||
return(0);
|
||||
} /* caseInsensitiveStringCompare */
|
||||
|
||||
|
||||
static int locateOneElement(char *buf)
|
||||
{
|
||||
char *ptr;
|
||||
|
@ -53,7 +34,7 @@ static int locateOneElement(char *buf)
|
|||
char **i;
|
||||
|
||||
if (PHYSFS_exists(buf))
|
||||
return(1); /* quick rejection: exists in current case. */
|
||||
return 1; /* quick rejection: exists in current case. */
|
||||
|
||||
ptr = strrchr(buf, '/'); /* find entry at end of path. */
|
||||
if (ptr == NULL)
|
||||
|
@ -69,19 +50,23 @@ static int locateOneElement(char *buf)
|
|||
ptr++; /* point past dirsep to entry itself. */
|
||||
} /* else */
|
||||
|
||||
if (rc != NULL)
|
||||
{
|
||||
for (i = rc; *i != NULL; i++)
|
||||
{
|
||||
if (caseInsensitiveStringCompare(*i, ptr) == 0)
|
||||
if (PHYSFS_utf8stricmp(*i, ptr) == 0)
|
||||
{
|
||||
strcpy(ptr, *i); /* found a match. Overwrite with this case. */
|
||||
PHYSFS_freeList(rc);
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* no match at all... */
|
||||
PHYSFS_freeList(rc);
|
||||
return(0);
|
||||
} /* if */
|
||||
|
||||
/* no match at all... */
|
||||
return 0;
|
||||
} /* locateOneElement */
|
||||
|
||||
|
||||
|
@ -89,26 +74,25 @@ int PHYSFSEXT_locateCorrectCase(char *buf)
|
|||
{
|
||||
int rc;
|
||||
char *ptr;
|
||||
char *prevptr;
|
||||
|
||||
while (*buf == '/') /* skip any '/' at start of string... */
|
||||
buf++;
|
||||
|
||||
ptr = prevptr = buf;
|
||||
ptr = buf;
|
||||
if (*ptr == '\0')
|
||||
return(0); /* Uh...I guess that's success. */
|
||||
return 0; /* Uh...I guess that's success. */
|
||||
|
||||
while (ptr = strchr(ptr + 1, '/'))
|
||||
while ( (ptr = strchr(ptr + 1, '/')) != NULL )
|
||||
{
|
||||
*ptr = '\0'; /* block this path section off */
|
||||
rc = locateOneElement(buf);
|
||||
*ptr = '/'; /* restore path separator */
|
||||
if (!rc)
|
||||
return(-2); /* missing element in path. */
|
||||
return -2; /* missing element in path. */
|
||||
} /* while */
|
||||
|
||||
/* check final element... */
|
||||
return(locateOneElement(buf) ? 0 : -1);
|
||||
return locateOneElement(buf) ? 0 : -1;
|
||||
} /* PHYSFSEXT_locateCorrectCase */
|
||||
|
||||
|
||||
|
@ -121,54 +105,54 @@ int main(int argc, char **argv)
|
|||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getLastError());
|
||||
return(1);
|
||||
fprintf(stderr, "PHYSFS_init(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_addToSearchPath(".", 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_addToSearchPath(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setWriteDir("."))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_setWriteDir(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_setWriteDir(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mkdir("/a/b/c"))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mkdir("/a/b/C"))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_mkdir(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
f = PHYSFS_openWrite("/a/b/c/x.txt");
|
||||
PHYSFS_close(f);
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
f = PHYSFS_openWrite("/a/b/C/X.txt");
|
||||
PHYSFS_close(f);
|
||||
if (f == NULL)
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_openWrite(): %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
PHYSFS_deinit();
|
||||
return(1);
|
||||
return 1;
|
||||
} /* if */
|
||||
|
||||
strcpy(buf, "/a/b/c/x.txt");
|
||||
|
@ -211,7 +195,7 @@ int main(int argc, char **argv)
|
|||
PHYSFS_delete("/a/b");
|
||||
PHYSFS_delete("/a");
|
||||
PHYSFS_deinit();
|
||||
return(0);
|
||||
return 0;
|
||||
} /* main */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#ifndef INCL_PHYSFSEXT_IGNORECASE_H
|
||||
#define INCL_PHYSFSEXT_IGNORECASE_H
|
||||
|
||||
/** \file ignorecase.h */
|
||||
|
||||
/**
|
||||
|
@ -15,14 +18,14 @@
|
|||
* or file (which brings security considerations and potential bugs). This
|
||||
* code favours exact case matches, but you will lose access to otherwise
|
||||
* duplicate filenames, or you might go down a wrong directory tree, etc.
|
||||
* In practive, this is rarely a problem, but you need to be aware of it.
|
||||
* In practice, this is rarely a problem, but you need to be aware of it.
|
||||
* - This doesn't do _anything_ with the write directory; you're on your
|
||||
* own for opening the right files for writing. You can sort of get around
|
||||
* this by adding your write directory to the search path, but then the
|
||||
* interpolated directory tree can screw you up even more.
|
||||
*
|
||||
* This code should be considered an aid for legacy code. New development
|
||||
* shouldn't do dumbass things that require this aid in the first place. :)
|
||||
* shouldn't do things that require this aid in the first place. :)
|
||||
*
|
||||
* Usage: Set up PhysicsFS as you normally would, then use
|
||||
* PHYSFSEXT_locateCorrectCase() to get a "correct" pathname to pass to
|
||||
|
@ -44,6 +47,9 @@
|
|||
* \author Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn int PHYSFSEXT_locateCorrectCase(char *buf)
|
||||
|
@ -61,8 +67,7 @@
|
|||
* existing match. If there is no match, the search aborts and reports an
|
||||
* error. Exact matches are favored over case-insensitive matches.
|
||||
*
|
||||
* THIS IS RISKY. Please do not use this function for anything but crappy
|
||||
* legacy code.
|
||||
* THIS IS RISKY. Please do not use this function for anything but legacy code.
|
||||
*
|
||||
* \param buf Buffer with null-terminated string of path/file to locate.
|
||||
* This buffer will be modified by this function.
|
||||
|
@ -71,5 +76,11 @@
|
|||
*/
|
||||
int PHYSFSEXT_locateCorrectCase(char *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker. */
|
||||
|
||||
/* end of ignorecase.h ... */
|
||||
|
||||
|
|
|
@ -3,9 +3,14 @@
|
|||
use warnings;
|
||||
use strict;
|
||||
|
||||
my $HASHBUCKETS1_16 = 256;
|
||||
my $HASHBUCKETS1_32 = 16;
|
||||
my $HASHBUCKETS2_16 = 16;
|
||||
my $HASHBUCKETS3_16 = 4;
|
||||
|
||||
print <<__EOF__;
|
||||
/*
|
||||
* This file is part of PhysicsFS (http://icculus.org/physfs/)
|
||||
* This file is part of PhysicsFS (https://icculus.org/physfs/)
|
||||
*
|
||||
* This data generated by physfs/extras/makecasefoldhashtable.pl ...
|
||||
* Do not manually edit this file!
|
||||
|
@ -13,17 +18,97 @@ print <<__EOF__;
|
|||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PHYSFS_CASEFOLDING_H_
|
||||
#define _INCLUDE_PHYSFS_CASEFOLDING_H_
|
||||
|
||||
#ifndef __PHYSICSFS_INTERNAL__
|
||||
#error Do not include this header from your applications.
|
||||
#endif
|
||||
|
||||
/* We build three simple hashmaps here: one that maps Unicode codepoints to
|
||||
a one, two, or three lowercase codepoints. To retrieve this info: look at
|
||||
case_fold_hashX, where X is 1, 2, or 3. Most foldable codepoints fold to one,
|
||||
a few dozen fold to two, and a handful fold to three. If the codepoint isn't
|
||||
in any of these hashes, it doesn't fold (no separate upper and lowercase).
|
||||
|
||||
Almost all these codepoints fit into 16 bits, so we hash them as such to save
|
||||
memory. If a codepoint is > 0xFFFF, we have separate hashes for them,
|
||||
since there are (currently) only about 120 of them and (currently) all of them
|
||||
map to a single lowercase codepoint. */
|
||||
|
||||
typedef struct CaseFoldMapping1_32
|
||||
{
|
||||
PHYSFS_uint32 from;
|
||||
PHYSFS_uint32 to0;
|
||||
} CaseFoldMapping1_32;
|
||||
|
||||
typedef struct CaseFoldMapping1_16
|
||||
{
|
||||
PHYSFS_uint16 from;
|
||||
PHYSFS_uint16 to0;
|
||||
} CaseFoldMapping1_16;
|
||||
|
||||
typedef struct CaseFoldMapping2_16
|
||||
{
|
||||
PHYSFS_uint16 from;
|
||||
PHYSFS_uint16 to0;
|
||||
PHYSFS_uint16 to1;
|
||||
} CaseFoldMapping2_16;
|
||||
|
||||
typedef struct CaseFoldMapping3_16
|
||||
{
|
||||
PHYSFS_uint16 from;
|
||||
PHYSFS_uint16 to0;
|
||||
PHYSFS_uint16 to1;
|
||||
PHYSFS_uint16 to2;
|
||||
} CaseFoldMapping3_16;
|
||||
|
||||
typedef struct CaseFoldHashBucket1_16
|
||||
{
|
||||
const CaseFoldMapping1_16 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket1_16;
|
||||
|
||||
typedef struct CaseFoldHashBucket1_32
|
||||
{
|
||||
const CaseFoldMapping1_32 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket1_32;
|
||||
|
||||
typedef struct CaseFoldHashBucket2_16
|
||||
{
|
||||
const CaseFoldMapping2_16 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket2_16;
|
||||
|
||||
typedef struct CaseFoldHashBucket3_16
|
||||
{
|
||||
const CaseFoldMapping3_16 *list;
|
||||
const PHYSFS_uint8 count;
|
||||
} CaseFoldHashBucket3_16;
|
||||
|
||||
__EOF__
|
||||
|
||||
|
||||
my @foldPairs;
|
||||
my @foldPairs1_16;
|
||||
my @foldPairs2_16;
|
||||
my @foldPairs3_16;
|
||||
my @foldPairs1_32;
|
||||
|
||||
for (my $i = 0; $i < 256; $i++) {
|
||||
$foldPairs[$i] = '';
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
|
||||
$foldPairs1_16[$i] = '';
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
|
||||
$foldPairs1_32[$i] = '';
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
|
||||
$foldPairs2_16[$i] = '';
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
|
||||
$foldPairs3_16[$i] = '';
|
||||
}
|
||||
|
||||
open(FH,'<','casefolding.txt') or die("failed to open casefolding.txt: $!\n");
|
||||
|
@ -38,47 +123,153 @@ while (<FH>) {
|
|||
|
||||
next if not /\A([a-fA-F0-9]+)\;\s*(.)\;\s*(.+)\;/;
|
||||
my ($code, $status, $mapping) = ($1, $2, $3);
|
||||
|
||||
my $hexxed = hex($code);
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & 0xFF);
|
||||
#print("// code '$code' status '$status' mapping '$mapping'\n");
|
||||
#print("// hexxed '$hexxed' hashed '$hashed'\n");
|
||||
|
||||
if (($status eq 'C') or ($status eq 'F')) {
|
||||
my ($map1, $map2, $map3) = ('0000', '0000', '0000');
|
||||
my ($map1, $map2, $map3) = (undef, undef, undef);
|
||||
$map1 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
$map2 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
$map3 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
|
||||
die("mapping space too small for '$code'\n") if ($mapping ne '');
|
||||
$foldPairs[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n";
|
||||
die("problem parsing mapping for '$code'\n") if (not defined($map1));
|
||||
|
||||
if ($hexxed < 128) {
|
||||
# Just ignore these, we'll handle the low-ASCII ones ourselves.
|
||||
} elsif ($hexxed > 0xFFFF) {
|
||||
# We just need to add the 32-bit 2 and/or 3 codepoint maps if this die()'s here.
|
||||
die("Uhoh, a codepoint > 0xFFFF that folds to multiple codepoints! Fixme.") if defined($map2);
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_32-1));
|
||||
#print("// hexxed '$hexxed' hashed1 '$hashed'\n");
|
||||
$foldPairs1_32[$hashed] .= " { 0x$code, 0x$map1 },\n";
|
||||
} elsif (not defined($map2)) {
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_16-1));
|
||||
#print("// hexxed '$hexxed' hashed1 '$hashed'\n");
|
||||
$foldPairs1_16[$hashed] .= " { 0x$code, 0x$map1 },\n";
|
||||
} elsif (not defined($map3)) {
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS2_16-1));
|
||||
#print("// hexxed '$hexxed' hashed2 '$hashed'\n");
|
||||
$foldPairs2_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2 },\n";
|
||||
} else {
|
||||
my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS3_16-1));
|
||||
#print("// hexxed '$hexxed' hashed3 '$hashed'\n");
|
||||
$foldPairs3_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
close(FH);
|
||||
|
||||
for (my $i = 0; $i < 256; $i++) {
|
||||
$foldPairs[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs[$i];
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
|
||||
$foldPairs1_16[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs1_16[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold_${num}";
|
||||
print("static const CaseFoldMapping ${sym}[] = {\n$str\n};\n\n");
|
||||
my $sym = "case_fold1_16_${num}";
|
||||
print("static const CaseFoldMapping1_16 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
print("\nstatic const CaseFoldHashBucket case_fold_hash[256] = {\n");
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
|
||||
$foldPairs1_32[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs1_32[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold1_32_${num}";
|
||||
print("static const CaseFoldMapping1_32 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < 256; $i++) {
|
||||
my $str = $foldPairs[$i];
|
||||
for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
|
||||
$foldPairs2_16[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs2_16[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold2_16_${num}";
|
||||
print("static const CaseFoldMapping2_16 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
|
||||
$foldPairs3_16[$i] =~ s/,\n\Z//;
|
||||
my $str = $foldPairs3_16[$i];
|
||||
next if $str eq '';
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold3_16_${num}";
|
||||
print("static const CaseFoldMapping3_16 ${sym}[] = {\n$str\n};\n\n");
|
||||
}
|
||||
|
||||
print("static const CaseFoldHashBucket1_16 case_fold_hash1_16[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
|
||||
my $str = $foldPairs1_16[$i];
|
||||
if ($str eq '') {
|
||||
print(" { 0, NULL },\n");
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold_${num}";
|
||||
print(" { __PHYSFS_ARRAYLEN($sym), $sym },\n");
|
||||
my $sym = "case_fold1_16_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
|
||||
print("static const CaseFoldHashBucket1_32 case_fold_hash1_32[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
|
||||
my $str = $foldPairs1_32[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold1_32_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
|
||||
print("static const CaseFoldHashBucket2_16 case_fold_hash2_16[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
|
||||
my $str = $foldPairs2_16[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold2_16_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
print("static const CaseFoldHashBucket3_16 case_fold_hash3_16[] = {\n");
|
||||
|
||||
for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
|
||||
my $str = $foldPairs3_16[$i];
|
||||
if ($str eq '') {
|
||||
print(" { NULL, 0 },\n");
|
||||
} else {
|
||||
my $num = '000' . $i;
|
||||
$num =~ s/\A.*?(\d\d\d)\Z/$1/;
|
||||
my $sym = "case_fold3_16_${num}";
|
||||
print(" { $sym, __PHYSFS_ARRAYLEN($sym) },\n");
|
||||
}
|
||||
}
|
||||
print("};\n\n");
|
||||
|
||||
print <<__EOF__;
|
||||
|
||||
#endif /* _INCLUDE_PHYSFS_CASEFOLDING_H_ */
|
||||
|
||||
/* end of physfs_casefolding.h ... */
|
||||
|
||||
__EOF__
|
||||
|
||||
exit 0;
|
||||
|
||||
# end of makecashfoldhashtable.pl ...
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This shell script is roughly equivalent to what "make dist" did in the
|
||||
# autotools build system and is called from a custom CMake target.
|
||||
|
||||
# !!! FIXME: This code sort of sucks. Consider using CPack instead...
|
||||
|
||||
if [ ! -f ./CMakeLists.txt ]; then
|
||||
echo "you are in the wrong place."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Wrong arguments."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
VERSION="$1"
|
||||
BASENAME="physfs-$VERSION"
|
||||
TARBALL="$BASENAME.tar.gz"
|
||||
TMPCPDIR="../9sdkujy75jv932-physfstmp-$VERSION"
|
||||
CPDIR="$TMPCPDIR/$BASENAME"
|
||||
|
||||
echo "Packing PhysicsFS $VERSION source tarball..."
|
||||
echo " + Setting up scratch dir..."
|
||||
rm -rf $TMPCPDIR
|
||||
mkdir $TMPCPDIR
|
||||
mkdir $CPDIR
|
||||
|
||||
echo " + Making copy of source tree in scratch dir..."
|
||||
cp -R . $CPDIR/
|
||||
echo " + Deleting cruft..."
|
||||
pushd $CPDIR >/dev/null
|
||||
rm -rf `svn propget svn:ignore .`
|
||||
rm -rf `svn status |grep '?' |sed -s 's/\?//'`
|
||||
popd >/dev/null
|
||||
rm -rf `find $CPDIR -type d -name '.svn'`
|
||||
echo " + Deleting Subversion metadata..."
|
||||
rm -rf `find $CPDIR -type d -name '.svn'`
|
||||
echo " + Fixing up permissions..."
|
||||
chmod -R a+rw $CPDIR
|
||||
chmod a+x `find $CPDIR -type d`
|
||||
echo " + Building final tarball..."
|
||||
rm -f $TARBALL
|
||||
tar -czf $TARBALL -C $TMPCPDIR $BASENAME
|
||||
echo " + Cleaning up..."
|
||||
rm -rf $TMPCPDIR
|
||||
echo " + All done! Packed to '$TARBALL' ..."
|
||||
set +e
|
||||
|
||||
exit 0
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||
|
||||
Name: PhysicsFS
|
||||
Description: PhysicsFS is a library to provide abstract access to various archives.
|
||||
URL: https://icculus.org/physfs/
|
||||
Version: @PHYSFS_VERSION@
|
||||
Libs: -L${libdir} -lphysfs
|
||||
Cflags: -I${includedir}
|
|
@ -1,103 +0,0 @@
|
|||
# $Id: installer.rb,v 1.3 2003/07/21 03:46:50 icculus Exp $
|
||||
|
||||
require 'rbconfig'
|
||||
require 'find'
|
||||
require 'ftools'
|
||||
|
||||
include Config
|
||||
|
||||
module Slimb
|
||||
class Installer
|
||||
def initialize target_dir = "", &user_skip
|
||||
@user_skip = user_skip or proc {|f| false}
|
||||
|
||||
@version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
|
||||
@libdir = File.join(CONFIG["libdir"], "ruby", @version)
|
||||
@sitedir = CONFIG["sitedir"] || File.join(@libdir, "site_ruby")
|
||||
@dest = File.join @sitedir, target_dir
|
||||
|
||||
File::makedirs @dest
|
||||
File::chmod 0755, @dest, true
|
||||
end
|
||||
|
||||
def skip? file
|
||||
@user_skip[file] or
|
||||
file[0] == ?. or file[-1] == ?~ or file[-1] == ?#
|
||||
end
|
||||
|
||||
def install_dir dir
|
||||
File::makedirs(File.join(@dest, dir))
|
||||
File::chmod(0755, File.join(@dest, dir), true)
|
||||
Dir.foreach(dir) {|file|
|
||||
next if skip? file
|
||||
|
||||
if File.ftype(File.join(dir, file)) == "directory"
|
||||
install_dir File.join(dir, file)
|
||||
else
|
||||
install_file File.join(dir, file)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def install_file file
|
||||
if file =~ /\.so$/
|
||||
install_so file
|
||||
else
|
||||
File::install file, File.join(@dest, file), 0644, true
|
||||
end
|
||||
end
|
||||
|
||||
def install_so file
|
||||
File::install file, File.join(CONFIG["sitearchdir"], file), 0644, true
|
||||
end
|
||||
|
||||
def uninstall_so file
|
||||
file = File.join(CONFIG["sitearchdir"], file)
|
||||
File::safe_unlink file
|
||||
end
|
||||
|
||||
def install something
|
||||
case something
|
||||
when Array
|
||||
something.each {|x|
|
||||
install x if x.is_a? String
|
||||
}
|
||||
when String
|
||||
if File.ftype(something) == "directory"
|
||||
install_dir something
|
||||
else
|
||||
install_file something
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def uninstall what = "*"
|
||||
case what
|
||||
when Array
|
||||
files = what.map {|x| File.join(@dest, x)}
|
||||
when String
|
||||
files = Dir[File.join(@dest, what)]
|
||||
end
|
||||
|
||||
files.each {|x|
|
||||
# FIXME: recursive uninstall is a must
|
||||
next if FileTest.directory? x
|
||||
File::safe_unlink x
|
||||
}
|
||||
end
|
||||
|
||||
def run files, argv
|
||||
if !argv.grep(/--uninstall/).empty?
|
||||
uninstall files
|
||||
else
|
||||
install files
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# self-installation
|
||||
if $0 == __FILE__
|
||||
$stderr.puts "Installing slimb installer..."
|
||||
Slimb::Installer.new("slimb").install File.basename(__FILE__)
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
require 'mkmf'
|
||||
|
||||
$CFLAGS += `sdl-config --cflags`.chomp
|
||||
$LDFLAGS += `sdl-config --libs`.chomp
|
||||
|
||||
have_library "physfs", "PHYSFS_init"
|
||||
have_library "SDL", "SDL_AllocRW"
|
||||
|
||||
create_makefile "physfs_so"
|
|
@ -1,7 +0,0 @@
|
|||
#!/usr/local/bin/ruby
|
||||
|
||||
if __FILE__ == $0
|
||||
require 'slimb/installer'
|
||||
files = ["physfs.rb", "physfs_so.so"]
|
||||
installer = Slimb::Installer.new.run files, ARGV
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/sh
|
||||
ruby extconf.rb
|
||||
make
|
||||
cd ..
|
||||
ruby installer.rb
|
||||
cd physfs
|
||||
ruby install.rb
|
||||
cd test
|
||||
ruby test_physfs.rb
|
|
@ -1,121 +0,0 @@
|
|||
#
|
||||
# PhysicsFS - ruby interface
|
||||
#
|
||||
# Author: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
# License: LGPL
|
||||
#
|
||||
|
||||
require 'physfs_so'
|
||||
|
||||
module PhysicsFS
|
||||
|
||||
class Version
|
||||
def initialize major, minor, patch
|
||||
@major = major
|
||||
@minor = minor
|
||||
@patch = patch
|
||||
end
|
||||
|
||||
attr_reader :major, :minor, :patch
|
||||
|
||||
def to_s
|
||||
"#@major.#@minor.#@patch"
|
||||
end
|
||||
end
|
||||
|
||||
class ArchiveInfo
|
||||
def initialize ext, desc, author, url
|
||||
@extension = ext
|
||||
@description = desc
|
||||
@author = author
|
||||
@url = url
|
||||
end
|
||||
|
||||
attr_reader :extension, :description
|
||||
attr_reader :author, :url
|
||||
|
||||
def to_s
|
||||
" * #@extension: #@description\n Written by #@author.\n #@url\n"
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# convenience methods
|
||||
#
|
||||
class << self
|
||||
|
||||
def init argv0 = $0
|
||||
init_internal argv0
|
||||
end
|
||||
|
||||
def append_search_path str
|
||||
add_to_search_path str, 1
|
||||
self
|
||||
end
|
||||
|
||||
def prepend_search_path str
|
||||
add_to_search_path str, 0
|
||||
self
|
||||
end
|
||||
|
||||
alias_method :<<, :append_search_path
|
||||
alias_method :push, :append_search_path
|
||||
alias_method :unshift, :prepend_search_path
|
||||
|
||||
def ls path = ""
|
||||
enumerate path
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# File - PhysicsFS abstract file - can be drawn from various sources
|
||||
#
|
||||
class File
|
||||
def write_str str
|
||||
write str, 1, str.length
|
||||
end
|
||||
|
||||
def cat
|
||||
prev_pos = tell
|
||||
seek 0
|
||||
r = read length, 1
|
||||
seek prev_pos
|
||||
r
|
||||
end
|
||||
|
||||
alias_method :size, :length
|
||||
end
|
||||
|
||||
#
|
||||
# RWops - general stdio like operations on file-like creatures
|
||||
#
|
||||
class RWops
|
||||
SEEK_SET = 0
|
||||
SEEK_CUR = 1
|
||||
SEEK_END = 2
|
||||
|
||||
# tell current position of RWopted entity
|
||||
def tell
|
||||
seek 0, SEEK_CUR
|
||||
end
|
||||
|
||||
# length of RWops abstracted entity
|
||||
def length
|
||||
cur = tell
|
||||
r = seek 0, SEEK_END
|
||||
seek cur, SEEK_SET
|
||||
r
|
||||
end
|
||||
|
||||
alias_method :size, :length
|
||||
|
||||
#
|
||||
# create rwops from PhysicsFS file object
|
||||
#
|
||||
def self.from_physfs file
|
||||
file.to_rwops
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# physfs.rb ends here #
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
||||
* Layer's (SDL) RWops i/o abstraction.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
|
||||
* General Public License: http://www.gnu.org/licenses/lgpl.txt
|
||||
*
|
||||
* SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
|
||||
#include "physfsrwops.h"
|
||||
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
int pos = 0;
|
||||
|
||||
if (whence == SEEK_SET)
|
||||
{
|
||||
pos = offset;
|
||||
} /* if */
|
||||
|
||||
else if (whence == SEEK_CUR)
|
||||
{
|
||||
PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
if (current == -1)
|
||||
{
|
||||
SDL_SetError("Can't find position in file: %s",
|
||||
PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) current;
|
||||
if ( ((PHYSFS_sint64) pos) != current )
|
||||
{
|
||||
SDL_SetError("Can't fit current file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
||||
return(pos);
|
||||
|
||||
pos += offset;
|
||||
} /* else if */
|
||||
|
||||
else if (whence == SEEK_END)
|
||||
{
|
||||
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
if (len == -1)
|
||||
{
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) len;
|
||||
if ( ((PHYSFS_sint64) pos) != len )
|
||||
{
|
||||
SDL_SetError("Can't fit end-of-file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos += offset;
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
SDL_SetError("Invalid 'whence' parameter.");
|
||||
return(-1);
|
||||
} /* else */
|
||||
|
||||
if ( pos < 0 )
|
||||
{
|
||||
SDL_SetError("Attempt to seek past start of file.");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
return(pos);
|
||||
} /* physfsrwops_seek */
|
||||
|
||||
|
||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
|
||||
if (rc != maxnum)
|
||||
{
|
||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
} /* if */
|
||||
|
||||
return((int) rc);
|
||||
} /* physfsrwops_read */
|
||||
|
||||
|
||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
|
||||
if (rc != num)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
|
||||
return((int) rc);
|
||||
} /* physfsrwops_write */
|
||||
|
||||
|
||||
static int physfsrwops_close(SDL_RWops *rw)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
if (!PHYSFS_close(handle))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
SDL_FreeRW(rw);
|
||||
return(0);
|
||||
} /* physfsrwops_close */
|
||||
|
||||
|
||||
static SDL_RWops *create_rwops(PHYSFS_File *handle)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
|
||||
if (handle == NULL)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
else
|
||||
{
|
||||
retval = SDL_AllocRW();
|
||||
if (retval != NULL)
|
||||
{
|
||||
retval->seek = physfsrwops_seek;
|
||||
retval->read = physfsrwops_read;
|
||||
retval->write = physfsrwops_write;
|
||||
retval->close = physfsrwops_close;
|
||||
retval->hidden.unknown.data1 = handle;
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
} /* create_rwops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
|
||||
{
|
||||
SDL_RWops *retval = NULL;
|
||||
if (handle == NULL)
|
||||
SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops().");
|
||||
else
|
||||
retval = create_rwops(handle);
|
||||
|
||||
return(retval);
|
||||
} /* PHYSFSRWOPS_makeRWops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
|
||||
{
|
||||
return(create_rwops(PHYSFS_openRead(fname)));
|
||||
} /* PHYSFSRWOPS_openRead */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
|
||||
{
|
||||
return(create_rwops(PHYSFS_openWrite(fname)));
|
||||
} /* PHYSFSRWOPS_openWrite */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
|
||||
{
|
||||
return(create_rwops(PHYSFS_openAppend(fname)));
|
||||
} /* PHYSFSRWOPS_openAppend */
|
||||
|
||||
|
||||
/* end of physfsrwops.c ... */
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* This code provides a glue layer between PhysicsFS and Simple Directmedia
|
||||
* Layer's (SDL) RWops i/o abstraction.
|
||||
*
|
||||
* License: this code is public domain. I make no warranty that it is useful,
|
||||
* correct, harmless, or environmentally safe.
|
||||
*
|
||||
* This particular file may be used however you like, including copying it
|
||||
* verbatim into a closed-source project, exploiting it commercially, and
|
||||
* removing any trace of my name from the source (although I hope you won't
|
||||
* do that). I welcome enhancements and corrections to this file, but I do
|
||||
* not require you to send me patches if you make changes.
|
||||
*
|
||||
* Unless otherwise stated, the rest of PhysicsFS falls under the GNU Lesser
|
||||
* General Public License: http://www.gnu.org/licenses/lgpl.txt
|
||||
*
|
||||
* SDL falls under the LGPL, too. You can get SDL at http://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_PHYSFSRWOPS_H_
|
||||
#define _INCLUDE_PHYSFSRWOPS_H_
|
||||
|
||||
#include "physfs.h"
|
||||
#include "SDL.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for reading, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for writing, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for appending, and make it accessible
|
||||
* via an SDL_RWops structure. The file will be closed in PhysicsFS when the
|
||||
* RWops is closed. PhysicsFS should be configured to your liking before
|
||||
* opening files through this method.
|
||||
*
|
||||
* @param filename File to open in platform-independent notation.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
||||
|
||||
/**
|
||||
* Make a SDL_RWops from an existing PhysicsFS file handle. You should
|
||||
* dispose of any references to the handle after successful creation of
|
||||
* the RWops. The actual PhysicsFS handle will be destroyed when the
|
||||
* RWops is closed.
|
||||
*
|
||||
* @param handle a valid PhysicsFS file handle.
|
||||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* include-once blocker */
|
||||
|
||||
/* end of physfsrwops.h ... */
|
||||
|
|
@ -1,462 +0,0 @@
|
|||
/*
|
||||
* PhysicsFS - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#include "physfs.h"
|
||||
#include "ruby.h"
|
||||
|
||||
#include "rb_physfs.h"
|
||||
#include "rb_physfs_file.h"
|
||||
|
||||
VALUE modulePhysfs;
|
||||
|
||||
/*
|
||||
* PhysicsFS::init str
|
||||
*
|
||||
* initialize PhysicsFS
|
||||
*/
|
||||
VALUE physfs_init (VALUE self, VALUE str)
|
||||
{
|
||||
int result = PHYSFS_init (STR2CSTR(str));
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::deinit
|
||||
*/
|
||||
VALUE physfs_deinit (VALUE self)
|
||||
{
|
||||
if (PHYSFS_deinit ())
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::version
|
||||
*
|
||||
* return PhysicsFS::Version object
|
||||
*/
|
||||
VALUE physfs_version (VALUE self)
|
||||
{
|
||||
char evalStr[200];
|
||||
PHYSFS_Version ver;
|
||||
|
||||
PHYSFS_getLinkedVersion (&ver);
|
||||
|
||||
sprintf (evalStr, "PhysicsFS::Version.new %d, %d, %d",
|
||||
ver.major, ver.minor, ver.patch);
|
||||
return rb_eval_string (evalStr);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::supported_archives
|
||||
*
|
||||
* return Array of PhysicsFS::ArchiveInfo objects
|
||||
*/
|
||||
VALUE physfs_supported_archives (VALUE self)
|
||||
{
|
||||
const PHYSFS_ArchiveInfo **info = PHYSFS_supportedArchiveTypes();
|
||||
VALUE klass = rb_const_get (modulePhysfs, rb_intern ("ArchiveInfo"));
|
||||
VALUE ary = rb_ary_new ();
|
||||
VALUE params[4];
|
||||
|
||||
while ( *info != 0 )
|
||||
{
|
||||
params[0] = rb_str_new2 ((*info)->extension);
|
||||
params[1] = rb_str_new2 ((*info)->description);
|
||||
params[2] = rb_str_new2 ((*info)->author);
|
||||
params[3] = rb_str_new2 ((*info)->url);
|
||||
|
||||
rb_ary_push (ary, rb_class_new_instance (4, params, klass));
|
||||
info++;
|
||||
}
|
||||
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::last_error
|
||||
*
|
||||
* return string representation of last PhysicsFS error
|
||||
*/
|
||||
VALUE physfs_last_error (VALUE self)
|
||||
{
|
||||
const char *last_error = PHYSFS_getLastError ();
|
||||
|
||||
if (last_error == 0)
|
||||
last_error = "";
|
||||
|
||||
return rb_str_new2 (last_error);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::dir_separator
|
||||
*
|
||||
* return platform directory separator
|
||||
*/
|
||||
VALUE physfs_dir_separator (VALUE self)
|
||||
{
|
||||
return rb_str_new2 (PHYSFS_getDirSeparator ());
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::permit_symlinks boolValue
|
||||
*
|
||||
* turn symlinks support on/off
|
||||
*/
|
||||
VALUE physfs_permit_symlinks (VALUE self, VALUE allow)
|
||||
{
|
||||
int p = 1;
|
||||
|
||||
if (allow == Qfalse || allow == Qnil)
|
||||
p = 0;
|
||||
|
||||
PHYSFS_permitSymbolicLinks (p);
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::cdrom_dirs
|
||||
*
|
||||
* return Array of strings containing available CDs
|
||||
*/
|
||||
VALUE physfs_cdrom_dirs (VALUE self)
|
||||
{
|
||||
char **cds = PHYSFS_getCdRomDirs();
|
||||
char **i;
|
||||
VALUE ary = rb_ary_new ();
|
||||
|
||||
for (i = cds; *i != 0; i++)
|
||||
rb_ary_push (ary, rb_str_new2 (*i));
|
||||
|
||||
PHYSFS_freeList (cds);
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::base_dir
|
||||
*
|
||||
* return base directory
|
||||
*/
|
||||
VALUE physfs_base_dir (VALUE self)
|
||||
{
|
||||
const char *base_dir = PHYSFS_getBaseDir ();
|
||||
if (base_dir == 0)
|
||||
base_dir = "";
|
||||
|
||||
return rb_str_new2 (base_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::user_dir
|
||||
*
|
||||
* return user directory
|
||||
*/
|
||||
VALUE physfs_user_dir (VALUE self)
|
||||
{
|
||||
const char *user_dir = PHYSFS_getBaseDir ();
|
||||
if (user_dir == 0)
|
||||
user_dir = "";
|
||||
|
||||
return rb_str_new2 (user_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::write_dir
|
||||
*
|
||||
* return write directory
|
||||
*/
|
||||
VALUE physfs_write_dir (VALUE self)
|
||||
{
|
||||
const char *write_dir = PHYSFS_getWriteDir ();
|
||||
if (write_dir == 0)
|
||||
return Qnil;
|
||||
|
||||
return rb_str_new2 (write_dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::write_dir= str
|
||||
*
|
||||
* set write directory to *str*
|
||||
*/
|
||||
VALUE physfs_set_write_dir (VALUE self, VALUE str)
|
||||
{
|
||||
int result = PHYSFS_setWriteDir (STR2CSTR(str));
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::add_to_search_path str, append
|
||||
*
|
||||
* if append > 0 - append str to search path, otherwise prepend it
|
||||
*/
|
||||
VALUE physfs_add_search_path (VALUE self, VALUE str, VALUE append)
|
||||
{
|
||||
int result = PHYSFS_addToSearchPath (STR2CSTR(str), FIX2INT(append));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::remove_from_search_path str
|
||||
*
|
||||
* removes str from search path
|
||||
*/
|
||||
VALUE physfs_remove_search_path (VALUE self, VALUE str)
|
||||
{
|
||||
int result = PHYSFS_removeFromSearchPath (STR2CSTR(str));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::search_path
|
||||
*
|
||||
* return current search_path - as array of strings
|
||||
*/
|
||||
VALUE physfs_search_path (VALUE self)
|
||||
{
|
||||
char **path = PHYSFS_getSearchPath ();
|
||||
char **i;
|
||||
VALUE ary = rb_ary_new ();
|
||||
|
||||
for (i = path ; *i != 0; i++)
|
||||
rb_ary_push (ary, rb_str_new2 (*i));
|
||||
|
||||
PHYSFS_freeList (path);
|
||||
return ary;
|
||||
}
|
||||
|
||||
//
|
||||
VALUE physfs_setSaneConfig(VALUE self, VALUE org, VALUE app, VALUE ext,
|
||||
VALUE includeCdroms, VALUE archivesFirst)
|
||||
{
|
||||
int res = PHYSFS_setSaneConfig (STR2CSTR(org), STR2CSTR(app), STR2CSTR(ext),
|
||||
RTEST(includeCdroms), RTEST(archivesFirst));
|
||||
if (res)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::mkdir newdir
|
||||
*
|
||||
* create new directory
|
||||
*/
|
||||
VALUE physfs_mkdir (VALUE self, VALUE newdir)
|
||||
{
|
||||
int result = PHYSFS_mkdir (STR2CSTR(newdir));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::delete name
|
||||
*
|
||||
* delete file with name
|
||||
*/
|
||||
VALUE physfs_delete (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_delete (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::real_dir name
|
||||
*
|
||||
* return real directory (in search path) of a name
|
||||
*/
|
||||
VALUE physfs_real_dir (VALUE self, VALUE name)
|
||||
{
|
||||
const char *path = PHYSFS_getRealDir (STR2CSTR(name));
|
||||
if (path == 0)
|
||||
return Qnil;
|
||||
|
||||
return rb_str_new2 (path);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::enumerate dir
|
||||
*
|
||||
* list a dir from a search path
|
||||
*/
|
||||
VALUE physfs_enumerate (VALUE self, VALUE dir)
|
||||
{
|
||||
char **files = PHYSFS_enumerateFiles (STR2CSTR(dir));
|
||||
char **i;
|
||||
VALUE ary = rb_ary_new ();
|
||||
|
||||
for (i = files; *i != 0; i++)
|
||||
rb_ary_push (ary, rb_str_new2 (*i));
|
||||
|
||||
PHYSFS_freeList (files);
|
||||
return ary;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::exists? name
|
||||
*
|
||||
* does a file with name exist?
|
||||
*/
|
||||
VALUE physfs_exists (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_exists (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::is_directory? name
|
||||
*
|
||||
* return true if name is directory
|
||||
*/
|
||||
VALUE physfs_is_directory (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_isDirectory (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::is_symlink? name
|
||||
*
|
||||
* return true if name is symlink
|
||||
*/
|
||||
VALUE physfs_is_symlink (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_isSymbolicLink (STR2CSTR(name));
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::last_mod_time name
|
||||
*
|
||||
* return last modification time of a file
|
||||
*/
|
||||
VALUE physfs_last_mod_time (VALUE self, VALUE name)
|
||||
{
|
||||
int result = PHYSFS_getLastModTime (STR2CSTR(name));
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::open_read name
|
||||
*
|
||||
* return +PhysicsFS::File+ ready for reading
|
||||
*/
|
||||
VALUE physfs_open_read (VALUE self, VALUE name)
|
||||
{
|
||||
PHYSFS_File *file = PHYSFS_openRead (STR2CSTR(name));
|
||||
return physfs_file_new (file);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::open_write name
|
||||
*
|
||||
* return PhysicsFS::File ready for writing
|
||||
*/
|
||||
VALUE physfs_open_write (VALUE self, VALUE name)
|
||||
{
|
||||
PHYSFS_File *file = PHYSFS_openWrite (STR2CSTR(name));
|
||||
return physfs_file_new (file);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::open_append name
|
||||
*
|
||||
* return PhysicsFS::File ready for appending
|
||||
*/
|
||||
VALUE physfs_open_append (VALUE self, VALUE name)
|
||||
{
|
||||
PHYSFS_File *file = PHYSFS_openAppend (STR2CSTR(name));
|
||||
return physfs_file_new (file);
|
||||
}
|
||||
|
||||
void Init_physfs_so (void)
|
||||
{
|
||||
modulePhysfs = rb_define_module ("PhysicsFS");
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "init_internal", physfs_init, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "deinit", physfs_deinit, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "version", physfs_version, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "supported_archives",
|
||||
physfs_supported_archives, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "last_error",
|
||||
physfs_last_error, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "dir_separator",
|
||||
physfs_dir_separator, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "permit_symlinks",
|
||||
physfs_permit_symlinks, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "cdrom_dirs",
|
||||
physfs_cdrom_dirs, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "base_dir", physfs_base_dir, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "user_dir", physfs_user_dir, 0);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "write_dir", physfs_write_dir, 0);
|
||||
rb_define_singleton_method (modulePhysfs, "write_dir=",
|
||||
physfs_set_write_dir, 1);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "add_to_search_path",
|
||||
physfs_add_search_path, 2);
|
||||
rb_define_singleton_method (modulePhysfs, "remove_from_search_path",
|
||||
physfs_remove_search_path, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "search_path",
|
||||
physfs_search_path, 0);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "set_sane_config",
|
||||
physfs_setSaneConfig, 5);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "mkdir", physfs_mkdir, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "delete", physfs_delete, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "real_dir",
|
||||
physfs_real_dir, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "enumerate", physfs_enumerate, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "exists?", physfs_exists, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "is_directory?",
|
||||
physfs_is_directory, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "is_symlink?",
|
||||
physfs_is_symlink, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "last_mod_time",
|
||||
physfs_last_mod_time, 1);
|
||||
|
||||
rb_define_singleton_method (modulePhysfs, "open_read",
|
||||
physfs_open_read, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "open_write",
|
||||
physfs_open_write, 1);
|
||||
rb_define_singleton_method (modulePhysfs, "open_append",
|
||||
physfs_open_append, 1);
|
||||
|
||||
init_physfs_file ();
|
||||
init_sdl_rwops ();
|
||||
}
|
||||
|
||||
/*
|
||||
// Local Variables:
|
||||
// mode: C
|
||||
// c-indentation-style: "stroustrup"
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
*/
|
|
@ -1,13 +0,0 @@
|
|||
/*
|
||||
* PhysicsFS - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#ifndef __RB__PHYSFS__H__
|
||||
#define __RB__PHYSFS__H__
|
||||
|
||||
extern VALUE modulePhysfs;
|
||||
|
||||
#endif
|
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* PhysicsFS File abstraction - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#include "physfs.h"
|
||||
#include "ruby.h"
|
||||
|
||||
#include "rb_physfs.h"
|
||||
#include "rb_physfs_file.h"
|
||||
#include "physfsrwops.h"
|
||||
|
||||
VALUE classPhysfsFile;
|
||||
|
||||
/*
|
||||
* construct new PhysicsFS::File object
|
||||
*/
|
||||
VALUE physfs_file_new (PHYSFS_File *file)
|
||||
{
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
return Data_Wrap_Struct (classPhysfsFile, 0, 0, file);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#close
|
||||
*
|
||||
* Close the file. It's illegal to use the object after its closure.
|
||||
*/
|
||||
VALUE physfs_file_close (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
|
||||
if (file == 0)
|
||||
return Qfalse;
|
||||
|
||||
result = PHYSFS_close (file);
|
||||
DATA_PTR(self) = 0;
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#read obj_size, num_objects
|
||||
*
|
||||
* Read *objCount* objects which are *objSize* each.
|
||||
* return String instance containing raw data or nil if failure.
|
||||
* #length of string will reflect real number of objects read.
|
||||
*/
|
||||
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount)
|
||||
{
|
||||
int objRead;
|
||||
void *buffer;
|
||||
VALUE result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil; //wasted file - no read possible
|
||||
|
||||
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
|
||||
if (buffer == 0)
|
||||
return Qnil;
|
||||
|
||||
objRead = PHYSFS_read (file, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
|
||||
if (objRead == -1)
|
||||
{
|
||||
free (buffer);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
|
||||
free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#write buffer, obj_size, num_objects
|
||||
*
|
||||
* return nil on failure or number of objects written.
|
||||
*/
|
||||
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_write (file, STR2CSTR(buf),
|
||||
FIX2UINT(objSize), FIX2UINT(objCount));
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#eof?
|
||||
*/
|
||||
VALUE physfs_file_eof (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_eof (file);
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#tell
|
||||
*
|
||||
* tells current position in file
|
||||
*/
|
||||
VALUE physfs_file_tell (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_tell (file);
|
||||
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#seek pos
|
||||
*
|
||||
* seek to pos in file
|
||||
*/
|
||||
VALUE physfs_file_seek (VALUE self, VALUE pos)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_seek (file, FIX2LONG(pos));
|
||||
|
||||
if (result)
|
||||
return Qtrue;
|
||||
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#length
|
||||
*/
|
||||
VALUE physfs_file_length (VALUE self)
|
||||
{
|
||||
int result;
|
||||
PHYSFS_File *file;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
result = PHYSFS_fileLength (file);
|
||||
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::File#to_rwops
|
||||
*
|
||||
* File object is converted to RWops object.
|
||||
* File object becomes unusable after that - every operation
|
||||
* should be done through new-born RWops object.
|
||||
*/
|
||||
VALUE physfs_file_to_rwops (VALUE self)
|
||||
{
|
||||
PHYSFS_File *file;
|
||||
SDL_RWops *rwops;
|
||||
|
||||
Data_Get_Struct (self, PHYSFS_File, file);
|
||||
if (file == 0)
|
||||
return Qnil;
|
||||
|
||||
rwops = PHYSFSRWOPS_makeRWops (file);
|
||||
if (rwops == 0)
|
||||
return Qnil;
|
||||
|
||||
DATA_PTR(self) = 0; // oh, gosh, we've sacrificed ourselves!
|
||||
return sdl_rwops_new (rwops);
|
||||
}
|
||||
|
||||
void init_physfs_file (void)
|
||||
{
|
||||
classPhysfsFile = rb_define_class_under (modulePhysfs, "File", rb_cObject);
|
||||
|
||||
rb_define_method (classPhysfsFile, "close", physfs_file_close, 0);
|
||||
rb_define_method (classPhysfsFile, "eof?", physfs_file_eof, 0);
|
||||
rb_define_method (classPhysfsFile, "tell", physfs_file_tell, 0);
|
||||
rb_define_method (classPhysfsFile, "seek", physfs_file_seek, 1);
|
||||
rb_define_method (classPhysfsFile, "length", physfs_file_length, 0);
|
||||
rb_define_method (classPhysfsFile, "read", physfs_file_read, 2);
|
||||
rb_define_method (classPhysfsFile, "write", physfs_file_write, 3);
|
||||
rb_define_method (classPhysfsFile, "to_rwops", physfs_file_to_rwops, 0);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* PhysicsFS File abstraction - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#ifndef __RB__PHYSFS__FILE__H__
|
||||
#define __RB__PHYSFS__FILE__H__
|
||||
|
||||
extern VALUE classPhysfsFile;
|
||||
|
||||
VALUE physfs_file_new (PHYSFS_file *file);
|
||||
VALUE physfs_file_close (VALUE self);
|
||||
VALUE physfs_file_read (VALUE self, VALUE objSize, VALUE objCount);
|
||||
VALUE physfs_file_write (VALUE self, VALUE buf, VALUE objSize, VALUE objCount);
|
||||
VALUE physfs_file_eof (VALUE self);
|
||||
VALUE physfs_file_tell (VALUE self);
|
||||
VALUE physfs_file_seek (VALUE self, VALUE pos);
|
||||
VALUE physfs_file_length (VALUE self);
|
||||
|
||||
void init_physfs_file (void);
|
||||
|
||||
#endif
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* SDL_RWops - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
#include "ruby.h"
|
||||
|
||||
#include "rb_physfs.h"
|
||||
#include "rb_sdl_rwops.h"
|
||||
|
||||
VALUE classRWops;
|
||||
|
||||
/*
|
||||
* RWops constructor
|
||||
*/
|
||||
VALUE sdl_rwops_new (SDL_RWops *ops)
|
||||
{
|
||||
VALUE result;
|
||||
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = Data_Wrap_Struct (classRWops, 0, SDL_FreeRW, ops);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops::from_file name, mode
|
||||
*
|
||||
* create RWops object from file
|
||||
*/
|
||||
VALUE sdl_rwops_from_file (VALUE self, VALUE name, VALUE mode)
|
||||
{
|
||||
SDL_RWops *ops = SDL_RWFromFile(STR2CSTR(name), STR2CSTR(mode));
|
||||
return sdl_rwops_new (ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops::from_memory string
|
||||
*
|
||||
* create RWops object from memory
|
||||
*/
|
||||
VALUE sdl_rwops_from_mem (VALUE self, VALUE str)
|
||||
{
|
||||
int len = RSTRING(str)->len;
|
||||
void *mem = STR2CSTR(str);
|
||||
SDL_RWops *ops = SDL_RWFromMem(mem, len);
|
||||
|
||||
return sdl_rwops_new (ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#seek offset, whence
|
||||
*
|
||||
* position RWops object
|
||||
*/
|
||||
VALUE sdl_rwops_seek (VALUE self, VALUE offset, VALUE whence)
|
||||
{
|
||||
int result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = SDL_RWseek(ops, FIX2INT(offset), FIX2INT(whence));
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#close
|
||||
*
|
||||
* close RWops. No use of the object is possible after that.
|
||||
*/
|
||||
VALUE sdl_rwops_close (VALUE self)
|
||||
{
|
||||
int result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = SDL_RWclose (ops);
|
||||
DATA_PTR(self) = 0;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#read
|
||||
*
|
||||
* read from RWops object objCount objSize'd entities.
|
||||
* return string containing raw data or nil
|
||||
*/
|
||||
VALUE sdl_rwops_read (VALUE self, VALUE objSize, VALUE objCount)
|
||||
{
|
||||
int objRead;
|
||||
void *buffer;
|
||||
VALUE result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
buffer = malloc (FIX2UINT(objSize) * FIX2UINT(objCount));
|
||||
if (buffer == 0)
|
||||
return Qnil;
|
||||
|
||||
objRead = SDL_RWread (ops, buffer, FIX2UINT(objSize), FIX2UINT(objCount));
|
||||
if (objRead == -1)
|
||||
{
|
||||
free (buffer);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
result = rb_str_new (buffer, objRead * FIX2UINT(objSize));
|
||||
free (buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* PhysicsFS::RWops#write buffer, size, n
|
||||
*
|
||||
* write raw string containing n objects size length each.
|
||||
* return number of objects written or nil
|
||||
*/
|
||||
VALUE sdl_rwops_write (VALUE self, VALUE buffer, VALUE size, VALUE n)
|
||||
{
|
||||
int result;
|
||||
SDL_RWops *ops;
|
||||
|
||||
Data_Get_Struct (self, SDL_RWops, ops);
|
||||
if (ops == 0)
|
||||
return Qnil;
|
||||
|
||||
result = SDL_RWwrite (ops, STR2CSTR(buffer), FIX2INT(size), FIX2INT(n));
|
||||
|
||||
if (result == -1)
|
||||
return Qnil;
|
||||
|
||||
return INT2FIX(result);
|
||||
}
|
||||
|
||||
void init_sdl_rwops (void)
|
||||
{
|
||||
classRWops = rb_define_class_under (modulePhysfs, "RWops", rb_cObject);
|
||||
|
||||
rb_define_method (classRWops, "seek", sdl_rwops_seek, 2);
|
||||
rb_define_method (classRWops, "read", sdl_rwops_read, 2);
|
||||
rb_define_method (classRWops, "write", sdl_rwops_write, 3);
|
||||
rb_define_method (classRWops, "close", sdl_rwops_close, 0);
|
||||
|
||||
rb_define_singleton_method (classRWops, "from_file",
|
||||
sdl_rwops_from_file, 2);
|
||||
rb_define_singleton_method (classRWops, "from_memory",
|
||||
sdl_rwops_from_mem, 1);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* SDL_RWops - ruby interface
|
||||
*
|
||||
* Author:: Ed Sinjiashvili (slimb@vlinkmail.com)
|
||||
* License:: LGPL
|
||||
*/
|
||||
|
||||
#ifndef __RB__SDL__RWOPS__H__
|
||||
#define __RB__SDL__RWOPS__H__
|
||||
|
||||
extern VALUE classRWops;
|
||||
|
||||
VALUE sdl_rwops_new (SDL_RWops *ops);
|
||||
void init_sdl_rwops (void);
|
||||
|
||||
#endif
|
|
@ -1,358 +0,0 @@
|
|||
#
|
||||
# PhysicsFS test program - mimics real physfs_test
|
||||
#
|
||||
require 'readline'
|
||||
require 'physfs'
|
||||
|
||||
def die msg
|
||||
puts "#{msg} - reason: #{PhysicsFS.last_error}"
|
||||
end
|
||||
|
||||
#
|
||||
# parse line to command and args
|
||||
#
|
||||
def parse line
|
||||
return false if line.nil?
|
||||
|
||||
if line.strip =~ /^(.*?) (?: (?:\s+(.*)) | $)/x
|
||||
run $1, $2
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# parse command args
|
||||
#
|
||||
def parse_args args
|
||||
args.strip!
|
||||
|
||||
dquoted = /^ " (.*?) "/x
|
||||
squoted = /^ ' (.*?) '/x
|
||||
unquoted = /^([^\s\'\"]+)/
|
||||
|
||||
regexps = [dquoted, squoted, unquoted]
|
||||
|
||||
result = []
|
||||
while args != ""
|
||||
regexps.each do |r|
|
||||
if args =~ r
|
||||
result << $1
|
||||
args.sub! r, ""
|
||||
args.sub!(/\s+/, "")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def usage cmd, prefix = "usage: "
|
||||
print prefix
|
||||
args = Commands::HELP[cmd]
|
||||
if args
|
||||
print cmd
|
||||
args.scan(/\w+/).each {|x|
|
||||
print " <#{x}>"
|
||||
}
|
||||
puts
|
||||
else
|
||||
puts %|#{cmd} (no arguments)|
|
||||
end
|
||||
end
|
||||
|
||||
# commands go below
|
||||
module Commands
|
||||
HELP = {
|
||||
"init" => "argv0",
|
||||
"addarchive" => "archiveLocation append",
|
||||
"removearchive" => "archiveLocation",
|
||||
"enumerate" => "dirToEnumerate",
|
||||
"ls" => "dirToEnumerate",
|
||||
"setwritedir" => "newWriteDir",
|
||||
"permitsymlinks" => "1or0",
|
||||
"setsaneconfig" => "org appName arcExt includeCdRoms archivesFirst",
|
||||
"mkdir" => "dirToMk",
|
||||
"delete" => "dirToDelete",
|
||||
"getrealdir" => "fileToFind",
|
||||
"exists" => "fileToCheck",
|
||||
"isdir" => "fileToCheck",
|
||||
"issymlink" => "fileToCheck",
|
||||
"cat" => "fileToCat",
|
||||
"filelength" => "fileToCheck",
|
||||
"append" => "fileToAppend",
|
||||
"write" => "fileToCreateOrTrash",
|
||||
"getlastmodtime" => "fileToExamine"
|
||||
}
|
||||
|
||||
def quit_cmd
|
||||
exit
|
||||
end
|
||||
|
||||
alias q_cmd quit_cmd
|
||||
|
||||
def help_cmd
|
||||
commands = ::Commands.instance_methods.grep(/_cmd$/).sort
|
||||
puts "Commands:"
|
||||
commands.each do |c|
|
||||
usage c.sub("_cmd", ""), " - "
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def e val
|
||||
if val
|
||||
puts "Successful."
|
||||
else
|
||||
puts "Failure. reason: #{PhysicsFS.last_error}"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def init_cmd arg
|
||||
e PhysicsFS.init(arg)
|
||||
end
|
||||
|
||||
def deinit_cmd
|
||||
e PhysicsFS.deinit
|
||||
end
|
||||
|
||||
def addarchive_cmd archive, append
|
||||
e PhysicsFS.add_to_search_path(archive, append)
|
||||
end
|
||||
|
||||
def removearchive_cmd archive
|
||||
e PhysicsFS.remove_from_search_path archive
|
||||
end
|
||||
|
||||
def enumerate_cmd path
|
||||
entries = PhysicsFS.enumerate(path)
|
||||
entries.each {|x|
|
||||
puts x
|
||||
}
|
||||
true
|
||||
end
|
||||
|
||||
alias ls_cmd enumerate_cmd
|
||||
|
||||
def getlasterror_cmd
|
||||
puts "Last error is [#{PhysicsFS.last_error}]"
|
||||
true
|
||||
end
|
||||
|
||||
def getdirsep_cmd
|
||||
puts "Directory separator is [#{PhysicsFS.dir_separator}]"
|
||||
true
|
||||
end
|
||||
|
||||
def getcdromdirs_cmd
|
||||
dirs = PhysicsFS.cdrom_dirs
|
||||
dirs.each {|x|
|
||||
puts x
|
||||
}
|
||||
puts " total [#{dirs.length}] drives."
|
||||
true
|
||||
end
|
||||
|
||||
def getsearchpath_cmd
|
||||
spath = PhysicsFS.search_path
|
||||
spath.each {|x|
|
||||
puts x
|
||||
}
|
||||
puts "total [#{spath.length}] directories."
|
||||
true
|
||||
end
|
||||
|
||||
def getbasedir_cmd
|
||||
dir = PhysicsFS.base_dir
|
||||
puts dir if dir
|
||||
true
|
||||
end
|
||||
|
||||
def getuserdir_cmd
|
||||
puts PhysicsFS.user_dir
|
||||
true
|
||||
end
|
||||
|
||||
def getwritedir_cmd
|
||||
dir = PhysicsFS.write_dir
|
||||
if dir
|
||||
puts "Write directory is [#{dir}]."
|
||||
else
|
||||
puts "No write directory defined."
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def setwritedir_cmd dir
|
||||
e(PhysicsFS.write_dir = dir)
|
||||
end
|
||||
|
||||
def permitsymlinks_cmd val
|
||||
if val.to_i == 1
|
||||
PhysicsFS.permit_symlinks true
|
||||
puts "Symlinks are now permitted"
|
||||
else
|
||||
PhysicsFS.permit_symlinks false
|
||||
puts "Symlinks are now forbidden"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def setsaneconfig_cmd org, appname, ext, includeCdroms, archivesFirst
|
||||
includeCdroms = includeCdroms.to_i == 1
|
||||
archiveFirst = archivesFirst == 1
|
||||
e PhysicsFS.set_sane_config(org, appname, ext, includeCdroms, archivesFirst)
|
||||
end
|
||||
|
||||
def mkdir_cmd dir
|
||||
e PhysicsFS.mkdir(dir)
|
||||
end
|
||||
|
||||
def delete_cmd dir
|
||||
e PhysicsFS.delete(dir)
|
||||
end
|
||||
|
||||
def getrealdir_cmd file
|
||||
dir = PhysicsFS.real_dir file
|
||||
if dir
|
||||
puts "Found at [#{dir}]"
|
||||
else
|
||||
puts "Not found."
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def exists_cmd file
|
||||
if PhysicsFS.exists? file
|
||||
puts "File exists"
|
||||
else
|
||||
puts "File does not exist"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def isdir_cmd file
|
||||
if PhysicsFS.is_directory? file
|
||||
puts "File is a directory"
|
||||
else
|
||||
puts "File is NOT a directory"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def issymlink_cmd file
|
||||
if PhysicsFS.is_symlink? file
|
||||
puts "File is a symlink"
|
||||
else
|
||||
puts "File is NOT a symlink"
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def cat_cmd filename
|
||||
file = PhysicsFS.open_read filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
puts file.cat
|
||||
true
|
||||
end
|
||||
|
||||
def filelength_cmd filename
|
||||
file = PhysicsFS.open_read filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
puts file.length
|
||||
file.close
|
||||
true
|
||||
end
|
||||
|
||||
WRITE_STR = "Rubyfied PhysicsFS works just fine.\n\n"
|
||||
|
||||
def append_cmd filename
|
||||
file = PhysicsFS.open_append filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
file.write WRITE_STR, 1, WRITE_STR.length
|
||||
file.close
|
||||
true
|
||||
end
|
||||
|
||||
def write_cmd filename
|
||||
file = PhysicsFS.open_write filename
|
||||
if file.nil?
|
||||
puts "failed to open. reason: #{PhysicsFS.last_error}"
|
||||
return true
|
||||
end
|
||||
|
||||
file.write_str WRITE_STR
|
||||
file.close
|
||||
true
|
||||
end
|
||||
|
||||
def getlastmodtime_cmd filename
|
||||
t = PhysicsFS.last_mod_time filename
|
||||
if t == -1
|
||||
puts "failed to determin. reason: #{PhysicsFS.last_error}"
|
||||
else
|
||||
puts "Last modified: #{Time.at(t)}"
|
||||
end
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
include Commands
|
||||
|
||||
def run command, args
|
||||
if args
|
||||
args = parse_args args
|
||||
else
|
||||
args = []
|
||||
end
|
||||
|
||||
begin
|
||||
cmd = method "#{command}_cmd"
|
||||
if args.length == cmd.arity
|
||||
return cmd.call *args
|
||||
else
|
||||
usage command
|
||||
true
|
||||
end
|
||||
rescue NameError
|
||||
puts 'Unknown command. Enter "help" for instructions.'
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
if __FILE__ == $0
|
||||
|
||||
PhysicsFS.init($0) or die "PhysicsFS init failed"
|
||||
|
||||
puts "PhysicsFS version: #{PhysicsFS.version}"
|
||||
puts
|
||||
|
||||
puts "Supported archives: "
|
||||
puts PhysicsFS.supported_archives
|
||||
puts
|
||||
|
||||
puts 'Enter commands. Enter "help" for instructions.'
|
||||
|
||||
loop {
|
||||
line = Readline::readline "physfs_rb> ", true
|
||||
break unless parse line
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
* ./physfshttpd archive1.zip archive2.zip /path/to/a/real/dir etc...
|
||||
*
|
||||
* The files are appended in order to the PhysicsFS search path, and when
|
||||
* a client request comes it, it looks for the file in said search path.
|
||||
* a client request comes in, it looks for the file in said search path.
|
||||
*
|
||||
* My goal was to make this work in less than 300 lines of C, so again, it's
|
||||
* not to be used for any serious purpose. Patches to make this application
|
||||
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
@ -54,7 +55,7 @@
|
|||
#include "physfs.h"
|
||||
|
||||
|
||||
#define DEFAULT_PORTNUM 6667
|
||||
#define DEFAULT_PORTNUM 8080
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -64,45 +65,153 @@ typedef struct
|
|||
} http_args;
|
||||
|
||||
|
||||
static char *txt404 =
|
||||
"HTTP/1.0 404 Not Found\n"
|
||||
"Connection: close\n"
|
||||
"Content-Type: text/html; charset=utf-8\n"
|
||||
"\n"
|
||||
"<html><head><title>404 Not Found</title></head>\n"
|
||||
"<body>Can't find that.</body></html>\n\n";
|
||||
#define txt404 \
|
||||
"HTTP/1.0 404 Not Found\n" \
|
||||
"Connection: close\n" \
|
||||
"Content-Type: text/html; charset=utf-8\n" \
|
||||
"\n" \
|
||||
"<html><head><title>404 Not Found</title></head>\n" \
|
||||
"<body>Can't find '%s'.</body></html>\n\n" \
|
||||
|
||||
#define txt200 \
|
||||
"HTTP/1.0 200 OK\n" \
|
||||
"Connection: close\n" \
|
||||
"Content-Type: %s\n" \
|
||||
"\n"
|
||||
|
||||
static const char *lastError(void)
|
||||
{
|
||||
return PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
|
||||
} /* lastError */
|
||||
|
||||
static int writeAll(const char *ipstr, const int sock, void *buf, const size_t len)
|
||||
{
|
||||
if (write(sock, buf, len) != len)
|
||||
{
|
||||
printf("%s: Write error to socket.\n", ipstr);
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
return 1;
|
||||
} /* writeAll */
|
||||
|
||||
static int writeString(const char *ipstr, const int sock, const char *fmt, ...)
|
||||
{
|
||||
/* none of this is robust against large strings or HTML escaping. */
|
||||
char buffer[1024];
|
||||
int len;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buffer, sizeof (buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
if (len < 0)
|
||||
{
|
||||
printf("uhoh, vsnprintf() failed!\n");
|
||||
return 0;
|
||||
} /* if */
|
||||
|
||||
return writeAll(ipstr, sock, buffer, len);
|
||||
} /* writeString */
|
||||
|
||||
|
||||
static void feed_file_http(const char *ipstr, int sock, const char *fname)
|
||||
{
|
||||
PHYSFS_File *in = PHYSFS_openRead(fname);
|
||||
char buffer[1024];
|
||||
printf("%s: requested [%s].\n", ipstr, fname);
|
||||
|
||||
if (in == NULL)
|
||||
{
|
||||
printf("%s: Can't open [%s]: %s.\n",
|
||||
ipstr, fname, PHYSFS_getLastError());
|
||||
write(sock, txt404, strlen(txt404)); /* !!! FIXME: Check retval */
|
||||
printf("%s: Can't open [%s]: %s.\n", ipstr, fname, lastError());
|
||||
writeString(ipstr, sock, txt404, fname);
|
||||
return;
|
||||
} /* if */
|
||||
else
|
||||
|
||||
/* !!! FIXME: mimetype */
|
||||
if (writeString(ipstr, sock, txt200, "text/plain; charset=utf-8"))
|
||||
{
|
||||
do
|
||||
{
|
||||
PHYSFS_sint64 br = PHYSFS_read(in, buffer, 1, sizeof (buffer));
|
||||
char buffer[1024];
|
||||
PHYSFS_sint64 br = PHYSFS_readBytes(in, buffer, sizeof (buffer));
|
||||
if (br == -1)
|
||||
{
|
||||
printf("%s: Read error: %s.\n", ipstr, PHYSFS_getLastError());
|
||||
printf("%s: Read error: %s.\n", ipstr, lastError());
|
||||
break;
|
||||
} /* if */
|
||||
|
||||
write(sock, buffer, (int) br); /* !!! FIXME: CHECK THIS RETVAL! */
|
||||
else if (!writeAll(ipstr, sock, buffer, (size_t) br))
|
||||
{
|
||||
break;
|
||||
} /* else if */
|
||||
} while (!PHYSFS_eof(in));
|
||||
} /* if */
|
||||
|
||||
PHYSFS_close(in);
|
||||
} /* else */
|
||||
} /* feed_file_http */
|
||||
|
||||
|
||||
static void feed_dirlist_http(const char *ipstr, int sock,
|
||||
const char *dname, char **list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!writeString(ipstr, sock, txt200, "text/html; charset=utf-8"))
|
||||
return;
|
||||
|
||||
else if (!writeString(ipstr, sock,
|
||||
"<html><head><title>Directory %s</title></head>"
|
||||
"<body><p><h1>Directory %s</h1></p><p><ul>\n",
|
||||
dname, dname))
|
||||
return;
|
||||
|
||||
if (strcmp(dname, "/") == 0)
|
||||
dname = "";
|
||||
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
const char *fname = list[i];
|
||||
if (!writeString(ipstr, sock,
|
||||
"<li><a href='%s/%s'>%s</a></li>\n", dname, fname, fname))
|
||||
break;
|
||||
} /* for */
|
||||
|
||||
writeString(ipstr, sock, "</ul></body></html>\n");
|
||||
} /* feed_dirlist_http */
|
||||
|
||||
static void feed_dir_http(const char *ipstr, int sock, const char *dname)
|
||||
{
|
||||
char **list = PHYSFS_enumerateFiles(dname);
|
||||
if (list == NULL)
|
||||
{
|
||||
printf("%s: Can't enumerate directory [%s]: %s.\n",
|
||||
ipstr, dname, lastError());
|
||||
writeString(ipstr, sock, txt404, dname);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
feed_dirlist_http(ipstr, sock, dname, list);
|
||||
PHYSFS_freeList(list);
|
||||
} /* feed_dir_http */
|
||||
|
||||
static void feed_http_request(const char *ipstr, int sock, const char *fname)
|
||||
{
|
||||
PHYSFS_Stat statbuf;
|
||||
|
||||
printf("%s: requested [%s].\n", ipstr, fname);
|
||||
|
||||
if (!PHYSFS_stat(fname, &statbuf))
|
||||
{
|
||||
printf("%s: Can't stat [%s]: %s.\n", ipstr, fname, lastError());
|
||||
writeString(ipstr, sock, txt404, fname);
|
||||
return;
|
||||
} /* if */
|
||||
|
||||
if (statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY)
|
||||
feed_dir_http(ipstr, sock, fname);
|
||||
else
|
||||
feed_file_http(ipstr, sock, fname);
|
||||
} /* feed_http_request */
|
||||
|
||||
|
||||
static void *do_http(void *_args)
|
||||
{
|
||||
http_args *args = (http_args *) _args;
|
||||
|
@ -135,7 +244,7 @@ static void *do_http(void *_args)
|
|||
ptr = strchr(buffer + 5, ' ');
|
||||
if (ptr != NULL)
|
||||
*ptr = '\0';
|
||||
feed_file_http(ipstr, args->sock, buffer + 4);
|
||||
feed_http_request(ipstr, args->sock, buffer + 4);
|
||||
} /* if */
|
||||
} /* else */
|
||||
|
||||
|
@ -144,7 +253,7 @@ static void *do_http(void *_args)
|
|||
close(args->sock);
|
||||
free(args->addr);
|
||||
free(args);
|
||||
return(NULL);
|
||||
return NULL;
|
||||
} /* do_http */
|
||||
|
||||
|
||||
|
@ -156,14 +265,14 @@ static void serve_http_request(int sock, struct sockaddr *addr,
|
|||
{
|
||||
printf("out of memory.\n");
|
||||
return;
|
||||
} // if
|
||||
} /* if */
|
||||
args->addr = (struct sockaddr *) malloc(addrlen);
|
||||
if (args->addr == NULL)
|
||||
{
|
||||
free(args);
|
||||
printf("out of memory.\n");
|
||||
return;
|
||||
} // if
|
||||
} /* if */
|
||||
|
||||
args->sock = sock;
|
||||
args->addrlen = addrlen;
|
||||
|
@ -194,7 +303,7 @@ static int create_listen_socket(short portnum)
|
|||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(portnum);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if ((bind(retval, &addr, (socklen_t) sizeof (addr)) == -1) ||
|
||||
if ((bind(retval, (struct sockaddr *) &addr, (socklen_t) sizeof (addr)) == -1) ||
|
||||
(listen(retval, 5) == -1))
|
||||
{
|
||||
close(retval);
|
||||
|
@ -202,7 +311,7 @@ static int create_listen_socket(short portnum)
|
|||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return(retval);
|
||||
return retval;
|
||||
} /* create_listen_socket */
|
||||
|
||||
|
||||
|
@ -219,7 +328,7 @@ void at_exit_cleanup(void)
|
|||
close(listensocket);
|
||||
|
||||
if (!PHYSFS_deinit())
|
||||
printf("PHYSFS_deinit() failed: %s\n", PHYSFS_getLastError());
|
||||
printf("PHYSFS_deinit() failed: %s\n", lastError());
|
||||
} /* at_exit_cleanup */
|
||||
|
||||
|
||||
|
@ -244,13 +353,13 @@ int main(int argc, char **argv)
|
|||
if (argc == 1)
|
||||
{
|
||||
printf("USAGE: %s <archive1> [archive2 [... archiveN]]\n", argv[0]);
|
||||
return(42);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
printf("PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
|
||||
return(42);
|
||||
printf("PHYSFS_init() failed: %s\n", lastError());
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
/* normally, this is bad practice, but oh well. */
|
||||
|
@ -258,7 +367,7 @@ int main(int argc, char **argv)
|
|||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!PHYSFS_addToSearchPath(argv[i], 1))
|
||||
if (!PHYSFS_mount(argv[i], NULL, 1))
|
||||
printf(" WARNING: failed to add [%s] to search path.\n", argv[i]);
|
||||
} /* else */
|
||||
|
||||
|
@ -266,7 +375,7 @@ int main(int argc, char **argv)
|
|||
if (listensocket < 0)
|
||||
{
|
||||
printf("listen socket failed to create.\n");
|
||||
return(42);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
while (1) /* infinite loop for now. */
|
||||
|
@ -278,13 +387,13 @@ int main(int argc, char **argv)
|
|||
{
|
||||
printf("accept() failed: %s\n", strerror(errno));
|
||||
close(listensocket);
|
||||
return(42);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
serve_http_request(s, &addr, len);
|
||||
} /* while */
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
/* end of physfshttpd.c ... */
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/
|
||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
||||
* You can get SDL at https://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
@ -23,102 +24,156 @@
|
|||
#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */
|
||||
#include "physfsrwops.h"
|
||||
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
/* SDL's RWOPS interface changed a little in SDL 2.0... */
|
||||
#if defined(SDL_VERSION_ATLEAST)
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#define TARGET_SDL2 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !TARGET_SDL2
|
||||
#ifndef RW_SEEK_SET
|
||||
#define RW_SEEK_SET SEEK_SET
|
||||
#endif
|
||||
#ifndef RW_SEEK_CUR
|
||||
#define RW_SEEK_CUR SEEK_CUR
|
||||
#endif
|
||||
#ifndef RW_SEEK_END
|
||||
#define RW_SEEK_END SEEK_END
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TARGET_SDL2
|
||||
static Sint64 SDLCALL physfsrwops_size(struct SDL_RWops *rw)
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
int pos = 0;
|
||||
return (Sint64) PHYSFS_fileLength(handle);
|
||||
} /* physfsrwops_size */
|
||||
#endif
|
||||
|
||||
if (whence == SEEK_SET)
|
||||
{
|
||||
pos = offset;
|
||||
} /* if */
|
||||
|
||||
else if (whence == SEEK_CUR)
|
||||
#if TARGET_SDL2
|
||||
static Sint64 SDLCALL physfsrwops_seek(struct SDL_RWops *rw, Sint64 offset, int whence)
|
||||
#else
|
||||
static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 pos = 0;
|
||||
|
||||
if (whence == RW_SEEK_SET)
|
||||
pos = (PHYSFS_sint64) offset;
|
||||
|
||||
else if (whence == RW_SEEK_CUR)
|
||||
{
|
||||
PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
const PHYSFS_sint64 current = PHYSFS_tell(handle);
|
||||
if (current == -1)
|
||||
{
|
||||
SDL_SetError("Can't find position in file: %s",
|
||||
PHYSFS_getLastError());
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos = (int) current;
|
||||
if ( ((PHYSFS_sint64) pos) != current )
|
||||
{
|
||||
SDL_SetError("Can't fit current file position in an int!");
|
||||
return(-1);
|
||||
PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
if (offset == 0) /* this is a "tell" call. We're done. */
|
||||
return(pos);
|
||||
{
|
||||
#if TARGET_SDL2
|
||||
return (Sint64) current;
|
||||
#else
|
||||
return (int) current;
|
||||
#endif
|
||||
} /* if */
|
||||
|
||||
pos += offset;
|
||||
pos = current + ((PHYSFS_sint64) offset);
|
||||
} /* else if */
|
||||
|
||||
else if (whence == SEEK_END)
|
||||
else if (whence == RW_SEEK_END)
|
||||
{
|
||||
PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
const PHYSFS_sint64 len = PHYSFS_fileLength(handle);
|
||||
if (len == -1)
|
||||
{
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
SDL_SetError("Can't find end of file: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
pos = (int) len;
|
||||
if ( ((PHYSFS_sint64) pos) != len )
|
||||
{
|
||||
SDL_SetError("Can't fit end-of-file position in an int!");
|
||||
return(-1);
|
||||
} /* if */
|
||||
|
||||
pos += offset;
|
||||
pos = len + ((PHYSFS_sint64) offset);
|
||||
} /* else if */
|
||||
|
||||
else
|
||||
{
|
||||
SDL_SetError("Invalid 'whence' parameter.");
|
||||
return(-1);
|
||||
return -1;
|
||||
} /* else */
|
||||
|
||||
if ( pos < 0 )
|
||||
{
|
||||
SDL_SetError("Attempt to seek past start of file.");
|
||||
return(-1);
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
return(pos);
|
||||
#if TARGET_SDL2
|
||||
return (Sint64) pos;
|
||||
#else
|
||||
return (int) pos;
|
||||
#endif
|
||||
} /* physfsrwops_seek */
|
||||
|
||||
|
||||
#if TARGET_SDL2
|
||||
static size_t SDLCALL physfsrwops_read(struct SDL_RWops *rw, void *ptr,
|
||||
size_t size, size_t maxnum)
|
||||
#else
|
||||
static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum);
|
||||
if (rc != maxnum)
|
||||
const PHYSFS_uint64 readlen = (PHYSFS_uint64) (maxnum * size);
|
||||
const PHYSFS_sint64 rc = PHYSFS_readBytes(handle, ptr, readlen);
|
||||
if (rc != ((PHYSFS_sint64) readlen))
|
||||
{
|
||||
if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
||||
#if TARGET_SDL2
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
return((int) rc);
|
||||
#if TARGET_SDL2
|
||||
return (size_t) rc / size;
|
||||
#else
|
||||
return (int) rc / size;
|
||||
#endif
|
||||
} /* physfsrwops_read */
|
||||
|
||||
|
||||
#if TARGET_SDL2
|
||||
static size_t SDLCALL physfsrwops_write(struct SDL_RWops *rw, const void *ptr,
|
||||
size_t size, size_t num)
|
||||
#else
|
||||
static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num)
|
||||
#endif
|
||||
{
|
||||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num);
|
||||
if (rc != num)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
const PHYSFS_uint64 writelen = (PHYSFS_uint64) (num * size);
|
||||
const PHYSFS_sint64 rc = PHYSFS_writeBytes(handle, ptr, writelen);
|
||||
if (rc != ((PHYSFS_sint64) writelen))
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
||||
return((int) rc);
|
||||
#if TARGET_SDL2
|
||||
return (size_t) rc;
|
||||
#else
|
||||
return (int) rc;
|
||||
#endif
|
||||
} /* physfsrwops_write */
|
||||
|
||||
|
||||
|
@ -127,12 +182,12 @@ static int physfsrwops_close(SDL_RWops *rw)
|
|||
PHYSFS_File *handle = (PHYSFS_File *) rw->hidden.unknown.data1;
|
||||
if (!PHYSFS_close(handle))
|
||||
{
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
return(-1);
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return -1;
|
||||
} /* if */
|
||||
|
||||
SDL_FreeRW(rw);
|
||||
return(0);
|
||||
return 0;
|
||||
} /* physfsrwops_close */
|
||||
|
||||
|
||||
|
@ -141,12 +196,15 @@ static SDL_RWops *create_rwops(PHYSFS_File *handle)
|
|||
SDL_RWops *retval = NULL;
|
||||
|
||||
if (handle == NULL)
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError());
|
||||
SDL_SetError("PhysicsFS error: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
else
|
||||
{
|
||||
retval = SDL_AllocRW();
|
||||
if (retval != NULL)
|
||||
{
|
||||
#if TARGET_SDL2
|
||||
retval->size = physfsrwops_size;
|
||||
#endif
|
||||
retval->seek = physfsrwops_seek;
|
||||
retval->read = physfsrwops_read;
|
||||
retval->write = physfsrwops_write;
|
||||
|
@ -155,7 +213,7 @@ static SDL_RWops *create_rwops(PHYSFS_File *handle)
|
|||
} /* if */
|
||||
} /* else */
|
||||
|
||||
return(retval);
|
||||
return retval;
|
||||
} /* create_rwops */
|
||||
|
||||
|
||||
|
@ -167,25 +225,25 @@ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle)
|
|||
else
|
||||
retval = create_rwops(handle);
|
||||
|
||||
return(retval);
|
||||
return retval;
|
||||
} /* PHYSFSRWOPS_makeRWops */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openRead(const char *fname)
|
||||
{
|
||||
return(create_rwops(PHYSFS_openRead(fname)));
|
||||
return create_rwops(PHYSFS_openRead(fname));
|
||||
} /* PHYSFSRWOPS_openRead */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname)
|
||||
{
|
||||
return(create_rwops(PHYSFS_openWrite(fname)));
|
||||
return create_rwops(PHYSFS_openWrite(fname));
|
||||
} /* PHYSFSRWOPS_openWrite */
|
||||
|
||||
|
||||
SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname)
|
||||
{
|
||||
return(create_rwops(PHYSFS_openAppend(fname)));
|
||||
return create_rwops(PHYSFS_openAppend(fname));
|
||||
} /* PHYSFSRWOPS_openAppend */
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
* Unless otherwise stated, the rest of PhysicsFS falls under the zlib license.
|
||||
* Please see LICENSE.txt in the root of the source tree.
|
||||
*
|
||||
* SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/
|
||||
* SDL 1.2 falls under the LGPL license. SDL 1.3+ is zlib, like PhysicsFS.
|
||||
* You can get SDL at https://www.libsdl.org/
|
||||
*
|
||||
* This file was written by Ryan C. Gordon. (icculus@icculus.org).
|
||||
*/
|
||||
|
@ -40,7 +41,7 @@ extern "C" {
|
|||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for writing, and make it accessible
|
||||
|
@ -52,7 +53,7 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname);
|
|||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
||||
|
||||
/**
|
||||
* Open a platform-independent filename for appending, and make it accessible
|
||||
|
@ -64,7 +65,7 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname);
|
|||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
||||
|
||||
/**
|
||||
* Make a SDL_RWops from an existing PhysicsFS file handle. You should
|
||||
|
@ -76,7 +77,7 @@ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname);
|
|||
* @return A valid SDL_RWops structure on success, NULL on error. Specifics
|
||||
* of the error can be gleaned from PHYSFS_getLastError().
|
||||
*/
|
||||
__EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle);
|
||||
PHYSFS_DECL SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_File *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ static void modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize)
|
|||
static void fail(const char *what, const char *why)
|
||||
{
|
||||
if (why == NULL)
|
||||
why = PHYSFS_getLastError();
|
||||
why = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode());
|
||||
fprintf(stderr, "%s failed: %s\n", what, why);
|
||||
failure = 1;
|
||||
} /* fail */
|
||||
|
@ -150,21 +150,21 @@ int main(int argc, char **argv)
|
|||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
|
||||
fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 2;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_setWriteDir(argv[2]))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_setWriteDir('%s') failed: %s\n",
|
||||
argv[2], PHYSFS_getLastError());
|
||||
argv[2], PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 3;
|
||||
} /* if */
|
||||
|
||||
if (!PHYSFS_mount(argv[1], NULL, 1))
|
||||
{
|
||||
fprintf(stderr, "PHYSFS_mount('%s') failed: %s\n",
|
||||
argv[1], PHYSFS_getLastError());
|
||||
argv[1], PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 4;
|
||||
} /* if */
|
||||
|
||||
|
|
|
@ -40,16 +40,16 @@ int main(int argc, char **argv)
|
|||
|
||||
if (!PHYSFS_init(argv[0]))
|
||||
{
|
||||
printf("PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
|
||||
return(42);
|
||||
printf("PHYSFS_init() failed: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
rc = PHYSFS_addToSearchPath(argv[0], 0);
|
||||
if (!rc)
|
||||
{
|
||||
printf("Couldn't find self-extract data: %s\n", PHYSFS_getLastError());
|
||||
printf("Couldn't find self-extract data: %s\n", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
printf("This might mean you didn't append a zipfile to the binary.\n");
|
||||
return(42);
|
||||
return 42;
|
||||
} /* if */
|
||||
|
||||
char **files = PHYSFS_enumerateFiles("/");
|
||||
|
@ -61,6 +61,6 @@ int main(int argc, char **argv)
|
|||
} /* for */
|
||||
PHYSFS_freeList(files);
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ ! -f "./install_manifest.txt" ]; then
|
||||
echo "ERROR: This needs to be run from your CMake build directory after installing." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
xargs rm -vf < install_manifest.txt
|
||||
exit 0
|
||||
|
237
lzma/7zC.txt
237
lzma/7zC.txt
|
@ -1,237 +0,0 @@
|
|||
7z ANSI-C Decoder 4.48
|
||||
----------------------
|
||||
|
||||
7z ANSI-C Decoder 4.48 Copyright (C) 1999-2006 Igor Pavlov
|
||||
|
||||
7z ANSI-C provides 7z/LZMA decoding.
|
||||
7z ANSI-C version is simplified version ported from C++ code.
|
||||
|
||||
LZMA is default and general compression method of 7z format
|
||||
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
||||
compression ratio and very fast decompression.
|
||||
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
Read lzma.txt for information about license.
|
||||
|
||||
|
||||
Files
|
||||
---------------------
|
||||
|
||||
7zAlloc.* - Allocate and Free
|
||||
7zBuffer.* - Buffer structure
|
||||
7zCrc.* - CRC32 code
|
||||
7zDecode.* - Low level memory->memory decoding
|
||||
7zExtract.* - High level stream->memory decoding
|
||||
7zHeader.* - .7z format constants
|
||||
7zIn.* - .7z archive opening
|
||||
7zItem.* - .7z structures
|
||||
7zMain.c - Test application
|
||||
7zMethodID.* - MethodID structure
|
||||
7zTypes.h - Base types and constants
|
||||
|
||||
|
||||
How To Use
|
||||
----------
|
||||
|
||||
You must download 7-Zip program from www.7-zip.org.
|
||||
|
||||
You can create .7z archive with 7z.exe or 7za.exe:
|
||||
|
||||
7za.exe a archive.7z *.htm -r -mx -m0fb=255
|
||||
|
||||
If you have big number of files in archive, and you need fast extracting,
|
||||
you can use partly-solid archives:
|
||||
|
||||
7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
|
||||
|
||||
In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
|
||||
512KB for extracting one file from such archive.
|
||||
|
||||
|
||||
Limitations of current version of 7z ANSI-C Decoder
|
||||
---------------------------------------------------
|
||||
|
||||
- It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
|
||||
- It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
|
||||
- It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
|
||||
|
||||
These limitations will be fixed in future versions.
|
||||
|
||||
|
||||
Using 7z ANSI-C Decoder Test application:
|
||||
-----------------------------------------
|
||||
|
||||
Usage: 7zDec <command> <archive_name>
|
||||
|
||||
<Command>:
|
||||
e: Extract files from archive
|
||||
l: List contents of archive
|
||||
t: Test integrity of archive
|
||||
|
||||
Example:
|
||||
|
||||
7zDec l archive.7z
|
||||
|
||||
lists contents of archive.7z
|
||||
|
||||
7zDec e archive.7z
|
||||
|
||||
extracts files from archive.7z to current folder.
|
||||
|
||||
|
||||
How to use .7z Decoder
|
||||
----------------------
|
||||
|
||||
.7z Decoder can be compiled in one of two modes:
|
||||
|
||||
1) Default mode. In that mode 7z Decoder will read full compressed
|
||||
block to RAM before decompressing.
|
||||
|
||||
2) Mode with defined _LZMA_IN_CB. In that mode 7z Decoder can read
|
||||
compressed block by parts. And you can specify desired buffer size.
|
||||
So memory requirements can be reduced. But decompressing speed will
|
||||
be 5-10% lower and code size is slightly larger.
|
||||
|
||||
|
||||
Memory allocation
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
7z Decoder uses two memory pools:
|
||||
1) Temporary pool
|
||||
2) Main pool
|
||||
Such scheme can allow you to avoid fragmentation of allocated blocks.
|
||||
|
||||
Steps for using 7z decoder
|
||||
--------------------------
|
||||
|
||||
Use code at 7zMain.c as example.
|
||||
|
||||
1) Declare variables:
|
||||
inStream /* implements ISzInStream interface */
|
||||
CArchiveDatabaseEx db; /* 7z archive database structure */
|
||||
ISzAlloc allocImp; /* memory functions for main pool */
|
||||
ISzAlloc allocTempImp; /* memory functions for temporary pool */
|
||||
|
||||
2) call InitCrcTable(); function to initialize CRC structures.
|
||||
|
||||
3) call SzArDbExInit(&db); function to initialize db structures.
|
||||
|
||||
4) call SzArchiveOpen(inStream, &db, &allocMain, &allocTemp) to open archive
|
||||
|
||||
This function opens archive "inStream" and reads headers to "db".
|
||||
All items in "db" will be allocated with "allocMain" functions.
|
||||
SzArchiveOpen function allocates and frees temporary structures by "allocTemp" functions.
|
||||
|
||||
5) List items or Extract items
|
||||
|
||||
Listing code:
|
||||
~~~~~~~~~~~~~
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < db.Database.NumFiles; i++)
|
||||
{
|
||||
CFileItem *f = db.Database.Files + i;
|
||||
printf("%10d %s\n", (int)f->Size, f->Name);
|
||||
}
|
||||
}
|
||||
|
||||
Extracting code:
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
SZ_RESULT SzExtract(
|
||||
ISzInStream *inStream,
|
||||
CArchiveDatabaseEx *db,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
If you need to decompress more than one file, you can send these values from previous call:
|
||||
blockIndex,
|
||||
outBuffer,
|
||||
outBufferSize,
|
||||
You can consider "outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
After decompressing you must free "outBuffer":
|
||||
allocImp.Free(outBuffer);
|
||||
|
||||
6) call SzArDbExFree(&db, allocImp.Free) to free allocated items in "db".
|
||||
|
||||
|
||||
|
||||
|
||||
Memory requirements for .7z decoding
|
||||
------------------------------------
|
||||
|
||||
Memory usage for Archive opening:
|
||||
- Temporary pool:
|
||||
- Memory for compressed .7z headers (if _LZMA_IN_CB is not defined)
|
||||
- Memory for uncompressed .7z headers
|
||||
- some other temporary blocks
|
||||
- Main pool:
|
||||
- Memory for database:
|
||||
Estimated size of one file structures in solid archive:
|
||||
- Size (4 or 8 Bytes)
|
||||
- CRC32 (4 bytes)
|
||||
- LastWriteTime (8 bytes)
|
||||
- Some file information (4 bytes)
|
||||
- File Name (variable length) + pointer + allocation structures
|
||||
|
||||
Memory usage for archive Decompressing:
|
||||
- Temporary pool:
|
||||
- Memory for compressed solid block (if _LZMA_IN_CB is not defined)
|
||||
- Memory for LZMA decompressing structures
|
||||
- Main pool:
|
||||
- Memory for decompressed solid block
|
||||
- Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
|
||||
temprorary buffers can be about 15% of solid block size.
|
||||
|
||||
|
||||
If _LZMA_IN_CB is defined, 7z Decoder will not allocate memory for
|
||||
compressed blocks. Instead of this, you must allocate buffer with desired
|
||||
size before calling 7z Decoder. Use 7zMain.c as example.
|
||||
|
||||
|
||||
|
||||
EXIT codes
|
||||
-----------
|
||||
|
||||
7z Decoder functions can return one of the following codes:
|
||||
|
||||
#define SZ_OK (0)
|
||||
#define SZE_DATA_ERROR (1)
|
||||
#define SZE_OUTOFMEMORY (2)
|
||||
#define SZE_CRC_ERROR (3)
|
||||
|
||||
#define SZE_NOTIMPL (4)
|
||||
#define SZE_FAIL (5)
|
||||
|
||||
#define SZE_ARCHIVE_ERROR (6)
|
||||
|
||||
|
||||
|
||||
LZMA Defines
|
||||
------------
|
||||
|
||||
_LZMA_IN_CB - Use special callback mode for input stream to reduce memory requirements
|
||||
|
||||
_SZ_FILE_SIZE_32 - define it if you need only support for files smaller than 4 GB
|
||||
_SZ_NO_INT_64 - define it if your compiler doesn't support long long int or __int64.
|
||||
|
||||
_LZMA_PROB32 - it can increase LZMA decompressing speed on some 32-bit CPUs.
|
||||
|
||||
_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
|
||||
|
||||
|
||||
---
|
||||
|
||||
http://www.7-zip.org
|
||||
http://www.7-zip.org/support.html
|
|
@ -1,471 +0,0 @@
|
|||
7z Format description (2.30 Beta 25)
|
||||
-----------------------------------
|
||||
|
||||
This file contains description of 7z archive format.
|
||||
7z archive can contain files compressed with any method.
|
||||
See "Methods.txt" for description for defined compressing methods.
|
||||
|
||||
|
||||
Format structure Overview
|
||||
-------------------------
|
||||
|
||||
Some fields can be optional.
|
||||
|
||||
Archive structure
|
||||
~~~~~~~~~~~~~~~~~
|
||||
SignatureHeader
|
||||
[PackedStreams]
|
||||
[PackedStreamsForHeaders]
|
||||
[
|
||||
Header
|
||||
or
|
||||
{
|
||||
Packed Header
|
||||
HeaderInfo
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
|
||||
Header structure
|
||||
~~~~~~~~~~~~~~~~
|
||||
{
|
||||
ArchiveProperties
|
||||
AdditionalStreams
|
||||
{
|
||||
PackInfo
|
||||
{
|
||||
PackPos
|
||||
NumPackStreams
|
||||
Sizes[NumPackStreams]
|
||||
CRCs[NumPackStreams]
|
||||
}
|
||||
CodersInfo
|
||||
{
|
||||
NumFolders
|
||||
Folders[NumFolders]
|
||||
{
|
||||
NumCoders
|
||||
CodersInfo[NumCoders]
|
||||
{
|
||||
ID
|
||||
NumInStreams;
|
||||
NumOutStreams;
|
||||
PropertiesSize
|
||||
Properties[PropertiesSize]
|
||||
}
|
||||
NumBindPairs
|
||||
BindPairsInfo[NumBindPairs]
|
||||
{
|
||||
InIndex;
|
||||
OutIndex;
|
||||
}
|
||||
PackedIndices
|
||||
}
|
||||
UnPackSize[Folders][Folders.NumOutstreams]
|
||||
CRCs[NumFolders]
|
||||
}
|
||||
SubStreamsInfo
|
||||
{
|
||||
NumUnPackStreamsInFolders[NumFolders];
|
||||
UnPackSizes[]
|
||||
CRCs[]
|
||||
}
|
||||
}
|
||||
MainStreamsInfo
|
||||
{
|
||||
(Same as in AdditionalStreams)
|
||||
}
|
||||
FilesInfo
|
||||
{
|
||||
NumFiles
|
||||
Properties[]
|
||||
{
|
||||
ID
|
||||
Size
|
||||
Data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeaderInfo structure
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
{
|
||||
(Same as in AdditionalStreams)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Notes about Notation and encoding
|
||||
---------------------------------
|
||||
|
||||
7z uses little endian encoding.
|
||||
|
||||
7z archive format has optional headers that are marked as
|
||||
[]
|
||||
Header
|
||||
[]
|
||||
|
||||
REAL_UINT64 means real UINT64.
|
||||
|
||||
UINT64 means real UINT64 encoded with the following scheme:
|
||||
|
||||
Size of encoding sequence depends from first byte:
|
||||
First_Byte Extra_Bytes Value
|
||||
(binary)
|
||||
0xxxxxxx : ( xxxxxxx )
|
||||
10xxxxxx BYTE y[1] : ( xxxxxx << (8 * 1)) + y
|
||||
110xxxxx BYTE y[2] : ( xxxxx << (8 * 2)) + y
|
||||
...
|
||||
1111110x BYTE y[6] : ( x << (8 * 6)) + y
|
||||
11111110 BYTE y[7] : y
|
||||
11111111 BYTE y[8] : y
|
||||
|
||||
|
||||
|
||||
Property IDs
|
||||
------------
|
||||
|
||||
0x00 = kEnd,
|
||||
|
||||
0x01 = kHeader,
|
||||
|
||||
0x02 = kArchiveProperties,
|
||||
|
||||
0x03 = kAdditionalStreamsInfo,
|
||||
0x04 = kMainStreamsInfo,
|
||||
0x05 = kFilesInfo,
|
||||
|
||||
0x06 = kPackInfo,
|
||||
0x07 = kUnPackInfo,
|
||||
0x08 = kSubStreamsInfo,
|
||||
|
||||
0x09 = kSize,
|
||||
0x0A = kCRC,
|
||||
|
||||
0x0B = kFolder,
|
||||
|
||||
0x0C = kCodersUnPackSize,
|
||||
0x0D = kNumUnPackStream,
|
||||
|
||||
0x0E = kEmptyStream,
|
||||
0x0F = kEmptyFile,
|
||||
0x10 = kAnti,
|
||||
|
||||
0x11 = kName,
|
||||
0x12 = kCreationTime,
|
||||
0x13 = kLastAccessTime,
|
||||
0x14 = kLastWriteTime,
|
||||
0x15 = kWinAttributes,
|
||||
0x16 = kComment,
|
||||
|
||||
0x17 = kEncodedHeader,
|
||||
|
||||
|
||||
7z format headers
|
||||
-----------------
|
||||
|
||||
SignatureHeader
|
||||
~~~~~~~~~~~~~~~
|
||||
BYTE kSignature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||
|
||||
ArchiveVersion
|
||||
{
|
||||
BYTE Major; // now = 0
|
||||
BYTE Minor; // now = 2
|
||||
};
|
||||
|
||||
UINT32 StartHeaderCRC;
|
||||
|
||||
StartHeader
|
||||
{
|
||||
REAL_UINT64 NextHeaderOffset
|
||||
REAL_UINT64 NextHeaderSize
|
||||
UINT32 NextHeaderCRC
|
||||
}
|
||||
|
||||
|
||||
...........................
|
||||
|
||||
|
||||
ArchiveProperties
|
||||
~~~~~~~~~~~~~~~~~
|
||||
BYTE NID::kArchiveProperties (0x02)
|
||||
for (;;)
|
||||
{
|
||||
BYTE PropertyType;
|
||||
if (aType == 0)
|
||||
break;
|
||||
UINT64 PropertySize;
|
||||
BYTE PropertyData[PropertySize];
|
||||
}
|
||||
|
||||
|
||||
Digests (NumStreams)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
BYTE AllAreDefined
|
||||
if (AllAreDefined == 0)
|
||||
{
|
||||
for(NumStreams)
|
||||
BIT Defined
|
||||
}
|
||||
UINT32 CRCs[NumDefined]
|
||||
|
||||
|
||||
PackInfo
|
||||
~~~~~~~~~~~~
|
||||
BYTE NID::kPackInfo (0x06)
|
||||
UINT64 PackPos
|
||||
UINT64 NumPackStreams
|
||||
|
||||
[]
|
||||
BYTE NID::kSize (0x09)
|
||||
UINT64 PackSizes[NumPackStreams]
|
||||
[]
|
||||
|
||||
[]
|
||||
BYTE NID::kCRC (0x0A)
|
||||
PackStreamDigests[NumPackStreams]
|
||||
[]
|
||||
|
||||
BYTE NID::kEnd
|
||||
|
||||
|
||||
Folder
|
||||
~~~~~~
|
||||
UINT64 NumCoders;
|
||||
for (NumCoders)
|
||||
{
|
||||
BYTE
|
||||
{
|
||||
0:3 DecompressionMethod.IDSize
|
||||
4:
|
||||
0 - IsSimple
|
||||
1 - Is not simple
|
||||
5:
|
||||
0 - No Attributes
|
||||
1 - There Are Attributes
|
||||
7:
|
||||
0 - Last Method in Alternative_Method_List
|
||||
1 - There are more alternative methods
|
||||
}
|
||||
BYTE DecompressionMethod.ID[DecompressionMethod.IDSize]
|
||||
if (!IsSimple)
|
||||
{
|
||||
UINT64 NumInStreams;
|
||||
UINT64 NumOutStreams;
|
||||
}
|
||||
if (DecompressionMethod[0] != 0)
|
||||
{
|
||||
UINT64 PropertiesSize
|
||||
BYTE Properties[PropertiesSize]
|
||||
}
|
||||
}
|
||||
|
||||
NumBindPairs = NumOutStreamsTotal - 1;
|
||||
|
||||
for (NumBindPairs)
|
||||
{
|
||||
UINT64 InIndex;
|
||||
UINT64 OutIndex;
|
||||
}
|
||||
|
||||
NumPackedStreams = NumInStreamsTotal - NumBindPairs;
|
||||
if (NumPackedStreams > 1)
|
||||
for(NumPackedStreams)
|
||||
{
|
||||
UINT64 Index;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
Coders Info
|
||||
~~~~~~~~~~~
|
||||
|
||||
BYTE NID::kUnPackInfo (0x07)
|
||||
|
||||
|
||||
BYTE NID::kFolder (0x0B)
|
||||
UINT64 NumFolders
|
||||
BYTE External
|
||||
switch(External)
|
||||
{
|
||||
case 0:
|
||||
Folders[NumFolders]
|
||||
case 1:
|
||||
UINT64 DataStreamIndex
|
||||
}
|
||||
|
||||
|
||||
BYTE ID::kCodersUnPackSize (0x0C)
|
||||
for(Folders)
|
||||
for(Folder.NumOutStreams)
|
||||
UINT64 UnPackSize;
|
||||
|
||||
|
||||
[]
|
||||
BYTE NID::kCRC (0x0A)
|
||||
UnPackDigests[NumFolders]
|
||||
[]
|
||||
|
||||
|
||||
|
||||
BYTE NID::kEnd
|
||||
|
||||
|
||||
|
||||
SubStreams Info
|
||||
~~~~~~~~~~~~~~
|
||||
BYTE NID::kSubStreamsInfo; (0x08)
|
||||
|
||||
[]
|
||||
BYTE NID::kNumUnPackStream; (0x0D)
|
||||
UINT64 NumUnPackStreamsInFolders[NumFolders];
|
||||
[]
|
||||
|
||||
|
||||
[]
|
||||
BYTE NID::kSize (0x09)
|
||||
UINT64 UnPackSizes[]
|
||||
[]
|
||||
|
||||
|
||||
[]
|
||||
BYTE NID::kCRC (0x0A)
|
||||
Digests[Number of streams with unknown CRC]
|
||||
[]
|
||||
|
||||
|
||||
BYTE NID::kEnd
|
||||
|
||||
|
||||
Streams Info
|
||||
~~~~~~~~~~~~
|
||||
|
||||
[]
|
||||
PackInfo
|
||||
[]
|
||||
|
||||
|
||||
[]
|
||||
CodersInfo
|
||||
[]
|
||||
|
||||
|
||||
[]
|
||||
SubStreamsInfo
|
||||
[]
|
||||
|
||||
BYTE NID::kEnd
|
||||
|
||||
|
||||
FilesInfo
|
||||
~~~~~~~~~
|
||||
BYTE NID::kFilesInfo; (0x05)
|
||||
UINT64 NumFiles
|
||||
|
||||
for (;;)
|
||||
{
|
||||
BYTE PropertyType;
|
||||
if (aType == 0)
|
||||
break;
|
||||
|
||||
UINT64 Size;
|
||||
|
||||
switch(PropertyType)
|
||||
{
|
||||
kEmptyStream: (0x0E)
|
||||
for(NumFiles)
|
||||
BIT IsEmptyStream
|
||||
|
||||
kEmptyFile: (0x0F)
|
||||
for(EmptyStreams)
|
||||
BIT IsEmptyFile
|
||||
|
||||
kAnti: (0x10)
|
||||
for(EmptyStreams)
|
||||
BIT IsAntiFile
|
||||
|
||||
case kCreationTime: (0x12)
|
||||
case kLastAccessTime: (0x13)
|
||||
case kLastWriteTime: (0x14)
|
||||
BYTE AllAreDefined
|
||||
if (AllAreDefined == 0)
|
||||
{
|
||||
for(NumFiles)
|
||||
BIT TimeDefined
|
||||
}
|
||||
BYTE External;
|
||||
if(External != 0)
|
||||
UINT64 DataIndex
|
||||
[]
|
||||
for(Definded Items)
|
||||
UINT32 Time
|
||||
[]
|
||||
|
||||
kNames: (0x11)
|
||||
BYTE External;
|
||||
if(External != 0)
|
||||
UINT64 DataIndex
|
||||
[]
|
||||
for(Files)
|
||||
{
|
||||
wchar_t Names[NameSize];
|
||||
wchar_t 0;
|
||||
}
|
||||
[]
|
||||
|
||||
kAttributes: (0x15)
|
||||
BYTE AllAreDefined
|
||||
if (AllAreDefined == 0)
|
||||
{
|
||||
for(NumFiles)
|
||||
BIT AttributesAreDefined
|
||||
}
|
||||
BYTE External;
|
||||
if(External != 0)
|
||||
UINT64 DataIndex
|
||||
[]
|
||||
for(Definded Attributes)
|
||||
UINT32 Attributes
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Header
|
||||
~~~~~~
|
||||
BYTE NID::kHeader (0x01)
|
||||
|
||||
[]
|
||||
ArchiveProperties
|
||||
[]
|
||||
|
||||
[]
|
||||
BYTE NID::kAdditionalStreamsInfo; (0x03)
|
||||
StreamsInfo
|
||||
[]
|
||||
|
||||
[]
|
||||
BYTE NID::kMainStreamsInfo; (0x04)
|
||||
StreamsInfo
|
||||
[]
|
||||
|
||||
[]
|
||||
FilesInfo
|
||||
[]
|
||||
|
||||
BYTE NID::kEnd
|
||||
|
||||
|
||||
HeaderInfo
|
||||
~~~~~~~~~~
|
||||
[]
|
||||
BYTE NID::kEncodedHeader; (0x17)
|
||||
StreamsInfo for Encoded Header
|
||||
[]
|
||||
|
||||
|
||||
---
|
||||
End of document
|
|
@ -1,32 +0,0 @@
|
|||
/* 7zCrc.c */
|
||||
|
||||
#include "7zCrc.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
UInt32 g_CrcTable[256];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 ; size--, p++)
|
||||
v = CRC_UPDATE_BYTE(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/* 7zCrc.h */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
extern UInt32 g_CrcTable[];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void);
|
||||
|
||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
|
||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||
|
||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||
/* 7zCrcT8.c */
|
||||
|
||||
#include "7zCrc.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
#define CRC_NUM_TABLES 8
|
||||
|
||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable()
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
#if CRC_NUM_TABLES > 1
|
||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
UInt32 r = g_CrcTable[i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdateT8(v, data, size, g_CrcTable);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdateT8(CRC_INIT_VAL, data, size, g_CrcTable) ^ 0xFFFFFFFF;
|
||||
}
|
119
lzma/C/Alloc.c
119
lzma/C/Alloc.c
|
@ -1,119 +0,0 @@
|
|||
/* Alloc.c */
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Alloc.h"
|
||||
|
||||
/* #define _SZ_ALLOC_DEBUG */
|
||||
|
||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
#include <stdio.h>
|
||||
int g_allocCount = 0;
|
||||
int g_allocCountMid = 0;
|
||||
int g_allocCountBig = 0;
|
||||
#endif
|
||||
|
||||
void *MyAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++);
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void MyFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
fprintf(stderr, "\nFree; count = %10d", --g_allocCount);
|
||||
#endif
|
||||
free(address);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void *MidAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++);
|
||||
#endif
|
||||
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void MidFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid);
|
||||
#endif
|
||||
if (address == 0)
|
||||
return;
|
||||
VirtualFree(address, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#ifndef MEM_LARGE_PAGES
|
||||
#undef _7ZIP_LARGE_PAGES
|
||||
#endif
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
SIZE_T g_LargePageSize = 0;
|
||||
typedef SIZE_T (WINAPI *GetLargePageMinimumP)();
|
||||
#endif
|
||||
|
||||
void SetLargePageSize()
|
||||
{
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
SIZE_T size = 0;
|
||||
GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP)
|
||||
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum");
|
||||
if (largePageMinimum == 0)
|
||||
return;
|
||||
size = largePageMinimum();
|
||||
if (size == 0 || (size & (size - 1)) != 0)
|
||||
return;
|
||||
g_LargePageSize = size;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void *BigAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++);
|
||||
#endif
|
||||
|
||||
#ifdef _7ZIP_LARGE_PAGES
|
||||
if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18))
|
||||
{
|
||||
void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)),
|
||||
MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
|
||||
if (res != 0)
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void BigFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig);
|
||||
#endif
|
||||
|
||||
if (address == 0)
|
||||
return;
|
||||
VirtualFree(address, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
/* Alloc.h */
|
||||
|
||||
#ifndef __COMMON_ALLOC_H
|
||||
#define __COMMON_ALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void *MyAlloc(size_t size);
|
||||
void MyFree(void *address);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
void SetLargePageSize();
|
||||
|
||||
void *MidAlloc(size_t size);
|
||||
void MidFree(void *address);
|
||||
void *BigAlloc(size_t size);
|
||||
void BigFree(void *address);
|
||||
|
||||
#else
|
||||
|
||||
#define MidAlloc(size) MyAlloc(size)
|
||||
#define MidFree(address) MyFree(address)
|
||||
#define BigAlloc(size) MyAlloc(size)
|
||||
#define BigFree(address) MyFree(address)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
/* 7zAlloc.c */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "7zAlloc.h"
|
||||
|
||||
/* #define _SZ_ALLOC_DEBUG */
|
||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
int g_allocCount = 0;
|
||||
int g_allocCountTemp = 0;
|
||||
#endif
|
||||
|
||||
void *SzAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
||||
g_allocCount++;
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SzFree(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
{
|
||||
g_allocCount--;
|
||||
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
||||
}
|
||||
#endif
|
||||
free(address);
|
||||
}
|
||||
|
||||
void *SzAllocTemp(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
||||
g_allocCountTemp++;
|
||||
#ifdef _WIN32
|
||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||
#endif
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SzFreeTemp(void *address)
|
||||
{
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
{
|
||||
g_allocCountTemp--;
|
||||
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
HeapFree(GetProcessHeap(), 0, address);
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
free(address);
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
/* 7zAlloc.h */
|
||||
|
||||
#ifndef __7Z_ALLOC_H
|
||||
#define __7Z_ALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct _ISzAlloc
|
||||
{
|
||||
void *(*Alloc)(size_t size);
|
||||
void (*Free)(void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
|
||||
void *SzAlloc(size_t size);
|
||||
void SzFree(void *address);
|
||||
|
||||
void *SzAllocTemp(size_t size);
|
||||
void SzFreeTemp(void *address);
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
/* 7zBuffer.c */
|
||||
|
||||
#include "7zBuffer.h"
|
||||
#include "7zAlloc.h"
|
||||
|
||||
void SzByteBufferInit(CSzByteBuffer *buffer)
|
||||
{
|
||||
buffer->Capacity = 0;
|
||||
buffer->Items = 0;
|
||||
}
|
||||
|
||||
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size))
|
||||
{
|
||||
buffer->Capacity = newCapacity;
|
||||
if (newCapacity == 0)
|
||||
{
|
||||
buffer->Items = 0;
|
||||
return 1;
|
||||
}
|
||||
buffer->Items = (Byte *)allocFunc(newCapacity);
|
||||
return (buffer->Items != 0);
|
||||
}
|
||||
|
||||
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *))
|
||||
{
|
||||
freeFunc(buffer->Items);
|
||||
buffer->Items = 0;
|
||||
buffer->Capacity = 0;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/* 7zBuffer.h */
|
||||
|
||||
#ifndef __7Z_BUFFER_H
|
||||
#define __7Z_BUFFER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "../../Types.h"
|
||||
|
||||
typedef struct _CSzByteBuffer
|
||||
{
|
||||
size_t Capacity;
|
||||
Byte *Items;
|
||||
}CSzByteBuffer;
|
||||
|
||||
void SzByteBufferInit(CSzByteBuffer *buffer);
|
||||
int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size));
|
||||
void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *));
|
||||
|
||||
#endif
|
|
@ -1,341 +0,0 @@
|
|||
/* 7zDecode.c */
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#include "7zDecode.h"
|
||||
#ifdef _SZ_ONE_DIRECTORY
|
||||
#include "LzmaDecode.h"
|
||||
#else
|
||||
#include "../../Compress/Lzma/LzmaDecode.h"
|
||||
#include "../../Compress/Branch/BranchX86.h"
|
||||
#include "../../Compress/Branch/BranchX86_2.h"
|
||||
#endif
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_BCJ2 0x0303011B
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
|
||||
typedef struct _CLzmaInCallbackImp
|
||||
{
|
||||
ILzmaInCallback InCallback;
|
||||
ISzInStream *InStream;
|
||||
CFileSize Size;
|
||||
} CLzmaInCallbackImp;
|
||||
|
||||
int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size)
|
||||
{
|
||||
CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
|
||||
size_t processedSize;
|
||||
SZ_RESULT res;
|
||||
size_t curSize = (1 << 20);
|
||||
if (curSize > cb->Size)
|
||||
curSize = (size_t)cb->Size;
|
||||
*size = 0;
|
||||
res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, curSize, &processedSize);
|
||||
*size = (SizeT)processedSize;
|
||||
if (processedSize > curSize)
|
||||
return (int)SZE_FAIL;
|
||||
cb->Size -= processedSize;
|
||||
if (res == SZ_OK)
|
||||
return 0;
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SZ_RESULT SzDecodeLzma(CCoderInfo *coder, CFileSize inSize,
|
||||
#ifdef _LZMA_IN_CB
|
||||
ISzInStream *inStream,
|
||||
#else
|
||||
const Byte *inBuffer,
|
||||
#endif
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
#ifdef _LZMA_IN_CB
|
||||
CLzmaInCallbackImp lzmaCallback;
|
||||
#else
|
||||
SizeT inProcessed;
|
||||
#endif
|
||||
|
||||
CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
|
||||
int result;
|
||||
SizeT outSizeProcessedLoc;
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
lzmaCallback.Size = inSize;
|
||||
lzmaCallback.InStream = inStream;
|
||||
lzmaCallback.InCallback.Read = LzmaReadImp;
|
||||
#endif
|
||||
|
||||
if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
|
||||
(unsigned)coder->Properties.Capacity) != LZMA_RESULT_OK)
|
||||
return SZE_FAIL;
|
||||
|
||||
state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
|
||||
if (state.Probs == 0)
|
||||
return SZE_OUTOFMEMORY;
|
||||
|
||||
#ifdef _LZMA_OUT_READ
|
||||
if (state.Properties.DictionarySize == 0)
|
||||
state.Dictionary = 0;
|
||||
else
|
||||
{
|
||||
state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
|
||||
if (state.Dictionary == 0)
|
||||
{
|
||||
allocMain->Free(state.Probs);
|
||||
return SZE_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
LzmaDecoderInit(&state);
|
||||
#endif
|
||||
|
||||
result = LzmaDecode(&state,
|
||||
#ifdef _LZMA_IN_CB
|
||||
&lzmaCallback.InCallback,
|
||||
#else
|
||||
inBuffer, (SizeT)inSize, &inProcessed,
|
||||
#endif
|
||||
outBuffer, (SizeT)outSize, &outSizeProcessedLoc);
|
||||
allocMain->Free(state.Probs);
|
||||
#ifdef _LZMA_OUT_READ
|
||||
allocMain->Free(state.Dictionary);
|
||||
#endif
|
||||
if (result == LZMA_RESULT_DATA_ERROR)
|
||||
return SZE_DATA_ERROR;
|
||||
if (result != LZMA_RESULT_OK)
|
||||
return SZE_FAIL;
|
||||
return (outSizeProcessedLoc == outSize) ? SZ_OK : SZE_DATA_ERROR;
|
||||
}
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
SZ_RESULT SzDecodeCopy(CFileSize inSize, ISzInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
void *inBuffer;
|
||||
size_t processedSize, curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)(inSize);
|
||||
RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, curSize, &processedSize));
|
||||
if (processedSize == 0)
|
||||
return SZE_DATA_ERROR;
|
||||
if (processedSize > curSize)
|
||||
return SZE_FAIL;
|
||||
memcpy(outBuffer, inBuffer, processedSize);
|
||||
outBuffer += processedSize;
|
||||
inSize -= processedSize;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
|
||||
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
||||
|
||||
SZ_RESULT CheckSupportedFolder(const CFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZE_NOTIMPL;
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
|
||||
return SZE_NOTIMPL;
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||
return SZE_NOTIMPL;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
if (IS_NO_BCJ(f->Coders[1]) ||
|
||||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
|
||||
return SZE_NOTIMPL;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
|
||||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
|
||||
IS_NO_BCJ2(f->Coders[3]))
|
||||
return SZE_NOTIMPL;
|
||||
if (f->NumPackStreams != 4 ||
|
||||
f->PackStreams[0] != 2 ||
|
||||
f->PackStreams[1] != 6 ||
|
||||
f->PackStreams[2] != 1 ||
|
||||
f->PackStreams[3] != 0 ||
|
||||
f->NumBindPairs != 3 ||
|
||||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
||||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
||||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
||||
return SZE_NOTIMPL;
|
||||
return SZ_OK;
|
||||
}
|
||||
return SZE_NOTIMPL;
|
||||
}
|
||||
|
||||
CFileSize GetSum(const CFileSize *values, UInt32 index)
|
||||
{
|
||||
CFileSize sum = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < index; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder,
|
||||
#ifdef _LZMA_IN_CB
|
||||
ISzInStream *inStream, CFileSize startPos,
|
||||
#else
|
||||
const Byte *inBuffer,
|
||||
#endif
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
UInt32 ci;
|
||||
size_t tempSizes[3] = { 0, 0, 0};
|
||||
size_t tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
||||
{
|
||||
UInt32 si = 0;
|
||||
CFileSize offset;
|
||||
CFileSize inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
size_t outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
CFileSize unpackSize = folder->UnPackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (size_t)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZE_OUTOFMEMORY;
|
||||
temp = (Byte *)allocMain->Alloc(outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
return SZE_OUTOFMEMORY;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize)
|
||||
return SZE_OUTOFMEMORY;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (size_t)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZE_NOTIMPL;
|
||||
}
|
||||
offset = GetSum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
#ifdef _LZMA_IN_CB
|
||||
RINOK(inStream->Seek(inStream, startPos + offset));
|
||||
#endif
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
if (inSize != outSizeCur)
|
||||
return SZE_DATA_ERROR;
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
#else
|
||||
memcpy(outBufCur, inBuffer + (size_t)offset, (size_t)inSize);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
SZ_RESULT res = SzDecodeLzma(coder, inSize,
|
||||
#ifdef _LZMA_IN_CB
|
||||
inStream,
|
||||
#else
|
||||
inBuffer + (size_t)offset,
|
||||
#endif
|
||||
outBufCur, outSizeCur, allocMain);
|
||||
RINOK(res)
|
||||
}
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ)
|
||||
{
|
||||
UInt32 state;
|
||||
if (ci != 1)
|
||||
return SZE_NOTIMPL;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
CFileSize offset = GetSum(packSizes, 1);
|
||||
CFileSize s3Size = packSizes[1];
|
||||
SZ_RESULT res;
|
||||
if (ci != 3)
|
||||
return SZE_NOTIMPL;
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
RINOK(inStream->Seek(inStream, startPos + offset));
|
||||
tempSizes[2] = (size_t)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZE_OUTOFMEMORY;
|
||||
tempBuf[2] = (Byte *)allocMain->Alloc(tempSizes[2]);
|
||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||
return SZE_OUTOFMEMORY;
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
RINOK(res)
|
||||
#endif
|
||||
|
||||
res = x86_2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
#ifdef _LZMA_IN_CB
|
||||
tempBuf[2], tempSizes[2],
|
||||
#else
|
||||
inBuffer + (size_t)offset, (size_t)s3Size,
|
||||
#endif
|
||||
outBuffer, outSize);
|
||||
RINOK(res)
|
||||
}
|
||||
else
|
||||
return SZE_NOTIMPL;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
|
||||
#ifdef _LZMA_IN_CB
|
||||
ISzInStream *inStream, CFileSize startPos,
|
||||
#else
|
||||
const Byte *inBuffer,
|
||||
#endif
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
int i;
|
||||
SZ_RESULT res = SzDecode2(packSizes, folder,
|
||||
#ifdef _LZMA_IN_CB
|
||||
inStream, startPos,
|
||||
#else
|
||||
inBuffer,
|
||||
#endif
|
||||
outBuffer, outSize, allocMain, tempBuf);
|
||||
for (i = 0; i < 3; i++)
|
||||
allocMain->Free(tempBuf[i]);
|
||||
return res;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
/* 7zDecode.h */
|
||||
|
||||
#ifndef __7Z_DECODE_H
|
||||
#define __7Z_DECODE_H
|
||||
|
||||
#include "7zItem.h"
|
||||
#include "7zAlloc.h"
|
||||
#ifdef _LZMA_IN_CB
|
||||
#include "7zIn.h"
|
||||
#endif
|
||||
|
||||
SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
|
||||
#ifdef _LZMA_IN_CB
|
||||
ISzInStream *stream, CFileSize startPos,
|
||||
#else
|
||||
const Byte *inBuffer,
|
||||
#endif
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
|
||||
#endif
|
|
@ -1,119 +0,0 @@
|
|||
/* 7zExtract.c */
|
||||
|
||||
#include "7zExtract.h"
|
||||
#include "7zDecode.h"
|
||||
#include "../../7zCrc.h"
|
||||
|
||||
SZ_RESULT SzExtract(
|
||||
ISzInStream *inStream,
|
||||
CArchiveDatabaseEx *db,
|
||||
UInt32 fileIndex,
|
||||
UInt32 *blockIndex,
|
||||
Byte **outBuffer,
|
||||
size_t *outBufferSize,
|
||||
size_t *offset,
|
||||
size_t *outSizeProcessed,
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp)
|
||||
{
|
||||
UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex];
|
||||
SZ_RESULT res = SZ_OK;
|
||||
*offset = 0;
|
||||
*outSizeProcessed = 0;
|
||||
if (folderIndex == (UInt32)-1)
|
||||
{
|
||||
allocMain->Free(*outBuffer);
|
||||
*blockIndex = folderIndex;
|
||||
*outBuffer = 0;
|
||||
*outBufferSize = 0;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
||||
{
|
||||
CFolder *folder = db->Database.Folders + folderIndex;
|
||||
CFileSize unPackSizeSpec = SzFolderGetUnPackSize(folder);
|
||||
size_t unPackSize = (size_t)unPackSizeSpec;
|
||||
CFileSize startOffset = SzArDbGetFolderStreamPos(db, folderIndex, 0);
|
||||
#ifndef _LZMA_IN_CB
|
||||
Byte *inBuffer = 0;
|
||||
size_t processedSize;
|
||||
CFileSize packSizeSpec;
|
||||
size_t packSize;
|
||||
RINOK(SzArDbGetFolderFullPackSize(db, folderIndex, &packSizeSpec));
|
||||
packSize = (size_t)packSizeSpec;
|
||||
if (packSize != packSizeSpec)
|
||||
return SZE_OUTOFMEMORY;
|
||||
#endif
|
||||
if (unPackSize != unPackSizeSpec)
|
||||
return SZE_OUTOFMEMORY;
|
||||
*blockIndex = folderIndex;
|
||||
allocMain->Free(*outBuffer);
|
||||
*outBuffer = 0;
|
||||
|
||||
RINOK(inStream->Seek(inStream, startOffset));
|
||||
|
||||
#ifndef _LZMA_IN_CB
|
||||
if (packSize != 0)
|
||||
{
|
||||
inBuffer = (Byte *)allocTemp->Alloc(packSize);
|
||||
if (inBuffer == 0)
|
||||
return SZE_OUTOFMEMORY;
|
||||
}
|
||||
res = inStream->Read(inStream, inBuffer, packSize, &processedSize);
|
||||
if (res == SZ_OK && processedSize != packSize)
|
||||
res = SZE_FAIL;
|
||||
#endif
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
*outBufferSize = unPackSize;
|
||||
if (unPackSize != 0)
|
||||
{
|
||||
*outBuffer = (Byte *)allocMain->Alloc(unPackSize);
|
||||
if (*outBuffer == 0)
|
||||
res = SZE_OUTOFMEMORY;
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = SzDecode(db->Database.PackSizes +
|
||||
db->FolderStartPackStreamIndex[folderIndex], folder,
|
||||
#ifdef _LZMA_IN_CB
|
||||
inStream, startOffset,
|
||||
#else
|
||||
inBuffer,
|
||||
#endif
|
||||
*outBuffer, unPackSize, allocTemp);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
if (folder->UnPackCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
|
||||
res = SZE_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef _LZMA_IN_CB
|
||||
allocTemp->Free(inBuffer);
|
||||
#endif
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
UInt32 i;
|
||||
CFileItem *fileItem = db->Database.Files + fileIndex;
|
||||
*offset = 0;
|
||||
for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
||||
*offset += (UInt32)db->Database.Files[i].Size;
|
||||
*outSizeProcessed = (size_t)fileItem->Size;
|
||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
||||
return SZE_FAIL;
|
||||
{
|
||||
if (fileItem->IsFileCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
||||
res = SZE_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/* 7zExtract.h */
|
||||
|
||||
#ifndef __7Z_EXTRACT_H
|
||||
#define __7Z_EXTRACT_H
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
SZ_RESULT SzExtract(
|
||||
ISzInStream *inStream,
|
||||
CArchiveDatabaseEx *db,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
#endif
|
|
@ -1,5 +0,0 @@
|
|||
/* 7zHeader.c */
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
|
@ -1,55 +0,0 @@
|
|||
/* 7zHeader.h */
|
||||
|
||||
#ifndef __7Z_HEADER_H
|
||||
#define __7Z_HEADER_H
|
||||
|
||||
#include "../../Types.h"
|
||||
|
||||
#define k7zSignatureSize 6
|
||||
extern Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
|
||||
enum EIdEnum
|
||||
{
|
||||
k7zIdEnd,
|
||||
|
||||
k7zIdHeader,
|
||||
|
||||
k7zIdArchiveProperties,
|
||||
|
||||
k7zIdAdditionalStreamsInfo,
|
||||
k7zIdMainStreamsInfo,
|
||||
k7zIdFilesInfo,
|
||||
|
||||
k7zIdPackInfo,
|
||||
k7zIdUnPackInfo,
|
||||
k7zIdSubStreamsInfo,
|
||||
|
||||
k7zIdSize,
|
||||
k7zIdCRC,
|
||||
|
||||
k7zIdFolder,
|
||||
|
||||
k7zIdCodersUnPackSize,
|
||||
k7zIdNumUnPackStream,
|
||||
|
||||
k7zIdEmptyStream,
|
||||
k7zIdEmptyFile,
|
||||
k7zIdAnti,
|
||||
|
||||
k7zIdName,
|
||||
k7zIdCreationTime,
|
||||
k7zIdLastAccessTime,
|
||||
k7zIdLastWriteTime,
|
||||
k7zIdWinAttributes,
|
||||
k7zIdComment,
|
||||
|
||||
k7zIdEncodedHeader,
|
||||
|
||||
k7zIdStartPos
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,55 +0,0 @@
|
|||
/* 7zIn.h */
|
||||
|
||||
#ifndef __7Z_IN_H
|
||||
#define __7Z_IN_H
|
||||
|
||||
#include "7zHeader.h"
|
||||
#include "7zItem.h"
|
||||
#include "7zAlloc.h"
|
||||
|
||||
typedef struct _CInArchiveInfo
|
||||
{
|
||||
CFileSize StartPositionAfterHeader;
|
||||
CFileSize DataStartPosition;
|
||||
}CInArchiveInfo;
|
||||
|
||||
typedef struct _CArchiveDatabaseEx
|
||||
{
|
||||
CArchiveDatabase Database;
|
||||
CInArchiveInfo ArchiveInfo;
|
||||
UInt32 *FolderStartPackStreamIndex;
|
||||
CFileSize *PackStreamStartPositions;
|
||||
UInt32 *FolderStartFileIndex;
|
||||
UInt32 *FileIndexToFolderIndexMap;
|
||||
}CArchiveDatabaseEx;
|
||||
|
||||
void SzArDbExInit(CArchiveDatabaseEx *db);
|
||||
void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *));
|
||||
CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder);
|
||||
int SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex, CFileSize *resSize);
|
||||
|
||||
typedef struct _ISzInStream
|
||||
{
|
||||
#ifdef _LZMA_IN_CB
|
||||
SZ_RESULT (*Read)(
|
||||
void *object, /* pointer to ISzInStream itself */
|
||||
void **buffer, /* out: pointer to buffer with data */
|
||||
size_t maxRequiredSize, /* max required size to read */
|
||||
size_t *processedSize); /* real processed size.
|
||||
processedSize can be less than maxRequiredSize.
|
||||
If processedSize == 0, then there are no more
|
||||
bytes in stream. */
|
||||
#else
|
||||
SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize);
|
||||
#endif
|
||||
SZ_RESULT (*Seek)(void *object, CFileSize pos);
|
||||
} ISzInStream;
|
||||
|
||||
|
||||
int SzArchiveOpen(
|
||||
ISzInStream *inStream,
|
||||
CArchiveDatabaseEx *db,
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
#endif
|
|
@ -1,134 +0,0 @@
|
|||
/* 7zItem.c */
|
||||
|
||||
#include "7zItem.h"
|
||||
#include "7zAlloc.h"
|
||||
|
||||
void SzCoderInfoInit(CCoderInfo *coder)
|
||||
{
|
||||
SzByteBufferInit(&coder->Properties);
|
||||
}
|
||||
|
||||
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p))
|
||||
{
|
||||
SzByteBufferFree(&coder->Properties, freeFunc);
|
||||
SzCoderInfoInit(coder);
|
||||
}
|
||||
|
||||
void SzFolderInit(CFolder *folder)
|
||||
{
|
||||
folder->NumCoders = 0;
|
||||
folder->Coders = 0;
|
||||
folder->NumBindPairs = 0;
|
||||
folder->BindPairs = 0;
|
||||
folder->NumPackStreams = 0;
|
||||
folder->PackStreams = 0;
|
||||
folder->UnPackSizes = 0;
|
||||
folder->UnPackCRCDefined = 0;
|
||||
folder->UnPackCRC = 0;
|
||||
folder->NumUnPackStreams = 0;
|
||||
}
|
||||
|
||||
void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p))
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < folder->NumCoders; i++)
|
||||
SzCoderInfoFree(&folder->Coders[i], freeFunc);
|
||||
freeFunc(folder->Coders);
|
||||
freeFunc(folder->BindPairs);
|
||||
freeFunc(folder->PackStreams);
|
||||
freeFunc(folder->UnPackSizes);
|
||||
SzFolderInit(folder);
|
||||
}
|
||||
|
||||
UInt32 SzFolderGetNumOutStreams(CFolder *folder)
|
||||
{
|
||||
UInt32 result = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < folder->NumCoders; i++)
|
||||
result += folder->Coders[i].NumOutStreams;
|
||||
return result;
|
||||
}
|
||||
|
||||
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for(i = 0; i < folder->NumBindPairs; i++)
|
||||
if (folder->BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for(i = 0; i < folder->NumBindPairs; i++)
|
||||
if (folder->BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
CFileSize SzFolderGetUnPackSize(CFolder *folder)
|
||||
{
|
||||
int i = (int)SzFolderGetNumOutStreams(folder);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
for (i--; i >= 0; i--)
|
||||
if (SzFolderFindBindPairForOutStream(folder, i) < 0)
|
||||
return folder->UnPackSizes[i];
|
||||
/* throw 1; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int FindPackStreamArrayIndex(int inStreamIndex) const
|
||||
{
|
||||
for(int i = 0; i < PackStreams.Size(); i++)
|
||||
if (PackStreams[i] == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
void SzFileInit(CFileItem *fileItem)
|
||||
{
|
||||
fileItem->IsFileCRCDefined = 0;
|
||||
fileItem->HasStream = 1;
|
||||
fileItem->IsDirectory = 0;
|
||||
fileItem->IsAnti = 0;
|
||||
fileItem->IsLastWriteTimeDefined = 0;
|
||||
fileItem->Name = 0;
|
||||
}
|
||||
|
||||
void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p))
|
||||
{
|
||||
freeFunc(fileItem->Name);
|
||||
SzFileInit(fileItem);
|
||||
}
|
||||
|
||||
void SzArchiveDatabaseInit(CArchiveDatabase *db)
|
||||
{
|
||||
db->NumPackStreams = 0;
|
||||
db->PackSizes = 0;
|
||||
db->PackCRCsDefined = 0;
|
||||
db->PackCRCs = 0;
|
||||
db->NumFolders = 0;
|
||||
db->Folders = 0;
|
||||
db->NumFiles = 0;
|
||||
db->Files = 0;
|
||||
}
|
||||
|
||||
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *))
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < db->NumFolders; i++)
|
||||
SzFolderFree(&db->Folders[i], freeFunc);
|
||||
for (i = 0; i < db->NumFiles; i++)
|
||||
SzFileFree(&db->Files[i], freeFunc);
|
||||
freeFunc(db->PackSizes);
|
||||
freeFunc(db->PackCRCsDefined);
|
||||
freeFunc(db->PackCRCs);
|
||||
freeFunc(db->Folders);
|
||||
freeFunc(db->Files);
|
||||
SzArchiveDatabaseInit(db);
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/* 7zItem.h */
|
||||
|
||||
#ifndef __7Z_ITEM_H
|
||||
#define __7Z_ITEM_H
|
||||
|
||||
#include "7zMethodID.h"
|
||||
#include "7zHeader.h"
|
||||
#include "7zBuffer.h"
|
||||
|
||||
typedef struct _CCoderInfo
|
||||
{
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
CMethodID MethodID;
|
||||
CSzByteBuffer Properties;
|
||||
}CCoderInfo;
|
||||
|
||||
void SzCoderInfoInit(CCoderInfo *coder);
|
||||
void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p));
|
||||
|
||||
typedef struct _CBindPair
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
}CBindPair;
|
||||
|
||||
typedef struct _CFolder
|
||||
{
|
||||
UInt32 NumCoders;
|
||||
CCoderInfo *Coders;
|
||||
UInt32 NumBindPairs;
|
||||
CBindPair *BindPairs;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 *PackStreams;
|
||||
CFileSize *UnPackSizes;
|
||||
int UnPackCRCDefined;
|
||||
UInt32 UnPackCRC;
|
||||
|
||||
UInt32 NumUnPackStreams;
|
||||
}CFolder;
|
||||
|
||||
void SzFolderInit(CFolder *folder);
|
||||
CFileSize SzFolderGetUnPackSize(CFolder *folder);
|
||||
int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex);
|
||||
UInt32 SzFolderGetNumOutStreams(CFolder *folder);
|
||||
CFileSize SzFolderGetUnPackSize(CFolder *folder);
|
||||
|
||||
typedef struct _CArchiveFileTime
|
||||
{
|
||||
UInt32 Low;
|
||||
UInt32 High;
|
||||
} CArchiveFileTime;
|
||||
|
||||
typedef struct _CFileItem
|
||||
{
|
||||
CArchiveFileTime LastWriteTime;
|
||||
/*
|
||||
CFileSize StartPos;
|
||||
UInt32 Attributes;
|
||||
*/
|
||||
CFileSize Size;
|
||||
UInt32 FileCRC;
|
||||
char *Name;
|
||||
|
||||
Byte IsFileCRCDefined;
|
||||
Byte HasStream;
|
||||
Byte IsDirectory;
|
||||
Byte IsAnti;
|
||||
Byte IsLastWriteTimeDefined;
|
||||
/*
|
||||
int AreAttributesDefined;
|
||||
int IsLastWriteTimeDefined;
|
||||
int IsStartPosDefined;
|
||||
*/
|
||||
}CFileItem;
|
||||
|
||||
void SzFileInit(CFileItem *fileItem);
|
||||
|
||||
typedef struct _CArchiveDatabase
|
||||
{
|
||||
UInt32 NumPackStreams;
|
||||
CFileSize *PackSizes;
|
||||
Byte *PackCRCsDefined;
|
||||
UInt32 *PackCRCs;
|
||||
UInt32 NumFolders;
|
||||
CFolder *Folders;
|
||||
UInt32 NumFiles;
|
||||
CFileItem *Files;
|
||||
}CArchiveDatabase;
|
||||
|
||||
void SzArchiveDatabaseInit(CArchiveDatabase *db);
|
||||
void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *));
|
||||
|
||||
|
||||
#endif
|
|
@ -1,428 +0,0 @@
|
|||
/*
|
||||
7zMain.c
|
||||
Test application for 7z Decoder
|
||||
LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "7zIn.h"
|
||||
#include "7zExtract.h"
|
||||
|
||||
#include "../../7zCrc.h"
|
||||
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
typedef HANDLE MY_FILE_HANDLE;
|
||||
#else
|
||||
typedef FILE *MY_FILE_HANDLE;
|
||||
#endif
|
||||
|
||||
void ConvertNumberToString(CFileSize value, char *s)
|
||||
{
|
||||
char temp[32];
|
||||
int pos = 0;
|
||||
do
|
||||
{
|
||||
temp[pos++] = (char)('0' + (int)(value % 10));
|
||||
value /= 10;
|
||||
}
|
||||
while (value != 0);
|
||||
do
|
||||
*s++ = temp[--pos];
|
||||
while(pos > 0);
|
||||
*s = '\0';
|
||||
}
|
||||
|
||||
#define PERIOD_4 (4 * 365 + 1)
|
||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||
|
||||
void ConvertFileTimeToString(CArchiveFileTime *ft, char *s)
|
||||
{
|
||||
unsigned year, mon, day, hour, min, sec;
|
||||
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
|
||||
Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
unsigned temp;
|
||||
UInt32 v;
|
||||
v64 /= 10000000;
|
||||
sec = (unsigned)(v64 % 60);
|
||||
v64 /= 60;
|
||||
min = (unsigned)(v64 % 60);
|
||||
v64 /= 60;
|
||||
hour = (unsigned)(v64 % 24);
|
||||
v64 /= 24;
|
||||
|
||||
v = (UInt32)v64;
|
||||
|
||||
year = (unsigned)(1601 + v / PERIOD_400 * 400);
|
||||
v %= PERIOD_400;
|
||||
|
||||
temp = (unsigned)(v / PERIOD_100);
|
||||
if (temp == 4)
|
||||
temp = 3;
|
||||
year += temp * 100;
|
||||
v -= temp * PERIOD_100;
|
||||
|
||||
temp = v / PERIOD_4;
|
||||
if (temp == 25)
|
||||
temp = 24;
|
||||
year += temp * 4;
|
||||
v -= temp * PERIOD_4;
|
||||
|
||||
temp = v / 365;
|
||||
if (temp == 4)
|
||||
temp = 3;
|
||||
year += temp;
|
||||
v -= temp * 365;
|
||||
|
||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
||||
ms[1] = 29;
|
||||
for (mon = 1; mon <= 12; mon++)
|
||||
{
|
||||
unsigned s = ms[mon - 1];
|
||||
if (v < s)
|
||||
break;
|
||||
v -= s;
|
||||
}
|
||||
day = (unsigned)v + 1;
|
||||
sprintf(s, "%04d-%02d-%02d %02d:%02d:%02d", year, mon, day, hour, min, sec);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
/*
|
||||
ReadFile and WriteFile functions in Windows have BUG:
|
||||
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
||||
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
||||
(Insufficient system resources exist to complete the requested service).
|
||||
*/
|
||||
#define kChunkSizeMax (1 << 24)
|
||||
#endif
|
||||
|
||||
size_t MyReadFile(MY_FILE_HANDLE file, void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
{
|
||||
size_t processedSize = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
||||
DWORD processedLoc = 0;
|
||||
BOOL res = ReadFile(file, data, curSize, &processedLoc, NULL);
|
||||
data = (void *)((unsigned char *)data + processedLoc);
|
||||
size -= processedLoc;
|
||||
processedSize += processedLoc;
|
||||
if (!res || processedLoc == 0)
|
||||
break;
|
||||
}
|
||||
while (size > 0);
|
||||
return processedSize;
|
||||
}
|
||||
#else
|
||||
return fread(data, 1, size, file);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t MyWriteFile(MY_FILE_HANDLE file, void *data, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
{
|
||||
size_t processedSize = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (size > kChunkSizeMax) ? kChunkSizeMax : (DWORD)size;
|
||||
DWORD processedLoc = 0;
|
||||
BOOL res = WriteFile(file, data, curSize, &processedLoc, NULL);
|
||||
data = (void *)((unsigned char *)data + processedLoc);
|
||||
size -= processedLoc;
|
||||
processedSize += processedLoc;
|
||||
if (!res)
|
||||
break;
|
||||
}
|
||||
while (size > 0);
|
||||
return processedSize;
|
||||
}
|
||||
#else
|
||||
return fwrite(data, 1, size, file);
|
||||
#endif
|
||||
}
|
||||
|
||||
int MyCloseFile(MY_FILE_HANDLE file)
|
||||
{
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
return (CloseHandle(file) != FALSE) ? 0 : 1;
|
||||
#else
|
||||
return fclose(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct _CFileInStream
|
||||
{
|
||||
ISzInStream InStream;
|
||||
MY_FILE_HANDLE File;
|
||||
} CFileInStream;
|
||||
|
||||
#ifdef _LZMA_IN_CB
|
||||
|
||||
#define kBufferSize (1 << 12)
|
||||
Byte g_Buffer[kBufferSize];
|
||||
|
||||
SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize)
|
||||
{
|
||||
CFileInStream *s = (CFileInStream *)object;
|
||||
size_t processedSizeLoc;
|
||||
if (maxRequiredSize > kBufferSize)
|
||||
maxRequiredSize = kBufferSize;
|
||||
processedSizeLoc = MyReadFile(s->File, g_Buffer, maxRequiredSize);
|
||||
*buffer = g_Buffer;
|
||||
if (processedSize != 0)
|
||||
*processedSize = processedSizeLoc;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize)
|
||||
{
|
||||
CFileInStream *s = (CFileInStream *)object;
|
||||
size_t processedSizeLoc = MyReadFile(s->File, buffer, size);
|
||||
if (processedSize != 0)
|
||||
*processedSize = processedSizeLoc;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
SZ_RESULT SzFileSeekImp(void *object, CFileSize pos)
|
||||
{
|
||||
CFileInStream *s = (CFileInStream *)object;
|
||||
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
{
|
||||
LARGE_INTEGER value;
|
||||
value.LowPart = (DWORD)pos;
|
||||
value.HighPart = (LONG)((UInt64)pos >> 32);
|
||||
#ifdef _SZ_FILE_SIZE_32
|
||||
/* VC 6.0 has bug with >> 32 shifts. */
|
||||
value.HighPart = 0;
|
||||
#endif
|
||||
value.LowPart = SetFilePointer(s->File, value.LowPart, &value.HighPart, FILE_BEGIN);
|
||||
if (value.LowPart == 0xFFFFFFFF)
|
||||
if(GetLastError() != NO_ERROR)
|
||||
return SZE_FAIL;
|
||||
return SZ_OK;
|
||||
}
|
||||
#else
|
||||
int res = fseek(s->File, (long)pos, SEEK_SET);
|
||||
if (res == 0)
|
||||
return SZ_OK;
|
||||
return SZE_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PrintError(char *sz)
|
||||
{
|
||||
printf("\nERROR: %s\n", sz);
|
||||
}
|
||||
|
||||
int main(int numargs, char *args[])
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CArchiveDatabaseEx db;
|
||||
SZ_RESULT res;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
|
||||
printf("\n7z ANSI-C Decoder 4.48 Copyright (c) 1999-2007 Igor Pavlov 2007-06-21\n");
|
||||
if (numargs == 1)
|
||||
{
|
||||
printf(
|
||||
"\nUsage: 7zDec <command> <archive_name>\n\n"
|
||||
"<Commands>\n"
|
||||
" e: Extract files from archive\n"
|
||||
" l: List contents of archive\n"
|
||||
" t: Test integrity of archive\n");
|
||||
return 0;
|
||||
}
|
||||
if (numargs < 3)
|
||||
{
|
||||
PrintError("incorrect command");
|
||||
return 1;
|
||||
}
|
||||
|
||||
archiveStream.File =
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
CreateFile(args[2], GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (archiveStream.File == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
archiveStream.File = fopen(args[2], "rb");
|
||||
if (archiveStream.File == 0)
|
||||
#endif
|
||||
{
|
||||
PrintError("can not open input file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
archiveStream.InStream.Read = SzFileReadImp;
|
||||
archiveStream.InStream.Seek = SzFileSeekImp;
|
||||
|
||||
allocImp.Alloc = SzAlloc;
|
||||
allocImp.Free = SzFree;
|
||||
|
||||
allocTempImp.Alloc = SzAllocTemp;
|
||||
allocTempImp.Free = SzFreeTemp;
|
||||
|
||||
CrcGenerateTable();
|
||||
|
||||
SzArDbExInit(&db);
|
||||
res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
char *command = args[1];
|
||||
int listCommand = 0;
|
||||
int testCommand = 0;
|
||||
int extractCommand = 0;
|
||||
if (strcmp(command, "l") == 0)
|
||||
listCommand = 1;
|
||||
if (strcmp(command, "t") == 0)
|
||||
testCommand = 1;
|
||||
else if (strcmp(command, "e") == 0)
|
||||
extractCommand = 1;
|
||||
|
||||
if (listCommand)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < db.Database.NumFiles; i++)
|
||||
{
|
||||
CFileItem *f = db.Database.Files + i;
|
||||
char s[32], t[32];
|
||||
ConvertNumberToString(f->Size, s);
|
||||
if (f->IsLastWriteTimeDefined)
|
||||
ConvertFileTimeToString(&f->LastWriteTime, t);
|
||||
else
|
||||
strcpy(t, " ");
|
||||
|
||||
printf("%10s %s %s\n", s, t, f->Name);
|
||||
}
|
||||
}
|
||||
else if (testCommand || extractCommand)
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
/*
|
||||
if you need cache, use these 3 variables.
|
||||
if you use external function, you can make these variable as static.
|
||||
*/
|
||||
UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
|
||||
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||||
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||||
|
||||
printf("\n");
|
||||
for (i = 0; i < db.Database.NumFiles; i++)
|
||||
{
|
||||
size_t offset;
|
||||
size_t outSizeProcessed;
|
||||
CFileItem *f = db.Database.Files + i;
|
||||
if (f->IsDirectory)
|
||||
printf("Directory ");
|
||||
else
|
||||
printf(testCommand ?
|
||||
"Testing ":
|
||||
"Extracting");
|
||||
printf(" %s", f->Name);
|
||||
if (f->IsDirectory)
|
||||
{
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
res = SzExtract(&archiveStream.InStream, &db, i,
|
||||
&blockIndex, &outBuffer, &outBufferSize,
|
||||
&offset, &outSizeProcessed,
|
||||
&allocImp, &allocTempImp);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (!testCommand)
|
||||
{
|
||||
MY_FILE_HANDLE outputHandle;
|
||||
size_t processedSize;
|
||||
char *fileName = f->Name;
|
||||
size_t nameLen = strlen(f->Name);
|
||||
for (; nameLen > 0; nameLen--)
|
||||
if (f->Name[nameLen - 1] == '/')
|
||||
{
|
||||
fileName = f->Name + nameLen;
|
||||
break;
|
||||
}
|
||||
|
||||
outputHandle =
|
||||
#ifdef USE_WINDOWS_FUNCTIONS
|
||||
CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ,
|
||||
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (outputHandle == INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
fopen(fileName, "wb+");
|
||||
if (outputHandle == 0)
|
||||
#endif
|
||||
{
|
||||
PrintError("can not open output file");
|
||||
res = SZE_FAIL;
|
||||
break;
|
||||
}
|
||||
processedSize = MyWriteFile(outputHandle, outBuffer + offset, outSizeProcessed);
|
||||
if (processedSize != outSizeProcessed)
|
||||
{
|
||||
PrintError("can not write output file");
|
||||
res = SZE_FAIL;
|
||||
break;
|
||||
}
|
||||
if (MyCloseFile(outputHandle))
|
||||
{
|
||||
PrintError("can not close output file");
|
||||
res = SZE_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
allocImp.Free(outBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintError("incorrect command");
|
||||
res = SZE_FAIL;
|
||||
}
|
||||
}
|
||||
SzArDbExFree(&db, allocImp.Free);
|
||||
|
||||
MyCloseFile(archiveStream.File);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
printf("\nEverything is Ok\n");
|
||||
return 0;
|
||||
}
|
||||
if (res == (SZ_RESULT)SZE_NOTIMPL)
|
||||
PrintError("decoder doesn't support this archive");
|
||||
else if (res == (SZ_RESULT)SZE_OUTOFMEMORY)
|
||||
PrintError("can not allocate memory");
|
||||
else if (res == (SZ_RESULT)SZE_CRC_ERROR)
|
||||
PrintError("CRC error");
|
||||
else
|
||||
printf("\nERROR #%d\n", res);
|
||||
return 1;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
/* 7zMethodID.c */
|
||||
|
||||
#include "7zMethodID.h"
|
||||
|
||||
/*
|
||||
int AreMethodsEqual(CMethodID *a1, CMethodID *a2)
|
||||
{
|
||||
return (*a1 == *a2) ? 1 : 0;
|
||||
}
|
||||
*/
|
|
@ -1,10 +0,0 @@
|
|||
/* 7zMethodID.h */
|
||||
|
||||
#ifndef __7Z_METHOD_ID_H
|
||||
#define __7Z_METHOD_ID_H
|
||||
|
||||
#include "../../Types.h"
|
||||
|
||||
typedef UInt64 CMethodID;
|
||||
|
||||
#endif
|
|
@ -1,211 +0,0 @@
|
|||
# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=7z_C - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "7z_C.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "7z_C - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x419 /d "NDEBUG"
|
||||
# ADD RSC /l 0x419 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" /opt:NOWIN98
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "7z_C - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W4 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x419 /d "_DEBUG"
|
||||
# ADD RSC /l 0x419 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "7z_C - Win32 Release"
|
||||
# Name "7z_C - Win32 Debug"
|
||||
# Begin Group "LZMA"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzma\LzmaDecode.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzma\LzmaDecode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Lzma\LzmaTypes.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Common"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zCrc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\7zCrc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Types.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Branch"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Branch\BranchTypes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Branch\BranchX86.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Branch\BranchX86.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Branch\BranchX86_2.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\Compress\Branch\BranchX86_2.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zAlloc.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zAlloc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zBuffer.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zBuffer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zDecode.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zDecode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zExtract.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zExtract.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zHeader.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zHeader.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zIn.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zIn.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zItem.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zItem.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zMain.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zMethodID.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\7zMethodID.h
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
|
@ -1,29 +0,0 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "7z_C"=.\7z_C.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
PROG = 7zDec.exe
|
||||
|
||||
!IFDEF CPU
|
||||
LIBS = $(LIBS) bufferoverflowU.lib
|
||||
CFLAGS = $(CFLAGS) -GS- -Zc:forScope -WX -GS- -Gy -W4
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF O
|
||||
!IFDEF CPU
|
||||
O=$(CPU)
|
||||
!ELSE
|
||||
O=O
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -D_LZMA_IN_CB
|
||||
CFLAGS_O1 = $(CFLAGS) -O1
|
||||
CFLAGS_O2 = $(CFLAGS) -O2
|
||||
|
||||
LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 -OPT:REF
|
||||
|
||||
PROGPATH = $O\$(PROG)
|
||||
|
||||
COMPL_O1 = $(CPP) $(CFLAGS_O1) $**
|
||||
COMPL_O2 = $(CPP) $(CFLAGS_O2) $**
|
||||
COMPL = $(CPP) $(CFLAGS_O1) $**
|
||||
|
||||
C_OBJS = \
|
||||
$O\7zCrc.obj \
|
||||
|
||||
|
||||
7Z_OBJS = \
|
||||
$O\7zAlloc.obj \
|
||||
$O\7zBuffer.obj \
|
||||
$O\7zDecode.obj \
|
||||
$O\7zExtract.obj \
|
||||
$O\7zHeader.obj \
|
||||
$O\7zIn.obj \
|
||||
$O\7zItem.obj \
|
||||
$O\7zMain.obj \
|
||||
$O\7zMethodID.obj \
|
||||
|
||||
OBJS = \
|
||||
$(7Z_OBJS) \
|
||||
$O\LzmaDecode.obj \
|
||||
$O\BranchX86.obj \
|
||||
$O\BranchX86_2.obj \
|
||||
$(C_OBJS) \
|
||||
|
||||
all: $(PROGPATH)
|
||||
|
||||
clean:
|
||||
-del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch
|
||||
|
||||
$O:
|
||||
if not exist "$O" mkdir "$O"
|
||||
|
||||
$(PROGPATH): $O $(OBJS)
|
||||
link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS)
|
||||
|
||||
|
||||
$(7Z_OBJS): $(*B).c
|
||||
$(COMPL)
|
||||
$O\LzmaDecode.obj: ../../Compress/Lzma/$(*B).c
|
||||
$(COMPL_O2)
|
||||
|
||||
$O\BranchX86.obj: ../../Compress/Branch/$(*B).c
|
||||
$(COMPL_O2)
|
||||
|
||||
$O\BranchX86_2.obj: ../../Compress/Branch/$(*B).c
|
||||
$(COMPL_O2)
|
||||
|
||||
$(C_OBJS): ../../$(*B).c
|
||||
$(COMPL_O2)
|
|
@ -1,55 +0,0 @@
|
|||
PROG = 7zDec
|
||||
CXX = g++
|
||||
LIB =
|
||||
RM = rm -f
|
||||
CFLAGS = -c -O2 -Wall -D_LZMA_IN_CB
|
||||
|
||||
OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o BranchX86.o BranchX86_2.o
|
||||
|
||||
all: $(PROG)
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
$(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB)
|
||||
|
||||
7zAlloc.o: 7zAlloc.c
|
||||
$(CXX) $(CFLAGS) 7zAlloc.c
|
||||
|
||||
7zBuffer.o: 7zBuffer.c
|
||||
$(CXX) $(CFLAGS) 7zBuffer.c
|
||||
|
||||
7zCrc.o: ../../7zCrc.c
|
||||
$(CXX) $(CFLAGS) ../../7zCrc.c
|
||||
|
||||
7zDecode.o: 7zDecode.c
|
||||
$(CXX) $(CFLAGS) 7zDecode.c
|
||||
|
||||
7zExtract.o: 7zExtract.c
|
||||
$(CXX) $(CFLAGS) 7zExtract.c
|
||||
|
||||
7zHeader.o: 7zHeader.c
|
||||
$(CXX) $(CFLAGS) 7zHeader.c
|
||||
|
||||
7zIn.o: 7zIn.c
|
||||
$(CXX) $(CFLAGS) 7zIn.c
|
||||
|
||||
7zItem.o: 7zItem.c
|
||||
$(CXX) $(CFLAGS) 7zItem.c
|
||||
|
||||
7zMain.o: 7zMain.c
|
||||
$(CXX) $(CFLAGS) 7zMain.c
|
||||
|
||||
7zMethodID.o: 7zMethodID.c
|
||||
$(CXX) $(CFLAGS) 7zMethodID.c
|
||||
|
||||
LzmaDecode.o: ../../Compress/Lzma/LzmaDecode.c
|
||||
$(CXX) $(CFLAGS) ../../Compress/Lzma/LzmaDecode.c
|
||||
|
||||
BranchX86.o: ../../Compress/Branch/BranchX86.c
|
||||
$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86.c
|
||||
|
||||
BranchX86_2.o: ../../Compress/Branch/BranchX86_2.c
|
||||
$(CXX) $(CFLAGS) ../../Compress/Branch/BranchX86_2.c
|
||||
|
||||
clean:
|
||||
-$(RM) $(PROG) $(OBJS)
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/* BranchARM.c */
|
||||
|
||||
#include "BranchARM.h"
|
||||
|
||||
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i + 4 <= size; i += 4)
|
||||
{
|
||||
if (data[i + 3] == 0xEB)
|
||||
{
|
||||
UInt32 dest;
|
||||
UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]);
|
||||
src <<= 2;
|
||||
if (encoding)
|
||||
dest = nowPos + i + 8 + src;
|
||||
else
|
||||
dest = src - (nowPos + i + 8);
|
||||
dest >>= 2;
|
||||
data[i + 2] = (Byte)(dest >> 16);
|
||||
data[i + 1] = (Byte)(dest >> 8);
|
||||
data[i + 0] = (Byte)dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
/* BranchARM.h */
|
||||
|
||||
#ifndef __BRANCH_ARM_H
|
||||
#define __BRANCH_ARM_H
|
||||
|
||||
#include "BranchTypes.h"
|
||||
|
||||
UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding);
|
||||
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
/* BranchARMThumb.c */
|
||||
|
||||
#include "BranchARMThumb.h"
|
||||
|
||||
UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i + 4 <= size; i += 2)
|
||||
{
|
||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||
(data[i + 3] & 0xF8) == 0xF8)
|
||||
{
|
||||
UInt32 dest;
|
||||
UInt32 src =
|
||||
((data[i + 1] & 0x7) << 19) |
|
||||
(data[i + 0] << 11) |
|
||||
((data[i + 3] & 0x7) << 8) |
|
||||
(data[i + 2]);
|
||||
|
||||
src <<= 1;
|
||||
if (encoding)
|
||||
dest = nowPos + i + 4 + src;
|
||||
else
|
||||
dest = src - (nowPos + i + 4);
|
||||
dest >>= 1;
|
||||
|
||||
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
||||
data[i + 0] = (Byte)(dest >> 11);
|
||||
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
||||
data[i + 2] = (Byte)dest;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue