mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-09 13:01:38 -07:00
Compare commits
1212 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ef5eb4b612 | |||
| 864b29f7f1 | |||
| 4d498b668a | |||
| 62d0b0ae72 | |||
| 2c9ef2e1bc | |||
| 9b68671082 | |||
| 03ab6add5c | |||
| 052633b73c | |||
| bf9a8032a1 | |||
| eb261f5b28 | |||
| f5febb633c | |||
| d2ac3c2228 | |||
| 51caa930ca | |||
| b7af4e7f6b | |||
| 82cd30a145 | |||
| 8caae16113 | |||
| dc789c43b6 | |||
| 2e73fb25af | |||
| 1577d60d02 | |||
| 3bd1918c5e | |||
| 263b3141b5 | |||
| 82263a8b38 | |||
| 61ad2a1345 | |||
| d589914956 | |||
| f54a026acc | |||
| fc06d7011d | |||
| ed7c9ec619 | |||
| 1d9f6346d4 | |||
| a3a3156ddd | |||
| 70bd4a5ab6 | |||
| 034aead930 | |||
| c8a5bafc6b | |||
| 0a7b9338f6 | |||
| bc0fa1240b | |||
| 292398dbe2 | |||
| 49da19e013 | |||
| bbd4c1054e | |||
| 152ac61faf | |||
| 4d65b1ab9c | |||
| 8b2f62000a | |||
| 166803a2a5 | |||
| 11a2b2a942 | |||
| 0a492acaa1 | |||
| e86d7f1fb0 | |||
| 962d599996 | |||
| ba536d67b4 | |||
| 8e4bdcfb98 | |||
| f3f0ab6e2c | |||
| 5a771732bd | |||
| 9b6647a019 | |||
| 7e40a5a711 | |||
| 27cbd0d931 | |||
| 12c316cd6b | |||
| b06583133a | |||
| a2e6fc5909 | |||
| 058065ce75 | |||
| 75a2015260 | |||
| 18776aa6b9 | |||
| 4cf48daa75 | |||
| 361aeac0cc | |||
| 2e66d621b5 | |||
| 566a11a585 | |||
| abb9fb3345 | |||
| 05a9652f76 | |||
| ba5df8edca | |||
| 9afee7e8d2 | |||
| c458186f68 | |||
| f9da0a59e4 | |||
| c19af95db0 | |||
| 840459bdb0 | |||
| 798660c007 | |||
| c039977048 | |||
| 7a9737b3d4 | |||
| 0f5d562625 | |||
| 21f9e7f5e5 | |||
| 6ee7b05b27 | |||
| e4c7e9903e | |||
| a96100d875 | |||
| 10c67051f2 | |||
| a3fbd09ef9 | |||
| 51248270e1 | |||
| 8fe431e53e | |||
| 61a7d88490 | |||
| 496765c043 | |||
| a62039882e | |||
| a2a05e40e6 | |||
| 45d08ea992 | |||
| c9c7aa2e90 | |||
| d0037fcf6b | |||
| b25fba6175 | |||
| afcdbf1ba6 | |||
| 8eff75a484 | |||
| e232cabfab | |||
| e5ed388191 | |||
| c0ac3de272 | |||
| abde9a99c3 | |||
| bdc74a03c0 | |||
| 2783461e69 | |||
| 0f9c75dc08 | |||
| cf937c6341 | |||
| 77210ffa56 | |||
| fb5bb1cd83 | |||
| 23c4615f5e | |||
| fa2b68dac6 | |||
| bd86cb22e0 | |||
| ec2635131b | |||
| 6b3cfdfb2b | |||
| bce66e3b42 | |||
| cffa035c1b | |||
| 1097192554 | |||
| 0c10b951a9 | |||
| ab2907cd51 | |||
| ea8d3d4531 | |||
| 256e4a0081 | |||
| e7adfff9bf | |||
| 721c9e2c97 | |||
| 42c7e39c99 | |||
| 96778c69bc | |||
| 4adcc403c2 | |||
| 2cca005056 | |||
| d27109640e | |||
| 931e0d4687 | |||
| 2e3224a138 | |||
| cfa3765d50 | |||
| 1287e8c734 | |||
| 11e884aec5 | |||
| 55a1ba710b | |||
| 0a8b266c71 | |||
| 7a6ac3ea92 | |||
| 394c12f68d | |||
| 1a57ad233d | |||
| c268463413 | |||
| 81fe93127d | |||
| aa5716d3f9 | |||
| f9c6f6856b | |||
| b9cc2606f2 | |||
| 5023313c03 | |||
| 98f9f7d42e | |||
| 3e0fd63682 | |||
| 1f643b5816 | |||
| 14adcb9db8 | |||
| 41a22bd83d | |||
| 648b83d6ea | |||
| 4e97b83312 | |||
| 07cd6cd670 | |||
| 3fae38a2f8 | |||
| 23054138c2 | |||
| 63f755554b | |||
| 2ac463f003 | |||
| 77227c2ff5 | |||
| 2afccd7fbd | |||
| 991181104b | |||
| 70aff9fbb2 | |||
| 2370884722 | |||
| c529b1b73a | |||
| acc29fbceb | |||
| 7cc5177078 | |||
| fc93ea7aa3 | |||
| 4c22982732 | |||
| fb935541c9 | |||
| 47023b2e6c | |||
| f4a390201c | |||
| d358ebd7e6 | |||
| 9711dd1381 | |||
| 4c328d83ba | |||
| 9911b132d2 | |||
| 534e5978d8 | |||
| c08bf1204f | |||
| 94d68c1f22 | |||
| 0ca379ed03 | |||
| 0ed2d8b127 | |||
| 3bee571e1f | |||
| 0b78544796 | |||
| 361f71deed | |||
| 61f39ae0a0 | |||
| 082324d7b9 | |||
| 5e99289d7a | |||
| e14a4e79ae | |||
| 39c85cafa2 | |||
| fa6be4ec58 | |||
| 25b8461bfb | |||
| ac43dd0777 | |||
| 963559676e | |||
| 20ce8c4c51 | |||
| 098c09835b | |||
| 4aa9d34b3d | |||
| 38d2a0ddb9 | |||
| 735bb147e2 | |||
| 7a511308ef | |||
| bc401fa392 | |||
| 96fbafe359 | |||
| e82b0ea4cd | |||
| 2160484b62 | |||
| f0ab58dfbb | |||
| c23b5825bb | |||
| f1872f495a | |||
| 9ed36445b9 | |||
| 5043c10d70 | |||
| e748d2f2af | |||
| ecde06e3a3 | |||
| 3505c1d790 | |||
| 150a72f75e | |||
| f96579824b | |||
| 2aa3cabd85 | |||
| 06d26df046 | |||
| 6e49b1cad7 | |||
| d928f425ec | |||
| ed3a9aed12 | |||
| aaccaa19bf | |||
| 35857d3103 | |||
| d47b0eeee7 | |||
| 287beaff35 | |||
| 8e9d1c7ebf | |||
| 53380632a1 | |||
| 984a95b8c7 | |||
| 72118fcc6a | |||
| 1b06f809de | |||
| 19fe508fb2 | |||
| aaaff9b66c | |||
| c660b43105 | |||
| 92b24fd02d | |||
| 886d0de040 | |||
| 16d797cb01 | |||
| bbf9678756 | |||
| d60c619c44 | |||
| e7abc05931 | |||
| 12dd912ce9 | |||
| 64a63b3879 | |||
| 93caf5b311 | |||
| aab2fa1af9 | |||
| 4cf176de0b | |||
| 735cfcd290 | |||
| 4aa4317c28 | |||
| d0ef6d2a9b | |||
| 434c84043d | |||
| 747116aeb0 | |||
| a182dc78f4 | |||
| 1a316c8a18 | |||
| 46e7fa52b3 | |||
| 52ea3748b4 | |||
| 0a2678973b | |||
| 04129c5bd5 | |||
| 6f363dcae3 | |||
| 8c4bd76280 | |||
| 92f385e7b5 | |||
| ac4e259e29 | |||
| 076b20a9a5 | |||
| 0b0230adce | |||
| e51915a529 | |||
| 187a475b84 | |||
| 39c0a619eb | |||
| 29f7eaad78 | |||
| 8f086a6957 | |||
| 8f512001b6 | |||
| 1d25522a3b | |||
| fdb538538a | |||
| 2feb1bf847 | |||
| 74bbb1167f | |||
| 515163864f | |||
| 1cdb975c91 | |||
| cd42d26eb3 | |||
| 8bc96652cd | |||
| 1631a2bac1 | |||
| 501635ca26 | |||
| edcd335b90 | |||
| 0cb9908f27 | |||
| 61858f5899 | |||
| c5911679d1 | |||
| 99d6a077fe | |||
| 8b680254ee | |||
| b873651da7 | |||
| b185d9e701 | |||
| b635622cac | |||
| b31d8b1ad0 | |||
| 2153cb7e0a | |||
| 15033eab28 | |||
| 8b4c530062 | |||
| 9ff9587b7b | |||
| d8acbda548 | |||
| 7e4a65114a | |||
| d9a2d29d00 | |||
| 27931249ce | |||
| 52318d0e0e | |||
| 8d673789be | |||
| 646c4c7458 | |||
| 2cc22d118d | |||
| 1182f41f99 | |||
| 098d1d2b5e | |||
| 31c85f0ec5 | |||
| 091d1f8c75 | |||
| 6c50e6ef34 | |||
| 67f48aca96 | |||
| fc64e787a3 | |||
| d13bed9a0a | |||
| 904c48b11a | |||
| 2ab5eb7213 | |||
| 5ce541e9ef | |||
| 0cf9c22033 | |||
| 38e06f13d6 | |||
| ccc94f6832 | |||
| 589820639c | |||
| 68b9260c9b | |||
| 49b2447113 | |||
| 89c50bbd82 | |||
| 2b3f3e11d3 | |||
| 4100cfec86 | |||
| cad3a50e4e | |||
| 4d9ee55468 | |||
| b72f009d87 | |||
| 2181e0fc27 | |||
| cd74cdfdaf | |||
| 49ab935ae9 | |||
| 6879c9d8df | |||
| 939bf4bb5d | |||
| 7861dfd667 | |||
| c5fc28de7d | |||
| 535d290293 | |||
| a0dd975686 | |||
| f48531efaf | |||
| c6a4116082 | |||
| aecd6b85e6 | |||
| 55439ef293 | |||
| d4cf103676 | |||
| 489fb087a4 | |||
| ff904ae174 | |||
| d8db5ec7b6 | |||
| 5d8b78cb88 | |||
| 9736402dfd | |||
| 0600054ad4 | |||
| b782fca75b | |||
| 0230b88078 | |||
| 55c9fb7c5c | |||
| 8201a9ce6e | |||
| 561a94cc50 | |||
| 0636887931 | |||
| 0c1b39d881 | |||
| 67ffae7e32 | |||
| 488a38a96d | |||
| 77e5854a16 | |||
| 2a42dab108 | |||
| 092d103d24 | |||
| 12b7df550f | |||
| 006bd2fe17 | |||
| d252768ac5 | |||
| dd7c2c0574 | |||
| c91898a888 | |||
| afa8eb2d6f | |||
| 1481015dc4 | |||
| 8cdedd4cd2 | |||
| 985e4eed60 | |||
| 9d0583e0d2 | |||
| 9aed26a234 | |||
| 3323d5c76c | |||
| 4b9afd787c | |||
| cedf01d094 | |||
| 4a71603a77 | |||
| aadc8477b9 | |||
| 9bf111bd3d | |||
| 8060da2132 | |||
| b495a302b0 | |||
| 9453b2387b | |||
| a4de59c8ee | |||
| fab40080e4 | |||
| fb30bda7d7 | |||
| 65206fe33e | |||
| 2f094134a3 | |||
| 69e1f42aed | |||
| c35c58b023 | |||
| 4b57aec1c6 | |||
| 2038bd0c15 | |||
| 19b24fcce2 | |||
| ed3354b433 | |||
| 963eeee361 | |||
| c3a316664a | |||
| 3d16880d95 | |||
| be6f355665 | |||
| 5dba08fb3b | |||
| f17077c05c | |||
| 8aa36072fc | |||
| 44ea82f845 | |||
| 0de7df9eab | |||
| 60e509b1e0 | |||
| 551c379f1b | |||
| c39a360372 | |||
| 683ee75703 | |||
| f6d1724835 | |||
| a99da47b0d | |||
| 0f217c715e | |||
| c4033c215e | |||
| e914d551e7 | |||
| c6e4b8ed5c | |||
| ab398f3704 | |||
| 699aec331d | |||
| baea6a1da8 | |||
| d2375a79f2 | |||
| ba48093666 | |||
| d4b87f1672 | |||
| e4006eb583 | |||
| b934e4b564 | |||
| 28c97a9467 | |||
| 28fca190ee | |||
| 78116e0ea2 | |||
| 5a50afa1fd | |||
| cf77a0e2b4 | |||
| e2593a6883 | |||
| 00a44d1ddb | |||
| d8445fd9df | |||
| 304db907f5 | |||
| b09cdc0f25 | |||
| bd81c6f5b4 | |||
| 4051dd9522 | |||
| 360cb9eb9a | |||
| 241a939c29 | |||
| 2f9c5d2d0b | |||
| 99c812b02d | |||
| d82c2ce50f | |||
| 6c12156b1a | |||
| eec3b3009f | |||
| 5ac7fe453f | |||
| 4654b41c3e | |||
| b09ea17f0e | |||
| 99ebfc337e | |||
| e5f9458905 | |||
| f9c083073e | |||
| ec0a9a5f8a | |||
| 47b924990f | |||
| 215bebb01a | |||
| 9fffa19c51 | |||
| b54f3d4ee9 | |||
| bcdcad5847 | |||
| 737b8e42e4 | |||
| c61e7c05da | |||
| a919828003 | |||
| 0bd33882b6 | |||
| e0e55a649c | |||
| f32d71eca0 | |||
| 74338733ba | |||
| 5fb98609cd | |||
| 19633ece80 | |||
| fb04103352 | |||
| 9abf43b0d2 | |||
| 7f97274ecc | |||
| b2edab193f | |||
| 184563bbe1 | |||
| 73f25ed182 | |||
| 533f6a552c | |||
| 32ac319525 | |||
| 569397bd7e | |||
| 3535d16c3a | |||
| 7f4efa90c8 | |||
| bab3cd988e | |||
| feda213c0c | |||
| c6593e8cde | |||
| 4d8d3919c0 | |||
| 20dc8b222d | |||
| 55733171c1 | |||
| 988926b59d | |||
| d72f8da6d7 | |||
| 0b697b24bd | |||
| b2c75dc3a2 | |||
| b5b3f1fb42 | |||
| bd73834e19 | |||
| 7f43c24297 | |||
| 1b3657122c | |||
| 0f28857c59 | |||
| 88485d5467 | |||
| 921530dd01 | |||
| dcf3023d93 | |||
| 6ac2c5c6dc | |||
| 45b3ae31af | |||
| b12c46b28a | |||
| 66a20264ab | |||
| d2d243cca8 | |||
| d4194962b0 | |||
| 635d671ee7 | |||
| ee8372145d | |||
| ccb736411b | |||
| e2e5641a45 | |||
| 7ca0b256eb | |||
| ca442defbb | |||
| b17ebeb6f6 | |||
| a8afcf1ca9 | |||
| 6545cc2d48 | |||
| 2a10c8fe5c | |||
| 7cd2d14b64 | |||
| fc5abfd68b | |||
| cb5c821989 | |||
| ab7652010b | |||
| 7990566f6b | |||
| b6baee5f77 | |||
| 24c3ec235a | |||
| 204c0fa4d8 | |||
| 3a0b66d5df | |||
| 07d3122c14 | |||
| c6957e4e31 | |||
| 8068a3899d | |||
| 4c0e9f1f89 | |||
| 3cce972125 | |||
| 52700d6a84 | |||
| 0c80a4b836 | |||
| 46f408cc9f | |||
| 5c068a9062 | |||
| e1fae5b902 | |||
| 20e5e95ff8 | |||
| a238f78855 | |||
| 5b96712ed0 | |||
| f141078073 | |||
| d47fed16a9 | |||
| bc43a8d38d | |||
| ccd5685cee | |||
| f0f8177a19 | |||
| 363b701925 | |||
| 0a897e2fae | |||
| 5f53d815d1 | |||
| 7b89f25818 | |||
| 8ebb84ad1e | |||
| f0e77a309d | |||
| 7ab531bd21 | |||
| d7af6de9b9 | |||
| 3072479c3c | |||
| 62031c24a2 | |||
| aa38889704 | |||
| 17562e476f | |||
| 6495f2cf98 | |||
| ea20b644cc | |||
| bf848637aa | |||
| 759f846b2b | |||
| 3758be55f5 | |||
| 8f4c59b080 | |||
| 1ff6212ffa | |||
| b60d29ae9a | |||
| 38d71e668d | |||
| 7cdf37eaf6 | |||
| 8d9adfd548 | |||
| a3e2d90f4c | |||
| fc81008ab5 | |||
| a1eae6304f | |||
| 49058620f0 | |||
| f68a3639b4 | |||
| f4e87c9720 | |||
| 23bf7973fa | |||
| 67e0751124 | |||
| f76559daf6 | |||
| 5e99ff6769 | |||
| 1ecb4aa9aa | |||
| a2b3c72647 | |||
| 0180a4fcd4 | |||
| abca3ceac8 | |||
| 866a9fdf19 | |||
| 20e954a864 | |||
| 03e40b333a | |||
| ebed66d4ce | |||
| 9e9f3c485b | |||
| d50a844720 | |||
| 89e559296e | |||
| d352e2fa31 | |||
| 71bc452764 | |||
| f048ad13b5 | |||
| d03d5d8f03 | |||
| 6ff0ce15e7 | |||
| 330b393e16 | |||
| a820246f64 | |||
| 1bf4c8c9ba | |||
| ca1d437435 | |||
| 8b8310711e | |||
| cdcb64b0d0 | |||
| 3c0f1caa41 | |||
| 8182ba4ee0 | |||
| 3d9328fd79 | |||
| 6c6f9f7d25 | |||
| c8f475174e | |||
| 3dec55f009 | |||
| 00d60e28c2 | |||
| ea00619c3b | |||
| bbe50bdaf1 | |||
| 6b59aee336 | |||
| 26a5614572 | |||
| 19ea090633 | |||
| 9841b11a54 | |||
| 5a6d5374d7 | |||
| 9099bc0b6e | |||
| e3b43b6e1c | |||
| b0d801f629 | |||
| c48057081e | |||
| ea76e09ea7 | |||
| c9fb078c0f | |||
| 1800030356 | |||
| 43ba2c6226 | |||
| 735181dc0e | |||
| 8a890fd3d3 | |||
| 15e31e47fa | |||
| 9b54b99bf6 | |||
| 67ca9166d3 | |||
| b2ced834ba | |||
| 18746c1444 | |||
| 09f366bec7 | |||
| 3998d0c81e | |||
| 2a002c3882 | |||
| fb756e3463 | |||
| 3c5661b51b | |||
| 26e06ba6a6 | |||
| 7c57dde255 | |||
| 9ec927b9e9 | |||
| 15a0d9f900 | |||
| f26e3c6509 | |||
| 6568625dea | |||
| 427f212170 | |||
| c1fb8eaf1a | |||
| 37469dc9c2 | |||
| dce57627c9 | |||
| 2992ca5df1 | |||
| a5ed5883c7 | |||
| 0036509f74 | |||
| 003c470a4d | |||
| d6540d9077 | |||
| 091c515fea | |||
| 4f2b9835f5 | |||
| 242d3b3c4d | |||
| c66ac9725e | |||
| feacc5cd11 | |||
| 3a761395be | |||
| a78d6fe0b3 | |||
| 08e466938f | |||
| e036155bdb | |||
| 2149afabe1 | |||
| ec32967daa | |||
| fc4a5e61c2 | |||
| e9608c9d05 | |||
| 581eebb197 | |||
| 10fa67fdaa | |||
| 10f2136675 | |||
| d97dd99d91 | |||
| 296674e18b | |||
| 52a926dd90 | |||
| d38ea63c78 | |||
| 2022a7615a | |||
| dca0fae781 | |||
| e16c6c1b6b | |||
| ede9881458 | |||
| a7f8c78358 | |||
| 3a90b40425 | |||
| 454709559b | |||
| c3933cead4 | |||
| 420f93ce78 | |||
| 2a212a7556 | |||
| 145a7a24e8 | |||
| 6c040497ef | |||
| 9ee4b76cd9 | |||
| 3f6775e29b | |||
| 4c17e2e97e | |||
| eac53fed59 | |||
| fed0c2ea26 | |||
| 21c1618d94 | |||
| d37699f51a | |||
| d82bfa98a7 | |||
| 9b15bda055 | |||
| 635842b322 | |||
| 3b8515beb0 | |||
| 7b62b81ebd | |||
| dcf4e51787 | |||
| 7dc09ed450 | |||
| 349641e95f | |||
| 9941ec85d8 | |||
| ef944b903b | |||
| 0c477f2c6b | |||
| 151396507e | |||
| 8441c0c51e | |||
| ae7bf468d1 | |||
| 907ef82d4b | |||
| 7a1ab62987 | |||
| 295cfc905c | |||
| 204924927a | |||
| f622a8393c | |||
| d75df7fd8a | |||
| 2bc5e0ebd7 | |||
| ca6cef9a7d | |||
| 1c2a30d7e9 | |||
| 4a75a1e839 | |||
| 6a2ff3a371 | |||
| 7ce1386d1a | |||
| d6f45e4d76 | |||
| 356f66784f | |||
| 166ab7b600 | |||
| 1cdb0abf80 | |||
| 0defd1d141 | |||
| 24ed07b6d5 | |||
| ecad730945 | |||
| efb7fd919b | |||
| 5d6b923244 | |||
| d8752da7d5 | |||
| 6952124988 | |||
| a6c93e2c41 | |||
| 788f3c22bf | |||
| c194dfbdf7 | |||
| 5e996a1c02 | |||
| b52bf11ea5 | |||
| 7915dde43c | |||
| 7675b9c28f | |||
| ebe5636307 | |||
| 6fe2df1d7d | |||
| 5376d32772 | |||
| 2924e478ee | |||
| 297700ad11 | |||
| 9d29914304 | |||
| b223bc0302 | |||
| 3562a38f8c | |||
| 201544ef8b | |||
| 837ba6c33b | |||
| 3ab01dbc00 | |||
| c241edaa30 | |||
| e0530df98a | |||
| 6cbce9fdff | |||
| c1eb536726 | |||
| b848ae7abb | |||
| f07453d0ae | |||
| 052051244f | |||
| 97490c6445 | |||
| 1247d36a12 | |||
| f3a463000d | |||
| c38842ecb2 | |||
| 8b825b23b1 | |||
| d2f62730bc | |||
| d167d18bb3 | |||
| 508d7c3336 | |||
| 2b31d85cd4 | |||
| e350c37e6f | |||
| 319a465429 | |||
| 9371325246 | |||
| 2fda3cf988 | |||
| 03b7194c97 | |||
| 39bff40a75 | |||
| 3dc6edfd2d | |||
| 762747273e | |||
| 0f392a95ae | |||
| 29786b0024 | |||
| 32ca50a097 | |||
| 8012e6fa43 | |||
| 54b7cefb09 | |||
| 3a61350f4b | |||
| bdbbaf6c88 | |||
| 24a1a8a626 | |||
| 38b64dc5df | |||
| e3360a0e5d | |||
| 4181444734 | |||
| 7958708641 | |||
| 40a8ed535a | |||
| c7d571f0b5 | |||
| 5d54b710e7 | |||
| 248f14a1ef | |||
| b76fc58543 | |||
| 9fc9981a9e | |||
| 8f563df7c5 | |||
| 730192adc4 | |||
| 8bf32ac697 | |||
| 540f724b1f | |||
| d5a8f2298e | |||
| 18c5a53685 | |||
| a1172d31f4 | |||
| 396debb9cb | |||
| c4cb2f2378 | |||
| 74ce99e0d7 | |||
| 89a233ccd2 | |||
| 2df6cabee0 | |||
| 82023cd629 | |||
| 1e17f44991 | |||
| 600c97cc0f | |||
| 7298054974 | |||
| 4d5a442d1f | |||
| 249f42f054 | |||
| 87788142bf | |||
| f0b08a6c67 | |||
| a144a49a9a | |||
| 2167f1b567 | |||
| c5c723b80c | |||
| 66461c9dbc | |||
| d77103e53e | |||
| 963908e508 | |||
| 9e5677ab02 | |||
| 46bb9bc5c7 | |||
| 118ab60588 | |||
| 223ae61c89 | |||
| 1f4baba06e | |||
| fa1ce7d5d1 | |||
| 775a488a36 | |||
| 018904f0ec | |||
| b358641e7d | |||
| ff745e0ad8 | |||
| 4201834b18 | |||
| 2631e07bea | |||
| 76a1851cb8 | |||
| 87a1792677 | |||
| 413077a5d9 | |||
| d56fdd2937 | |||
| 6639b7d017 | |||
| 7702a488e5 | |||
| 3108752a0c | |||
| 56c0d32ea0 | |||
| c0e84b0592 | |||
| f2e590be7a | |||
| 60ec3594ab | |||
| 49d1f6aca0 | |||
| 49cd9648b0 | |||
| 1692dcf8d5 | |||
| 5ec4719124 | |||
| 911c98e235 | |||
| 535c64c318 | |||
| 171f38b9b5 | |||
| b2645b3201 | |||
| a9936d1570 | |||
| 3032a4274d | |||
| 31c21a054b | |||
| def4fdc3f3 | |||
| 3fed1af7df | |||
| adb4692ce8 | |||
| bb4ff84a4a | |||
| 5d2c1b175e | |||
| 2ab6de8ee4 | |||
| 1896ae5d15 | |||
| 6e4fab19a2 | |||
| 103dcfe897 | |||
| 8caadbacf7 | |||
| 870d776875 | |||
| 59e66ffe49 | |||
| 418a0132d0 | |||
| a381846034 | |||
| 1c5ce75d9f | |||
| 8693a045bb | |||
| b567679eb6 | |||
| e6c8d3d1db | |||
| 12c4afd824 | |||
| 968a07ed7a | |||
| f9c600a760 | |||
| 82561cfbac | |||
| 277ae4e2b0 | |||
| 0f9e747583 | |||
| 4e146a75b6 | |||
| 33d0e2037b | |||
| 7a04b7262e | |||
| f2d5e4b995 | |||
| ada42aa184 | |||
| ed580b3060 | |||
| 29e4762011 | |||
| eff4833840 | |||
| 9867037aa2 | |||
| 57c14f6a9b | |||
| 1ed105205c | |||
| 8233f49beb | |||
| 2c01a4613c | |||
| b0eda47b26 | |||
| 291111e626 | |||
| 47693da4aa | |||
| 9f39209712 | |||
| c47dcbbe2f | |||
| f313538ea5 | |||
| 956ffdf654 | |||
| ef4a527c36 | |||
| 3fe0680ad5 | |||
| 182b269e46 | |||
| 05856ac93e | |||
| 60c29e195a | |||
| 6b23662ce6 | |||
| 77d6364405 | |||
| 077a611a5e | |||
| e82146bf17 | |||
| 0c3522133d | |||
| 1223e8cf7f | |||
| bcb01bdc52 | |||
| dfb5f8ea2c | |||
| 02eab95dd1 | |||
| 67a1e6e46a | |||
| fda1e4409c | |||
| 703c1b0fcf | |||
| e1654e9dd3 | |||
| f8bdd42027 | |||
| f5dcbf517b | |||
| 075193af1d | |||
| 808e7ed4ae | |||
| f0ba5d3821 | |||
| 88f6b5f16b | |||
| 68e6e1b779 | |||
| 9528325777 | |||
| b3aa6afba9 | |||
| 716fe2f427 | |||
| 7df1cc075c | |||
| b0f0a02d3c | |||
| 7cda64e52d | |||
| d6d34bd62f | |||
| 68dde07d5d | |||
| fad4ae8eb2 | |||
| acd8a4bc95 | |||
| 6714e05183 | |||
| f9b5f2b7b1 | |||
| 67fa5df89c | |||
| 023cc9ca54 | |||
| b7924de5c6 | |||
| 4b4481ea27 | |||
| 47be46ae60 | |||
| e84802468b | |||
| 623d789529 | |||
| 827f36e2c0 | |||
| 1a5ed4eb7f | |||
| 5151403aaa | |||
| d5772c939a | |||
| 19097bc5bc | |||
| dbebe9e92c | |||
| be0a543077 | |||
| 67b6a8ee89 | |||
| 780375d865 | |||
| cbcf94669e | |||
| 46da53ba15 | |||
| 06e8d03fba | |||
| 65bf7f6653 | |||
| a6b9341593 | |||
| 47610725ea | |||
| 341ba34773 | |||
| 3b2864d8a6 | |||
| c7d4af5c79 | |||
| f2ec438166 | |||
| a95b064d6d | |||
| c503a75873 | |||
| 9a982cc5b5 | |||
| 685f7d0fea | |||
| f5d9ca64f9 | |||
| cde442fa2c | |||
| 84f966cb8f | |||
| b2b88f1d99 | |||
| 9d23a392a6 | |||
| 57214c63cb | |||
| 6726df4d58 | |||
| 02a58c1247 | |||
| 72a7b35513 | |||
| 2d699fd13b | |||
| 13c321b8fb | |||
| fa42a788c8 | |||
| 843eaf8893 | |||
| 30fa8f8ac2 | |||
| 0ec4e8d5d4 | |||
| af63eff8d7 | |||
| b5d2dd617d | |||
| 8d951ab7f1 | |||
| e24315eed8 | |||
| dc55e88588 | |||
| 7abaf77292 | |||
| e79883e4fd | |||
| 5da76ae34b | |||
| a6d5f9877f | |||
| 994825671d | |||
| b7b5043aea | |||
| 1bf4a6f711 | |||
| 073f51e284 | |||
| b5784bc2ef | |||
| b42bb5be26 | |||
| b6f356c211 | |||
| b052da1065 | |||
| 586e85281e | |||
| ec3ea3752f | |||
| 8294480cb4 | |||
| 6fe8692b98 | |||
| d8e0a86600 | |||
| 8b29b07f5a | |||
| 1d6936fafc | |||
| b22d71a74e | |||
| 7fc2081543 | |||
| b8c2b0105b | |||
| d72db2698b | |||
| e0d9092df8 | |||
| f863264af6 | |||
| 14736c2a8b | |||
| 0af1b75a02 | |||
| 7a8aa03e54 | |||
| 846c0f7cfc | |||
| 1886193c6c | |||
| 100e907890 | |||
| 383c222553 | |||
| ae6e76bbb3 | |||
| ed7284add2 | |||
| 9ecbd70daa | |||
| b8989d9bf9 | |||
| 0f1c5b3891 | |||
| 41ff7a6010 | |||
| 0234f50da1 | |||
| d7cc166eab | |||
| eef44425c3 | |||
| 167b320cdd | |||
| dcf53236ff | |||
| 5b1a531755 | |||
| 97b2d1fe5c | |||
| c5af69ffa6 | |||
| 12d56103d9 | |||
| 8ff713f3bb | |||
| 03972d565e | |||
| 4dcf253330 | |||
| 012f386057 | |||
| 3fa684d6ba | |||
| 8c327567c0 | |||
| 31bc982a53 | |||
| cbd2d89637 | |||
| 67151d39e1 | |||
| d715158fe3 | |||
| 75c0eef6ac | |||
| 4030c5a689 | |||
| 119cafd963 | |||
| 5fc54ec7e5 | |||
| fb0b9de7a9 | |||
| 2c9156e2c1 | |||
| 236347b5bc | |||
| c5d2b01923 | |||
| bf75fd9d34 | |||
| 9a8c69d1c0 | |||
| 6c943722f3 | |||
| 219343f3c0 | |||
| 36b2f13ee0 | |||
| 70ce878dfb | |||
| 9c1612f122 | |||
| 6cba4d3483 | |||
| 738cf837de | |||
| 2550918f27 | |||
| aa5a222c6d | |||
| 2795f09fa8 | |||
| adcaace03c | |||
| f205df1996 | |||
| c59ad24856 | |||
| 2b9b0ac62e | |||
| 08bc6a1698 | |||
| 67e6f57192 | |||
| 24ddb8506f | |||
| 6ff0cc0b40 | |||
| 7620fe1ac6 | |||
| 22e0f5ecd0 | |||
| fce2042375 | |||
| 57594153a1 | |||
| ff93ea5bf1 | |||
| 4a54676f31 | |||
| 0d900521bc | |||
| bd7ffcc048 | |||
| 2f771bee7b | |||
| ae5214c1f2 | |||
| 24493e89ad | |||
| 84d8798ad3 | |||
| 0570c84a83 | |||
| a3860e23c6 | |||
| ab7e1e01de | |||
| bbafc3fbd6 | |||
| 194fa7cd98 | |||
| 4c12addcaf | |||
| 0bd27381c3 | |||
| 6dce07790a | |||
| 203ae32b79 | |||
| 3c493194c9 | |||
| 692764aad3 | |||
| 937e5de1d8 | |||
| 7de67f8c1b | |||
| f5d66bcb6f | |||
| bf82c40964 | |||
| aa6299f114 | |||
| 7ffca8ed58 | |||
| 030405dbb6 | |||
| 8862f9118b | |||
| e2e98672bd | |||
| 51f295cacc | |||
| 0c50ac3396 | |||
| 2da81a4a26 | |||
| b6d4853a33 | |||
| 020b147222 | |||
| 34b037f19b | |||
| 88ee5d1a6d | |||
| 0892d84c17 | |||
| 2501d50f9c | |||
| 1e4a4181e2 | |||
| 3e1daa002c | |||
| 4c13dee18f | |||
| 95497626e3 | |||
| 9ada48054f | |||
| 99d6c58971 | |||
| b974b3ccfd | |||
| 75cf45f0be | |||
| d337a11e83 | |||
| a86386d882 | |||
| bbf40bf318 | |||
| b054585066 | |||
| 90c44c34a9 | |||
| e449cc9e2d | |||
| 909ed93cd3 | |||
| 9c97b11ab9 | |||
| 5ae44b25da | |||
| b2ecb37b35 | |||
| 144d034475 | |||
| 50d8dc91cf | |||
| e58915e12f | |||
| 7f8c2a44a4 | |||
| d986eee36b | |||
| b3e712e0b8 | |||
| 05434daa69 | |||
| 2c4a478987 | |||
| a80ca23937 | |||
| ba02ef8f25 | |||
| ef3d8bdc42 | |||
| 951511704d | |||
| 23aae6ab0f | |||
| 3748e117a9 | |||
| 33798b8b80 | |||
| 2e85083d0a | |||
| 23b8a9033a | |||
| 313b6874b1 | |||
| 6004412365 | |||
| adac039a2b | |||
| adcc865c70 | |||
| fe533fb809 | |||
| fa62963da7 | |||
| 1f5bb99548 | |||
| f1cd56c28a | |||
| 852c8b533c | |||
| 582a72574e | |||
| b249ddde48 | |||
| b020ba2b5f | |||
| 03c6862d51 | |||
| b7f953b2ee | |||
| 0b064765c9 | |||
| eb3ddce706 | |||
| 5fdc9fa3b6 | |||
| bfb231fb8a | |||
| 74fb74d9cb | |||
| 97d7e295dd | |||
| 0727e91aeb | |||
| 8dc70f797c | |||
| 2cf8a9da6f | |||
| c1c7128634 | |||
| 0e9ef50e63 | |||
| e05944601a | |||
| 49cf0125a9 | |||
| 0602a16ad6 | |||
| 09a0dad115 | |||
| 243a3f5006 | |||
| 33ca85bd4e | |||
| ca15eb26f0 | |||
| 28eebc14d0 | |||
| 4210aa9ab9 | |||
| 5bbdbadc25 | |||
| 00f24a3249 | |||
| d8a798372b | |||
| 8d5c865814 | |||
| 5134d6bc63 | |||
| ede57720fd | |||
| 830d2007a6 | |||
| 5f3b6c9722 | |||
| 93f7d3bfb9 | |||
| f0ef10aa57 | |||
| bf91fcc6f7 | |||
| 2d894a0164 | |||
| 731b9c902f | |||
| ac0f3c8433 | |||
| 56bfbbf501 | |||
| 63b5d472fa | |||
| 233e3c76fd | |||
| 2334dadb6a | |||
| 6f4f2754d6 | |||
| 30ced04137 | |||
| c39bd7e089 | |||
| 3470d986f0 | |||
| 7c0257fcda | |||
| 9af6d6c9c6 | |||
| 1ecab2fcbc | |||
| a262c0bbf3 | |||
| 7f3f164736 | |||
| 085db569f1 | |||
| 133af6f826 | |||
| 1c2301e2f1 | |||
| ef999f660b | |||
| fad330acd1 | |||
| 8f1af2630d | |||
| eea92a3371 | |||
| ff275df5ea | |||
| 6e56e5457d | |||
| afaa5f2deb | |||
| 0674b1b6ee | |||
| 1ef8602f19 | |||
| ee597fc9b8 | |||
| e254581a1b | |||
| 38ea140b3f | |||
| d939d6079a | |||
| 6e9475d61d | |||
| f6134422e6 | |||
| 5c05038af0 | |||
| 5da5ebff13 | |||
| 798932523e | |||
| 5267a864db | |||
| f02334237a | |||
| d5ea492ef5 | |||
| 96ac405952 | |||
| 38d58e818c | |||
| 090723179b | |||
| 5b55fbff23 | |||
| 64f200dc74 | |||
| c02ff3af27 | |||
| 13c6352b8e | |||
| 707c2b3d7a | |||
| 14eed79a21 | |||
| 2ca30e3acd | |||
| caf9716bf1 | |||
| d569daae33 | |||
| 28f7f57247 | |||
| 34cb558279 | |||
| f36e19e86f | |||
| 86fada718e | |||
| 2a94b66f4d | |||
| 4ee413aa32 | |||
| 2d824e4809 | |||
| 9474c99795 | |||
| 84a7f222ff | |||
| d29423c24e | |||
| 02a8bba02e | |||
| 6ea68869c9 |
@@ -0,0 +1,10 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
end_of_line = lf
|
||||||
|
|
||||||
|
[*.y{,a}ml]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
tab_width = 2
|
||||||
+20
-13
@@ -58,8 +58,8 @@ jobs:
|
|||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Download LLVM, botan and setup PATH
|
- name: Download LLVM, botan and setup PATH
|
||||||
run: |
|
run: |
|
||||||
brew install llvm@11 botan
|
brew install llvm@13 botan
|
||||||
echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
|
echo "/usr/local/opt/llvm@13/bin" >> $GITHUB_PATH
|
||||||
TMP_PATH=$(xcrun --show-sdk-path)/user/include
|
TMP_PATH=$(xcrun --show-sdk-path)/user/include
|
||||||
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
|
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
|
||||||
- name: build odin
|
- name: build odin
|
||||||
@@ -104,13 +104,13 @@ jobs:
|
|||||||
run: ./odin check examples/all -vet -strict-style -target:linux_arm64
|
run: ./odin check examples/all -vet -strict-style -target:linux_arm64
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
build_windows:
|
build_windows:
|
||||||
runs-on: windows-2019
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: build Odin
|
- name: build Odin
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
./build.bat 1
|
./build.bat 1
|
||||||
- name: Odin version
|
- name: Odin version
|
||||||
run: ./odin version
|
run: ./odin version
|
||||||
@@ -121,58 +121,65 @@ jobs:
|
|||||||
- name: Odin check
|
- name: Odin check
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin check examples/demo -vet
|
odin check examples/demo -vet
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run
|
- name: Odin run
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin run examples/demo
|
odin run examples/demo
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run -debug
|
- name: Odin run -debug
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin run examples/demo -debug
|
odin run examples/demo -debug
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin check examples/all
|
- name: Odin check examples/all
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin check examples/all -strict-style
|
odin check examples/all -strict-style
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Core library tests
|
- name: Core library tests
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
cd tests\core
|
cd tests\core
|
||||||
call build.bat
|
call build.bat
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Vendor library tests
|
- name: Vendor library tests
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
cd tests\vendor
|
cd tests\vendor
|
||||||
call build.bat
|
call build.bat
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin internals tests
|
- name: Odin internals tests
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
cd tests\internal
|
cd tests\internal
|
||||||
call build.bat
|
call build.bat
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
- name: Odin documentation tests
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
|
cd tests\documentation
|
||||||
|
call build.bat
|
||||||
|
timeout-minutes: 10
|
||||||
- name: core:math/big tests
|
- name: core:math/big tests
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
cd tests\core\math\big
|
cd tests\core\math\big
|
||||||
call build.bat
|
call build.bat
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin check examples/all for Windows 32bits
|
- name: Odin check examples/all for Windows 32bits
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin check examples/all -strict-style -target:windows_i386
|
odin check examples/all -strict-style -target:windows_i386
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
|
|||||||
@@ -7,24 +7,26 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_windows:
|
build_windows:
|
||||||
runs-on: windows-2019
|
if: github.repository == 'odin-lang/Odin'
|
||||||
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: build Odin
|
- name: build Odin
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
./build.bat 1 1
|
./build.bat 1 1
|
||||||
- name: Odin run
|
- name: Odin run
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin run examples/demo
|
odin run examples/demo
|
||||||
- name: Copy artifacts
|
- name: Copy artifacts
|
||||||
run: |
|
run: |
|
||||||
rm bin/llvm/windows/LLVM-C.lib
|
rm bin/llvm/windows/LLVM-C.lib
|
||||||
mkdir dist
|
mkdir dist
|
||||||
cp odin.exe dist
|
cp odin.exe dist
|
||||||
|
cp LICENSE dist
|
||||||
cp LLVM-C.dll dist
|
cp LLVM-C.dll dist
|
||||||
cp -r shared dist
|
cp -r shared dist
|
||||||
cp -r core dist
|
cp -r core dist
|
||||||
@@ -37,6 +39,7 @@ jobs:
|
|||||||
name: windows_artifacts
|
name: windows_artifacts
|
||||||
path: dist
|
path: dist
|
||||||
build_ubuntu:
|
build_ubuntu:
|
||||||
|
if: github.repository == 'odin-lang/Odin'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
@@ -50,6 +53,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir dist
|
mkdir dist
|
||||||
cp odin dist
|
cp odin dist
|
||||||
|
cp LICENSE dist
|
||||||
cp libLLVM* dist
|
cp libLLVM* dist
|
||||||
cp -r shared dist
|
cp -r shared dist
|
||||||
cp -r core dist
|
cp -r core dist
|
||||||
@@ -61,13 +65,14 @@ jobs:
|
|||||||
name: ubuntu_artifacts
|
name: ubuntu_artifacts
|
||||||
path: dist
|
path: dist
|
||||||
build_macos:
|
build_macos:
|
||||||
|
if: github.repository == 'odin-lang/Odin'
|
||||||
runs-on: macOS-latest
|
runs-on: macOS-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- name: Download LLVM and setup PATH
|
- name: Download LLVM and setup PATH
|
||||||
run: |
|
run: |
|
||||||
brew install llvm@11
|
brew install llvm@13
|
||||||
echo "/usr/local/opt/llvm@11/bin" >> $GITHUB_PATH
|
echo "/usr/local/opt/llvm@13/bin" >> $GITHUB_PATH
|
||||||
TMP_PATH=$(xcrun --show-sdk-path)/user/include
|
TMP_PATH=$(xcrun --show-sdk-path)/user/include
|
||||||
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
|
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
|
||||||
- name: build odin
|
- name: build odin
|
||||||
@@ -78,6 +83,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir dist
|
mkdir dist
|
||||||
cp odin dist
|
cp odin dist
|
||||||
|
cp LICENSE dist
|
||||||
cp -r shared dist
|
cp -r shared dist
|
||||||
cp -r core dist
|
cp -r core dist
|
||||||
cp -r vendor dist
|
cp -r vendor dist
|
||||||
|
|||||||
+6
-1
@@ -22,6 +22,10 @@ bld/
|
|||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
![Cc]ore/[Ll]og/
|
![Cc]ore/[Ll]og/
|
||||||
|
tests/documentation/verify/
|
||||||
|
tests/documentation/all.odin-doc
|
||||||
|
tests/internal/test_map
|
||||||
|
tests/internal/test_rtti
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
# Visual Studio Code options directory
|
# Visual Studio Code options directory
|
||||||
@@ -268,6 +272,7 @@ bin/
|
|||||||
|
|
||||||
# - Linux/MacOS
|
# - Linux/MacOS
|
||||||
odin
|
odin
|
||||||
|
!odin/
|
||||||
odin.dSYM
|
odin.dSYM
|
||||||
*.bin
|
*.bin
|
||||||
demo.bin
|
demo.bin
|
||||||
@@ -284,4 +289,4 @@ shared/
|
|||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
examples/bug/
|
examples/bug/
|
||||||
build.sh
|
build.sh
|
||||||
!core/debug/
|
!core/debug/
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -11,7 +11,7 @@
|
|||||||
<img src="https://img.shields.io/badge/platforms-Windows%20|%20Linux%20|%20macOS-green.svg">
|
<img src="https://img.shields.io/badge/platforms-Windows%20|%20Linux%20|%20macOS-green.svg">
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<a href="https://discord.gg/odinlang">
|
<a href="https://discord.com/invite/sVBPHEv">
|
||||||
<img src="https://img.shields.io/discord/568138951836172421?logo=discord">
|
<img src="https://img.shields.io/discord/568138951836172421?logo=discord">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/odin-lang/odin/actions">
|
<a href="https://github.com/odin-lang/odin/actions">
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -3,18 +3,20 @@
|
|||||||
setlocal EnableDelayedExpansion
|
setlocal EnableDelayedExpansion
|
||||||
|
|
||||||
where /Q cl.exe || (
|
where /Q cl.exe || (
|
||||||
set __VSCMD_ARG_NO_LOGO=1
|
set __VSCMD_ARG_NO_LOGO=1
|
||||||
for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i
|
for /f "tokens=*" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.VisualStudio.Workload.NativeDesktop -property installationPath') do set VS=%%i
|
||||||
if "!VS!" equ "" (
|
if "!VS!" equ "" (
|
||||||
echo ERROR: Visual Studio installation not found
|
echo ERROR: Visual Studio installation not found
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
call "!VS!\VC\Auxiliary\Build\vcvarsall.bat" amd64 || exit /b 1
|
call "!VS!\VC\Auxiliary\Build\vcvarsall.bat" amd64 || exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%VSCMD_ARG_TGT_ARCH%" neq "x64" (
|
if "%VSCMD_ARG_TGT_ARCH%" neq "x64" (
|
||||||
echo ERROR: please run this from MSVC x64 native tools command prompt, 32-bit target is not supported!
|
if "%ODIN_IGNORE_MSVC_CHECK%" == "" (
|
||||||
exit /b 1
|
echo ERROR: please run this from MSVC x64 native tools command prompt, 32-bit target is not supported!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
for /f "usebackq tokens=1,2 delims=,=- " %%i in (`wmic os get LocalDateTime /value`) do @if %%i==LocalDateTime (
|
for /f "usebackq tokens=1,2 delims=,=- " %%i in (`wmic os get LocalDateTime /value`) do @if %%i==LocalDateTime (
|
||||||
@@ -48,8 +50,14 @@ set odin_version_raw="dev-%curr_year%-%curr_month%"
|
|||||||
set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
|
set compiler_flags= -nologo -Oi -TP -fp:precise -Gm- -MP -FC -EHsc- -GR- -GF
|
||||||
set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\"
|
set compiler_defines= -DODIN_VERSION_RAW=\"%odin_version_raw%\"
|
||||||
|
|
||||||
for /f %%i in ('git rev-parse --short HEAD') do set GIT_SHA=%%i
|
if not exist .git\ goto skip_git_hash
|
||||||
|
for /f "tokens=1,2" %%i IN ('git show "--pretty=%%cd %%h" "--date=format:%%Y-%%m" --no-patch --no-notes HEAD') do (
|
||||||
|
set odin_version_raw=dev-%%i
|
||||||
|
set GIT_SHA=%%j
|
||||||
|
)
|
||||||
if %ERRORLEVEL% equ 0 set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\"
|
if %ERRORLEVEL% equ 0 set compiler_defines=%compiler_defines% -DGIT_SHA=\"%GIT_SHA%\"
|
||||||
|
:skip_git_hash
|
||||||
|
|
||||||
if %nightly% equ 1 set compiler_defines=%compiler_defines% -DNIGHTLY
|
if %nightly% equ 1 set compiler_defines=%compiler_defines% -DNIGHTLY
|
||||||
|
|
||||||
if %release_mode% EQU 0 ( rem Debug
|
if %release_mode% EQU 0 ( rem Debug
|
||||||
@@ -72,6 +80,16 @@ set libs= ^
|
|||||||
Synchronization.lib ^
|
Synchronization.lib ^
|
||||||
bin\llvm\windows\LLVM-C.lib
|
bin\llvm\windows\LLVM-C.lib
|
||||||
|
|
||||||
|
rem DO NOT TOUCH!
|
||||||
|
rem THIS TILDE STUFF IS FOR DEVELOPMENT ONLY!
|
||||||
|
set tilde_backend=0
|
||||||
|
if %tilde_backend% EQU 1 (
|
||||||
|
set libs=%libs% src\tilde\tb.lib
|
||||||
|
set compiler_defines=%compiler_defines% -DODIN_TILDE_BACKEND
|
||||||
|
)
|
||||||
|
rem DO NOT TOUCH!
|
||||||
|
|
||||||
|
|
||||||
set linker_flags= -incremental:no -opt:ref -subsystem:console
|
set linker_flags= -incremental:no -opt:ref -subsystem:console
|
||||||
|
|
||||||
if %release_mode% EQU 0 ( rem Debug
|
if %release_mode% EQU 0 ( rem Debug
|
||||||
@@ -96,4 +114,4 @@ if %release_mode% EQU 0 odin run examples/demo
|
|||||||
|
|
||||||
del *.obj > NUL 2> NUL
|
del *.obj > NUL 2> NUL
|
||||||
|
|
||||||
:end_of_build
|
:end_of_build
|
||||||
+76
-136
@@ -1,123 +1,90 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
: ${CXX=clang++}
|
|
||||||
: ${CPPFLAGS=}
|
: ${CPPFLAGS=}
|
||||||
|
: ${CXX=clang++}
|
||||||
: ${CXXFLAGS=}
|
: ${CXXFLAGS=}
|
||||||
: ${LDFLAGS=}
|
: ${LDFLAGS=}
|
||||||
: ${ODIN_VERSION=dev-$(date +"%Y-%m")}
|
: ${LLVM_CONFIG=}
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
|
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
|
||||||
CXXFLAGS="$CXXFLAGS -std=c++14"
|
CXXFLAGS="$CXXFLAGS -std=c++14"
|
||||||
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
|
|
||||||
|
|
||||||
GIT_SHA=$(git rev-parse --short HEAD || :)
|
|
||||||
if [ "$GIT_SHA" ]; then CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""; fi
|
|
||||||
|
|
||||||
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
|
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
|
||||||
OS=$(uname)
|
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
|
||||||
|
OS_ARCH="$(uname -m)"
|
||||||
|
OS_NAME="$(uname -s)"
|
||||||
|
|
||||||
panic() {
|
if [ -d ".git" ] && [ -n "$(command -v git)" ]; then
|
||||||
printf "%s\n" "$1"
|
GIT_SHA=$(git show --pretty='%h' --no-patch --no-notes HEAD)
|
||||||
|
CPPFLAGS="$CPPFLAGS -DGIT_SHA=\"$GIT_SHA\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
error() {
|
||||||
|
printf "ERROR: %s\n" "$1"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
|
if [ -z "$LLVM_CONFIG" ]; then
|
||||||
|
# darwin, linux, openbsd
|
||||||
config_darwin() {
|
if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17"
|
||||||
ARCH=$(uname -m)
|
elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13"
|
||||||
: ${LLVM_CONFIG=llvm-config}
|
elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12"
|
||||||
|
elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11"
|
||||||
# allow for arm only llvm's with version 13
|
# freebsd
|
||||||
if [ ARCH == arm64 ]; then
|
elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config-17"
|
||||||
MIN_LLVM_VERSION=("13.0.0")
|
elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config-13"
|
||||||
|
elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config-12"
|
||||||
|
elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config-11"
|
||||||
|
# fallback
|
||||||
|
elif [ -n "$(command -v llvm-config)" ]; then LLVM_CONFIG="llvm-config"
|
||||||
else
|
else
|
||||||
# allow for x86 / amd64 all llvm versions beginning from 11
|
error "No llvm-config command found. Set LLVM_CONFIG to proceed."
|
||||||
MIN_LLVM_VERSION=("11.1.0")
|
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
|
LLVM_VERSION="$($LLVM_CONFIG --version)"
|
||||||
if [ ARCH == arm64 ]; then
|
LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')"
|
||||||
panic "Requirement: llvm-config must be base version 13 for arm64"
|
LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')"
|
||||||
else
|
LLVM_VERSION_PATCH="$(echo $LLVM_VERSION | awk -F. '{print $3}')"
|
||||||
panic "Requirement: llvm-config must be base version greater than 11 for amd64/x86"
|
|
||||||
|
if [ $LLVM_VERSION_MAJOR -lt 11 ] ||
|
||||||
|
([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]); then
|
||||||
|
error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14 or 17"
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$OS_NAME" in
|
||||||
|
Darwin)
|
||||||
|
if [ "$OS_ARCH" == "arm64" ]; then
|
||||||
|
if [ $LLVM_VERSION_MAJOR -lt 13 ] || [ $LLVM_VERSION_MAJOR -gt 17 ]; then
|
||||||
|
error "Darwin Arm64 requires LLVM 13, 14 or 17"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MAX_LLVM_VERSION=("14.999.999")
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
if [ $(version $($LLVM_CONFIG --version)) -gt $(version $MAX_LLVM_VERSION) ]; then
|
|
||||||
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
|
|
||||||
panic "Requirement: llvm-config must be base version smaller than 15"
|
|
||||||
fi
|
|
||||||
|
|
||||||
LDFLAGS="$LDFLAGS -liconv -ldl -framework System"
|
LDFLAGS="$LDFLAGS -liconv -ldl -framework System"
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
|
||||||
LDFLAGS="$LDFLAGS -lLLVM-C"
|
LDFLAGS="$LDFLAGS -lLLVM-C"
|
||||||
}
|
;;
|
||||||
|
FreeBSD)
|
||||||
config_freebsd() {
|
|
||||||
: ${LLVM_CONFIG=}
|
|
||||||
|
|
||||||
if [ ! "$LLVM_CONFIG" ]; then
|
|
||||||
if which llvm-config11 > /dev/null 2>&1; then
|
|
||||||
LLVM_CONFIG=llvm-config11
|
|
||||||
elif which llvm-config12 > /dev/null 2>&1; then
|
|
||||||
LLVM_CONFIG=llvm-config12
|
|
||||||
elif which llvm-config13 > /dev/null 2>&1; then
|
|
||||||
LLVM_CONFIG=llvm-config13
|
|
||||||
else
|
|
||||||
panic "Unable to find LLVM-config"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
||||||
}
|
;;
|
||||||
|
Linux)
|
||||||
config_openbsd() {
|
|
||||||
: ${LLVM_CONFIG=/usr/local/bin/llvm-config}
|
|
||||||
|
|
||||||
LDFLAGS="$LDFLAGS -liconv"
|
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
LDFLAGS="$LDFLAGS -ldl $($LLVM_CONFIG --libs core native --system-libs --libfiles)"
|
||||||
}
|
# Copy libLLVM*.so into current directory for linking
|
||||||
|
# NOTE: This is needed by the Linux release pipeline!
|
||||||
config_linux() {
|
|
||||||
: ${LLVM_CONFIG=}
|
|
||||||
|
|
||||||
if [ ! "$LLVM_CONFIG" ]; then
|
|
||||||
if which llvm-config > /dev/null 2>&1; then
|
|
||||||
LLVM_CONFIG=llvm-config
|
|
||||||
elif which llvm-config-11 > /dev/null 2>&1; then
|
|
||||||
LLVM_CONFIG=llvm-config-11
|
|
||||||
elif which llvm-config-11-64 > /dev/null 2>&1; then
|
|
||||||
LLVM_CONFIG=llvm-config-11-64
|
|
||||||
else
|
|
||||||
panic "Unable to find LLVM-config"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
MIN_LLVM_VERSION=("11.0.0")
|
|
||||||
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
|
|
||||||
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
|
|
||||||
panic "Requirement: llvm-config must be base version greater than 11"
|
|
||||||
fi
|
|
||||||
|
|
||||||
MAX_LLVM_VERSION=("14.999.999")
|
|
||||||
if [ $(version $($LLVM_CONFIG --version)) -gt $(version $MAX_LLVM_VERSION) ]; then
|
|
||||||
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
|
|
||||||
panic "Requirement: llvm-config must be base version smaller than 15"
|
|
||||||
fi
|
|
||||||
|
|
||||||
LDFLAGS="$LDFLAGS -ldl"
|
|
||||||
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
|
||||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs --libfiles) -Wl,-rpath=\$ORIGIN"
|
|
||||||
|
|
||||||
# Creates a copy of the llvm library in the build dir, this is meant to support compiler explorer.
|
|
||||||
# The annoyance is that this copy can be cluttering the development folder. TODO: split staging folders
|
|
||||||
# for development and compiler explorer builds
|
|
||||||
cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
|
cp $(readlink -f $($LLVM_CONFIG --libfiles)) ./
|
||||||
}
|
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
|
||||||
|
;;
|
||||||
|
OpenBSD)
|
||||||
|
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||||
|
LDFLAGS="$LDFLAGS -liconv"
|
||||||
|
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Platform \"$OS_NAME\" unsupported"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
build_odin() {
|
build_odin() {
|
||||||
case $1 in
|
case $1 in
|
||||||
@@ -128,13 +95,20 @@ build_odin() {
|
|||||||
EXTRAFLAGS="-O3"
|
EXTRAFLAGS="-O3"
|
||||||
;;
|
;;
|
||||||
release-native)
|
release-native)
|
||||||
EXTRAFLAGS="-O3 -march=native"
|
if [ "$OS_ARCH" == "arm64" ]; then
|
||||||
|
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
|
||||||
|
EXTRAFLAGS="-O3 -mcpu=native"
|
||||||
|
else
|
||||||
|
# Use preferred flag for x86 / amd64
|
||||||
|
EXTRAFLAGS="-O3 -march=native"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
nightly)
|
nightly)
|
||||||
EXTRAFLAGS="-DNIGHTLY -O3"
|
EXTRAFLAGS="-DNIGHTLY -O3"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
panic "Build mode unsupported!"
|
error "Build mode \"$1\" unsupported!"
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
@@ -146,54 +120,20 @@ run_demo() {
|
|||||||
./odin run examples/demo/demo.odin -file
|
./odin run examples/demo/demo.odin -file
|
||||||
}
|
}
|
||||||
|
|
||||||
have_which() {
|
if [ $# -eq 0 ]; then
|
||||||
if ! which which > /dev/null 2>&1; then
|
|
||||||
panic "Could not find \`which\`"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
have_which
|
|
||||||
|
|
||||||
case $OS in
|
|
||||||
Linux)
|
|
||||||
config_linux
|
|
||||||
;;
|
|
||||||
Darwin)
|
|
||||||
config_darwin
|
|
||||||
;;
|
|
||||||
OpenBSD)
|
|
||||||
config_openbsd
|
|
||||||
;;
|
|
||||||
FreeBSD)
|
|
||||||
config_freebsd
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
panic "Platform unsupported!"
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
build_odin debug
|
build_odin debug
|
||||||
run_demo
|
run_demo
|
||||||
exit 0
|
elif [ $# -eq 1 ]; then
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $# -eq 1 ]]; then
|
|
||||||
case $1 in
|
case $1 in
|
||||||
report)
|
report)
|
||||||
if [[ ! -f "./odin" ]]; then
|
[ ! -f "./odin" ] && build_odin debug
|
||||||
build_odin debug
|
|
||||||
fi
|
|
||||||
|
|
||||||
./odin report
|
./odin report
|
||||||
exit 0
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
build_odin $1
|
build_odin $1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
run_demo
|
run_demo
|
||||||
exit 0
|
|
||||||
else
|
else
|
||||||
panic "Too many arguments!"
|
error "Too many arguments!"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -2,25 +2,25 @@ package bufio
|
|||||||
|
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
|
||||||
// Loadahead_Reader provides io lookahead.
|
// Lookahead_Reader provides io lookahead.
|
||||||
// This is useful for tokenizers/parsers.
|
// This is useful for tokenizers/parsers.
|
||||||
// Loadahead_Reader is similar to bufio.Reader, but unlike bufio.Reader, Loadahead_Reader's buffer size
|
// Lookahead_Reader is similar to bufio.Reader, but unlike bufio.Reader, Lookahead_Reader's buffer size
|
||||||
// will EXACTLY match the specified size, whereas bufio.Reader's buffer size may differ from the specified size.
|
// will EXACTLY match the specified size, whereas bufio.Reader's buffer size may differ from the specified size.
|
||||||
// This makes sure that the buffer will not be accidentally read beyond the expected size.
|
// This makes sure that the buffer will not be accidentally read beyond the expected size.
|
||||||
Loadahead_Reader :: struct {
|
Lookahead_Reader :: struct {
|
||||||
r: io.Reader,
|
r: io.Reader,
|
||||||
buf: []byte,
|
buf: []byte,
|
||||||
n: int,
|
n: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
lookahead_reader_init :: proc(lr: ^Loadahead_Reader, r: io.Reader, buf: []byte) -> ^Loadahead_Reader {
|
lookahead_reader_init :: proc(lr: ^Lookahead_Reader, r: io.Reader, buf: []byte) -> ^Lookahead_Reader {
|
||||||
lr.r = r
|
lr.r = r
|
||||||
lr.buf = buf
|
lr.buf = buf
|
||||||
lr.n = 0
|
lr.n = 0
|
||||||
return lr
|
return lr
|
||||||
}
|
}
|
||||||
|
|
||||||
lookahead_reader_buffer :: proc(lr: ^Loadahead_Reader) -> []byte {
|
lookahead_reader_buffer :: proc(lr: ^Lookahead_Reader) -> []byte {
|
||||||
return lr.buf[:lr.n]
|
return lr.buf[:lr.n]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ lookahead_reader_buffer :: proc(lr: ^Loadahead_Reader) -> []byte {
|
|||||||
// lookahead_reader_peek returns a slice of the Lookahead_Reader which holds n bytes
|
// lookahead_reader_peek returns a slice of the Lookahead_Reader which holds n bytes
|
||||||
// If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest.
|
// If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest.
|
||||||
// NOTE: The returned buffer is not a copy of the underlying buffer
|
// NOTE: The returned buffer is not a copy of the underlying buffer
|
||||||
lookahead_reader_peek :: proc(lr: ^Loadahead_Reader, n: int) -> ([]byte, io.Error) {
|
lookahead_reader_peek :: proc(lr: ^Lookahead_Reader, n: int) -> ([]byte, io.Error) {
|
||||||
switch {
|
switch {
|
||||||
case n < 0:
|
case n < 0:
|
||||||
return nil, .Negative_Read
|
return nil, .Negative_Read
|
||||||
@@ -58,13 +58,13 @@ lookahead_reader_peek :: proc(lr: ^Loadahead_Reader, n: int) -> ([]byte, io.Erro
|
|||||||
// lookahead_reader_peek_all returns a slice of the Lookahead_Reader populating the full buffer
|
// lookahead_reader_peek_all returns a slice of the Lookahead_Reader populating the full buffer
|
||||||
// If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest.
|
// If the Lookahead_Reader cannot hold enough bytes, it will read from the underlying reader to populate the rest.
|
||||||
// NOTE: The returned buffer is not a copy of the underlying buffer
|
// NOTE: The returned buffer is not a copy of the underlying buffer
|
||||||
lookahead_reader_peek_all :: proc(lr: ^Loadahead_Reader) -> ([]byte, io.Error) {
|
lookahead_reader_peek_all :: proc(lr: ^Lookahead_Reader) -> ([]byte, io.Error) {
|
||||||
return lookahead_reader_peek(lr, len(lr.buf))
|
return lookahead_reader_peek(lr, len(lr.buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// lookahead_reader_consume drops the first n populated bytes from the Lookahead_Reader.
|
// lookahead_reader_consume drops the first n populated bytes from the Lookahead_Reader.
|
||||||
lookahead_reader_consume :: proc(lr: ^Loadahead_Reader, n: int) -> io.Error {
|
lookahead_reader_consume :: proc(lr: ^Lookahead_Reader, n: int) -> io.Error {
|
||||||
switch {
|
switch {
|
||||||
case n == 0:
|
case n == 0:
|
||||||
return nil
|
return nil
|
||||||
@@ -78,6 +78,6 @@ lookahead_reader_consume :: proc(lr: ^Loadahead_Reader, n: int) -> io.Error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lookahead_reader_consume_all :: proc(lr: ^Loadahead_Reader) -> io.Error {
|
lookahead_reader_consume_all :: proc(lr: ^Lookahead_Reader) -> io.Error {
|
||||||
return lookahead_reader_consume(lr, lr.n)
|
return lookahead_reader_consume(lr, lr.n)
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-44
@@ -14,51 +14,29 @@ read_writer_init :: proc(rw: ^Read_Writer, r: ^Reader, w: ^Writer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) {
|
read_writer_to_stream :: proc(rw: ^Read_Writer) -> (s: io.Stream) {
|
||||||
s.stream_data = rw
|
s.procedure = _read_writer_procedure
|
||||||
s.stream_vtable = &_read_writer_vtable
|
s.data = rw
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_read_writer_vtable := io.Stream_VTable{
|
_read_writer_procedure := proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||||
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
rw := (^Read_Writer)(stream_data)
|
||||||
b := (^Read_Writer)(s.stream_data).r
|
n_int: int
|
||||||
return reader_read(b, p)
|
#partial switch mode {
|
||||||
},
|
case .Flush:
|
||||||
impl_unread_byte = proc(s: io.Stream) -> io.Error {
|
err = writer_flush(rw.w)
|
||||||
b := (^Read_Writer)(s.stream_data).r
|
return
|
||||||
return reader_unread_byte(b)
|
case .Read:
|
||||||
},
|
n_int, err = reader_read(rw.r, p)
|
||||||
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
|
n = i64(n_int)
|
||||||
b := (^Read_Writer)(s.stream_data).r
|
return
|
||||||
return reader_read_rune(b)
|
case .Write:
|
||||||
},
|
n_int, err = writer_write(rw.w, p)
|
||||||
impl_unread_rune = proc(s: io.Stream) -> io.Error {
|
n = i64(n_int)
|
||||||
b := (^Read_Writer)(s.stream_data).r
|
return
|
||||||
return reader_unread_rune(b)
|
case .Query:
|
||||||
},
|
return io.query_utility({.Flush, .Read, .Write, .Query})
|
||||||
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
|
}
|
||||||
b := (^Read_Writer)(s.stream_data).r
|
return 0, .Empty
|
||||||
return reader_write_to(b, w)
|
}
|
||||||
},
|
|
||||||
impl_flush = proc(s: io.Stream) -> io.Error {
|
|
||||||
b := (^Read_Writer)(s.stream_data).w
|
|
||||||
return writer_flush(b)
|
|
||||||
},
|
|
||||||
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
|
||||||
b := (^Read_Writer)(s.stream_data).w
|
|
||||||
return writer_write(b, p)
|
|
||||||
},
|
|
||||||
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
|
|
||||||
b := (^Read_Writer)(s.stream_data).w
|
|
||||||
return writer_write_byte(b, c)
|
|
||||||
},
|
|
||||||
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
|
|
||||||
b := (^Read_Writer)(s.stream_data).w
|
|
||||||
return writer_write_rune(b, r)
|
|
||||||
},
|
|
||||||
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
|
|
||||||
b := (^Read_Writer)(s.stream_data).w
|
|
||||||
return writer_read_from(b, r)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
+26
-76
@@ -118,9 +118,7 @@ reader_peek :: proc(b: ^Reader, n: int) -> (data: []byte, err: io.Error) {
|
|||||||
b.last_rune_size = -1
|
b.last_rune_size = -1
|
||||||
|
|
||||||
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
|
for b.w-b.r < n && b.w-b.r < len(b.buf) && b.err == nil {
|
||||||
if fill_err := _reader_read_new_chunk(b); fill_err != nil {
|
_reader_read_new_chunk(b) or_return
|
||||||
return nil, fill_err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n > len(b.buf) {
|
if n > len(b.buf) {
|
||||||
@@ -156,9 +154,7 @@ reader_discard :: proc(b: ^Reader, n: int) -> (discarded: int, err: io.Error) {
|
|||||||
for {
|
for {
|
||||||
skip := reader_buffered(b)
|
skip := reader_buffered(b)
|
||||||
if skip == 0 {
|
if skip == 0 {
|
||||||
if fill_err := _reader_read_new_chunk(b); fill_err != nil {
|
_reader_read_new_chunk(b) or_return
|
||||||
return 0, fill_err
|
|
||||||
}
|
|
||||||
skip = reader_buffered(b)
|
skip = reader_buffered(b)
|
||||||
}
|
}
|
||||||
skip = min(skip, remaining)
|
skip = min(skip, remaining)
|
||||||
@@ -223,20 +219,18 @@ reader_read :: proc(b: ^Reader, p: []byte) -> (n: int, err: io.Error) {
|
|||||||
|
|
||||||
// reader_read_byte reads and returns a single byte
|
// reader_read_byte reads and returns a single byte
|
||||||
// If no byte is available, it return an error
|
// If no byte is available, it return an error
|
||||||
reader_read_byte :: proc(b: ^Reader) -> (byte, io.Error) {
|
reader_read_byte :: proc(b: ^Reader) -> (c: byte, err: io.Error) {
|
||||||
b.last_rune_size = -1
|
b.last_rune_size = -1
|
||||||
for b.r == b.w {
|
for b.r == b.w {
|
||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return 0, _reader_consume_err(b)
|
return 0, _reader_consume_err(b)
|
||||||
}
|
}
|
||||||
if err := _reader_read_new_chunk(b); err != nil {
|
_reader_read_new_chunk(b) or_return
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c := b.buf[b.r]
|
c = b.buf[b.r]
|
||||||
b.r += 1
|
b.r += 1
|
||||||
b.last_byte = int(c)
|
b.last_byte = int(c)
|
||||||
return c, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// reader_unread_byte unreads the last byte. Only the most recently read byte can be unread
|
// reader_unread_byte unreads the last byte. Only the most recently read byte can be unread
|
||||||
@@ -264,15 +258,12 @@ reader_read_rune :: proc(b: ^Reader) -> (r: rune, size: int, err: io.Error) {
|
|||||||
!utf8.full_rune(b.buf[b.r:b.w]) &&
|
!utf8.full_rune(b.buf[b.r:b.w]) &&
|
||||||
b.err == nil &&
|
b.err == nil &&
|
||||||
b.w-b.w < len(b.buf) {
|
b.w-b.w < len(b.buf) {
|
||||||
if err = _reader_read_new_chunk(b); err != nil {
|
_reader_read_new_chunk(b) or_return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
b.last_rune_size = -1
|
b.last_rune_size = -1
|
||||||
if b.r == b.w {
|
if b.r == b.w {
|
||||||
err = _reader_consume_err(b)
|
return 0, 0, _reader_consume_err(b)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
r, size = rune(b.buf[b.r]), 1
|
r, size = rune(b.buf[b.r]), 1
|
||||||
if r >= utf8.RUNE_SELF {
|
if r >= utf8.RUNE_SELF {
|
||||||
@@ -305,39 +296,20 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
|
|||||||
return i64(n), err
|
return i64(n), err
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err = write_buf(b, w)
|
n = write_buf(b, w) or_return
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m: i64
|
m: i64
|
||||||
if nr, ok := io.to_writer_to(b.rd); ok {
|
|
||||||
m, err = io.write_to(nr, w)
|
|
||||||
n += m
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nw, ok := io.to_reader_from(w); ok {
|
|
||||||
m, err = io.read_from(nw, b.rd)
|
|
||||||
n += m
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.w-b.r < len(b.buf) {
|
if b.w-b.r < len(b.buf) {
|
||||||
if err = _reader_read_new_chunk(b); err != nil {
|
_reader_read_new_chunk(b) or_return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for b.r < b.w {
|
for b.r < b.w {
|
||||||
m, err = write_buf(b, w)
|
m, err = write_buf(b, w)
|
||||||
n += m
|
n += m // this needs to be done before returning
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = _reader_read_new_chunk(b); err != nil {
|
_reader_read_new_chunk(b) or_return
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.err == .EOF {
|
if b.err == .EOF {
|
||||||
@@ -352,48 +324,28 @@ reader_write_to :: proc(b: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
|
|||||||
|
|
||||||
// reader_to_stream converts a Reader into an io.Stream
|
// reader_to_stream converts a Reader into an io.Stream
|
||||||
reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) {
|
reader_to_stream :: proc(b: ^Reader) -> (s: io.Stream) {
|
||||||
s.stream_data = b
|
s.data = b
|
||||||
s.stream_vtable = &_reader_vtable
|
s.procedure = _reader_proc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_reader_vtable := io.Stream_VTable{
|
_reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||||
impl_destroy = proc(s: io.Stream) -> io.Error {
|
b := (^Reader)(stream_data)
|
||||||
b := (^Reader)(s.stream_data)
|
#partial switch mode {
|
||||||
|
case .Read:
|
||||||
|
return io._i64_err(reader_read(b, p))
|
||||||
|
case .Destroy:
|
||||||
reader_destroy(b)
|
reader_destroy(b)
|
||||||
return nil
|
return
|
||||||
},
|
case .Query:
|
||||||
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
return io.query_utility({.Read, .Destroy, .Query})
|
||||||
b := (^Reader)(s.stream_data)
|
}
|
||||||
return reader_read(b, p)
|
return 0, .Empty
|
||||||
},
|
|
||||||
impl_read_byte = proc(s: io.Stream) -> (c: byte, err: io.Error) {
|
|
||||||
b := (^Reader)(s.stream_data)
|
|
||||||
return reader_read_byte(b)
|
|
||||||
},
|
|
||||||
impl_unread_byte = proc(s: io.Stream) -> io.Error {
|
|
||||||
b := (^Reader)(s.stream_data)
|
|
||||||
return reader_unread_byte(b)
|
|
||||||
},
|
|
||||||
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
|
|
||||||
b := (^Reader)(s.stream_data)
|
|
||||||
return reader_read_rune(b)
|
|
||||||
},
|
|
||||||
impl_unread_rune = proc(s: io.Stream) -> io.Error {
|
|
||||||
b := (^Reader)(s.stream_data)
|
|
||||||
return reader_unread_rune(b)
|
|
||||||
},
|
|
||||||
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
|
|
||||||
b := (^Reader)(s.stream_data)
|
|
||||||
return reader_write_to(b, w)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Utility procedures
|
// Utility procedures
|
||||||
//
|
//
|
||||||
@@ -435,9 +387,7 @@ reader_read_slice :: proc(b: ^Reader, delim: byte) -> (line: []byte, err: io.Err
|
|||||||
|
|
||||||
s = b.w - b.r
|
s = b.w - b.r
|
||||||
|
|
||||||
if err = _reader_read_new_chunk(b); err != nil {
|
_reader_read_new_chunk(b) or_break
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if i := len(line)-1; i >= 0 {
|
if i := len(line)-1; i >= 0 {
|
||||||
|
|||||||
+25
-36
@@ -159,7 +159,7 @@ writer_write_rune :: proc(b: ^Writer, r: rune) -> (size: int, err: io.Error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// writer_write writes a string into the buffer
|
// writer_write_string writes a string into the buffer
|
||||||
// It returns the number of bytes written
|
// It returns the number of bytes written
|
||||||
// If n < len(p), it will return an error explaining why the write is short
|
// If n < len(p), it will return an error explaining why the write is short
|
||||||
writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) {
|
writer_write_string :: proc(b: ^Writer, s: string) -> (int, io.Error) {
|
||||||
@@ -173,14 +173,6 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
|
|||||||
if b.err != nil {
|
if b.err != nil {
|
||||||
return 0, b.err
|
return 0, b.err
|
||||||
}
|
}
|
||||||
if writer_buffered(b) == 0 {
|
|
||||||
if w, ok := io.to_reader_from(b.wr); !ok {
|
|
||||||
n, err = io.read_from(w, r)
|
|
||||||
b.err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if writer_available(b) == 0 {
|
if writer_available(b) == 0 {
|
||||||
writer_flush(b) or_return
|
writer_flush(b) or_return
|
||||||
@@ -222,38 +214,35 @@ writer_read_from :: proc(b: ^Writer, r: io.Reader) -> (n: i64, err: io.Error) {
|
|||||||
|
|
||||||
// writer_to_stream converts a Writer into an io.Stream
|
// writer_to_stream converts a Writer into an io.Stream
|
||||||
writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) {
|
writer_to_stream :: proc(b: ^Writer) -> (s: io.Stream) {
|
||||||
s.stream_data = b
|
s.data = b
|
||||||
s.stream_vtable = &_writer_vtable
|
s.procedure = _writer_proc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writer_to_stream converts a Writer into an io.Stream
|
||||||
|
writer_to_writer :: proc(b: ^Writer) -> (s: io.Writer) {
|
||||||
|
return writer_to_stream(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_writer_vtable := io.Stream_VTable{
|
_writer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||||
impl_destroy = proc(s: io.Stream) -> io.Error {
|
b := (^Writer)(stream_data)
|
||||||
b := (^Writer)(s.stream_data)
|
#partial switch mode {
|
||||||
|
case .Flush:
|
||||||
|
err = writer_flush(b)
|
||||||
|
return
|
||||||
|
case .Write:
|
||||||
|
n_int: int
|
||||||
|
n_int, err = writer_write(b, p)
|
||||||
|
n = i64(n_int)
|
||||||
|
return
|
||||||
|
case .Destroy:
|
||||||
writer_destroy(b)
|
writer_destroy(b)
|
||||||
return nil
|
return
|
||||||
},
|
case .Query:
|
||||||
impl_flush = proc(s: io.Stream) -> io.Error {
|
return io.query_utility({.Flush, .Write, .Destroy, .Query})
|
||||||
b := (^Writer)(s.stream_data)
|
}
|
||||||
return writer_flush(b)
|
return 0, .Empty
|
||||||
},
|
|
||||||
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
|
||||||
b := (^Writer)(s.stream_data)
|
|
||||||
return writer_write(b, p)
|
|
||||||
},
|
|
||||||
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
|
|
||||||
b := (^Writer)(s.stream_data)
|
|
||||||
return writer_write_byte(b, c)
|
|
||||||
},
|
|
||||||
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
|
|
||||||
b := (^Writer)(s.stream_data)
|
|
||||||
return writer_write_rune(b, r)
|
|
||||||
},
|
|
||||||
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
|
|
||||||
b := (^Writer)(s.stream_data)
|
|
||||||
return writer_read_from(b, r)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,15 @@ cap :: proc(array: Array_Type) -> int ---
|
|||||||
|
|
||||||
size_of :: proc($T: typeid) -> int ---
|
size_of :: proc($T: typeid) -> int ---
|
||||||
align_of :: proc($T: typeid) -> int ---
|
align_of :: proc($T: typeid) -> int ---
|
||||||
offset_of :: proc($T: typeid) -> uintptr ---
|
|
||||||
|
// e.g. offset_of(t.f), where t is an instance of the type T
|
||||||
|
offset_of_selector :: proc(selector: $T) -> uintptr ---
|
||||||
|
// e.g. offset_of(T, f), where T can be the type instead of a variable
|
||||||
|
offset_of_member :: proc($T: typeid, member: $M) -> uintptr ---
|
||||||
|
offset_of :: proc{offset_of_selector, offset_of_member}
|
||||||
|
// e.g. offset_of(T, "f"), where T can be the type instead of a variable
|
||||||
|
offset_of_by_string :: proc($T: typeid, member: string) -> uintptr ---
|
||||||
|
|
||||||
type_of :: proc(x: expr) -> type ---
|
type_of :: proc(x: expr) -> type ---
|
||||||
type_info_of :: proc($T: typeid) -> ^runtime.Type_Info ---
|
type_info_of :: proc($T: typeid) -> ^runtime.Type_Info ---
|
||||||
typeid_of :: proc($T: typeid) -> typeid ---
|
typeid_of :: proc($T: typeid) -> typeid ---
|
||||||
|
|||||||
+31
-61
@@ -38,6 +38,11 @@ buffer_init_string :: proc(b: ^Buffer, s: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
|
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
|
||||||
|
if b.buf == nil {
|
||||||
|
b.buf = make([dynamic]byte, len, cap, allocator)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
b.buf.allocator = allocator
|
b.buf.allocator = allocator
|
||||||
reserve(&b.buf, cap)
|
reserve(&b.buf, cap)
|
||||||
resize(&b.buf, len)
|
resize(&b.buf, len)
|
||||||
@@ -108,8 +113,11 @@ _buffer_grow :: proc(b: ^Buffer, n: int) -> int {
|
|||||||
if i, ok := _buffer_try_grow(b, n); ok {
|
if i, ok := _buffer_try_grow(b, n); ok {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.buf == nil && n <= SMALL_BUFFER_SIZE {
|
if b.buf == nil && n <= SMALL_BUFFER_SIZE {
|
||||||
b.buf = make([dynamic]byte, n, SMALL_BUFFER_SIZE)
|
// Fixes #2756 by preserving allocator if already set on Buffer via init_buffer_allocator
|
||||||
|
reserve(&b.buf, SMALL_BUFFER_SIZE)
|
||||||
|
resize(&b.buf, n)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,69 +378,31 @@ buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #n
|
|||||||
|
|
||||||
|
|
||||||
buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) {
|
buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) {
|
||||||
s.stream_data = b
|
s.data = b
|
||||||
s.stream_vtable = &_buffer_vtable
|
s.procedure = _buffer_proc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_buffer_vtable := io.Stream_VTable{
|
_buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||||
impl_size = proc(s: io.Stream) -> i64 {
|
b := (^Buffer)(stream_data)
|
||||||
b := (^Buffer)(s.stream_data)
|
#partial switch mode {
|
||||||
return i64(buffer_capacity(b))
|
case .Read:
|
||||||
},
|
return io._i64_err(buffer_read(b, p))
|
||||||
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
case .Read_At:
|
||||||
b := (^Buffer)(s.stream_data)
|
return io._i64_err(buffer_read_at(b, p, int(offset)))
|
||||||
return buffer_read(b, p)
|
case .Write:
|
||||||
},
|
return io._i64_err(buffer_write(b, p))
|
||||||
impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
|
case .Write_At:
|
||||||
b := (^Buffer)(s.stream_data)
|
return io._i64_err(buffer_write_at(b, p, int(offset)))
|
||||||
return buffer_read_at(b, p, int(offset))
|
case .Size:
|
||||||
},
|
n = i64(buffer_capacity(b))
|
||||||
impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
|
return
|
||||||
b := (^Buffer)(s.stream_data)
|
case .Destroy:
|
||||||
return buffer_read_byte(b)
|
|
||||||
},
|
|
||||||
impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_read_rune(b)
|
|
||||||
},
|
|
||||||
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_write(b, p)
|
|
||||||
},
|
|
||||||
impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_write_at(b, p, int(offset))
|
|
||||||
},
|
|
||||||
impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_write_byte(b, c)
|
|
||||||
},
|
|
||||||
impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_write_rune(b, r)
|
|
||||||
},
|
|
||||||
impl_unread_byte = proc(s: io.Stream) -> io.Error {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_unread_byte(b)
|
|
||||||
},
|
|
||||||
impl_unread_rune = proc(s: io.Stream) -> io.Error {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_unread_rune(b)
|
|
||||||
},
|
|
||||||
impl_destroy = proc(s: io.Stream) -> io.Error {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
buffer_destroy(b)
|
buffer_destroy(b)
|
||||||
return nil
|
return
|
||||||
},
|
case .Query:
|
||||||
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
|
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy})
|
||||||
b := (^Buffer)(s.stream_data)
|
}
|
||||||
return buffer_write_to(b, w)
|
return 0, .Empty
|
||||||
},
|
|
||||||
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
|
|
||||||
b := (^Buffer)(s.stream_data)
|
|
||||||
return buffer_read_from(b, r)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-39
@@ -16,8 +16,8 @@ reader_init :: proc(r: ^Reader, s: []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
|
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
|
||||||
s.stream_data = r
|
s.data = r
|
||||||
s.stream_vtable = &_reader_vtable
|
s.procedure = _reader_proc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,41 +137,22 @@ reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
|
|||||||
|
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_reader_vtable := io.Stream_VTable{
|
_reader_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||||
impl_size = proc(s: io.Stream) -> i64 {
|
r := (^Reader)(stream_data)
|
||||||
r := (^Reader)(s.stream_data)
|
#partial switch mode {
|
||||||
return reader_size(r)
|
case .Read:
|
||||||
},
|
return io._i64_err(reader_read(r, p))
|
||||||
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
case .Read_At:
|
||||||
r := (^Reader)(s.stream_data)
|
return io._i64_err(reader_read_at(r, p, offset))
|
||||||
return reader_read(r, p)
|
case .Seek:
|
||||||
},
|
n, err = reader_seek(r, offset, whence)
|
||||||
impl_read_at = proc(s: io.Stream, p: []byte, off: i64) -> (n: int, err: io.Error) {
|
return
|
||||||
r := (^Reader)(s.stream_data)
|
case .Size:
|
||||||
return reader_read_at(r, p, off)
|
n = reader_size(r)
|
||||||
},
|
return
|
||||||
impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
|
case .Query:
|
||||||
r := (^Reader)(s.stream_data)
|
return io.query_utility({.Read, .Read_At, .Seek, .Size, .Query})
|
||||||
return reader_read_byte(r)
|
}
|
||||||
},
|
return 0, .Empty
|
||||||
impl_unread_byte = proc(s: io.Stream) -> io.Error {
|
|
||||||
r := (^Reader)(s.stream_data)
|
|
||||||
return reader_unread_byte(r)
|
|
||||||
},
|
|
||||||
impl_read_rune = proc(s: io.Stream) -> (ch: rune, size: int, err: io.Error) {
|
|
||||||
r := (^Reader)(s.stream_data)
|
|
||||||
return reader_read_rune(r)
|
|
||||||
},
|
|
||||||
impl_unread_rune = proc(s: io.Stream) -> io.Error {
|
|
||||||
r := (^Reader)(s.stream_data)
|
|
||||||
return reader_unread_rune(r)
|
|
||||||
},
|
|
||||||
impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
|
|
||||||
r := (^Reader)(s.stream_data)
|
|
||||||
return reader_seek(r, offset, whence)
|
|
||||||
},
|
|
||||||
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
|
|
||||||
r := (^Reader)(s.stream_data)
|
|
||||||
return reader_write_to(r, w)
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1118,7 +1118,7 @@ expand_macro :: proc(cpp: ^Preprocessor, rest: ^^Token, tok: ^Token) -> bool {
|
|||||||
|
|
||||||
search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) {
|
search_include_next :: proc(cpp: ^Preprocessor, filename: string) -> (path: string, ok: bool) {
|
||||||
for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 {
|
for ; cpp.include_next_index < len(cpp.include_paths); cpp.include_next_index += 1 {
|
||||||
tpath := filepath.join(elems={cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
|
tpath := filepath.join({cpp.include_paths[cpp.include_next_index], filename}, allocator=context.temp_allocator)
|
||||||
if os.exists(tpath) {
|
if os.exists(tpath) {
|
||||||
return strings.clone(tpath), true
|
return strings.clone(tpath), true
|
||||||
}
|
}
|
||||||
@@ -1136,7 +1136,7 @@ search_include_paths :: proc(cpp: ^Preprocessor, filename: string) -> (path: str
|
|||||||
}
|
}
|
||||||
|
|
||||||
for include_path in cpp.include_paths {
|
for include_path in cpp.include_paths {
|
||||||
tpath := filepath.join(elems={include_path, filename}, allocator=context.temp_allocator)
|
tpath := filepath.join({include_path, filename}, allocator=context.temp_allocator)
|
||||||
if os.exists(tpath) {
|
if os.exists(tpath) {
|
||||||
path, ok = strings.clone(tpath), true
|
path, ok = strings.clone(tpath), true
|
||||||
cpp.filepath_cache[filename] = path
|
cpp.filepath_cache[filename] = path
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ advance_rune :: proc(t: ^Tokenizer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
advance_rune_n :: proc(t: ^Tokenizer, n: int) {
|
advance_rune_n :: proc(t: ^Tokenizer, n: int) {
|
||||||
for in 0..<n {
|
for _ in 0..<n {
|
||||||
advance_rune(t)
|
advance_rune(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,4 +63,4 @@ foreign libc {
|
|||||||
// strictly conformant C implementation is 16 on the platforms we care about.
|
// strictly conformant C implementation is 16 on the platforms we care about.
|
||||||
// The choice of 4096 bytes for storage of this type is more than enough on all
|
// The choice of 4096 bytes for storage of this type is more than enough on all
|
||||||
// relevant platforms.
|
// relevant platforms.
|
||||||
jmp_buf :: struct #align 16 { _: [4096]char, }
|
jmp_buf :: struct #align(16) { _: [4096]char, }
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ foreign _ {
|
|||||||
// strictly conformant C implementation is 16 on the platforms we care about.
|
// strictly conformant C implementation is 16 on the platforms we care about.
|
||||||
// The choice of 4096 bytes for storage of this type is more than enough on all
|
// The choice of 4096 bytes for storage of this type is more than enough on all
|
||||||
// relevant platforms.
|
// relevant platforms.
|
||||||
va_list :: struct #align 16 {
|
va_list :: struct #align(16) {
|
||||||
_: [4096]u8,
|
_: [4096]u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ foreign libc {
|
|||||||
fscanf :: proc(stream: ^FILE, format: cstring, #c_vararg args: ..any) -> int ---
|
fscanf :: proc(stream: ^FILE, format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
printf :: proc(format: cstring, #c_vararg args: ..any) -> int ---
|
printf :: proc(format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
scanf :: proc(format: cstring, #c_vararg args: ..any) -> int ---
|
scanf :: proc(format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
snprintf :: proc(s: [^]char, format: cstring, #c_vararg args: ..any) -> int ---
|
snprintf :: proc(s: [^]char, n: size_t, format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
sscanf :: proc(s, format: cstring, #c_vararg args: ..any) -> int ---
|
sscanf :: proc(s, format: cstring, #c_vararg args: ..any) -> int ---
|
||||||
vfprintf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
|
vfprintf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
|
||||||
vfscanf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
|
vfscanf :: proc(stream: ^FILE, format: cstring, arg: ^va_list) -> int ---
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ when ODIN_OS == .Windows {
|
|||||||
@(link_name="_Cnd_destroy") cnd_destroy :: proc(cond: ^cnd_t) ---
|
@(link_name="_Cnd_destroy") cnd_destroy :: proc(cond: ^cnd_t) ---
|
||||||
@(link_name="_Cnd_init") cnd_init :: proc(cond: ^cnd_t) -> int ---
|
@(link_name="_Cnd_init") cnd_init :: proc(cond: ^cnd_t) -> int ---
|
||||||
@(link_name="_Cnd_signal") cnd_signal :: proc(cond: ^cnd_t) -> int ---
|
@(link_name="_Cnd_signal") cnd_signal :: proc(cond: ^cnd_t) -> int ---
|
||||||
@(link_name="_Cnd_timedwait") cnd_timedwait :: proc(cond: ^cnd_t, ts: ^timespec) -> int ---
|
@(link_name="_Cnd_timedwait") cnd_timedwait :: proc(cond: ^cnd_t, mtx: ^mtx_t, ts: ^timespec) -> int ---
|
||||||
@(link_name="_Cnd_wait") cnd_wait :: proc(cond: ^cnd_t, mtx: ^mtx_t) -> int ---
|
@(link_name="_Cnd_wait") cnd_wait :: proc(cond: ^cnd_t, mtx: ^mtx_t) -> int ---
|
||||||
|
|
||||||
// 7.26.4 Mutex functions
|
// 7.26.4 Mutex functions
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ when ODIN_OS == .Windows {
|
|||||||
clock_t :: distinct long
|
clock_t :: distinct long
|
||||||
time_t :: distinct i64
|
time_t :: distinct i64
|
||||||
|
|
||||||
timespec :: struct #align 8 {
|
timespec :: struct #align(8) {
|
||||||
tv_sec: time_t,
|
tv_sec: time_t,
|
||||||
tv_nsec: long,
|
tv_nsec: long,
|
||||||
}
|
}
|
||||||
|
|
||||||
tm :: struct #align 8 {
|
tm :: struct #align(8) {
|
||||||
tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst: int,
|
tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst: int,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ foreign libc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Large enough and aligned enough for any wide-spread in-use libc.
|
// Large enough and aligned enough for any wide-spread in-use libc.
|
||||||
mbstate_t :: struct #align 16 { _: [32]char, }
|
mbstate_t :: struct #align(16) { _: [32]char, }
|
||||||
|
|
||||||
// Odin does not have default argument promotion so the need for a separate type
|
// Odin does not have default argument promotion so the need for a separate type
|
||||||
// here isn't necessary, though make it distinct just to be safe.
|
// here isn't necessary, though make it distinct just to be safe.
|
||||||
|
|||||||
+19
-40
@@ -188,7 +188,8 @@ input_size_from_memory :: proc(z: ^Context_Memory_Input) -> (res: i64, err: Erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error) {
|
input_size_from_stream :: proc(z: ^Context_Stream_Input) -> (res: i64, err: Error) {
|
||||||
return io.size(z.input), nil
|
res, _ = io.size(z.input)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
input_size :: proc{input_size_from_memory, input_size_from_stream}
|
input_size :: proc{input_size_from_memory, input_size_from_stream}
|
||||||
@@ -215,24 +216,16 @@ read_slice_from_stream :: #force_inline proc(z: ^Context_Stream_Input, size: int
|
|||||||
// TODO: REMOVE ALL USE OF context.temp_allocator here
|
// TODO: REMOVE ALL USE OF context.temp_allocator here
|
||||||
// the is literally no need for it
|
// the is literally no need for it
|
||||||
b := make([]u8, size, context.temp_allocator)
|
b := make([]u8, size, context.temp_allocator)
|
||||||
_, e := z.input->impl_read(b[:])
|
_ = io.read(z.input, b[:]) or_return
|
||||||
if e == .None {
|
return b, nil
|
||||||
return b, .None
|
|
||||||
}
|
|
||||||
|
|
||||||
return []u8{}, e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read_slice :: proc{read_slice_from_memory, read_slice_from_stream}
|
read_slice :: proc{read_slice_from_memory, read_slice_from_stream}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
|
read_data :: #force_inline proc(z: ^$C, $T: typeid) -> (res: T, err: io.Error) {
|
||||||
b, e := read_slice(z, size_of(T))
|
b := read_slice(z, size_of(T)) or_return
|
||||||
if e == .None {
|
return (^T)(&b[0])^, nil
|
||||||
return (^T)(&b[0])^, .None
|
|
||||||
}
|
|
||||||
|
|
||||||
return T{}, e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
@@ -249,12 +242,8 @@ read_u8_from_memory :: #force_inline proc(z: ^Context_Memory_Input) -> (res: u8,
|
|||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) {
|
read_u8_from_stream :: #force_inline proc(z: ^Context_Stream_Input) -> (res: u8, err: io.Error) {
|
||||||
b, e := read_slice_from_stream(z, 1)
|
b := read_slice_from_stream(z, 1) or_return
|
||||||
if e == .None {
|
return b[0], nil
|
||||||
return b[0], .None
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, e
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}
|
read_u8 :: proc{read_u8_from_memory, read_u8_from_stream}
|
||||||
@@ -319,12 +308,9 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
|
|||||||
size :: size_of(T)
|
size :: size_of(T)
|
||||||
|
|
||||||
// Get current position to read from.
|
// Get current position to read from.
|
||||||
curr, e1 := z.input->impl_seek(0, .Current)
|
curr := z.input->impl_seek(0, .Current) or_return
|
||||||
if e1 != .None {
|
r, e1 := io.to_reader_at(z.input)
|
||||||
return T{}, e1
|
if !e1 {
|
||||||
}
|
|
||||||
r, e2 := io.to_reader_at(z.input)
|
|
||||||
if !e2 {
|
|
||||||
return T{}, .Empty
|
return T{}, .Empty
|
||||||
}
|
}
|
||||||
when size <= 128 {
|
when size <= 128 {
|
||||||
@@ -332,8 +318,8 @@ peek_data_from_stream :: #force_inline proc(z: ^Context_Stream_Input, $T: typeid
|
|||||||
} else {
|
} else {
|
||||||
b := make([]u8, size, context.temp_allocator)
|
b := make([]u8, size, context.temp_allocator)
|
||||||
}
|
}
|
||||||
_, e3 := io.read_at(r, b[:], curr)
|
_, e2 := io.read_at(r, b[:], curr)
|
||||||
if e3 != .None {
|
if e2 != .None {
|
||||||
return T{}, .Empty
|
return T{}, .Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,16 +332,9 @@ peek_data_at_offset_from_stream :: #force_inline proc(z: ^Context_Stream_Input,
|
|||||||
size :: size_of(T)
|
size :: size_of(T)
|
||||||
|
|
||||||
// Get current position to return to.
|
// Get current position to return to.
|
||||||
cur_pos, e1 := z.input->impl_seek(0, .Current)
|
cur_pos := z.input->impl_seek(0, .Current) or_return
|
||||||
if e1 != .None {
|
|
||||||
return T{}, e1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Seek to offset.
|
// Seek to offset.
|
||||||
pos, e2 := z.input->impl_seek(offset, .Start)
|
pos := z.input->impl_seek(offset, .Start) or_return
|
||||||
if e2 != .None {
|
|
||||||
return T{}, e2
|
|
||||||
}
|
|
||||||
|
|
||||||
r, e3 := io.to_reader_at(z.input)
|
r, e3 := io.to_reader_at(z.input)
|
||||||
if !e3 {
|
if !e3 {
|
||||||
@@ -464,7 +443,7 @@ peek_bits_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width:
|
|||||||
if z.num_bits < u64(width) {
|
if z.num_bits < u64(width) {
|
||||||
refill_lsb(z)
|
refill_lsb(z)
|
||||||
}
|
}
|
||||||
return u32(z.code_buffer & ~(~u64(0) << width))
|
return u32(z.code_buffer &~ (~u64(0) << width))
|
||||||
}
|
}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
@@ -472,7 +451,7 @@ peek_bits_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width:
|
|||||||
if z.num_bits < u64(width) {
|
if z.num_bits < u64(width) {
|
||||||
refill_lsb(z)
|
refill_lsb(z)
|
||||||
}
|
}
|
||||||
return u32(z.code_buffer & ~(~u64(0) << width))
|
return u32(z.code_buffer &~ (~u64(0) << width))
|
||||||
}
|
}
|
||||||
|
|
||||||
peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
|
peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
|
||||||
@@ -480,13 +459,13 @@ peek_bits_lsb :: proc{peek_bits_lsb_from_memory, peek_bits_lsb_from_stream}
|
|||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
|
peek_bits_no_refill_lsb_from_memory :: #force_inline proc(z: ^Context_Memory_Input, width: u8) -> u32 {
|
||||||
assert(z.num_bits >= u64(width))
|
assert(z.num_bits >= u64(width))
|
||||||
return u32(z.code_buffer & ~(~u64(0) << width))
|
return u32(z.code_buffer &~ (~u64(0) << width))
|
||||||
}
|
}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
|
peek_bits_no_refill_lsb_from_stream :: #force_inline proc(z: ^Context_Stream_Input, width: u8) -> u32 {
|
||||||
assert(z.num_bits >= u64(width))
|
assert(z.num_bits >= u64(width))
|
||||||
return u32(z.code_buffer & ~(~u64(0) << width))
|
return u32(z.code_buffer &~ (~u64(0) << width))
|
||||||
}
|
}
|
||||||
|
|
||||||
peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}
|
peek_bits_no_refill_lsb :: proc{peek_bits_no_refill_lsb_from_memory, peek_bits_no_refill_lsb_from_stream}
|
||||||
|
|||||||
@@ -335,10 +335,8 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp
|
|||||||
|
|
||||||
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
|
// fmt.printf("GZIP: Expected Payload Size: %v\n", expected_output_size);
|
||||||
|
|
||||||
zlib_error := zlib.inflate_raw(z=z, expected_output_size=expected_output_size)
|
zlib.inflate_raw(z, expected_output_size=expected_output_size) or_return
|
||||||
if zlib_error != nil {
|
|
||||||
return zlib_error
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
Read CRC32 using the ctx bit reader because zlib may leave bytes in there.
|
Read CRC32 using the ctx bit reader because zlib may leave bytes in there.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -177,12 +177,10 @@ decompress_slice_to_string :: proc(input: []u8, model := DEFAULT_MODEL, allocato
|
|||||||
max_output_size := decompress_bound(len(input), model)
|
max_output_size := decompress_bound(len(input), model)
|
||||||
|
|
||||||
buf: [dynamic]u8
|
buf: [dynamic]u8
|
||||||
if !resize(&buf, max_output_size) {
|
resize(&buf, max_output_size) or_return
|
||||||
return "", .Out_Of_Memory
|
|
||||||
}
|
|
||||||
|
|
||||||
length, result := decompress_slice_to_output_buffer(input, buf[:])
|
length, result := decompress_slice_to_output_buffer(input, buf[:])
|
||||||
resize(&buf, length)
|
resize(&buf, length) or_return
|
||||||
return string(buf[:]), result
|
return string(buf[:]), result
|
||||||
}
|
}
|
||||||
decompress :: proc{decompress_slice_to_output_buffer, decompress_slice_to_string}
|
decompress :: proc{decompress_slice_to_output_buffer, decompress_slice_to_string}
|
||||||
@@ -307,12 +305,10 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
|
|||||||
max_output_size := compress_bound(len(input))
|
max_output_size := compress_bound(len(input))
|
||||||
|
|
||||||
buf: [dynamic]u8
|
buf: [dynamic]u8
|
||||||
if !resize(&buf, max_output_size) {
|
resize(&buf, max_output_size) or_return
|
||||||
return {}, .Out_Of_Memory
|
|
||||||
}
|
|
||||||
|
|
||||||
length, result := compress_string_to_buffer(input, buf[:])
|
length, result := compress_string_to_buffer(input, buf[:])
|
||||||
resize(&buf, length)
|
resize(&buf, length) or_return
|
||||||
return buf[:length], result
|
return buf[:length], result
|
||||||
}
|
}
|
||||||
compress :: proc{compress_string_to_buffer, compress_string}
|
compress :: proc{compress_string_to_buffer, compress_string}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//+vet !using-param
|
||||||
package zlib
|
package zlib
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -146,15 +147,7 @@ grow_buffer :: proc(buf: ^[dynamic]u8) -> (err: compress.Error) {
|
|||||||
Double until we reach the maximum allowed.
|
Double until we reach the maximum allowed.
|
||||||
*/
|
*/
|
||||||
new_size := min(len(buf) << 1, compress.COMPRESS_OUTPUT_ALLOCATE_MAX)
|
new_size := min(len(buf) << 1, compress.COMPRESS_OUTPUT_ALLOCATE_MAX)
|
||||||
resize(buf, new_size)
|
return resize(buf, new_size)
|
||||||
if len(buf) != new_size {
|
|
||||||
/*
|
|
||||||
Resize failed.
|
|
||||||
*/
|
|
||||||
return .Resize_Failed
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -181,7 +174,7 @@ write_byte :: #force_inline proc(z: ^$C, c: u8) -> (err: io.Error) #no_bounds_ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
|
repl_byte :: proc(z: ^$C, count: u16, c: u8) -> (err: io.Error) #no_bounds_check {
|
||||||
/*
|
/*
|
||||||
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
|
TODO(Jeroen): Once we have a magic ring buffer, we can just peek/write into it
|
||||||
without having to worry about wrapping, so no need for a temp allocation to give to
|
without having to worry about wrapping, so no need for a temp allocation to give to
|
||||||
@@ -305,10 +298,10 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro
|
|||||||
code := u16(compress.peek_bits_lsb(z,16))
|
code := u16(compress.peek_bits_lsb(z,16))
|
||||||
|
|
||||||
k := int(z_bit_reverse(code, 16))
|
k := int(z_bit_reverse(code, 16))
|
||||||
s: u8
|
|
||||||
|
|
||||||
#no_bounds_check for s = HUFFMAN_FAST_BITS+1; ; {
|
s: u8 = HUFFMAN_FAST_BITS+1
|
||||||
if k < t.maxcode[s] {
|
for {
|
||||||
|
#no_bounds_check if k < t.maxcode[s] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s += 1
|
s += 1
|
||||||
@@ -471,7 +464,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse ZLIB stream without header.
|
// Parse ZLIB stream without header.
|
||||||
inflate_raw(z=ctx, expected_output_size=expected_output_size) or_return
|
inflate_raw(ctx, expected_output_size=expected_output_size) or_return
|
||||||
|
|
||||||
if !raw {
|
if !raw {
|
||||||
compress.discard_to_next_byte_lsb(ctx)
|
compress.discard_to_next_byte_lsb(ctx)
|
||||||
@@ -509,8 +502,8 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
|
|||||||
/*
|
/*
|
||||||
Try to pre-allocate the output buffer.
|
Try to pre-allocate the output buffer.
|
||||||
*/
|
*/
|
||||||
reserve(&z.output.buf, expected_output_size)
|
reserve(&z.output.buf, expected_output_size) or_return
|
||||||
resize (&z.output.buf, expected_output_size)
|
resize (&z.output.buf, expected_output_size) or_return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(z.output.buf) != expected_output_size {
|
if len(z.output.buf) != expected_output_size {
|
||||||
@@ -653,7 +646,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
|
|||||||
}
|
}
|
||||||
|
|
||||||
if int(z.bytes_written) != len(z.output.buf) {
|
if int(z.bytes_written) != len(z.output.buf) {
|
||||||
resize(&z.output.buf, int(z.bytes_written))
|
resize(&z.output.buf, int(z.bytes_written)) or_return
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -665,7 +658,7 @@ inflate_from_byte_array :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, e
|
|||||||
ctx.input_data = input
|
ctx.input_data = input
|
||||||
ctx.output = buf
|
ctx.output = buf
|
||||||
|
|
||||||
return inflate_from_context(ctx=&ctx, raw=raw, expected_output_size=expected_output_size)
|
return inflate_from_context(&ctx, raw=raw, expected_output_size=expected_output_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
|
inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := false, expected_output_size := -1) -> (err: Error) {
|
||||||
@@ -674,7 +667,7 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
|
|||||||
ctx.input_data = input
|
ctx.input_data = input
|
||||||
ctx.output = buf
|
ctx.output = buf
|
||||||
|
|
||||||
return inflate_raw(z=&ctx, expected_output_size=expected_output_size)
|
return inflate_raw(&ctx, expected_output_size=expected_output_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
inflate :: proc{inflate_from_context, inflate_from_byte_array}
|
inflate :: proc{inflate_from_context, inflate_from_byte_array}
|
||||||
|
|||||||
@@ -27,27 +27,28 @@ Bit_Array_Iterator :: struct {
|
|||||||
word_idx: int,
|
word_idx: int,
|
||||||
bit_idx: uint,
|
bit_idx: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Wraps a `Bit_Array` into an Iterator
|
||||||
- ba: ^Bit_Array - the array to iterate over
|
|
||||||
|
|
||||||
Out:
|
Inputs:
|
||||||
- it: ^Bit_Array_Iterator - the iterator that holds iteration state
|
- ba: Pointer to the Bit_Array
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- it: Iterator struct
|
||||||
*/
|
*/
|
||||||
make_iterator :: proc (ba: ^Bit_Array) -> (it: Bit_Array_Iterator) {
|
make_iterator :: proc (ba: ^Bit_Array) -> (it: Bit_Array_Iterator) {
|
||||||
return Bit_Array_Iterator { array = ba }
|
return Bit_Array_Iterator { array = ba }
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Returns the next bit, including its set-state. ok=false once exhausted
|
||||||
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
|
|
||||||
|
|
||||||
Out:
|
Inputs:
|
||||||
- set: bool - the state of the bit at `index`
|
- it: The iterator that holds the state.
|
||||||
- index: int - the next bit of the Bit_Array referenced by `it`.
|
|
||||||
- ok: bool - `true` if the iterator returned a valid index,
|
Returns:
|
||||||
`false` if there were no more bits
|
- set: `true` if the bit at `index` is set.
|
||||||
|
- index: The next bit of the Bit_Array referenced by `it`.
|
||||||
|
- ok: `true` if the iterator can continue, `false` if the iterator is done
|
||||||
*/
|
*/
|
||||||
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
|
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
|
||||||
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
||||||
@@ -64,39 +65,51 @@ iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok:
|
|||||||
|
|
||||||
return set, index, true
|
return set, index, true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Returns the next Set Bit, for example if `0b1010`, then the iterator will return index={1, 3} over two calls.
|
||||||
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
|
|
||||||
|
|
||||||
Out:
|
Inputs:
|
||||||
- index: int - the next set bit of the Bit_Array referenced by `it`.
|
- it: The iterator that holds the state.
|
||||||
- ok: bool - `true` if the iterator returned a valid index,
|
|
||||||
`false` if there were no more bits set
|
Returns:
|
||||||
|
- index: The next *set* bit of the Bit_Array referenced by `it`.
|
||||||
|
- ok: `true` if the iterator can continue, `false` if the iterator is done
|
||||||
*/
|
*/
|
||||||
iterate_by_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
|
iterate_by_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
|
||||||
return iterate_internal_(it, true)
|
return iterate_internal_(it, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Returns the next Unset Bit, for example if `0b1010`, then the iterator will return index={0, 2} over two calls.
|
||||||
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
|
|
||||||
|
|
||||||
Out:
|
Inputs:
|
||||||
- index: int - the next unset bit of the Bit_Array referenced by `it`.
|
- it: The iterator that holds the state.
|
||||||
- ok: bool - `true` if the iterator returned a valid index,
|
|
||||||
`false` if there were no more unset bits
|
Returns:
|
||||||
|
- index: The next *unset* bit of the Bit_Array referenced by `it`.
|
||||||
|
- ok: `true` if the iterator can continue, `false` if the iterator is done
|
||||||
*/
|
*/
|
||||||
iterate_by_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
|
iterate_by_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
|
||||||
return iterate_internal_(it, false)
|
return iterate_internal_(it, false)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Iterates through set/unset bits
|
||||||
|
|
||||||
|
*Private*
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- it: The iterator that holds the state.
|
||||||
|
- ITERATE_SET_BITS: `true` for returning only set bits, false for returning only unset bits
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- index: The next *unset* bit of the Bit_Array referenced by `it`.
|
||||||
|
- ok: `true` if the iterator can continue, `false` if the iterator is done
|
||||||
|
*/
|
||||||
@(private="file")
|
@(private="file")
|
||||||
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
|
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
|
||||||
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||||
when ! ITERATE_SET_BITS { word = ~word }
|
when ! ITERATE_SET_BITS { word = ~word }
|
||||||
|
|
||||||
// if the word is empty or we have already gone over all the bits in it,
|
// If the word is empty or we have already gone over all the bits in it,
|
||||||
// b.bit_idx is greater than the index of any set bit in the word,
|
// b.bit_idx is greater than the index of any set bit in the word,
|
||||||
// meaning that word >> b.bit_idx == 0.
|
// meaning that word >> b.bit_idx == 0.
|
||||||
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
|
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
|
||||||
@@ -106,14 +119,14 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
|
|||||||
when ! ITERATE_SET_BITS { word = ~word }
|
when ! ITERATE_SET_BITS { word = ~word }
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are iterating the set bits, reaching the end of the array means we have no more bits to check
|
// If we are iterating the set bits, reaching the end of the array means we have no more bits to check
|
||||||
when ITERATE_SET_BITS {
|
when ITERATE_SET_BITS {
|
||||||
if it.word_idx >= len(it.array.bits) {
|
if it.word_idx >= len(it.array.bits) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reaching here means that the word has some set bits
|
// Reaching here means that the word has some set bits
|
||||||
it.bit_idx += uint(intrinsics.count_trailing_zeros(word >> it.bit_idx))
|
it.bit_idx += uint(intrinsics.count_trailing_zeros(word >> it.bit_idx))
|
||||||
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
||||||
|
|
||||||
@@ -124,24 +137,21 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
|
|||||||
}
|
}
|
||||||
return index, index <= it.array.max_index
|
return index, index <= it.array.max_index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Gets the state of a bit in the bit-array
|
||||||
- ba: ^Bit_Array - a pointer to the Bit Array
|
|
||||||
- index: The bit index. Can be an enum member.
|
|
||||||
|
|
||||||
Out:
|
Inputs:
|
||||||
- res: The bit you're interested in.
|
- ba: Pointer to the Bit_Array
|
||||||
- ok: Whether the index was valid. Returns `false` if the index is smaller than the bias.
|
- index: Which bit in the array
|
||||||
|
|
||||||
The `ok` return value may be ignored.
|
Returns:
|
||||||
|
- res: `true` if the bit at `index` is set.
|
||||||
|
- ok: Whether the index was valid. Returns `false` if the index is smaller than the bias.
|
||||||
*/
|
*/
|
||||||
get :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (res: bool, ok: bool) {
|
get :: proc(ba: ^Bit_Array, #any_int index: uint) -> (res: bool, ok: bool) #optional_ok {
|
||||||
idx := int(index) - ba.bias
|
idx := int(index) - ba.bias
|
||||||
|
|
||||||
if ba == nil || int(index) < ba.bias { return false, false }
|
if ba == nil || int(index) < ba.bias { return false, false }
|
||||||
context.allocator = allocator
|
|
||||||
|
|
||||||
leg_index := idx >> INDEX_SHIFT
|
leg_index := idx >> INDEX_SHIFT
|
||||||
bit_index := idx & INDEX_MASK
|
bit_index := idx & INDEX_MASK
|
||||||
@@ -157,18 +167,36 @@ get :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator
|
|||||||
|
|
||||||
return res, true
|
return res, true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Gets the state of a bit in the bit-array
|
||||||
- ba: ^Bit_Array - a pointer to the Bit Array
|
|
||||||
- index: The bit index. Can be an enum member.
|
|
||||||
|
|
||||||
Out:
|
*Bypasses all Checks*
|
||||||
- ok: Whether or not we managed to set requested bit.
|
|
||||||
|
|
||||||
`set` automatically resizes the Bit Array to accommodate the requested index if needed.
|
Inputs:
|
||||||
|
- ba: Pointer to the Bit_Array
|
||||||
|
- index: Which bit in the array
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- `true` if bit is set
|
||||||
*/
|
*/
|
||||||
set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
|
unsafe_get :: #force_inline proc(ba: ^Bit_Array, #any_int index: uint) -> bool #no_bounds_check {
|
||||||
|
return bool((ba.bits[index >> INDEX_SHIFT] >> uint(index & INDEX_MASK)) & 1)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Sets the state of a bit in the bit-array
|
||||||
|
|
||||||
|
*Conditionally Allocates (Resizes backing data when `index > len(ba.bits)`)*
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- ba: Pointer to the Bit_Array
|
||||||
|
- index: Which bit in the array
|
||||||
|
- set_to: `true` sets the bit on, `false` to turn it off
|
||||||
|
- allocator: (default is context.allocator)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- ok: Whether the set was successful, `false` on allocation failure or bad index
|
||||||
|
*/
|
||||||
|
set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator := context.allocator) -> (ok: bool) {
|
||||||
|
|
||||||
idx := int(index) - ba.bias
|
idx := int(index) - ba.bias
|
||||||
|
|
||||||
@@ -181,65 +209,97 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator
|
|||||||
resize_if_needed(ba, leg_index) or_return
|
resize_if_needed(ba, leg_index) or_return
|
||||||
|
|
||||||
ba.max_index = max(idx, ba.max_index)
|
ba.max_index = max(idx, ba.max_index)
|
||||||
ba.bits[leg_index] |= 1 << uint(bit_index)
|
|
||||||
|
if set_to{ ba.bits[leg_index] |= 1 << uint(bit_index) }
|
||||||
|
else { ba.bits[leg_index] &= ~(1 << uint(bit_index)) }
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In:
|
Sets the state of a bit in the bit-array
|
||||||
- ba: ^Bit_Array - a pointer to the Bit Array
|
|
||||||
- index: The bit index. Can be an enum member.
|
|
||||||
|
|
||||||
Out:
|
*Bypasses all checks*
|
||||||
- ok: Whether or not we managed to unset requested bit.
|
|
||||||
|
|
||||||
`unset` automatically resizes the Bit Array to accommodate the requested index if needed.
|
Inputs:
|
||||||
|
- ba: Pointer to the Bit_Array
|
||||||
|
- index: Which bit in the array
|
||||||
*/
|
*/
|
||||||
unset :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
|
unsafe_set :: proc(ba: ^Bit_Array, bit: int) #no_bounds_check {
|
||||||
|
ba.bits[bit >> INDEX_SHIFT] |= 1 << uint(bit & INDEX_MASK)
|
||||||
idx := int(index) - ba.bias
|
|
||||||
|
|
||||||
if ba == nil || int(index) < ba.bias { return false }
|
|
||||||
context.allocator = allocator
|
|
||||||
|
|
||||||
leg_index := idx >> INDEX_SHIFT
|
|
||||||
bit_index := idx & INDEX_MASK
|
|
||||||
|
|
||||||
resize_if_needed(ba, leg_index) or_return
|
|
||||||
|
|
||||||
ba.max_index = max(idx, ba.max_index)
|
|
||||||
ba.bits[leg_index] &= ~(1 << uint(bit_index))
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
|
Unsets the state of a bit in the bit-array. (Convienence wrapper for `set`)
|
||||||
|
|
||||||
|
*Conditionally Allocates (Resizes backing data when `index > len(ba.bits)`)*
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- ba: Pointer to the Bit_Array
|
||||||
|
- index: Which bit in the array
|
||||||
|
- allocator: (default is context.allocator)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- ok: Whether the unset was successful, `false` on allocation failure or bad index
|
||||||
*/
|
*/
|
||||||
create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -> (res: ^Bit_Array, ok: bool) #optional_ok {
|
unset :: #force_inline proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
|
||||||
|
return set(ba, index, false, allocator)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Unsets the state of a bit in the bit-array
|
||||||
|
|
||||||
|
*Bypasses all Checks*
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- ba: Pointer to the Bit_Array
|
||||||
|
- index: Which bit in the array
|
||||||
|
*/
|
||||||
|
unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
|
||||||
|
b.bits[bit >> INDEX_SHIFT] &= ~(1 << uint(bit & INDEX_MASK))
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
|
||||||
|
|
||||||
|
*Allocates (`new(Bit_Array) & make(ba.bits)`)*
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- max_index: maximum starting index
|
||||||
|
- min_index: minimum starting index (used as a bias)
|
||||||
|
- allocator: (default is context.allocator)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
- ba: Allocates a bit_Array, backing data is set to `max-min / 64` indices, rounded up (eg 65 - 0 allocates for [2]u64).
|
||||||
|
*/
|
||||||
|
create :: proc(max_index: int, min_index: int = 0, allocator := context.allocator) -> (res: ^Bit_Array, ok: bool) #optional_ok {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
size_in_bits := max_index - min_index
|
size_in_bits := max_index - min_index
|
||||||
|
|
||||||
if size_in_bits < 1 { return {}, false }
|
if size_in_bits < 1 { return {}, false }
|
||||||
|
|
||||||
legs := size_in_bits >> INDEX_SHIFT
|
legs := size_in_bits >> INDEX_SHIFT
|
||||||
|
if size_in_bits & INDEX_MASK > 0 {legs+=1}
|
||||||
|
bits, err := make([dynamic]u64, legs)
|
||||||
|
ok = err == mem.Allocator_Error.None
|
||||||
res = new(Bit_Array)
|
res = new(Bit_Array)
|
||||||
|
res.bits = bits
|
||||||
res.bias = min_index
|
res.bias = min_index
|
||||||
res.max_index = max_index
|
res.max_index = max_index
|
||||||
res.free_pointer = true
|
res.free_pointer = true
|
||||||
return res, resize_if_needed(res, legs)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets all bits to `false`.
|
Sets all values in the Bit_Array to zero.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- ba: The target Bit_Array
|
||||||
*/
|
*/
|
||||||
clear :: proc(ba: ^Bit_Array) {
|
clear :: proc(ba: ^Bit_Array) {
|
||||||
if ba == nil { return }
|
if ba == nil { return }
|
||||||
mem.zero_slice(ba.bits[:])
|
mem.zero_slice(ba.bits[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Releases the memory used by the Bit Array.
|
Deallocates the Bit_Array and its backing storage
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
- ba: The target Bit_Array
|
||||||
*/
|
*/
|
||||||
destroy :: proc(ba: ^Bit_Array) {
|
destroy :: proc(ba: ^Bit_Array) {
|
||||||
if ba == nil { return }
|
if ba == nil { return }
|
||||||
@@ -248,9 +308,8 @@ destroy :: proc(ba: ^Bit_Array) {
|
|||||||
free(ba)
|
free(ba)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Resizes the Bit Array. For internal use.
|
Resizes the Bit Array. For internal use. Provisions needed capacity+1
|
||||||
If you want to reserve the memory for a given-sized Bit Array up front, you can use `create`.
|
If you want to reserve the memory for a given-sized Bit Array up front, you can use `create`.
|
||||||
*/
|
*/
|
||||||
@(private="file")
|
@(private="file")
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ List :: struct {
|
|||||||
|
|
||||||
|
|
||||||
Node :: struct {
|
Node :: struct {
|
||||||
next, prev: ^Node,
|
prev, next: ^Node,
|
||||||
}
|
}
|
||||||
|
|
||||||
push_front :: proc(list: ^List, node: ^Node) {
|
push_front :: proc "contextless" (list: ^List, node: ^Node) {
|
||||||
if list.head != nil {
|
if list.head != nil {
|
||||||
list.head.prev = node
|
list.head.prev = node
|
||||||
node.prev, node.next = nil, list.head
|
node.prev, node.next = nil, list.head
|
||||||
@@ -34,7 +34,7 @@ push_front :: proc(list: ^List, node: ^Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
push_back :: proc(list: ^List, node: ^Node) {
|
push_back :: proc "contextless" (list: ^List, node: ^Node) {
|
||||||
if list.tail != nil {
|
if list.tail != nil {
|
||||||
list.tail.next = node
|
list.tail.next = node
|
||||||
node.prev, node.next = list.tail, nil
|
node.prev, node.next = list.tail, nil
|
||||||
@@ -45,7 +45,7 @@ push_back :: proc(list: ^List, node: ^Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove :: proc(list: ^List, node: ^Node) {
|
remove :: proc "contextless" (list: ^List, node: ^Node) {
|
||||||
if node != nil {
|
if node != nil {
|
||||||
if node.next != nil {
|
if node.next != nil {
|
||||||
node.next.prev = node.prev
|
node.next.prev = node.prev
|
||||||
@@ -83,12 +83,34 @@ remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove_by_proc_contextless :: proc(list: ^List, to_erase: proc "contextless" (^Node) -> bool) {
|
||||||
|
for node := list.head; node != nil; {
|
||||||
|
next := node.next
|
||||||
|
if to_erase(node) {
|
||||||
|
if node.next != nil {
|
||||||
|
node.next.prev = node.prev
|
||||||
|
}
|
||||||
|
if node.prev != nil {
|
||||||
|
node.prev.next = node.next
|
||||||
|
}
|
||||||
|
if list.head == node {
|
||||||
|
list.head = node.next
|
||||||
|
}
|
||||||
|
if list.tail == node {
|
||||||
|
list.tail = node.prev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node = next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is_empty :: proc(list: ^List) -> bool {
|
|
||||||
|
|
||||||
|
is_empty :: proc "contextless" (list: ^List) -> bool {
|
||||||
return list.head == nil
|
return list.head == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pop_front :: proc(list: ^List) -> ^Node {
|
pop_front :: proc "contextless" (list: ^List) -> ^Node {
|
||||||
link := list.head
|
link := list.head
|
||||||
if link == nil {
|
if link == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -108,7 +130,7 @@ pop_front :: proc(list: ^List) -> ^Node {
|
|||||||
return link
|
return link
|
||||||
|
|
||||||
}
|
}
|
||||||
pop_back :: proc(list: ^List) -> ^Node {
|
pop_back :: proc "contextless" (list: ^List) -> ^Node {
|
||||||
link := list.tail
|
link := list.tail
|
||||||
if link == nil {
|
if link == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -134,25 +156,25 @@ Iterator :: struct($T: typeid) {
|
|||||||
offset: uintptr,
|
offset: uintptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator_head :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
|
iterator_head :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
|
||||||
where intrinsics.type_has_field(T, field_name),
|
where intrinsics.type_has_field(T, field_name),
|
||||||
intrinsics.type_field_type(T, field_name) == Node {
|
intrinsics.type_field_type(T, field_name) == Node {
|
||||||
return {list.head, offset_of_by_string(T, field_name)}
|
return {list.head, offset_of_by_string(T, field_name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator_tail :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
|
iterator_tail :: proc "contextless" (list: List, $T: typeid, $field_name: string) -> Iterator(T)
|
||||||
where intrinsics.type_has_field(T, field_name),
|
where intrinsics.type_has_field(T, field_name),
|
||||||
intrinsics.type_field_type(T, field_name) == Node {
|
intrinsics.type_field_type(T, field_name) == Node {
|
||||||
return {list.tail, offset_of_by_string(T, field_name)}
|
return {list.tail, offset_of_by_string(T, field_name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator_from_node :: proc(node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
|
iterator_from_node :: proc "contextless" (node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
|
||||||
where intrinsics.type_has_field(T, field_name),
|
where intrinsics.type_has_field(T, field_name),
|
||||||
intrinsics.type_field_type(T, field_name) == Node {
|
intrinsics.type_field_type(T, field_name) == Node {
|
||||||
return {node, offset_of_by_string(T, field_name)}
|
return {node, offset_of_by_string(T, field_name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
|
iterate_next :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
|
||||||
node := it.curr
|
node := it.curr
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
@@ -162,7 +184,7 @@ iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
|
|||||||
return (^T)(uintptr(node) - it.offset), true
|
return (^T)(uintptr(node) - it.offset), true
|
||||||
}
|
}
|
||||||
|
|
||||||
iterate_prev :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
|
iterate_prev :: proc "contextless" (it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
|
||||||
node := it.curr
|
node := it.curr
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Queue :: struct($T: typeid) {
|
|||||||
DEFAULT_CAPACITY :: 16
|
DEFAULT_CAPACITY :: 16
|
||||||
|
|
||||||
// Procedure to initialize a queue
|
// Procedure to initialize a queue
|
||||||
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> bool {
|
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> runtime.Allocator_Error {
|
||||||
if q.data.allocator.procedure == nil {
|
if q.data.allocator.procedure == nil {
|
||||||
q.data.allocator = allocator
|
q.data.allocator = allocator
|
||||||
}
|
}
|
||||||
@@ -55,11 +55,11 @@ space :: proc(q: $Q/Queue($T)) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reserve enough space for at least the specified capacity
|
// Reserve enough space for at least the specified capacity
|
||||||
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> bool {
|
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error {
|
||||||
if uint(capacity) > q.len {
|
if capacity > space(q^) {
|
||||||
return _grow(q, uint(capacity))
|
return _grow(q, uint(capacity))
|
||||||
}
|
}
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -112,25 +112,25 @@ peek_back :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Push an element to the back of the queue
|
// Push an element to the back of the queue
|
||||||
push_back :: proc(q: ^$Q/Queue($T), elem: T) -> bool {
|
push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
|
||||||
if space(q^) == 0 {
|
if space(q^) == 0 {
|
||||||
_grow(q) or_return
|
_grow(q) or_return
|
||||||
}
|
}
|
||||||
idx := (q.offset+uint(q.len))%builtin.len(q.data)
|
idx := (q.offset+uint(q.len))%builtin.len(q.data)
|
||||||
q.data[idx] = elem
|
q.data[idx] = elem
|
||||||
q.len += 1
|
q.len += 1
|
||||||
return true
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push an element to the front of the queue
|
// Push an element to the front of the queue
|
||||||
push_front :: proc(q: ^$Q/Queue($T), elem: T) -> bool {
|
push_front :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
|
||||||
if space(q^) == 0 {
|
if space(q^) == 0 {
|
||||||
_grow(q) or_return
|
_grow(q) or_return
|
||||||
}
|
}
|
||||||
q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data)
|
q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data)
|
||||||
q.len += 1
|
q.len += 1
|
||||||
q.data[q.offset] = elem
|
q.data[q.offset] = elem
|
||||||
return true
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Push multiple elements to the front of the queue
|
// Push multiple elements to the front of the queue
|
||||||
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> bool {
|
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) {
|
||||||
n := uint(builtin.len(elems))
|
n := uint(builtin.len(elems))
|
||||||
if space(q^) < int(n) {
|
if space(q^) < int(n) {
|
||||||
_grow(q, q.len + n) or_return
|
_grow(q, q.len + n) or_return
|
||||||
@@ -188,7 +188,7 @@ push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> bool {
|
|||||||
copy(q.data[insert_from:], elems[:insert_to])
|
copy(q.data[insert_from:], elems[:insert_to])
|
||||||
copy(q.data[:insert_from], elems[insert_to:])
|
copy(q.data[:insert_from], elems[insert_to:])
|
||||||
q.len += n
|
q.len += n
|
||||||
return true
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consume `n` elements from the front of the queue
|
// Consume `n` elements from the front of the queue
|
||||||
@@ -225,7 +225,7 @@ clear :: proc(q: ^$Q/Queue($T)) {
|
|||||||
|
|
||||||
|
|
||||||
// Internal growinh procedure
|
// Internal growinh procedure
|
||||||
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> bool {
|
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
|
||||||
new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
|
new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
|
||||||
n := uint(builtin.len(q.data))
|
n := uint(builtin.len(q.data))
|
||||||
builtin.resize(&q.data, int(new_capacity)) or_return
|
builtin.resize(&q.data, int(new_capacity)) or_return
|
||||||
@@ -234,5 +234,5 @@ _grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> bool {
|
|||||||
copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff])
|
copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff])
|
||||||
q.offset += new_capacity - n
|
q.offset += new_capacity - n
|
||||||
}
|
}
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ init :: proc(sorter: ^$S/Sorter($K)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destroy :: proc(sorter: ^$S/Sorter($K)) {
|
destroy :: proc(sorter: ^$S/Sorter($K)) {
|
||||||
for _, v in &sorter.relations {
|
for _, v in sorter.relations {
|
||||||
delete(v.dependents)
|
delete(v.dependents)
|
||||||
}
|
}
|
||||||
delete(sorter.relations)
|
delete(sorter.relations)
|
||||||
@@ -80,7 +80,7 @@ sort :: proc(sorter: ^$S/Sorter($K)) -> (sorted, cycled: [dynamic]K) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for root in &sorted do for k, _ in relations[root].dependents {
|
for root in sorted do for k, _ in relations[root].dependents {
|
||||||
relation := &relations[k]
|
relation := &relations[k]
|
||||||
relation.dependencies -= 1
|
relation.dependencies -= 1
|
||||||
if relation.dependencies == 0 {
|
if relation.dependencies == 0 {
|
||||||
|
|||||||
@@ -9,14 +9,16 @@ package fiat
|
|||||||
u1 :: distinct u8
|
u1 :: distinct u8
|
||||||
i1 :: distinct i8
|
i1 :: distinct i8
|
||||||
|
|
||||||
cmovznz_u64 :: #force_inline proc "contextless" (arg1: u1, arg2, arg3: u64) -> (out1: u64) {
|
@(optimization_mode="none")
|
||||||
|
cmovznz_u64 :: proc "contextless" (arg1: u1, arg2, arg3: u64) -> (out1: u64) {
|
||||||
x1 := (u64(arg1) * 0xffffffffffffffff)
|
x1 := (u64(arg1) * 0xffffffffffffffff)
|
||||||
x2 := ((x1 & arg3) | ((~x1) & arg2))
|
x2 := ((x1 & arg3) | ((~x1) & arg2))
|
||||||
out1 = x2
|
out1 = x2
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmovznz_u32 :: #force_inline proc "contextless" (arg1: u1, arg2, arg3: u32) -> (out1: u32) {
|
@(optimization_mode="none")
|
||||||
|
cmovznz_u32 :: proc "contextless" (arg1: u1, arg2, arg3: u32) -> (out1: u32) {
|
||||||
x1 := (u32(arg1) * 0xffffffff)
|
x1 := (u32(arg1) * 0xffffffff)
|
||||||
x2 := ((x1 & arg3) | ((~x1) & arg2))
|
x2 := ((x1 & arg3) | ((~x1) & arg2))
|
||||||
out1 = x2
|
out1 = x2
|
||||||
|
|||||||
@@ -305,7 +305,8 @@ fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Ele
|
|||||||
out1[4] = x5
|
out1[4] = x5
|
||||||
}
|
}
|
||||||
|
|
||||||
fe_cond_assign :: proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: int) {
|
@(optimization_mode="none")
|
||||||
|
fe_cond_assign :: #force_no_inline proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: int) {
|
||||||
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
||||||
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
||||||
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
||||||
@@ -596,7 +597,8 @@ fe_set :: proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
|||||||
out1[4] = x5
|
out1[4] = x5
|
||||||
}
|
}
|
||||||
|
|
||||||
fe_cond_swap :: proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) {
|
@(optimization_mode="none")
|
||||||
|
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: int) {
|
||||||
mask := -u64(arg1)
|
mask := -u64(arg1)
|
||||||
x := (out1[0] ~ out2[0]) & mask
|
x := (out1[0] ~ out2[0]) & mask
|
||||||
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ fe_opp :: proc "contextless" (out1: ^Loose_Field_Element, arg1: ^Tight_Field_Ele
|
|||||||
out1[2] = x3
|
out1[2] = x3
|
||||||
}
|
}
|
||||||
|
|
||||||
fe_cond_assign :: proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: bool) {
|
@(optimization_mode="none")
|
||||||
|
fe_cond_assign :: #force_no_inline proc "contextless" (out1, arg1: ^Tight_Field_Element, arg2: bool) {
|
||||||
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0])
|
||||||
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1])
|
||||||
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2])
|
||||||
@@ -342,7 +343,8 @@ fe_set :: #force_inline proc "contextless" (out1, arg1: ^Tight_Field_Element) {
|
|||||||
out1[2] = x3
|
out1[2] = x3
|
||||||
}
|
}
|
||||||
|
|
||||||
fe_cond_swap :: proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: bool) {
|
@(optimization_mode="none")
|
||||||
|
fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Tight_Field_Element, arg1: bool) {
|
||||||
mask := -u64(arg1)
|
mask := -u64(arg1)
|
||||||
x := (out1[0] ~ out2[0]) & mask
|
x := (out1[0] ~ out2[0]) & mask
|
||||||
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
x1, y1 := out1[0] ~ x, out2[0] ~ x
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_blake2.update(&ctx, buf[:read])
|
_blake2.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_blake2.update(&ctx, buf[:read])
|
_blake2.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,23 @@ KEY_SIZE :: 32
|
|||||||
NONCE_SIZE :: 12
|
NONCE_SIZE :: 12
|
||||||
XNONCE_SIZE :: 24
|
XNONCE_SIZE :: 24
|
||||||
|
|
||||||
|
@(private)
|
||||||
_MAX_CTR_IETF :: 0xffffffff
|
_MAX_CTR_IETF :: 0xffffffff
|
||||||
|
|
||||||
|
@(private)
|
||||||
_BLOCK_SIZE :: 64
|
_BLOCK_SIZE :: 64
|
||||||
|
@(private)
|
||||||
_STATE_SIZE_U32 :: 16
|
_STATE_SIZE_U32 :: 16
|
||||||
|
@(private)
|
||||||
_ROUNDS :: 20
|
_ROUNDS :: 20
|
||||||
|
|
||||||
|
@(private)
|
||||||
_SIGMA_0 : u32 : 0x61707865
|
_SIGMA_0 : u32 : 0x61707865
|
||||||
|
@(private)
|
||||||
_SIGMA_1 : u32 : 0x3320646e
|
_SIGMA_1 : u32 : 0x3320646e
|
||||||
|
@(private)
|
||||||
_SIGMA_2 : u32 : 0x79622d32
|
_SIGMA_2 : u32 : 0x79622d32
|
||||||
|
@(private)
|
||||||
_SIGMA_3 : u32 : 0x6b206574
|
_SIGMA_3 : u32 : 0x6b206574
|
||||||
|
|
||||||
Context :: struct {
|
Context :: struct {
|
||||||
@@ -179,6 +187,7 @@ reset :: proc (ctx: ^Context) {
|
|||||||
ctx._is_initialized = false
|
ctx._is_initialized = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
|
_do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
|
||||||
// Enforce the maximum consumed keystream per nonce.
|
// Enforce the maximum consumed keystream per nonce.
|
||||||
//
|
//
|
||||||
@@ -441,6 +450,7 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_hchacha20 :: proc (dst, key, nonce: []byte) {
|
_hchacha20 :: proc (dst, key, nonce: []byte) {
|
||||||
x0, x1, x2, x3 := _SIGMA_0, _SIGMA_1, _SIGMA_2, _SIGMA_3
|
x0, x1, x2, x3 := _SIGMA_0, _SIGMA_1, _SIGMA_2, _SIGMA_3
|
||||||
x4 := util.U32_LE(key[0:4])
|
x4 := util.U32_LE(key[0:4])
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ KEY_SIZE :: chacha20.KEY_SIZE
|
|||||||
NONCE_SIZE :: chacha20.NONCE_SIZE
|
NONCE_SIZE :: chacha20.NONCE_SIZE
|
||||||
TAG_SIZE :: poly1305.TAG_SIZE
|
TAG_SIZE :: poly1305.TAG_SIZE
|
||||||
|
|
||||||
|
@(private)
|
||||||
_P_MAX :: 64 * 0xffffffff // 64 * (2^32-1)
|
_P_MAX :: 64 * 0xffffffff // 64 * (2^32-1)
|
||||||
|
|
||||||
|
@(private)
|
||||||
_validate_common_slice_sizes :: proc (tag, key, nonce, aad, text: []byte) {
|
_validate_common_slice_sizes :: proc (tag, key, nonce, aad, text: []byte) {
|
||||||
if len(tag) != TAG_SIZE {
|
if len(tag) != TAG_SIZE {
|
||||||
panic("crypto/chacha20poly1305: invalid destination tag size")
|
panic("crypto/chacha20poly1305: invalid destination tag size")
|
||||||
@@ -37,7 +39,10 @@ _validate_common_slice_sizes :: proc (tag, key, nonce, aad, text: []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_PAD: [16]byte
|
_PAD: [16]byte
|
||||||
|
|
||||||
|
@(private)
|
||||||
_update_mac_pad16 :: #force_inline proc (ctx: ^poly1305.Context, x_len: int) {
|
_update_mac_pad16 :: #force_inline proc (ctx: ^poly1305.Context, x_len: int) {
|
||||||
if pad_len := 16 - (x_len & (16-1)); pad_len != 16 {
|
if pad_len := 16 - (x_len & (16-1)); pad_len != 16 {
|
||||||
poly1305.update(ctx, _PAD[:pad_len])
|
poly1305.update(ctx, _PAD[:pad_len])
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ compare_constant_time :: proc "contextless" (a, b: []byte) -> int {
|
|||||||
//
|
//
|
||||||
// The execution time of this routine is constant regardless of the
|
// The execution time of this routine is constant regardless of the
|
||||||
// contents of the memory being compared.
|
// contents of the memory being compared.
|
||||||
|
@(optimization_mode="none")
|
||||||
compare_byte_ptrs_constant_time :: proc "contextless" (a, b: ^byte, n: int) -> int {
|
compare_byte_ptrs_constant_time :: proc "contextless" (a, b: ^byte, n: int) -> int {
|
||||||
x := mem.slice_ptr(a, n)
|
x := mem.slice_ptr(a, n)
|
||||||
y := mem.slice_ptr(b, n)
|
y := mem.slice_ptr(b, n)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ hash_stream_128_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -164,7 +164,7 @@ hash_stream_128_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -249,7 +249,7 @@ hash_stream_128_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -334,7 +334,7 @@ hash_stream_160_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -419,7 +419,7 @@ hash_stream_160_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -504,7 +504,7 @@ hash_stream_160_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -589,7 +589,7 @@ hash_stream_192_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -674,7 +674,7 @@ hash_stream_192_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -759,7 +759,7 @@ hash_stream_192_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -844,7 +844,7 @@ hash_stream_224_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -929,7 +929,7 @@ hash_stream_224_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -1014,7 +1014,7 @@ hash_stream_224_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -1099,7 +1099,7 @@ hash_stream_256_3 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -1184,7 +1184,7 @@ hash_stream_256_4 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
@@ -1270,7 +1270,7 @@ hash_stream_256_5 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
ctx.str_len = u32(len(buf[:read]))
|
ctx.str_len = u32(len(buf[:read]))
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -241,7 +241,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -323,7 +323,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import "core:mem"
|
|||||||
KEY_SIZE :: 32
|
KEY_SIZE :: 32
|
||||||
TAG_SIZE :: 16
|
TAG_SIZE :: 16
|
||||||
|
|
||||||
|
@(private)
|
||||||
_BLOCK_SIZE :: 16
|
_BLOCK_SIZE :: 16
|
||||||
|
|
||||||
sum :: proc (dst, msg, key: []byte) {
|
sum :: proc (dst, msg, key: []byte) {
|
||||||
@@ -141,6 +142,7 @@ reset :: proc (ctx: ^Context) {
|
|||||||
ctx._is_initialized = false
|
ctx._is_initialized = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_blocks :: proc (ctx: ^Context, msg: []byte, final := false) {
|
_blocks :: proc (ctx: ^Context, msg: []byte, final := false) {
|
||||||
n: field.Tight_Field_Element = ---
|
n: field.Tight_Field_Element = ---
|
||||||
final_byte := byte(!final)
|
final_byte := byte(!final)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows {
|
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows && ODIN_OS != .JS {
|
||||||
_rand_bytes :: proc (dst: []byte) {
|
_rand_bytes :: proc(dst: []byte) {
|
||||||
unimplemented("crypto: rand_bytes not supported on this OS")
|
unimplemented("crypto: rand_bytes not supported on this OS")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package crypto
|
||||||
|
|
||||||
|
foreign import "odin_env"
|
||||||
|
foreign odin_env {
|
||||||
|
@(link_name = "rand_bytes")
|
||||||
|
env_rand_bytes :: proc "contextless" (buf: []byte) ---
|
||||||
|
}
|
||||||
|
|
||||||
|
_MAX_PER_CALL_BYTES :: 65536 // 64kiB
|
||||||
|
|
||||||
|
_rand_bytes :: proc(dst: []byte) {
|
||||||
|
dst := dst
|
||||||
|
|
||||||
|
for len(dst) > 0 {
|
||||||
|
to_read := min(len(dst), _MAX_PER_CALL_BYTES)
|
||||||
|
env_rand_bytes(dst[:to_read])
|
||||||
|
|
||||||
|
dst = dst[to_read:]
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-22
@@ -1,8 +1,8 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:os"
|
|
||||||
import "core:sys/unix"
|
import "core:sys/linux"
|
||||||
|
|
||||||
_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1
|
_MAX_PER_CALL_BYTES :: 33554431 // 2^25 - 1
|
||||||
|
|
||||||
@@ -12,26 +12,25 @@ _rand_bytes :: proc (dst: []byte) {
|
|||||||
|
|
||||||
for l > 0 {
|
for l > 0 {
|
||||||
to_read := min(l, _MAX_PER_CALL_BYTES)
|
to_read := min(l, _MAX_PER_CALL_BYTES)
|
||||||
ret := unix.sys_getrandom(raw_data(dst), uint(to_read), 0)
|
n_read, errno := linux.getrandom(dst[:to_read], {})
|
||||||
if ret < 0 {
|
#partial switch errno {
|
||||||
switch os.Errno(-ret) {
|
case .NONE:
|
||||||
case os.EINTR:
|
// Do nothing
|
||||||
// Call interupted by a signal handler, just retry the
|
case .EINTR:
|
||||||
// request.
|
// Call interupted by a signal handler, just retry the
|
||||||
continue
|
// request.
|
||||||
case os.ENOSYS:
|
continue
|
||||||
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
case .ENOSYS:
|
||||||
// and does not support getrandom.
|
// The kernel is apparently prehistoric (< 3.17 circa 2014)
|
||||||
panic("crypto: getrandom not available in kernel")
|
// and does not support getrandom.
|
||||||
case:
|
panic("crypto: getrandom not available in kernel")
|
||||||
// All other failures are things that should NEVER happen
|
case:
|
||||||
// unless the kernel interface changes (ie: the Linux
|
// All other failures are things that should NEVER happen
|
||||||
// developers break userland).
|
// unless the kernel interface changes (ie: the Linux
|
||||||
panic(fmt.tprintf("crypto: getrandom failed: %d", ret))
|
// developers break userland).
|
||||||
}
|
panic(fmt.tprintf("crypto: getrandom failed: %v", errno))
|
||||||
}
|
}
|
||||||
|
l -= n_read
|
||||||
l -= ret
|
dst = dst[n_read:]
|
||||||
dst = dst[ret:]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -221,7 +221,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ hash_stream_320 :: proc(s: io.Stream) -> ([DIGEST_SIZE_320]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -232,7 +232,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ hash_stream_224 :: proc(s: io.Stream) -> ([DIGEST_SIZE_224]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ hash_stream_384 :: proc(s: io.Stream) -> ([DIGEST_SIZE_384]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -310,7 +310,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_sha3.update(&ctx, buf[:read])
|
_sha3.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ hash_stream_256 :: proc(s: io.Stream) -> ([DIGEST_SIZE_256]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -146,7 +146,7 @@ hash_stream_512 :: proc(s: io.Stream) -> ([DIGEST_SIZE_512]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_tiger.update(&ctx, buf[:read])
|
_tiger.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_tiger.update(&ctx, buf[:read])
|
_tiger.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_tiger.update(&ctx, buf[:read])
|
_tiger.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ hash_stream_128 :: proc(s: io.Stream) -> ([DIGEST_SIZE_128]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_tiger.update(&ctx, buf[:read])
|
_tiger.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -150,7 +150,7 @@ hash_stream_160 :: proc(s: io.Stream) -> ([DIGEST_SIZE_160]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_tiger.update(&ctx, buf[:read])
|
_tiger.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
@@ -229,7 +229,7 @@ hash_stream_192 :: proc(s: io.Stream) -> ([DIGEST_SIZE_192]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
_tiger.update(&ctx, buf[:read])
|
_tiger.update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ package util
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
// Keep vet happy
|
||||||
|
_ :: mem
|
||||||
|
|
||||||
// @note(bp): this can replace the other two
|
// @note(bp): this can replace the other two
|
||||||
cast_slice :: #force_inline proc "contextless" ($D: typeid/[]$DE, src: $S/[]$SE) -> D {
|
cast_slice :: #force_inline proc "contextless" ($D: typeid/[]$DE, src: $S/[]$SE) -> D {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ hash_stream :: proc(s: io.Stream) -> ([DIGEST_SIZE]byte, bool) {
|
|||||||
defer delete(buf)
|
defer delete(buf)
|
||||||
read := 1
|
read := 1
|
||||||
for read > 0 {
|
for read > 0 {
|
||||||
read, _ = s->impl_read(buf)
|
read, _ = io.read(s, buf)
|
||||||
if read > 0 {
|
if read > 0 {
|
||||||
update(&ctx, buf[:read])
|
update(&ctx, buf[:read])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import "core:mem"
|
|||||||
SCALAR_SIZE :: 32
|
SCALAR_SIZE :: 32
|
||||||
POINT_SIZE :: 32
|
POINT_SIZE :: 32
|
||||||
|
|
||||||
|
@(private)
|
||||||
_BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
_BASE_POINT: [32]byte = {9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_scalar_bit :: #force_inline proc "contextless" (s: ^[32]byte, i: int) -> u8 {
|
_scalar_bit :: #force_inline proc "contextless" (s: ^[32]byte, i: int) -> u8 {
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return 0
|
return 0
|
||||||
@@ -15,6 +17,7 @@ _scalar_bit :: #force_inline proc "contextless" (s: ^[32]byte, i: int) -> u8 {
|
|||||||
return (s[i>>3] >> uint(i&7)) & 1
|
return (s[i>>3] >> uint(i&7)) & 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_scalarmult :: proc (out, scalar, point: ^[32]byte) {
|
_scalarmult :: proc (out, scalar, point: ^[32]byte) {
|
||||||
// Montgomery pseduo-multiplication taken from Monocypher.
|
// Montgomery pseduo-multiplication taken from Monocypher.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package debug_pe
|
package debug_pe
|
||||||
|
|
||||||
import "core:runtime"
|
|
||||||
import "core:io"
|
|
||||||
|
|
||||||
Section_Header32 :: struct {
|
Section_Header32 :: struct {
|
||||||
name: [8]u8,
|
name: [8]u8,
|
||||||
virtual_size: u32le,
|
virtual_size: u32le,
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
//+build js
|
||||||
|
//+private
|
||||||
|
package dynlib
|
||||||
|
|
||||||
|
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
_unload_library :: proc(library: Library) -> bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
@@ -248,7 +248,7 @@ _read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.all
|
|||||||
field_length += 1
|
field_length += 1
|
||||||
|
|
||||||
case '\n', '\r':
|
case '\n', '\r':
|
||||||
if !is_quoted { break read_loop }
|
is_quoted or_break read_loop
|
||||||
|
|
||||||
case r.comma:
|
case r.comma:
|
||||||
field_length = 0
|
field_length = 0
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ write :: proc(w: ^Writer, record: []string) -> io.Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case:
|
case:
|
||||||
if strings.contains_rune(field, w.comma) >= 0 {
|
if strings.contains_rune(field, w.comma) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if strings.contains_any(field, CHAR_SET) {
|
if strings.contains_any(field, CHAR_SET) {
|
||||||
|
|||||||
@@ -184,28 +184,26 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
|
|||||||
|
|
||||||
advance :: proc(t: ^Tokenizer) -> (err: Error) {
|
advance :: proc(t: ^Tokenizer) -> (err: Error) {
|
||||||
if t == nil { return .Tokenizer_Is_Nil }
|
if t == nil { return .Tokenizer_Is_Nil }
|
||||||
using t
|
|
||||||
|
|
||||||
#no_bounds_check {
|
#no_bounds_check {
|
||||||
if read_offset < len(src) {
|
if t.read_offset < len(t.src) {
|
||||||
offset = read_offset
|
t.offset = t.read_offset
|
||||||
r, w = rune(src[read_offset]), 1
|
t.r, t.w = rune(t.src[t.read_offset]), 1
|
||||||
switch {
|
switch {
|
||||||
case r == 0:
|
case t.r == 0:
|
||||||
return .Illegal_NUL_Character
|
return .Illegal_NUL_Character
|
||||||
case r >= utf8.RUNE_SELF:
|
case t.r >= utf8.RUNE_SELF:
|
||||||
r, w = utf8.decode_rune_in_string(src[read_offset:])
|
t.r, t.w = utf8.decode_rune_in_string(t.src[t.read_offset:])
|
||||||
if r == utf8.RUNE_ERROR && w == 1 {
|
if t.r == utf8.RUNE_ERROR && t.w == 1 {
|
||||||
return .Illegal_UTF_Encoding
|
return .Illegal_UTF_Encoding
|
||||||
} else if r == utf8.RUNE_BOM && offset > 0 {
|
} else if t.r == utf8.RUNE_BOM && t.offset > 0 {
|
||||||
return .Illegal_BOM
|
return .Illegal_BOM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_offset += w
|
t.read_offset += t.w
|
||||||
return .None
|
return .None
|
||||||
} else {
|
} else {
|
||||||
offset = len(src)
|
t.offset = len(t.src)
|
||||||
r = -1
|
t.r = -1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,26 +271,25 @@ _extract_xml_entity :: proc(t: ^Tokenizer) -> (entity: string, err: Error) {
|
|||||||
All of these would be in the ASCII range.
|
All of these would be in the ASCII range.
|
||||||
Even if one is not, it doesn't matter. All characters we need to compare to extract are.
|
Even if one is not, it doesn't matter. All characters we need to compare to extract are.
|
||||||
*/
|
*/
|
||||||
using t
|
|
||||||
|
|
||||||
length := len(t.src)
|
length := len(t.src)
|
||||||
found := false
|
found := false
|
||||||
|
|
||||||
#no_bounds_check {
|
#no_bounds_check {
|
||||||
for read_offset < length {
|
for t.read_offset < length {
|
||||||
if src[read_offset] == ';' {
|
if t.src[t.read_offset] == ';' {
|
||||||
|
t.read_offset += 1
|
||||||
found = true
|
found = true
|
||||||
read_offset += 1
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
read_offset += 1
|
t.read_offset += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if found {
|
if found {
|
||||||
return string(src[offset + 1 : read_offset - 1]), .None
|
return string(t.src[t.offset + 1 : t.read_offset - 1]), .None
|
||||||
}
|
}
|
||||||
return string(src[offset : read_offset]), .Invalid_Entity_Encoding
|
return string(t.src[t.offset : t.read_offset]), .Invalid_Entity_Encoding
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package hex
|
||||||
|
|
||||||
|
import "core:strings"
|
||||||
|
|
||||||
|
encode :: proc(src: []byte, allocator := context.allocator) -> []byte #no_bounds_check {
|
||||||
|
dst := make([]byte, len(src) * 2, allocator)
|
||||||
|
for i, j := 0, 0; i < len(src); i += 1 {
|
||||||
|
v := src[i]
|
||||||
|
dst[j] = HEXTABLE[v>>4]
|
||||||
|
dst[j+1] = HEXTABLE[v&0x0f]
|
||||||
|
j += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
decode :: proc(src: []byte, allocator := context.allocator) -> (dst: []byte, ok: bool) #no_bounds_check {
|
||||||
|
if len(src) % 2 == 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = make([]byte, len(src) / 2, allocator)
|
||||||
|
for i, j := 0, 1; j < len(src); j += 2 {
|
||||||
|
p := src[j-1]
|
||||||
|
q := src[j]
|
||||||
|
|
||||||
|
a := hex_digit(p) or_return
|
||||||
|
b := hex_digit(q) or_return
|
||||||
|
|
||||||
|
dst[i] = (a << 4) | b
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decodes the given sequence into one byte.
|
||||||
|
// Should be called with one byte worth of the source, eg: 0x23 -> '#'.
|
||||||
|
decode_sequence :: proc(str: string) -> (res: byte, ok: bool) {
|
||||||
|
str := str
|
||||||
|
if strings.has_prefix(str, "0x") || strings.has_prefix(str, "0X") {
|
||||||
|
str = str[2:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(str) != 2 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
upper := hex_digit(str[0]) or_return
|
||||||
|
lower := hex_digit(str[1]) or_return
|
||||||
|
|
||||||
|
return upper << 4 | lower, true
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
HEXTABLE := [16]byte {
|
||||||
|
'0', '1', '2', '3',
|
||||||
|
'4', '5', '6', '7',
|
||||||
|
'8', '9', 'a', 'b',
|
||||||
|
'c', 'd', 'e', 'f',
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
hex_digit :: proc(char: byte) -> (u8, bool) {
|
||||||
|
switch char {
|
||||||
|
case '0' ..= '9': return char - '0', true
|
||||||
|
case 'a' ..= 'f': return char - 'a' + 10, true
|
||||||
|
case 'A' ..= 'F': return char - 'A' + 10, true
|
||||||
|
case: return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
|
|||||||
meta_data = make([]Meta, int(capacity))
|
meta_data = make([]Meta, int(capacity))
|
||||||
count := 0
|
count := 0
|
||||||
defer meta_data = meta_data[:count]
|
defer meta_data = meta_data[:count]
|
||||||
for m in &meta_data {
|
for &m in meta_data {
|
||||||
m.name = read_name(r) or_return
|
m.name = read_name(r) or_return
|
||||||
|
|
||||||
type := read_value(r, Meta_Value_Type) or_return
|
type := read_value(r, Meta_Value_Type) or_return
|
||||||
@@ -116,7 +116,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
|
|||||||
layer_count := 0
|
layer_count := 0
|
||||||
layers = make(Layer_Stack, stack_count)
|
layers = make(Layer_Stack, stack_count)
|
||||||
defer layers = layers[:layer_count]
|
defer layers = layers[:layer_count]
|
||||||
for layer in &layers {
|
for &layer in layers {
|
||||||
layer.name = read_name(r) or_return
|
layer.name = read_name(r) or_return
|
||||||
layer.components = read_value(r, u8) or_return
|
layer.components = read_value(r, u8) or_return
|
||||||
type := read_value(r, Layer_Data_Type) or_return
|
type := read_value(r, Layer_Data_Type) or_return
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
|||||||
case complex128: r, i = f64(real(z)), f64(imag(z))
|
case complex128: r, i = f64(real(z)), f64(imag(z))
|
||||||
case: return .Unsupported_Type
|
case: return .Unsupported_Type
|
||||||
}
|
}
|
||||||
|
|
||||||
io.write_byte(w, '[') or_return
|
io.write_byte(w, '[') or_return
|
||||||
io.write_f64(w, r) or_return
|
io.write_f64(w, r) or_return
|
||||||
io.write_string(w, ", ") or_return
|
io.write_string(w, ", ") or_return
|
||||||
@@ -165,8 +165,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
|||||||
|
|
||||||
case runtime.Type_Info_String:
|
case runtime.Type_Info_String:
|
||||||
switch s in a {
|
switch s in a {
|
||||||
case string: io.write_quoted_string(w, s) or_return
|
case string: io.write_quoted_string(w, s, '"', nil, true) or_return
|
||||||
case cstring: io.write_quoted_string(w, string(s)) or_return
|
case cstring: io.write_quoted_string(w, string(s), '"', nil, true) or_return
|
||||||
}
|
}
|
||||||
|
|
||||||
case runtime.Type_Info_Boolean:
|
case runtime.Type_Info_Boolean:
|
||||||
@@ -207,7 +207,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
|||||||
case runtime.Type_Info_Relative_Pointer:
|
case runtime.Type_Info_Relative_Pointer:
|
||||||
return .Unsupported_Type
|
return .Unsupported_Type
|
||||||
|
|
||||||
case runtime.Type_Info_Relative_Slice:
|
case runtime.Type_Info_Relative_Multi_Pointer:
|
||||||
return .Unsupported_Type
|
return .Unsupported_Type
|
||||||
|
|
||||||
case runtime.Type_Info_Matrix:
|
case runtime.Type_Info_Matrix:
|
||||||
@@ -265,9 +265,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
|||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for bucket_index in 0..<map_cap {
|
for bucket_index in 0..<map_cap {
|
||||||
if !runtime.map_hash_is_valid(hs[bucket_index]) {
|
runtime.map_hash_is_valid(hs[bucket_index]) or_continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
opt_write_iteration(w, opt, i) or_return
|
opt_write_iteration(w, opt, i) or_return
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
@@ -284,8 +283,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
|||||||
#partial switch info in ti.variant {
|
#partial switch info in ti.variant {
|
||||||
case runtime.Type_Info_String:
|
case runtime.Type_Info_String:
|
||||||
switch s in a {
|
switch s in a {
|
||||||
case string: name = s
|
case string: name = s
|
||||||
case cstring: name = string(s)
|
case cstring: name = string(s)
|
||||||
}
|
}
|
||||||
opt_write_key(w, opt, name) or_return
|
opt_write_key(w, opt, name) or_return
|
||||||
|
|
||||||
@@ -404,7 +403,7 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err
|
|||||||
switch opt.spec {
|
switch opt.spec {
|
||||||
case .JSON, .JSON5:
|
case .JSON, .JSON5:
|
||||||
io.write_quoted_string(w, name) or_return
|
io.write_quoted_string(w, name) or_return
|
||||||
io.write_string(w, ": ") or_return
|
io.write_string(w, ": " if opt.pretty else ":") or_return
|
||||||
|
|
||||||
case .MJSON:
|
case .MJSON:
|
||||||
if opt.mjson_keys_use_quotes {
|
if opt.mjson_keys_use_quotes {
|
||||||
@@ -412,11 +411,11 @@ opt_write_key :: proc(w: io.Writer, opt: ^Marshal_Options, name: string) -> (err
|
|||||||
} else {
|
} else {
|
||||||
io.write_string(w, name) or_return
|
io.write_string(w, name) or_return
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.mjson_keys_use_equal_sign {
|
if opt.mjson_keys_use_equal_sign {
|
||||||
io.write_string(w, " = ") or_return
|
io.write_string(w, " = " if opt.pretty else "=") or_return
|
||||||
} else {
|
} else {
|
||||||
io.write_string(w, ": ") or_return
|
io.write_string(w, ": " if opt.pretty else ":") or_return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,12 +440,12 @@ opt_write_start :: proc(w: io.Writer, opt: ^Marshal_Options, c: byte) -> (err: i
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert comma seperation and write indentations
|
// insert comma separation and write indentations
|
||||||
opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int) -> (err: io.Error) {
|
opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int) -> (err: io.Error) {
|
||||||
switch opt.spec {
|
switch opt.spec {
|
||||||
case .JSON, .JSON5:
|
case .JSON, .JSON5:
|
||||||
if iteration > 0 {
|
if iteration > 0 {
|
||||||
io.write_string(w, ", ") or_return
|
io.write_byte(w, ',') or_return
|
||||||
|
|
||||||
if opt.pretty {
|
if opt.pretty {
|
||||||
io.write_byte(w, '\n') or_return
|
io.write_byte(w, '\n') or_return
|
||||||
@@ -461,8 +460,8 @@ opt_write_iteration :: proc(w: io.Writer, opt: ^Marshal_Options, iteration: int)
|
|||||||
if opt.pretty {
|
if opt.pretty {
|
||||||
io.write_byte(w, '\n') or_return
|
io.write_byte(w, '\n') or_return
|
||||||
} else {
|
} else {
|
||||||
// comma seperation necessary for non pretty output!
|
// comma separation necessary for non pretty output!
|
||||||
io.write_string(w, ", ") or_return
|
io.write_byte(w, ',') or_return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package json
|
|||||||
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
|
import "core:unicode/utf16"
|
||||||
import "core:strconv"
|
import "core:strconv"
|
||||||
|
|
||||||
Parser :: struct {
|
Parser :: struct {
|
||||||
@@ -262,8 +263,17 @@ parse_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> (obj: Object, er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
obj[key] = elem
|
// NOTE(gonz): There are code paths for which this traversal ends up
|
||||||
|
// inserting empty key/values into the object and for those we do not
|
||||||
|
// want to allocate anything
|
||||||
|
if key != "" {
|
||||||
|
reserve_error := reserve(&obj, len(obj) + 1)
|
||||||
|
if reserve_error == mem.Allocator_Error.Out_Of_Memory {
|
||||||
|
return nil, .Out_Of_Memory
|
||||||
|
}
|
||||||
|
obj[key] = elem
|
||||||
|
}
|
||||||
|
|
||||||
if parse_comma(p) {
|
if parse_comma(p) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -342,7 +352,7 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
|
|||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
r, w := utf8.decode_rune_in_string(s)
|
r, w := utf8.decode_rune_in_string(s[i:])
|
||||||
if r == utf8.RUNE_ERROR && w == 1 {
|
if r == utf8.RUNE_ERROR && w == 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -403,11 +413,19 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
|
|||||||
}
|
}
|
||||||
i += 6
|
i += 6
|
||||||
|
|
||||||
|
// If this is a surrogate pair, decode as such by taking the next rune too.
|
||||||
|
if r >= utf8.SURROGATE_MIN && r <= utf8.SURROGATE_HIGH_MAX && len(s) > i + 2 && s[i:i+2] == "\\u" {
|
||||||
|
r2 := get_u4_rune(s[i:])
|
||||||
|
if r2 >= utf8.SURROGATE_LOW_MIN && r2 <= utf8.SURROGATE_MAX {
|
||||||
|
i += 6
|
||||||
|
r = utf16.decode_surrogate_pair(r, r2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buf, buf_width := utf8.encode_rune(r)
|
buf, buf_width := utf8.encode_rune(r)
|
||||||
copy(b[w:], buf[:buf_width])
|
copy(b[w:], buf[:buf_width])
|
||||||
w += buf_width
|
w += buf_width
|
||||||
|
|
||||||
|
|
||||||
case '0':
|
case '0':
|
||||||
if spec != .JSON {
|
if spec != .JSON {
|
||||||
b[w] = '\x00'
|
b[w] = '\x00'
|
||||||
|
|||||||
@@ -163,8 +163,9 @@ get_token :: proc(t: ^Tokenizer) -> (token: Token, err: Error) {
|
|||||||
|
|
||||||
skip_alphanum :: proc(t: ^Tokenizer) {
|
skip_alphanum :: proc(t: ^Tokenizer) {
|
||||||
for t.offset < len(t.data) {
|
for t.offset < len(t.data) {
|
||||||
switch next_rune(t) {
|
switch t.r {
|
||||||
case 'A'..='Z', 'a'..='z', '0'..='9', '_':
|
case 'A'..='Z', 'a'..='z', '0'..='9', '_':
|
||||||
|
next_rune(t)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ Error :: enum {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
destroy_value :: proc(value: Value) {
|
destroy_value :: proc(value: Value, allocator := context.allocator) {
|
||||||
|
context.allocator = allocator
|
||||||
#partial switch v in value {
|
#partial switch v in value {
|
||||||
case Object:
|
case Object:
|
||||||
for key, elem in v {
|
for key, elem in v {
|
||||||
@@ -103,5 +104,4 @@ destroy_value :: proc(value: Value) {
|
|||||||
case String:
|
case String:
|
||||||
delete(v)
|
delete(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ unmarshal_string :: proc(data: string, ptr: ^$T, spec := DEFAULT_SPECIFICATION,
|
|||||||
@(private)
|
@(private)
|
||||||
assign_bool :: proc(val: any, b: bool) -> bool {
|
assign_bool :: proc(val: any, b: bool) -> bool {
|
||||||
v := reflect.any_core(val)
|
v := reflect.any_core(val)
|
||||||
switch dst in &v {
|
switch &dst in v {
|
||||||
case bool: dst = bool(b)
|
case bool: dst = bool(b)
|
||||||
case b8: dst = b8 (b)
|
case b8: dst = b8 (b)
|
||||||
case b16: dst = b16 (b)
|
case b16: dst = b16 (b)
|
||||||
@@ -85,7 +85,7 @@ assign_bool :: proc(val: any, b: bool) -> bool {
|
|||||||
@(private)
|
@(private)
|
||||||
assign_int :: proc(val: any, i: $T) -> bool {
|
assign_int :: proc(val: any, i: $T) -> bool {
|
||||||
v := reflect.any_core(val)
|
v := reflect.any_core(val)
|
||||||
switch dst in &v {
|
switch &dst in v {
|
||||||
case i8: dst = i8 (i)
|
case i8: dst = i8 (i)
|
||||||
case i16: dst = i16 (i)
|
case i16: dst = i16 (i)
|
||||||
case i16le: dst = i16le (i)
|
case i16le: dst = i16le (i)
|
||||||
@@ -122,7 +122,7 @@ assign_int :: proc(val: any, i: $T) -> bool {
|
|||||||
@(private)
|
@(private)
|
||||||
assign_float :: proc(val: any, f: $T) -> bool {
|
assign_float :: proc(val: any, f: $T) -> bool {
|
||||||
v := reflect.any_core(val)
|
v := reflect.any_core(val)
|
||||||
switch dst in &v {
|
switch &dst in v {
|
||||||
case f16: dst = f16 (f)
|
case f16: dst = f16 (f)
|
||||||
case f16le: dst = f16le(f)
|
case f16le: dst = f16le(f)
|
||||||
case f16be: dst = f16be(f)
|
case f16be: dst = f16be(f)
|
||||||
@@ -150,7 +150,7 @@ assign_float :: proc(val: any, f: $T) -> bool {
|
|||||||
@(private)
|
@(private)
|
||||||
unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool {
|
unmarshal_string_token :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool {
|
||||||
val := val
|
val := val
|
||||||
switch dst in &val {
|
switch &dst in val {
|
||||||
case string:
|
case string:
|
||||||
dst = str
|
dst = str
|
||||||
return true
|
return true
|
||||||
@@ -215,6 +215,12 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch &dst in v {
|
||||||
|
// Handle json.Value as an unknown type
|
||||||
|
case Value:
|
||||||
|
dst = parse_value(p) or_return
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
#partial switch token.kind {
|
#partial switch token.kind {
|
||||||
case .Null:
|
case .Null:
|
||||||
|
|||||||
@@ -19,43 +19,39 @@ import "core:fmt"
|
|||||||
*/
|
*/
|
||||||
print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error) {
|
print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error) {
|
||||||
if doc == nil { return }
|
if doc == nil { return }
|
||||||
using fmt
|
written += fmt.wprintf(writer, "[XML Prolog]\n")
|
||||||
|
|
||||||
written += wprintf(writer, "[XML Prolog]\n")
|
|
||||||
|
|
||||||
for attr in doc.prologue {
|
for attr in doc.prologue {
|
||||||
written += wprintf(writer, "\t%v: %v\n", attr.key, attr.val)
|
written += fmt.wprintf(writer, "\t%v: %v\n", attr.key, attr.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
written += wprintf(writer, "[Encoding] %v\n", doc.encoding)
|
written += fmt.wprintf(writer, "[Encoding] %v\n", doc.encoding)
|
||||||
|
|
||||||
if len(doc.doctype.ident) > 0 {
|
if len(doc.doctype.ident) > 0 {
|
||||||
written += wprintf(writer, "[DOCTYPE] %v\n", doc.doctype.ident)
|
written += fmt.wprintf(writer, "[DOCTYPE] %v\n", doc.doctype.ident)
|
||||||
|
|
||||||
if len(doc.doctype.rest) > 0 {
|
if len(doc.doctype.rest) > 0 {
|
||||||
wprintf(writer, "\t%v\n", doc.doctype.rest)
|
fmt.wprintf(writer, "\t%v\n", doc.doctype.rest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for comment in doc.comments {
|
for comment in doc.comments {
|
||||||
written += wprintf(writer, "[Pre-root comment] %v\n", comment)
|
written += fmt.wprintf(writer, "[Pre-root comment] %v\n", comment)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(doc.elements) > 0 {
|
if len(doc.elements) > 0 {
|
||||||
wprintln(writer, " --- ")
|
fmt.wprintln(writer, " --- ")
|
||||||
print_element(writer, doc, 0)
|
print_element(writer, doc, 0)
|
||||||
wprintln(writer, " --- ")
|
fmt.wprintln(writer, " --- ")
|
||||||
}
|
}
|
||||||
|
|
||||||
return written, .None
|
return written, .None
|
||||||
}
|
}
|
||||||
|
|
||||||
print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID, indent := 0) -> (written: int, err: io.Error) {
|
print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID, indent := 0) -> (written: int, err: io.Error) {
|
||||||
using fmt
|
|
||||||
|
|
||||||
tab :: proc(writer: io.Writer, indent: int) {
|
tab :: proc(writer: io.Writer, indent: int) {
|
||||||
for _ in 0..=indent {
|
for _ in 0..=indent {
|
||||||
wprintf(writer, "\t")
|
fmt.wprintf(writer, "\t")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,22 +60,24 @@ print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID,
|
|||||||
element := doc.elements[element_id]
|
element := doc.elements[element_id]
|
||||||
|
|
||||||
if element.kind == .Element {
|
if element.kind == .Element {
|
||||||
wprintf(writer, "<%v>\n", element.ident)
|
fmt.wprintf(writer, "<%v>\n", element.ident)
|
||||||
if len(element.value) > 0 {
|
|
||||||
tab(writer, indent + 1)
|
for value in element.value {
|
||||||
wprintf(writer, "[Value] %v\n", element.value)
|
switch v in value {
|
||||||
|
case string:
|
||||||
|
tab(writer, indent + 1)
|
||||||
|
fmt.wprintf(writer, "[Value] %v\n", v)
|
||||||
|
case Element_ID:
|
||||||
|
print_element(writer, doc, v, indent + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for attr in element.attribs {
|
for attr in element.attribs {
|
||||||
tab(writer, indent + 1)
|
tab(writer, indent + 1)
|
||||||
wprintf(writer, "[Attr] %v: %v\n", attr.key, attr.val)
|
fmt.wprintf(writer, "[Attr] %v: %v\n", attr.key, attr.val)
|
||||||
}
|
|
||||||
|
|
||||||
for child in element.children {
|
|
||||||
print_element(writer, doc, child, indent + 1)
|
|
||||||
}
|
}
|
||||||
} else if element.kind == .Comment {
|
} else if element.kind == .Comment {
|
||||||
wprintf(writer, "[COMMENT] %v\n", element.value)
|
fmt.wprintf(writer, "[COMMENT] %v\n", element.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
return written, .None
|
return written, .None
|
||||||
|
|||||||
@@ -72,10 +72,10 @@ example :: proc() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Found `<charlist>` with %v children, %v elements total\n", len(docs[0].elements[charlist].children), docs[0].element_count)
|
printf("Found `<charlist>` with %v children, %v elements total\n", len(docs[0].elements[charlist].value), docs[0].element_count)
|
||||||
|
|
||||||
crc32 := doc_hash(docs[0])
|
crc32 := doc_hash(docs[0], false)
|
||||||
printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0xcaa042b9 else "🤬", crc32)
|
printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0x420dbac5 else "🤬", crc32)
|
||||||
|
|
||||||
for round in 0..<N {
|
for round in 0..<N {
|
||||||
defer xml.destroy(docs[round])
|
defer xml.destroy(docs[round])
|
||||||
|
|||||||
@@ -13,20 +13,25 @@ find_child_by_ident :: proc(doc: ^Document, parent_id: Element_ID, ident: string
|
|||||||
tag := doc.elements[parent_id]
|
tag := doc.elements[parent_id]
|
||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
for child_id in tag.children {
|
for v in tag.value {
|
||||||
child := doc.elements[child_id]
|
switch child_id in v {
|
||||||
/*
|
case string: continue
|
||||||
Skip commments. They have no name.
|
case Element_ID:
|
||||||
*/
|
child := doc.elements[child_id]
|
||||||
if child.kind != .Element { continue }
|
/*
|
||||||
|
Skip commments. They have no name.
|
||||||
|
*/
|
||||||
|
if child.kind != .Element { continue }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If the ident matches and it's the nth such child, return it.
|
If the ident matches and it's the nth such child, return it.
|
||||||
*/
|
*/
|
||||||
if child.ident == ident {
|
if child.ident == ident {
|
||||||
if count == nth { return child_id, true }
|
if count == nth { return child_id, true }
|
||||||
count += 1
|
count += 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,38 +125,38 @@ error :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
advance_rune :: proc(using t: ^Tokenizer) {
|
advance_rune :: proc(t: ^Tokenizer) {
|
||||||
#no_bounds_check {
|
#no_bounds_check {
|
||||||
/*
|
/*
|
||||||
Already bounds-checked here.
|
Already bounds-checked here.
|
||||||
*/
|
*/
|
||||||
if read_offset < len(src) {
|
if t.read_offset < len(t.src) {
|
||||||
offset = read_offset
|
t.offset = t.read_offset
|
||||||
if ch == '\n' {
|
if t.ch == '\n' {
|
||||||
line_offset = offset
|
t.line_offset = t.offset
|
||||||
line_count += 1
|
t.line_count += 1
|
||||||
}
|
}
|
||||||
r, w := rune(src[read_offset]), 1
|
r, w := rune(t.src[t.read_offset]), 1
|
||||||
switch {
|
switch {
|
||||||
case r == 0:
|
case r == 0:
|
||||||
error(t, t.offset, "illegal character NUL")
|
error(t, t.offset, "illegal character NUL")
|
||||||
case r >= utf8.RUNE_SELF:
|
case r >= utf8.RUNE_SELF:
|
||||||
r, w = #force_inline utf8.decode_rune_in_string(src[read_offset:])
|
r, w = #force_inline utf8.decode_rune_in_string(t.src[t.read_offset:])
|
||||||
if r == utf8.RUNE_ERROR && w == 1 {
|
if r == utf8.RUNE_ERROR && w == 1 {
|
||||||
error(t, t.offset, "illegal UTF-8 encoding")
|
error(t, t.offset, "illegal UTF-8 encoding")
|
||||||
} else if r == utf8.RUNE_BOM && offset > 0 {
|
} else if r == utf8.RUNE_BOM && t.offset > 0 {
|
||||||
error(t, t.offset, "illegal byte order mark")
|
error(t, t.offset, "illegal byte order mark")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
read_offset += w
|
t.read_offset += w
|
||||||
ch = r
|
t.ch = r
|
||||||
} else {
|
} else {
|
||||||
offset = len(src)
|
t.offset = len(t.src)
|
||||||
if ch == '\n' {
|
if t.ch == '\n' {
|
||||||
line_offset = offset
|
t.line_offset = t.offset
|
||||||
line_count += 1
|
t.line_count += 1
|
||||||
}
|
}
|
||||||
ch = -1
|
t.ch = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,16 +125,19 @@ Document :: struct {
|
|||||||
|
|
||||||
Element :: struct {
|
Element :: struct {
|
||||||
ident: string,
|
ident: string,
|
||||||
value: string,
|
value: [dynamic]Value,
|
||||||
attribs: Attributes,
|
attribs: Attributes,
|
||||||
|
|
||||||
kind: enum {
|
kind: enum {
|
||||||
Element = 0,
|
Element = 0,
|
||||||
Comment,
|
Comment,
|
||||||
},
|
},
|
||||||
|
|
||||||
parent: Element_ID,
|
parent: Element_ID,
|
||||||
children: [dynamic]Element_ID,
|
}
|
||||||
|
|
||||||
|
Value :: union {
|
||||||
|
string,
|
||||||
|
Element_ID,
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute :: struct {
|
Attribute :: struct {
|
||||||
@@ -247,9 +250,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
|
|
||||||
err = .Unexpected_Token
|
err = .Unexpected_Token
|
||||||
element, parent: Element_ID
|
element, parent: Element_ID
|
||||||
|
|
||||||
tag_is_open := false
|
|
||||||
first_element := true
|
|
||||||
open: Token
|
open: Token
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -275,16 +275,10 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
e.g. <odin - Start of new element.
|
e.g. <odin - Start of new element.
|
||||||
*/
|
*/
|
||||||
element = new_element(doc)
|
element = new_element(doc)
|
||||||
tag_is_open = true
|
if element == 0 { // First Element
|
||||||
|
parent = element
|
||||||
if first_element {
|
|
||||||
/*
|
|
||||||
First element.
|
|
||||||
*/
|
|
||||||
parent = element
|
|
||||||
first_element = false
|
|
||||||
} else {
|
} else {
|
||||||
append(&doc.elements[parent].children, element)
|
append(&doc.elements[parent].value, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.elements[element].parent = parent
|
doc.elements[element].parent = parent
|
||||||
@@ -324,7 +318,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
expect(t, .Gt) or_return
|
expect(t, .Gt) or_return
|
||||||
parent = doc.elements[element].parent
|
parent = doc.elements[element].parent
|
||||||
element = parent
|
element = parent
|
||||||
tag_is_open = false
|
|
||||||
|
|
||||||
case:
|
case:
|
||||||
error(t, t.offset, "Expected close tag, got: %#v\n", end_token)
|
error(t, t.offset, "Expected close tag, got: %#v\n", end_token)
|
||||||
@@ -344,7 +337,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
}
|
}
|
||||||
parent = doc.elements[element].parent
|
parent = doc.elements[element].parent
|
||||||
element = parent
|
element = parent
|
||||||
tag_is_open = false
|
|
||||||
|
|
||||||
} else if open.kind == .Exclaim {
|
} else if open.kind == .Exclaim {
|
||||||
/*
|
/*
|
||||||
@@ -392,8 +384,8 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
el := new_element(doc)
|
el := new_element(doc)
|
||||||
doc.elements[el].parent = element
|
doc.elements[el].parent = element
|
||||||
doc.elements[el].kind = .Comment
|
doc.elements[el].kind = .Comment
|
||||||
doc.elements[el].value = comment
|
append(&doc.elements[el].value, comment)
|
||||||
append(&doc.elements[element].children, el)
|
append(&doc.elements[element].value, el)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,9 +428,6 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
/*
|
/*
|
||||||
End of file.
|
End of file.
|
||||||
*/
|
*/
|
||||||
if tag_is_open {
|
|
||||||
return doc, .Premature_EOF
|
|
||||||
}
|
|
||||||
break loop
|
break loop
|
||||||
|
|
||||||
case:
|
case:
|
||||||
@@ -450,7 +439,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
needs_processing |= .Decode_SGML_Entities in opts.flags
|
needs_processing |= .Decode_SGML_Entities in opts.flags
|
||||||
|
|
||||||
if !needs_processing {
|
if !needs_processing {
|
||||||
doc.elements[element].value = body_text
|
append(&doc.elements[element].value, body_text)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,10 +461,10 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
|
|||||||
|
|
||||||
decoded, decode_err := entity.decode_xml(body_text, decode_opts)
|
decoded, decode_err := entity.decode_xml(body_text, decode_opts)
|
||||||
if decode_err == .None {
|
if decode_err == .None {
|
||||||
doc.elements[element].value = decoded
|
append(&doc.elements[element].value, decoded)
|
||||||
append(&doc.strings_to_free, decoded)
|
append(&doc.strings_to_free, decoded)
|
||||||
} else {
|
} else {
|
||||||
doc.elements[element].value = body_text
|
append(&doc.elements[element].value, body_text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,7 +507,7 @@ destroy :: proc(doc: ^Document) {
|
|||||||
|
|
||||||
for el in doc.elements {
|
for el in doc.elements {
|
||||||
delete(el.attribs)
|
delete(el.attribs)
|
||||||
delete(el.children)
|
delete(el.value)
|
||||||
}
|
}
|
||||||
delete(doc.elements)
|
delete(doc.elements)
|
||||||
|
|
||||||
@@ -710,6 +699,5 @@ new_element :: proc(doc: ^Document) -> (id: Element_ID) {
|
|||||||
|
|
||||||
cur := doc.element_count
|
cur := doc.element_count
|
||||||
doc.element_count += 1
|
doc.element_count += 1
|
||||||
|
|
||||||
return cur
|
return cur
|
||||||
}
|
}
|
||||||
+4
-1
@@ -35,6 +35,8 @@ Floating-point, complex numbers, and quaternions:
|
|||||||
%F synonym for %f
|
%F synonym for %f
|
||||||
%h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd)
|
%h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd)
|
||||||
%H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD)
|
%H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD)
|
||||||
|
%m number of bytes in the best unit of measurement, e.g. 123.45mib
|
||||||
|
%M number of bytes in the best unit of measurement, e.g. 123.45MiB
|
||||||
String and slice of bytes
|
String and slice of bytes
|
||||||
%s the uninterpreted bytes of the string or slice
|
%s the uninterpreted bytes of the string or slice
|
||||||
%q a double-quoted string safely escaped with Odin syntax
|
%q a double-quoted string safely escaped with Odin syntax
|
||||||
@@ -68,7 +70,7 @@ A period with no following number specifies a precision of 0.
|
|||||||
Examples:
|
Examples:
|
||||||
%f default width, default precision
|
%f default width, default precision
|
||||||
%8f width 8, default precision
|
%8f width 8, default precision
|
||||||
%.3f default width, precision 2
|
%.2f default width, precision 2
|
||||||
%8.3f width 8, precision 3
|
%8.3f width 8, precision 3
|
||||||
%8.f width 8, precision 0
|
%8.f width 8, precision 0
|
||||||
|
|
||||||
@@ -85,6 +87,7 @@ Other flags:
|
|||||||
add leading 0z for dozenal (%#z)
|
add leading 0z for dozenal (%#z)
|
||||||
add leading 0x or 0X for hexadecimal (%#x or %#X)
|
add leading 0x or 0X for hexadecimal (%#x or %#X)
|
||||||
remove leading 0x for %p (%#p)
|
remove leading 0x for %p (%#p)
|
||||||
|
add a space between bytes and the unit of measurement (%#m or %#M)
|
||||||
' ' (space) leave a space for elided sign in numbers (% d)
|
' ' (space) leave a space for elided sign in numbers (% d)
|
||||||
0 pad with leading zeros rather than spaces
|
0 pad with leading zeros rather than spaces
|
||||||
|
|
||||||
|
|||||||
+697
-181
File diff suppressed because it is too large
Load Diff
+17
-20
@@ -7,43 +7,40 @@ foreign import "odin_env"
|
|||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
foreign odin_env {
|
foreign odin_env {
|
||||||
write :: proc "c" (fd: u32, p: []byte) ---
|
write :: proc "contextless" (fd: u32, p: []byte) ---
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
write_vtable := io.Stream_VTable{
|
write_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||||
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
|
if mode == .Write {
|
||||||
fd := u32(uintptr(s.stream_data))
|
fd := u32(uintptr(stream_data))
|
||||||
write(fd, p)
|
write(fd, p)
|
||||||
return len(p), nil
|
return i64(len(p)), nil
|
||||||
},
|
}
|
||||||
|
return 0, .Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
stdout := io.Writer{
|
stdout := io.Writer{
|
||||||
stream = {
|
procedure = write_stream_proc,
|
||||||
stream_vtable = &write_vtable,
|
data = rawptr(uintptr(1)),
|
||||||
stream_data = rawptr(uintptr(1)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
@(private="file")
|
@(private="file")
|
||||||
stderr := io.Writer{
|
stderr := io.Writer{
|
||||||
stream = {
|
procedure = write_stream_proc,
|
||||||
stream_vtable = &write_vtable,
|
data = rawptr(uintptr(2)),
|
||||||
stream_data = rawptr(uintptr(2)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print formats using the default print settings and writes to stdout
|
// print formats using the default print settings and writes to stdout
|
||||||
print :: proc(args: ..any, sep := " ") -> int { return wprint(w=stdout, args=args, sep=sep) }
|
print :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stdout, args=args, sep=sep, flush=flush) }
|
||||||
// println formats using the default print settings and writes to stdout
|
// println formats using the default print settings and writes to stdout
|
||||||
println :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stdout, args=args, sep=sep) }
|
println :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stdout, args=args, sep=sep, flush=flush) }
|
||||||
// printf formats according to the specififed format string and writes to stdout
|
// printf formats according to the specififed format string and writes to stdout
|
||||||
printf :: proc(fmt: string, args: ..any) -> int { return wprintf(stdout, fmt, ..args) }
|
printf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stdout, fmt, ..args, flush=flush) }
|
||||||
|
|
||||||
// eprint formats using the default print settings and writes to stderr
|
// eprint formats using the default print settings and writes to stderr
|
||||||
eprint :: proc(args: ..any, sep := " ") -> int { return wprint(w=stderr, args=args, sep=sep) }
|
eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return wprint(w=stderr, args=args, sep=sep, flush=flush) }
|
||||||
// eprintln formats using the default print settings and writes to stderr
|
// eprintln formats using the default print settings and writes to stderr
|
||||||
eprintln :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stderr, args=args, sep=sep) }
|
eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return wprintln(w=stderr, args=args, sep=sep, flush=flush) }
|
||||||
// eprintf formats according to the specififed format string and writes to stderr
|
// eprintf formats according to the specififed format string and writes to stderr
|
||||||
eprintf :: proc(fmt: string, args: ..any) -> int { return wprintf(stderr, fmt, ..args) }
|
eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return wprintf(stderr, fmt, ..args, flush=flush) }
|
||||||
|
|||||||
+51
-21
@@ -4,42 +4,72 @@ package fmt
|
|||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
import "core:bufio"
|
||||||
|
|
||||||
// fprint formats using the default print settings and writes to fd
|
// fprint formats using the default print settings and writes to fd
|
||||||
fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
fprint :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
buf: [1024]byte
|
||||||
return wprint(w=w, args=args, sep=sep)
|
b: bufio.Writer
|
||||||
|
defer bufio.writer_flush(&b)
|
||||||
|
|
||||||
|
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
|
||||||
|
w := bufio.writer_to_writer(&b)
|
||||||
|
return wprint(w, ..args, sep=sep, flush=flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fprintln formats using the default print settings and writes to fd
|
// fprintln formats using the default print settings and writes to fd
|
||||||
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ", flush := true) -> int {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
buf: [1024]byte
|
||||||
return wprintln(w=w, args=args, sep=sep)
|
b: bufio.Writer
|
||||||
|
defer bufio.writer_flush(&b)
|
||||||
|
|
||||||
|
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
|
||||||
|
|
||||||
|
w := bufio.writer_to_writer(&b)
|
||||||
|
return wprintln(w, ..args, sep=sep, flush=flush)
|
||||||
}
|
}
|
||||||
// fprintf formats according to the specified format string and writes to fd
|
// fprintf formats according to the specified format string and writes to fd
|
||||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any, flush := true) -> int {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
buf: [1024]byte
|
||||||
return wprintf(w, fmt, ..args)
|
b: bufio.Writer
|
||||||
|
defer bufio.writer_flush(&b)
|
||||||
|
|
||||||
|
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
|
||||||
|
|
||||||
|
w := bufio.writer_to_writer(&b)
|
||||||
|
return wprintf(w, fmt, ..args, flush=flush)
|
||||||
}
|
}
|
||||||
fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info) -> (n: int, err: io.Error) {
|
fprint_type :: proc(fd: os.Handle, info: ^runtime.Type_Info, flush := true) -> (n: int, err: io.Error) {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
buf: [1024]byte
|
||||||
return wprint_type(w, info)
|
b: bufio.Writer
|
||||||
|
defer bufio.writer_flush(&b)
|
||||||
|
|
||||||
|
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
|
||||||
|
|
||||||
|
w := bufio.writer_to_writer(&b)
|
||||||
|
return wprint_type(w, info, flush=flush)
|
||||||
}
|
}
|
||||||
fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
|
fprint_typeid :: proc(fd: os.Handle, id: typeid, flush := true) -> (n: int, err: io.Error) {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
buf: [1024]byte
|
||||||
return wprint_typeid(w, id)
|
b: bufio.Writer
|
||||||
|
defer bufio.writer_flush(&b)
|
||||||
|
|
||||||
|
bufio.writer_init_with_buf(&b, os.stream_from_handle(fd), buf[:])
|
||||||
|
|
||||||
|
w := bufio.writer_to_writer(&b)
|
||||||
|
return wprint_typeid(w, id, flush=flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
// print formats using the default print settings and writes to os.stdout
|
// print formats using the default print settings and writes to os.stdout
|
||||||
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
|
print :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stdout, ..args, sep=sep, flush=flush) }
|
||||||
// println formats using the default print settings and writes to os.stdout
|
// println formats using the default print settings and writes to os.stdout
|
||||||
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
|
println :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stdout, ..args, sep=sep, flush=flush) }
|
||||||
// printf formats according to the specified format string and writes to os.stdout
|
// printf formats according to the specified format string and writes to os.stdout
|
||||||
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
|
printf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stdout, fmt, ..args, flush=flush) }
|
||||||
|
|
||||||
// eprint formats using the default print settings and writes to os.stderr
|
// eprint formats using the default print settings and writes to os.stderr
|
||||||
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
|
eprint :: proc(args: ..any, sep := " ", flush := true) -> int { return fprint(os.stderr, ..args, sep=sep, flush=flush) }
|
||||||
// eprintln formats using the default print settings and writes to os.stderr
|
// eprintln formats using the default print settings and writes to os.stderr
|
||||||
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
|
eprintln :: proc(args: ..any, sep := " ", flush := true) -> int { return fprintln(os.stderr, ..args, sep=sep, flush=flush) }
|
||||||
// eprintf formats according to the specified format string and writes to os.stderr
|
// eprintf formats according to the specified format string and writes to os.stderr
|
||||||
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
|
eprintf :: proc(fmt: string, args: ..any, flush := true) -> int { return fprintf(os.stderr, fmt, ..args, flush=flush) }
|
||||||
|
|||||||
@@ -634,7 +634,7 @@ alpha_add_if_missing :: proc(img: ^Image, alpha_key := Alpha_Key{}, allocator :=
|
|||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
// Can we allocate the return buffer?
|
// Can we allocate the return buffer?
|
||||||
if !resize(&buf.buf, bytes_wanted) {
|
if resize(&buf.buf, bytes_wanted) != nil {
|
||||||
delete(buf.buf)
|
delete(buf.buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -826,7 +826,7 @@ alpha_drop_if_present :: proc(img: ^Image, options := Options{}, alpha_key := Al
|
|||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
|
|
||||||
// Can we allocate the return buffer?
|
// Can we allocate the return buffer?
|
||||||
if !resize(&buf.buf, bytes_wanted) {
|
if resize(&buf.buf, bytes_wanted) != nil {
|
||||||
delete(buf.buf)
|
delete(buf.buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1075,7 @@ apply_palette_rgb :: proc(img: ^Image, palette: [256]RGB_Pixel, allocator := con
|
|||||||
// Can we allocate the return buffer?
|
// Can we allocate the return buffer?
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
bytes_wanted := compute_buffer_size(img.width, img.height, 3, 8)
|
bytes_wanted := compute_buffer_size(img.width, img.height, 3, 8)
|
||||||
if !resize(&buf.buf, bytes_wanted) {
|
if resize(&buf.buf, bytes_wanted) != nil {
|
||||||
delete(buf.buf)
|
delete(buf.buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -1112,7 +1112,7 @@ apply_palette_rgba :: proc(img: ^Image, palette: [256]RGBA_Pixel, allocator := c
|
|||||||
// Can we allocate the return buffer?
|
// Can we allocate the return buffer?
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
bytes_wanted := compute_buffer_size(img.width, img.height, 4, 8)
|
bytes_wanted := compute_buffer_size(img.width, img.height, 4, 8)
|
||||||
if !resize(&buf.buf, bytes_wanted) {
|
if resize(&buf.buf, bytes_wanted) != nil {
|
||||||
delete(buf.buf)
|
delete(buf.buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -1147,7 +1147,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
|
|||||||
// Can we allocate the return buffer?
|
// Can we allocate the return buffer?
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
bytes_wanted := compute_buffer_size(img.width, img.height, img.channels + 2, img.depth)
|
bytes_wanted := compute_buffer_size(img.width, img.height, img.channels + 2, img.depth)
|
||||||
if !resize(&buf.buf, bytes_wanted) {
|
if resize(&buf.buf, bytes_wanted) != nil {
|
||||||
delete(buf.buf)
|
delete(buf.buf)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,48 @@
|
|||||||
package image
|
package image
|
||||||
|
|
||||||
import "core:os"
|
import "core:mem"
|
||||||
|
import "core:bytes"
|
||||||
|
|
||||||
|
Loader_Proc :: #type proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error)
|
||||||
|
Destroy_Proc :: #type proc(img: ^Image)
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_internal_loaders: [Which_File_Type]Loader_Proc
|
||||||
|
_internal_destroyers: [Which_File_Type]Destroy_Proc
|
||||||
|
|
||||||
|
register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) {
|
||||||
|
assert(loader != nil)
|
||||||
|
assert(destroyer != nil)
|
||||||
|
assert(_internal_loaders[kind] == nil)
|
||||||
|
_internal_loaders[kind] = loader
|
||||||
|
|
||||||
|
assert(_internal_destroyers[kind] == nil)
|
||||||
|
_internal_destroyers[kind] = destroyer
|
||||||
|
}
|
||||||
|
|
||||||
|
load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
||||||
|
loader := _internal_loaders[which(data)]
|
||||||
|
if loader == nil {
|
||||||
|
return nil, .Unsupported_Format
|
||||||
|
}
|
||||||
|
return loader(data, options, allocator)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
destroy :: proc(img: ^Image, allocator := context.allocator) {
|
||||||
|
if img == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
context.allocator = allocator
|
||||||
|
destroyer := _internal_destroyers[img.which]
|
||||||
|
if destroyer != nil {
|
||||||
|
destroyer(img)
|
||||||
|
} else {
|
||||||
|
assert(img.metadata == nil)
|
||||||
|
bytes.buffer_destroy(&img.pixels)
|
||||||
|
free(img)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Which_File_Type :: enum {
|
Which_File_Type :: enum {
|
||||||
Unknown,
|
Unknown,
|
||||||
@@ -28,11 +70,6 @@ Which_File_Type :: enum {
|
|||||||
XBM, // X BitMap
|
XBM, // X BitMap
|
||||||
}
|
}
|
||||||
|
|
||||||
which :: proc{
|
|
||||||
which_bytes,
|
|
||||||
which_file,
|
|
||||||
}
|
|
||||||
|
|
||||||
which_bytes :: proc(data: []byte) -> Which_File_Type {
|
which_bytes :: proc(data: []byte) -> Which_File_Type {
|
||||||
test_tga :: proc(s: string) -> bool {
|
test_tga :: proc(s: string) -> bool {
|
||||||
get8 :: #force_inline proc(s: ^string) -> u8 {
|
get8 :: #force_inline proc(s: ^string) -> u8 {
|
||||||
@@ -164,16 +201,3 @@ which_bytes :: proc(data: []byte) -> Which_File_Type {
|
|||||||
}
|
}
|
||||||
return .Unknown
|
return .Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
which_file :: proc(path: string) -> Which_File_Type {
|
|
||||||
f, err := os.open(path)
|
|
||||||
if err != 0 {
|
|
||||||
return .Unknown
|
|
||||||
}
|
|
||||||
header: [128]byte
|
|
||||||
os.read(f, header[:])
|
|
||||||
file_type := which_bytes(header[:])
|
|
||||||
os.close(f)
|
|
||||||
return file_type
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
//+build js
|
||||||
|
package image
|
||||||
|
|
||||||
|
load :: proc{
|
||||||
|
load_from_bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
which :: proc{
|
||||||
|
which_bytes,
|
||||||
|
}
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package image
|
|
||||||
|
|
||||||
import "core:mem"
|
|
||||||
import "core:os"
|
|
||||||
import "core:bytes"
|
|
||||||
|
|
||||||
Loader_Proc :: #type proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error)
|
|
||||||
Destroy_Proc :: #type proc(img: ^Image)
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_internal_loaders: [Which_File_Type]Loader_Proc
|
|
||||||
_internal_destroyers: [Which_File_Type]Destroy_Proc
|
|
||||||
|
|
||||||
register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) {
|
|
||||||
assert(loader != nil)
|
|
||||||
assert(destroyer != nil)
|
|
||||||
assert(_internal_loaders[kind] == nil)
|
|
||||||
_internal_loaders[kind] = loader
|
|
||||||
|
|
||||||
assert(_internal_destroyers[kind] == nil)
|
|
||||||
_internal_destroyers[kind] = destroyer
|
|
||||||
}
|
|
||||||
|
|
||||||
load :: proc{
|
|
||||||
load_from_bytes,
|
|
||||||
load_from_file,
|
|
||||||
}
|
|
||||||
|
|
||||||
load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
|
||||||
loader := _internal_loaders[which(data)]
|
|
||||||
if loader == nil {
|
|
||||||
return nil, .Unsupported_Format
|
|
||||||
}
|
|
||||||
return loader(data, options, allocator)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
|
||||||
data, ok := os.read_entire_file(filename, allocator)
|
|
||||||
defer delete(data, allocator)
|
|
||||||
if ok {
|
|
||||||
return load_from_bytes(data, options, allocator)
|
|
||||||
} else {
|
|
||||||
return nil, .Unable_To_Read_File
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy :: proc(img: ^Image, allocator := context.allocator) {
|
|
||||||
if img == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
context.allocator = allocator
|
|
||||||
destroyer := _internal_destroyers[img.which]
|
|
||||||
if destroyer != nil {
|
|
||||||
destroyer(img)
|
|
||||||
} else {
|
|
||||||
assert(img.metadata == nil)
|
|
||||||
bytes.buffer_destroy(&img.pixels)
|
|
||||||
free(img)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
//+build !js
|
||||||
|
package image
|
||||||
|
|
||||||
|
import "core:os"
|
||||||
|
|
||||||
|
load :: proc{
|
||||||
|
load_from_bytes,
|
||||||
|
load_from_file,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
||||||
|
data, ok := os.read_entire_file(filename, allocator)
|
||||||
|
defer delete(data, allocator)
|
||||||
|
if ok {
|
||||||
|
return load_from_bytes(data, options, allocator)
|
||||||
|
} else {
|
||||||
|
return nil, .Unable_To_Read_File
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
which :: proc{
|
||||||
|
which_bytes,
|
||||||
|
which_file,
|
||||||
|
}
|
||||||
|
|
||||||
|
which_file :: proc(path: string) -> Which_File_Type {
|
||||||
|
f, err := os.open(path)
|
||||||
|
if err != 0 {
|
||||||
|
return .Unknown
|
||||||
|
}
|
||||||
|
header: [128]byte
|
||||||
|
os.read(f, header[:])
|
||||||
|
file_type := which_bytes(header[:])
|
||||||
|
os.close(f)
|
||||||
|
return file_type
|
||||||
|
}
|
||||||
@@ -4,13 +4,14 @@ import "core:bytes"
|
|||||||
import "core:image"
|
import "core:image"
|
||||||
|
|
||||||
destroy :: proc(img: ^image.Image) -> bool {
|
destroy :: proc(img: ^image.Image) -> bool {
|
||||||
if img == nil do return false
|
if img == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
defer free(img)
|
defer free(img)
|
||||||
bytes.buffer_destroy(&img.pixels)
|
bytes.buffer_destroy(&img.pixels)
|
||||||
|
|
||||||
info, ok := img.metadata.(^image.Netpbm_Info)
|
info := img.metadata.(^image.Netpbm_Info) or_return
|
||||||
if !ok do return false
|
|
||||||
|
|
||||||
header_destroy(&info.header)
|
header_destroy(&info.header)
|
||||||
free(info)
|
free(info)
|
||||||
@@ -19,9 +20,9 @@ destroy :: proc(img: ^image.Image) -> bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
header_destroy :: proc(using header: ^Header) {
|
header_destroy :: proc(header: ^Header) {
|
||||||
if format == .P7 && tupltype != "" {
|
if header.format == .P7 && header.tupltype != "" {
|
||||||
delete(tupltype)
|
delete(header.tupltype)
|
||||||
tupltype = ""
|
header.tupltype = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
//+vet !using-stmt
|
||||||
package netpbm
|
package netpbm
|
||||||
|
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:image"
|
import "core:image"
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:os"
|
|
||||||
import "core:strconv"
|
import "core:strconv"
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:unicode"
|
import "core:unicode"
|
||||||
@@ -27,23 +27,6 @@ PFM :: Formats{.Pf, .PF}
|
|||||||
ASCII :: Formats{.P1, .P2, .P3}
|
ASCII :: Formats{.P1, .P2, .P3}
|
||||||
BINARY :: Formats{.P4, .P5, .P6} + PAM + PFM
|
BINARY :: Formats{.P4, .P5, .P6} + PAM + PFM
|
||||||
|
|
||||||
load :: proc {
|
|
||||||
load_from_file,
|
|
||||||
load_from_bytes,
|
|
||||||
}
|
|
||||||
|
|
||||||
load_from_file :: proc(filename: string, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
|
||||||
context.allocator = allocator
|
|
||||||
|
|
||||||
data, ok := os.read_entire_file(filename); defer delete(data)
|
|
||||||
if !ok {
|
|
||||||
err = .Unable_To_Read_File
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return load_from_bytes(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
load_from_bytes :: proc(data: []byte, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
load_from_bytes :: proc(data: []byte, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
@@ -67,24 +50,6 @@ load_from_bytes :: proc(data: []byte, allocator := context.allocator) -> (img: ^
|
|||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
save :: proc {
|
|
||||||
save_to_file,
|
|
||||||
save_to_buffer,
|
|
||||||
}
|
|
||||||
|
|
||||||
save_to_file :: proc(filename: string, img: ^Image, custom_info: Info = {}, allocator := context.allocator) -> (err: Error) {
|
|
||||||
context.allocator = allocator
|
|
||||||
|
|
||||||
data: []byte; defer delete(data)
|
|
||||||
data = save_to_buffer(img, custom_info) or_return
|
|
||||||
|
|
||||||
if ok := os.write_entire_file(filename, data); !ok {
|
|
||||||
return .Unable_To_Write_File
|
|
||||||
}
|
|
||||||
|
|
||||||
return Format_Error.None
|
|
||||||
}
|
|
||||||
|
|
||||||
save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context.allocator) -> (buffer: []byte, err: Error) {
|
save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context.allocator) -> (buffer: []byte, err: Error) {
|
||||||
context.allocator = allocator
|
context.allocator = allocator
|
||||||
|
|
||||||
@@ -197,18 +162,18 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context
|
|||||||
// convert from native endianness
|
// convert from native endianness
|
||||||
if img.depth == 16 {
|
if img.depth == 16 {
|
||||||
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
|
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
|
||||||
for p in &pixels {
|
for &p in pixels {
|
||||||
p = u16be(transmute(u16) p)
|
p = u16be(transmute(u16) p)
|
||||||
}
|
}
|
||||||
} else if header.format in PFM {
|
} else if header.format in PFM {
|
||||||
if header.little_endian {
|
if header.little_endian {
|
||||||
pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):])
|
pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):])
|
||||||
for p in &pixels {
|
for &p in pixels {
|
||||||
p = f32le(transmute(f32) p)
|
p = f32le(transmute(f32) p)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):])
|
pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):])
|
||||||
for p in &pixels {
|
for &p in pixels {
|
||||||
p = f32be(transmute(f32) p)
|
p = f32be(transmute(f32) p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -614,18 +579,18 @@ decode_image :: proc(img: ^Image, header: Header, data: []byte, allocator := con
|
|||||||
if header.format in PFM {
|
if header.format in PFM {
|
||||||
pixels := mem.slice_data_cast([]f32, img.pixels.buf[:])
|
pixels := mem.slice_data_cast([]f32, img.pixels.buf[:])
|
||||||
if header.little_endian {
|
if header.little_endian {
|
||||||
for p in &pixels {
|
for &p in pixels {
|
||||||
p = f32(transmute(f32le) p)
|
p = f32(transmute(f32le) p)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for p in &pixels {
|
for &p in pixels {
|
||||||
p = f32(transmute(f32be) p)
|
p = f32(transmute(f32be) p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if img.depth == 16 {
|
if img.depth == 16 {
|
||||||
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
||||||
for p in &pixels {
|
for &p in pixels {
|
||||||
p = u16(transmute(u16be) p)
|
p = u16(transmute(u16be) p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
//+build js
|
||||||
|
package netpbm
|
||||||
|
|
||||||
|
load :: proc {
|
||||||
|
load_from_bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
save :: proc {
|
||||||
|
save_to_buffer,
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//+build !js
|
||||||
|
package netpbm
|
||||||
|
|
||||||
|
import "core:os"
|
||||||
|
|
||||||
|
load :: proc {
|
||||||
|
load_from_file,
|
||||||
|
load_from_bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
load_from_file :: proc(filename: string, allocator := context.allocator) -> (img: ^Image, err: Error) {
|
||||||
|
context.allocator = allocator
|
||||||
|
|
||||||
|
data, ok := os.read_entire_file(filename); defer delete(data)
|
||||||
|
if !ok {
|
||||||
|
err = .Unable_To_Read_File
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return load_from_bytes(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
save :: proc {
|
||||||
|
save_to_file,
|
||||||
|
save_to_buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
save_to_file :: proc(filename: string, img: ^Image, custom_info: Info = {}, allocator := context.allocator) -> (err: Error) {
|
||||||
|
context.allocator = allocator
|
||||||
|
|
||||||
|
data: []byte; defer delete(data)
|
||||||
|
data = save_to_buffer(img, custom_info) or_return
|
||||||
|
|
||||||
|
if ok := os.write_entire_file(filename, data); !ok {
|
||||||
|
return .Unable_To_Write_File
|
||||||
|
}
|
||||||
|
|
||||||
|
return Format_Error.None
|
||||||
|
}
|
||||||
@@ -36,7 +36,7 @@ destroy :: proc(img: ^Image) {
|
|||||||
bytes.buffer_destroy(&img.pixels)
|
bytes.buffer_destroy(&img.pixels)
|
||||||
|
|
||||||
if v, ok := img.metadata.(^image.PNG_Info); ok {
|
if v, ok := img.metadata.(^image.PNG_Info); ok {
|
||||||
for chunk in &v.chunks {
|
for chunk in v.chunks {
|
||||||
delete(chunk.data)
|
delete(chunk.data)
|
||||||
}
|
}
|
||||||
delete(v.chunks)
|
delete(v.chunks)
|
||||||
@@ -80,11 +80,10 @@ time :: proc(c: image.PNG_Chunk) -> (res: tIME, ok: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
core_time :: proc(c: image.PNG_Chunk) -> (t: coretime.Time, ok: bool) {
|
core_time :: proc(c: image.PNG_Chunk) -> (t: coretime.Time, ok: bool) {
|
||||||
if png_time, png_ok := time(c); png_ok {
|
if t, png_ok := time(c); png_ok {
|
||||||
using png_time
|
|
||||||
return coretime.datetime_to_time(
|
return coretime.datetime_to_time(
|
||||||
int(year), int(month), int(day),
|
int(t.year), int(t.month), int(t.day),
|
||||||
int(hour), int(minute), int(second),
|
int(t.hour), int(t.minute), int(t.second),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return {}, false
|
return {}, false
|
||||||
@@ -99,7 +98,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
|
|||||||
case .tEXt:
|
case .tEXt:
|
||||||
ok = true
|
ok = true
|
||||||
|
|
||||||
fields := bytes.split(s=c.data, sep=[]u8{0}, allocator=context.temp_allocator)
|
fields := bytes.split(c.data, sep=[]u8{0}, allocator=context.temp_allocator)
|
||||||
if len(fields) == 2 {
|
if len(fields) == 2 {
|
||||||
res.keyword = strings.clone(string(fields[0]))
|
res.keyword = strings.clone(string(fields[0]))
|
||||||
res.text = strings.clone(string(fields[1]))
|
res.text = strings.clone(string(fields[1]))
|
||||||
@@ -110,7 +109,7 @@ text :: proc(c: image.PNG_Chunk) -> (res: Text, ok: bool) {
|
|||||||
case .zTXt:
|
case .zTXt:
|
||||||
ok = true
|
ok = true
|
||||||
|
|
||||||
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
||||||
if len(fields) != 3 || len(fields[1]) != 0 {
|
if len(fields) != 3 || len(fields[1]) != 0 {
|
||||||
// Compression method must be 0=Deflate, which thanks to the split above turns
|
// Compression method must be 0=Deflate, which thanks to the split above turns
|
||||||
// into an empty slice
|
// into an empty slice
|
||||||
@@ -199,7 +198,7 @@ text_destroy :: proc(text: Text) {
|
|||||||
iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
|
iccp :: proc(c: image.PNG_Chunk) -> (res: iCCP, ok: bool) {
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
||||||
|
|
||||||
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
fields := bytes.split_n(c.data, sep=[]u8{0}, n=3, allocator=context.temp_allocator)
|
||||||
|
|
||||||
if len(fields[0]) < 1 || len(fields[0]) > 79 {
|
if len(fields[0]) < 1 || len(fields[0]) > 79 {
|
||||||
// Invalid profile name
|
// Invalid profile name
|
||||||
@@ -263,7 +262,7 @@ splt :: proc(c: image.PNG_Chunk) -> (res: sPLT, ok: bool) {
|
|||||||
}
|
}
|
||||||
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator)
|
||||||
|
|
||||||
fields := bytes.split_n(s=c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
|
fields := bytes.split_n(c.data, sep=[]u8{0}, n=2, allocator=context.temp_allocator)
|
||||||
if len(fields) != 2 {
|
if len(fields) != 2 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user