Skip to content

Instantly share code, notes, and snippets.

@flamewing
Last active May 10, 2020 18:32
Show Gist options
  • Save flamewing/95b7c4a57ba1ab219042b88fb95e4774 to your computer and use it in GitHub Desktop.
Save flamewing/95b7c4a57ba1ab219042b88fb95e4774 to your computer and use it in GitHub Desktop.
In-progress update of bigendian_io.hh.
// Godbolt: https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAM1QDsCBlZAQwBtMQBGAJlICsupVs1qhkAUm4AhSVNIBnTO2QE8dSplroAwqlYBXALa1Bm9ABk8tTADkjAI0zEuAFgBsvAA6p5hNbV0DY0FvX1U6S2s7Q0dnTndeRWVw2gYCZmICQKMTTgUlTBV/NIyCSNsHJ0F5dMzs4Lya0vLo2K4ASgVUfWJkDgByAHoAKgBqAFph8dGAWQwOUe1ZZYBmKVGrLHpx9Pt5ccN5kFGCcTXR5HH7Zl9L1CoqRQJjlzP13fGAdzx0AiRRlwTKajYaDcQABgAgiMIZCQYtUJ4AJ7EPDABAEUYQbTtUYAMWEhkw31Eo244M4nHG5M4AA5RmdtFRCcSrMAAHTyOh4ZAAAWAhmYeFY7LQhjO2FhIKlYwAKgg8PJRp5iKhgMRmIYNkqqMRMJhRlyqARPhkFkjuhcRKM9fgaqj7PoCAbCKMROhBiRRod8FQkRtTlD4fotE4TggDc7iIYlfdwwaAOI2ACqo3MmHkimIowTmicbFGAAV9PZWDy0zzNIo3UrPCWy/II%2BgZaN7P6/ga8XqDQx7iazfjulpmClSKNMIQI9mAG5OXx0UYrUZxjsVvq0RRjkgtiAj0YWnrLzwpXEif3CKOjWfEee0dkylvyxXK1XqzXa0Z2ggOp2YdAbWh41GBBEUjBA91db5WFYVsDX0RQqH0Vgx0dQM4TGAB1ABJWUAAkAHlk1lUZIRsABNUYMMhAAlajSNlMi3lGb4/m6TFMFnQDVzwQxPDLP9mIyDV6H9e4WxmbBqO0XD6MhKQsPMHCKK9PEcJsbAGAYfF8Ookiixo2UsO0ZNzBootk2owt8IYbB7yDMYGH1ICk1TdNMzDXNrA1GDi1LctLHXasaGzQ49U/TB0mFeQ7PQlsyMtRtulYf9wNnG1CgnWd/2YC5EVEqhnJTNMMyzHM828ot638ysN0wFs2DoYBmMncNnxVNUNUMdlRiwgraFQAgx0UA1GQxAhPBAQZBk%2BGb2WAWh9HZEhgEGMtAozMEVlsmUwShWFJBWPAqFDArFKkAB9eSE2wGwABEsNI86sPw87cP27gViwKgrANM7Lqw667oemwnpet69r2j6rGQAwsAZFZtDYYASEncUtvew7aBh/Q4cZZB7TZCUMeh2GRoRwh8yIYgichzHsdxhGCCRTxMHO78hQIeQachWEptGGx9X/Ihwu%2B6xvREfQ2FYf1gtmBgADVtBig6jpFn70Agc6ZgYbRzvlyTcXEAB2JYTbV6wNfO7CbBWbh2n28EAE4VeOr7RnO86dNuyT/oTc6bvux7zod52nYOr6fvdz3qO96jff9oGg4BW3OBDg6zCOtOoddzACo9r2fcU2VZXMbAE8DkHg4h0PnY%2BiOxfzmPC5wkuy4D4GPdGHgVleav060TO%2B%2Bzk6o6kMjZTLgu46rnmw7Duvc8jj2x4n6PY87xv16L1vy47meIVrlYM6oDHj%2BJvPLvHyem%2Bn%2BHbrOW6o6n87t9L3eg6zz7F7F9vSOel%2BW5v1/jYLup8ywXxXtfde5074PyfjfeOwCPaf3rgaYB/8rrvxAanWmShFCfycKqbMkhpBImdMuYgWBszPmsJOMMZYCAEHYOOAe1p%2BrZnsGiFh%2BARDdVuqgUY/VMQAGt%2BqfGAqgcRwt2p9D/Pebg3BT4DxPrTVWqDLbnRhiIYAHtDYm2Ntoc2f5NbnRcn7c69sh5f1Fp2HS2gy5YRsIpdSUcRzfjwKhVm50oBsFNEieQ50rBlmsO0XEQSfpgLUd/YxWsdZ6wNig6J2kpIOKcY47AUdgp9HCdYMB%2BCrGoOSfYp6aSXE5Lqrg5RDsebZzdh7MxyCClJMhMXOO2h8I2AYMRD2bifzOg9lANAG4CChMSTYkirTzqFgshknpjC%2BleKgHWPUoymnjPaZ0ieAANQsukhk1EwAADxVHkips9D6FJabKNpHSuljMjlcuO0zqKSjWZHDZXTsA7Ooko301SXZ1JKRPcw512kzELApSS9yxY3HkEYTAEBDm4nQAI42Uh7CoD0LlYZV42A/DvliJFTEemZnhRAaceL0D2zWMbR%2BnwFTMOoGwRQlialH3AUYjRDSLHQoNLCslSKNgFQgGASASLcQe0dMKVQtBzohj1MwZA4FSwItZenDl6jNba11vraiar57WMjvyokiKJXnWNQi01aqPp4LOQfcOSSLWmt%2BYPWebKjp1LOtoQshZ4nUQYM9GwIdaCagzJ4RVBoaj/jRWnJ28E2SGm/JgTUvgABeZNH7HkoUdKgbM3hpyNvfXBGromW21X6/Vh8SY4zJtoKNZZ7DsgQNze1H0VTMAFDlKw7iNw8k1m2Z08hTSeDlYlTIlaDrts7QBHttx%2B1kIzMOuVrBGoTrbRqad3bUS9uQPOwdS79DdrcC4a17Kok2I0Y44FoL8LgshXqz%2B1aGbaAHYu5gngm0tptVUiG0JBj8wGgsfCLNaAJpDUSeQ4a%2BiJuyloN06B8CkhqPoB4H4QzqNgqlNQxAYp8yfEqT4JBhEEZatrRWWJtbjC6eYTooxgDLGkFiBtUaJDSFkLRrRpIIANtYzIaQnReb/vdBsZAyAsTxtJGeZcBUOzVgbRqVEGZ2i4f/fwhNfxnw3DdLlXiI4PHCkIP6cCyBhHNT%2BIsBjUhOBGzdHB6wnwnBMXpZob0qBpyEyhHzYWOV7OJvdBkdAY4sJWkAnweCmI9SHDSt4TI/hYwyYVNFQTNh8LONlOpLZJd0kQD6JkcY6AYYAFZaTjGQJ4TwrLwNhojTBhkRsZDVz5pR6jH5%2BpYzoMFQwbIxzCfAkqKWFxLPWcTShgqzAKXCmYCq0YwUQ58xVJgUrQ2bMsRAk6Wz%2BUgJUGTQQHoBpBTIFVEl1RwrNX1K9VsrZui6um0MWdr1Pq/UBo6aEhk3A3CSDcFHMrBhIO/fhoYmkRtwQrHMHN/951pwnA1IQJUEAYvOn/LqVAWolhsekNZ5T4OUtpYy1l9SOXytoD1MAQ9WBgkZgOIq1U4x4IdswGuw1YtvaqXUuda5kIcJ6xog9KQpcIDs0ILiZ0vELy1qZiB0N7JpejFlBKbFBzjkcMxTBQXmIDoHXdlDuBUaQAgDV4yWU0v7xbT1xSgwdqnYs/SezuiXP5Y87kvzxUgT6CYDfKwalDXznW7Zxz%2B3ju%2BfYAgC77w3anBe5Dr7su/vZTc%2Borz53AT5Chsj9XaPtvOdx4dwnp3weXe%2BHmn%2BNPPvsCs5j3b7Pgek9yt7UXql%2BarHodzqMDPsf4%2BJ9eW6l2oxRVnc0eV86DbIeoB%2BGzPRt3vuD%2BH9OUf6A2YA7JBSFwlIweNf/bPsfmJ4ckERzN1UqPltY/X7MEgBoxR8R5COASfw2GCwEugfQkYBHaAwgmbUcKDScEK8V5WTsquQY1YexYCRQwQxp9xOwi58TX4A4S6aBS4y6yhczowQGOz2j6AqDizCKsyb7Rr1axo1wSZNRwEEq4GN7nL2qFrkGUGPx8wAFQYGjAERRCisAhxQFi6wHMzwFEjG6y7IFd4HxEFXhz4L5wJwFVZRwgEsF66CjYEj4/CG7RTS4Sh65wHUHfp/K/oHx8wYp6CaJ0BND0BYgI4CTI6H7o5WZGzH7nLsEwGMi6EwQyAoHnJCEOH6HDIiDq4rCPy64gDh4e7uGGGnAIwOFjhOGSg0paFOx8wCzAB6YLg76ZCmEH4WYWGY5/6Oy2HkKMjiGhqjDhEhzoGYHWBxEpCjDHC%2BH%2BHeSBHpD0D2Eq5jiipSBm5sBP7y4xpUGRHd6QGYCi52GMxcESEFHVz7LOhK6tgq6CLu7xGyra7eFTGlH%2BCMjhEtEW7UEn66C0BhZYxlGJF75mGpF8aWHWEHxZHi6DEIEm4CFOxFGYhDLbFFALgVEEDoCqHEBP5sxcF1YyCdHe5sG9HQHZEDGS5Ej5GpzOEHy3HYoPEpDLHgkZLHBWbfG0rrE2EAkcE5EXGglWZji5E8Ey5SC0Ato3HfgYF3F0AwlLEIw4n5F3jKFbTlEwZ65DL4ApBsB5rUmcCrFP5jj3EhiPFEnUl0lXFhHwnIm/H/I9F9FAnaB4mYC8HDHnKjFHIqgTFYp8k7H%2BCQ4EoakCnLHG4qEgDm5tFdHg6t6KiUkJEmFI4pFo5HHpH/HSnnEgnyn0nXFoGkmYF2iWmATPGvEgBUDMqswkEdH3ymnVxnGcEulgnEkenvFekWn8mwmcny6ImcDilhl/ERnon9GylYkGg0lykKmCnulQnelJlUnaA0mEkGkMl%2BnMl0Csn%2BDsnBFVlclGmtGYCiljjlmal0DLHClEwMmhmomnE5kylFkEmxnKnjEOGfiJl9mzEEq9l6nUm1nYDcl1SmkaGupmmyhfE/CaCqBMzGG77JEo6HGyDkgnFSmAnOncEGhy4QkknxmYhwGBJbDHn%2BjgEUFxq%2BCkghnzFPlZnOwSlRGZHjn3kSFPnulCHvmHn0CGaiHzFyknBcEflHmGaG6GlqHhnnJ8zJiqAMLtgCJDLXjq4KKBlYz%2Bhh5u7UwKInACK0WXh7HnnmFHHXkZGRmYnRkwUhx4h2KpLOIZKPI3qbIK5jGqnMBOgCJEDmoIZ6iZgQCyhjBWC4j9RHJ9DHjImoF6i7bECARWDrGgVFrdEQVOlRkPk9RRixkCUpIlLCUTLXJTIzISUqnZjSXCxyXMAKUlQQBYSXhqU6W/mOx6U9BcSoDyXoCKXyAh53igQahUzjASgQCjLhkmWSmOx8wWrmplj16nlJE2kXl2lXngg3nmV3kA5prBn8y4n5my62WCUOXpJOU3LiUzlSUyU1hwpEi5VogWzKVjBZrqWoCaWYDaU/k9796cY6IWI3YGKcomLcoTrRGDA45Xp47CWE6eDE7u5k5KA/T7DtQ7BcHjAUoKbACkAKhlaeBnUZAZDAArWhURThV%2BaqDICaI3CtkqUpWSqHqsAyrmqkq9V4r17w7fhjg2BpV/E2oloXpapxK6pPWqxQB6jh7EALYECfU1CMi%2BGHr0BZocnB7DVvaFb8yGzeFwJlXBX2pzzPX6WARZrGU0HjisDViTV00HxOqBls0M7M101hUGWCJISsBM3pU0GnIEGC2M3fjqFHw/oUFUHgV8wu4gGFB77CZ6hi7/isVFVaiWD2AKb%2Bh4joahr0DMpXh2wZH0FAHnRSHCg0103cXAlWW3S5zSUA11XRmQisB%2BLyDyxz64mQWWVVbrkXDCCZijDAZe0Pm8GQjEDAD8EEFlkRTq1egc01yCH/lNTGk1U64vF6482KCfEsz82EHZ1oUswEpu2BlITBEgUS14W00VUYku0SE10e2DQnDB08Wx1unh2wpR2eAx2h0y7x2J2xmQmemYhq0qDbgIwd111ji4EcntKeCMjj1KFXEShjjR0kQJ1b3tH4GoFZ0Jq53IU%2BEF367vHBlcFl2n0AVfFwLAYb0H3rn31gVmVT2vmCJ0AZgYEIAzZWAFgZ3N1tb/1KoQDgNwpKoSWfYU2Pzk6p333/5/0wMIBQNoMAOfbwPLkFDOgoOOzQMAOpV4PsAEPi100AB%2BxDkDCD4U5DW5DddNnlAiCVI489t0mD1g6DcD72uIyVDJtDza72ZDyDlDNcrDR4lMnD3DEDIjH2/DEw8uwjn2YjFDzDGV4thaowowdBoagB0GTBoBmVztspPdbdlx8uWikde9k53Um9sZQhqtqdKgAkYh9Vxj0hIAs9VMjIXjwoeuwjy9gdQ9Y4m965m5HJWZaJFlORFjeZLpYdNjSodj%2BZcdB98M7pHVyuWKLjzobj8%2Bcxj8%2BT6tf4jIe9ETbpm5o5t5rd5jcTlj%2BJVxA9tjw9ldfdDjB9TjFdvjf4F9HTEhATrAeuvj89usdtzBgTIAwTwhPwu97TVTVxqhd9TddTuZqFi9nt3djTiTnT1jEdqT7T9j%2B9E9z5jsQhfT8%2B6d8xwzozrjfjC97tS9czgWYTpzh96MazLdGz9VWzXdZj9jBzg9aTSTY9mTPTCaVz50JAAzqFdzPjDz4z/zIT8z7zSzOFqzMTY5uzqF2AxyZTbzgL6T/dKT7zJzjj5zzjAS0LRyiqXhl9/pBeoajI%2BLLMhTPZDz/TrZlTb9bpQ52L6zE59VbLhLQduLJLLTZLoLnTHz05BhkluTMEpThT50dLKg2pcCKriOarhy9LrLBLHL6LfLyzHZax3zxLvFqA4rlVvdo9Urhz5LkrcrVLFd2r/TZFTgqg02%2BdTLASnrsWKqjI0LPLizJrO9suqAArpjCTqFso1rOztrTTrpDrILxzzrlL2TCr7lapyrNLXL8%2BAb3r7Amr8x7rhbdA5FHi7AhuCbvLidkTZrJpfxOjej/6Nt0GUa1SHbBo9tYBx9%2BF/6MwzB4w7Ub4hgXWSGu2DwGRBFRFhmM2XoosiGTUqsOUJB76LMGQSoVg2mDYmIK4XBx2sTSbezEh8snZI9Vj5zUJLuZ4MLBU9ZAZQZJdI0%2BBn9jpp7qFF7FuV72JeQgzlxtJsZt7AS97YkCMP7PJYJYRg5dZTJIAbhoxnhjIBBU9fr50KevV04jIUHXZMZw5%2BiZsd7tASID7uHl7tJjbudR9PxmZMbEr0ZeHf7Kb%2BRSdIx2bs5kxJHZH9wpbJTYHpH5HkHlHUgnzG5TbTDmVfMmxWlnM4wZY2BhoSI5thy3UUgNwAkC4aAcMbYPUKejg0EOUMwT%2BSRXFCTDhCp7HSpnHqpc5eoAAjoemFL6w2VsRWXQJDrjVfUhwqyh9Sfwe/RaxZyrlZ/K8Mjm3OROB2MQvMb4SuSkF5wjL4b5x4XUQFxKEF4Kz8zKZZwSdZwfDk7m/OSntBJIgSr4SUTMUl3WlfQl5WSlyrjUf51WYF/y189l4C7G5K8C20yxxk2c1mxF1x1ikcoqJzBV1feWzV/W%2BJ7Uzl1BXkfGza/U0CwydK%2Bm2C104NyHEV3OUWwEsLK534fmwUzq0W9WzgbWws%2BE%2BGx1wx1%2ByK3qyoCt781t710c/1%2BCztxx8N3Z9x5%2BVfqwGzKinF1N6d4S7q/SzV/i/Szdx81l5lT2zNh5xuI7TXJa1ZXxagUIXWI2OdNcCZngzDHARAPF4UKwObthVtKleyHjwgAT4qsImT3VxT1T8m7LlE7hcHqEiXgQZj9BZPX%2BQmtVcTwDVwSz/6VgDDOz9oDBbT9ValXz6gQL0t0LxcxXYpXgOmmL6T%2BTzL2wNTzz%2ByFr%2BmpL/cwb6wRz7KHrtVa%2Bylbz/Nzi497xer5cyODlHAtL%2BLyzOb4i5b0b7T%2BgB70r070K4t6CdjyFUIfIMABFIBF7xT3r6zwHwjPL8prH/H37977L0qhkMMA70NCn5T4b8l1ffaMmjGNr1uTz9DZlc76t/VVH83TH3WAQAn/Md78n1L2z6X3Lw75yG37QNn731b9oHn9mKMQXzT7RvryX2P74RXymtXw73X%2BBQ3291j275r8mtGp30nxL3P7L%2Bnyb7vyP6n%2BP%2BBMQNPzz0Xz3xf4v0msv%2Bmqv8ryFar5H9vwmp8KiECYgwf77yP598T%2BP/CmOf3n54wr%2BElG/qlTv4W8IBZff0kvyr4v8Z%2Ba/L%2BuHxDpq9zmD9JqI4GAC7tE%2BJPQ/sX2P4D98BVgUPt8w37CtXeOA4XqSGQAUCO%2B//YgYANIHACB%2BTA93JQPQH89uudA90rgO4S68SB9/BAf3xn7sgzAVA7LjQIj6Pkv%2BjAswKIPYHiCyBUg9cBrD4Eq8BBW/egRrwTQAkTyRAn3giiAFj8T%2BxgpELIILSPw22giAxgwRR6LkuY4FZHnik05KhQGq1dajYHSxfJ8cweR0MAHajWAqch2VAKOzND0AIwigeQKQBuq7VSch5CnPsAOw046ccfJ6g6nGTgoQUGeGSAwHOiQhFIkIBgLuDLA3BzoVWYXHoMF4MkhCnggJBIQ8a8U9czQmoSywkb5DzohQ8oSULKEVCJ%2Br7J6r0P6HFDShD0CoefTgJjDCwBQsvDbiKGDDphIeKMBw2IDzDFh5eV6AMKmHlD1hMjYgKMIILjClhbOFYQcOGEKtAkGwqmNsL6EXCy4VwoYWT2r6nDUC5w3Ya8LWG%2BhtseoLGLfRZiPCJhqww4XqABGaA%2BgoI54XsMmFvDRi50SEU4GhF80vhCwp4T8P2FvCKYiVWFiwGdDIxiASIWEdiIRFrChkkULyJ8JCrfDlhOItYcxQjxnDMRYI64TlluHMithrInYQyIpGHDkBjoXNHMN5FYj%2BR4IioeNwVSGBaRzdekZcMZGHCfAT/WUaKJPofRm8BUBUS8KVEMA7BujfRhBmcHNCMwSPJwTVjVzeCB2zdD/ooIMHON7hsLK0QSlQqVEnRJwq0Ub2Zo6MjR1WaDF6PcEWjoMiIa0ZozMZktZQvJR1smCUFNRMATnFsqD1YFmDwBGgnnrAjB7qC%2B%2BsYtAWHwW4A5Ix0YwermKEEMCmoQiNVomLAL782B5gjgZYId694wAx3HPjmNX75iIxjrKMa0yVCliCCQhdgJHVMHd94B6Y0hoyAQ5tix%2BpY2wev0wF4xuxcY8KCiMBHQYRxEvYYBYMD46D3%2BCTSMcuKEjlcNxagscZwKkHsMkqHY6gQuIRgHiHRFdUIAQG%2BiHJXch2XokeVUH1jsxjYmfpZjf62j9xS4h8QmgWwvi3xkWT8SeIRSWZtxafa8Q3VbZ%2BjDGBoUMeaONE1YfK/bTRjH3L7Doy6XYwej2LJa5jbozfOmjHyXSrYvxZPYdGmPPG38pxo/RkLOMd7aNaC7bYMXynQCsEgxGE6DEMjk5hj%2BBuze8WWMdh7dJi/zTYrcUu6TcMOX0TujUVfKXcjeNTG8QWMXFET1ekkrFLoGRAyTp6ck47i7jQDIhlJZJVSfBNNySdOxQE7SQYN0kwR9JSISEJmH6pTZmEJk/1nlCBqF4Q0QbayRJxo4aTCJkdciTXCcmt4MwRkn1lmL1wuNZJgUyQcFM7J2TRJ3Y4sZHVTBwIIphXWzkq1GDYBqxhmXQLpg1BxTH4jnZzluSWAn06aB3EHvUT0BbhPA8gPXAmMljA8iAY4HsaWNIBocGplbL1odyjYhEGiR4dqTMwGhViupvUscP2PqnOx7u84zSXeMym9jRgi0kKlFIYDDpw0KqDCC1DgRjcagyBRGDxNt5UTJw80radG1WlhSlQeUp2LtP2meSM0owPaZu3elHS/g2Fd7L1JwYrSMBa08fsBPElRTCwo%2BOivJISkBJuRak2yaFPqHYCIZBU4rpsWpFhg4E1UvAHqFQ5LSD4p0zmIyFNFTTZhXBQGVtAGmEynYxM86WTL1yri0RVM7ADTJCrN16ZpMqofELc41BkRucVEUCNZnszm6nMw5ONwZk8yMwCUj0SLMGk1wuZCMRmSgFuF4jNh8s2mY7CVmIxpZU0/4ULL6CvtNZHMumjrJVl284CJssWUNKBHHgpp0khVipOSkwVRZnNW2UJL1wuTDJzsmtkFLdmZ0PZ41TmF7LyhuT/J70o3gHJtkSS6AnskAG7SSl%2ByUp0c92bHLtkhyQAxUrqaVJRzhoKpyc12QrPykZyppX08rJHP9nFy6ZEss6YyEQiuDbe1fa2WnKJm1ySZCMBuQKSmnWCW5gcxWXQmpgIxq5NcBCu9STHece%2BZ3bltzLwBeDZZxwkWS4O7l65mBfcmOQfDHlA8mpiA%2B5tPPnytkVZSI9WVTCXldyUgU0teQ1QMFizqZI86LlOAJmmz%2B5W8lgN1LGm1cp5kPQ%2BXrIXn4iyA18tmcvIvkdStA681uU7FfkTzd5iLfeavSPlqy5ZgCscOfLiygK3mz0/uTvRHlQL35k8ved/NnnzzVZwyO4YvOQXAK0FKAK%2BUXK1m4Kd5n8ghaqx/lzzeZJC/mSfJIBnzUeU0rQazOLnAyRJp7MSQQSikBVjhBKXGfjOHlazvZTsyyS7OwWyKw57k%2BaJXJTkjzE5sUwuUoufkHxy5B0nRXfK1k6zQxeuJ8eBOhiQT6A4C/uaYranmLIReAV8VYo/E2LkF989uedLMWItmZwswBQIoiKIT7ByE5wYJODluCzKXXRjvs3W6OsZW9rF1kN0Vz/c8m/rK/vSycCvt%2BO2oc1EJz444cZFz83wpFjcysxkA04VeuTzgWhtbuDbdrmzPPhT5fsfEeCFkzgRA4Qca%2BYpT5wXSiydyKiZ%2BRPzHAhh/JAkCfmh0EXZkYlDQ0stPVyXcih8eAJTk%2B1S5BEn5Mch%2BY5iKUbynYUi2qSPJLnxyoZ6NKOYcsgXpL7qbjT0ehUKW6zWFMsyTsbKYk1KciMOTOZws9HvKEhASm%2BZzWMV6K9lnUvGQcq1lHKIleucRf/LOVgq6Zg8jZRAv7l8w8QXoCAIT2ETBwTYyOegDyhWB4grAWYLGp8pADnKa4%2ByhFVgsRWNSiAFK3ZZSo9L%2Bk2IbfMhf/LZgdpU59KmOSrM%2BWfUiRJAJEByrpXN1qlhCxmN8r/mbC2Y3y/hbCqwUAqhVac0yRkuuXZK7lKsimSzDgGwLRV9y4hVSKFA0irZvy8SUKvlWIrm6yKr0ANgGhTgAwxw9qaSoPjkqdl5qtOdSo/mOq05vhYKKaEoQsrJV6QS6p6v7ncqPRvK93PysFWuqa4Iq5hW8o5hTSeVVomVYCs5VmrOViqy5RqBVXvk1Vv8p5UatjU6tWyVoiVVTClUJr%2BFfytNSatbnVr7U9am%2BYRzo7zc7RAS6uKB3OiLLFOtUuXO9lTILLoZUYJZdgSN4ZlW1KMz/ucyimh4h1WSntTktnXo0R1vaw0iFM66Tr7Rcyn%2BqZLoCqBSc3QHyebR%2BjZhVlTXZDulzqnPznVV6uleEvtmhzj1XkGFamp1moKDCTMjMM3I8UmL4VLqjNY7HoU0qYFIbeuTwtGYe8l5Ks7kbYpjlAaP5RameZ3PA0%2BNINFChBaQpg3trU1uiulUqquXDrc1RCthRqvw6YKG1Jq5tSiWC4zLUZhReZbusQoHr4I7hLGUPP779r4OjG/dfoEPWsaDV2ylKeOpo0u99B26skgsvggM90V/Gk9YyUa56EL1rZBWTepHn3rM5mMgTextoWvqvFYGxuSAHp6M8TMsGumnaCliSJaViKt9ShuD7pAU1pqxpXQqzWZKblLMGruqs7LPLyNYcJtRkhHIibG%2Bgg%2BjTuvhlSbjNGK/VSev%2BkfYuNYW/HjJqi3Pqgpwmjdbi03XJN4lm3WVpmxC0SbFlBIqAU%2B3gqA8mYVmmNVfRZJ%2BA6ALZcrcKvB5dq51Jwu5YhoPkVMw29S7eumpjmtbV6s3dclGsilX9Alky/ze%2B3o7gVolom%2B1h9ydZbcklIcXHk1phYnCRhDLQDqCQK2rbhtCMfrdU31xYtpO/6GwIBmOCBkooi7bMMhk8D4pkMqGHtQhz1DXhi6ny/BSACe1zhWYr2oKZlz3KJYZsLBPbB%2BHDyIUatIoT9kFrE15bMCLuD7TeC%2B0ej5NV9IusCLfYtrAtm/WZdDsxCw6OIn2/1Y80YXva8d8OgneMz4rwdfCpJVHaloe6Q6sdHahjQEjh0vaPReMBVoAsZK47ntCO44WOoC1pbptdGxnaFoFk86yd2moGQiVyUs7ed0KlLQLrp2Y7hd5yTtQqmghkdZdEupHf6RR2vtadk2zddhu/oSbcdUsTXSTtZ186YFWu77SlIHUKbgeSmurU7FFRm6NdYu/HXbpgo1MT6VGj9tMqF1TrxNMO5ncmg92262dMCqLHLs2HejKdPnc9X50vUKz3d0sT3aTu91rq0pfusbejsF306VdJu0PQLPN0Z6rd8u8fhzpgpc6w9ZeyPdbqE2K7DdtG4Pdjpl3h709DeyvX2ti3S609Fu8XVnv90TazKfMQsKqGuClh/QIYBHO9O6pGBjw/gY4KrG4iI7FQZpVcKLzjA5QsNq4OgNLFaikhXQLAQCCBGShmlNMyoJrd1F7ABgQsQiWCNpiwBOcXQHo2dv%2BnwzMQiMJGczGRkMQQBmsJcWjPRgsJMYPELGf8QHL5gzVwD9gXjOxh6xwYeQYmCAE0NI7SZ4wcmDxApjwBKZzOreg0FCpA5M7zogoJEI4FY1oheNLGz5TrtXlJ60uympaapq1nuqXd/ckpe6BRzmpRMJUCXWyqDWyrQ1xw8NcSIFWkretJa8VX4TDXJrrK2y2tZnW61pzzNZXT4Bwfq0KSC2UPDVnctwI9Z81pGrVaBrFUJqy1zo6VQoaHkRElDFGwbZCWr73B/KUYBBjricNUAd8y6wrRkHgX5qsNUh%2BNbDgsNfLK11hoctgByG%2BbKNee6jQXuV1t6RdpugJOQcoNUjqDfGu3aMU50r6UjzACg%2BUr3UZHaDUepveNonWEHjdL5ZI2QfyNpGijzGgJFns43968jBRqg40Yl387yjGO2gVZShUoQVcJB0Xekc6M8qeIfEeg4h0YPrL/1zdF3KkcKNMaaDTR0o8QZsk0dc9BuqJUbvWMh6cdR6njZkbDUTGx%2BAx6HCaWl2O7muKepadxuKOrHRDpxzQySS/lxq5jiKkQ6yqtmkriDYKlQy/LD1D7Sjkh1nq8o%2BMAavjAaymcGr%2BM4bojhyjYznr0VIm1iWx5vTscqN7H299xsY4jrPWKbk9zB5%2BbiZWMCHnjCMc49zq91rGbKqJy477o5kj6KjQerdTicOMPGujd46vQOtJPHHG9NejExDoSNsmkjJe0Y2SeaN97a9HRyU6UcFM9GYmujQ0f%2BmoioBHQNQT6azkhAZIfgagLUHpwABSNW2/IBCkCoBRM91KUMqb5hjQHFU0GaJ8HZDMgn89AG6qKBRyDAaQWVcELSC9MrBBgIET4DsCiGyFFs8gUWMwEWyY0mY4wd0OMEn3hZdocIZU22qj7KnRgQhPrKXvnzvrZU623wvARVSBIRRjIGzQZoVQYKI2Dhe6W6gzNpnuYGZrM9UMz7t9zoeZgZoWYCklsjoq9csyvJACtnaAS8ms1MpTO6MGzzhJsxXWzOgD%2BkHZgs1fSLM9nSzCMfsyApABzmyN1ZoY2OfrNG70zyp5s8niH7tnUenZpc92a%2B2rntA65qhZBidDDmKFo5oJdUn3OVHDzujalrKb41Jasli5/0suevOr0%2BTLGv85LvpP4cXzqJd86yew3TmE0oecLYlr3VaaLzgFq8yWZAvxbpNTPWTclpSmblBjegWs9aYnMHnGzR5t1vDOW0LqALoC96VhdbJLq6KK6mrq7NzakWgwqZii1OaouIWAkoy/qv038L/nYZIAIC0xZeP9zWD8Jzgw1qqLsk7lOmhVfJYw5CX687F3DdGubqipKiyeUNOxeItW87DdaoBdBbwqwXC9iR8c5meouYdhL8%2BUS56PEuSXezxJ1S06uBXSLb1OlumvpddxEjqiyl7SwBq0NwyHLmlkK/WrMvGWuLg7VsJpytCKBjgYWTU%2Bdt4knt6mlsz6d%2BpObDGJNSQdWrXjGXNhvmfMPUMgB6C%2BA0oLAFKxcAjBE8hCC0IkKiA%2BplgusJMwPdlY%2BGYgGAeVpvl926hIECrmBIqxqw0sWxGQ/V9NLdKQJh0n2VWtkt1I4MzWM07h9NM4dlCz8r6JWzCmVv9mGgCgE1uvFNYRhrXepc3Zk70drT40CAx6BfGtchZIZjrWNSa9y1dH1Vxrb106%2BU3Ovfq7rtINmCMu7ScA3AwNzM92ltgQ27rD14IhJ1wrxG%2Bj0FFjuEfOZ2VikjiRyqJWeQZIiuUjbynlQthRUYqLhsMELnR5eWGaCHHKqDTOt1oPDylalMHip2RUfK0VPykLmV4ZUW9cFnsahWxPVwMbQlFqjjdcr42uqclEMHTf6bs3SbUKgMHohhqHQCo/eZavNTNh95S0CNHVAkl0ovUharNkm5zZGRy1bUBBWvDLeyhdUma9WI23LZNv2wA9ZKg2zLSHnK2z4fcJWmZWFvNUXEolD5MREDtfJdkboLqnsDomA2F85uEamNW0qCMMkUd9XDaIFqu3cUVvYJZlV9tY3RbkyQO4sFuTbJQ7UjCO%2B%2BjQOg3wbmIGO7/TjuYgE7kN%2BgGDdEI2js4i1epCmHMSM4PULeD2FemwAgowUEKUuD8lQIo0/q0qKwDcaxqeByUbAV7D4JdvU3JUQ6d9FPfOhg3Z7nuD%2BqZVbTy1NCIVaWlHClQA1J7pdzwBvZjtm24a6sHWxWilpp2CeC6FeyOik275N7fPWGvkgPtp2oA5uN7F9nBCHIHg%2BgCmksARijBaQE%2BLEJvfaUMlIH/90YIA%2BAcf297u5MON7f4pNUc7/tvO4XYLubIQ7ukEu8/fLv0BobVduezXcORydlGjQqG9wGbvK3z0N99u8mE7uPoqAgKPuwPdvRD2oUo94VOPZPuyolNXa9%2B0rZU0P2Cez9te7bHfvb2CECtZuofaEeA0z7cjy%2B9uTPSq3tbsSXWw%2Bn1tL3X0MjpCI1HkdaPzbqBP%2B3Al/sgNRGSDh4IhFAeTiwbUD2xzWNsNdw3Ahsex0A8ccgOy6h99xwg4cfghwQyDgHJOPgcLVgnERiBz44Ad%2BOwnyDs20o/Qc72hbWD0pCJVwfiVg73yMO8LDPukP7rLgaO5Q40rUPg5tDxO0ejKfJ2mHOj%2BGqw/YdWJu7F8bhzejvTD2CCY9gnv9UBqiOZ7MdiRywakdn217x6cx5oxRJWJPb39pe/04nuyoz7UzzRx7evsDU9Hd9wx69Ufv7pV7sNlwNM8lpWOQG8xWJ748cfXPEI0EZx%2BA9thuOYHcTx5yE78c3PbnW9iRtY4ufPOrnjjsJ8k/8d3PIn4D1xzdmgc/PPH4LtRg44eCAvwnwLr55oyCd/PEn8LxF0C6Bci17nhiaJ2bFidfMMk0T/51i8xeIucXqT/exLT4n%2BiXQouSm7eLPZF7/L8yqQAuiwilbvyKd/udneyetUxKXSN6uWAlvCxcwBAZSundjtVP478uYiAveUdp32eMz9J2hwD17iPz6vKEuy%2BdDURLdaOhWXy%2Bxu5OhXTQd6m5XGJSNxXkr6u5U5of135XPLmOYfeKfrPi5GDzmuq8Am7M5ynCOPqwifNxsdJjrfhNgADc6vMAz0RlzXCNe53nK%2Bds1yK/RlSM35yABgAqGNDvD00C%2BKGjU8NC9Xo38x4VH64zgiBRncloJ9VS2sCMu4EwcmvCFpCEMWaDILWUE5ARjBIHTb72xmYzM94PYP2eCK0u8HgPOloOMiz24QukgVS7obGWWzqKFYZAhWUfRO90b9xqXdNOsH5GQAkqlpba845bN4JYQCuac2Ny4kTdiZRXAiPVz5TJvUInzlRUMK%2BMUCv6gRjII92HRGDPvQQ5bld7%2B9lzp2MTf7ld1Izj4EAI3BKcQAu5wZLus3NVRsEdBGTBUgPQHlN2Jnzp6YPqdV76ilWGBBVUO4D%2BD8aHILIe/3lmIyl0RI%2B/vrH%2BieYqJmI%2BUfV3n9X9324HwtL/sQ5R%2BKO%2B6UMfdG577Gq2TII09oAEUCNzljYBpuM3Ero96EjHDG50BzHz%2B2ch4/CvMPX1RkIJ%2BDzTvQw1MerMJ7A8LoxPrACTwh/8ryAZPiD5TMoULQl4FPqDwZXSsPu%2BEwzXaoUMQDirL057XbjJ/3L3dRghovVw98e95dZPHK57i151WFgYRf%2BCKBW2xF6np2tVmwI5Jh06loi334nPRluITHfvC3FEiundfEtLXmyK1iE3SvNlGGvNhasEzqow1sbnl2JgE3SsCPKyKvFuZ5c191VsLwL9Xuk7YYcNerqvqrZ0ZAIyCGGHl5Myr5TJeU6rS1sh0Q/IYa%2B2H6PDHqRm33A9wJIPfGD7DB5yuEfEPP5ZTxmeGBsRJuGH/j4yDuspUoX8uPbzZ8O%2BruLCbEZb5R7iPjve3rd/t0O6HewPOPFIYHGO%2B4sMe%2BPWH9T3PhSrw4nQon1N%2Bm5M/SfaMcnu7xO/VRf3lPwPtTwjA08QAtPVCNFBD/0/OhDPxnzN3D7HBlUDS1n57%2B97s8jzD7T3iRjS45nO3aUKpxwfxPpd8QldyNll4YNJBSA0QYbnhLQAjdRutWouPXKG/Dccv8Iby6DhTpAqTnYKFdSwIwnYAC%2B55QvqXwSlOPi/UAavkQML%2Bl%2BdygyVapG%2BLk3WzbNi5Ffr6DLlKzaJ9GYJwLOGt92jZtBv0a5iD1%2B0BcI7odgMQA07s0nXTLoNwYNPc5P43eDy99inIo2vKH2Ru19U4de5f6ar1S3160RnWu3XJ9D1xj14viTQ/Ar/O5H%2BwLjUY/nuCSlQ/tdyuk/h9%2B31mFnDp%2BIoJzrP95/kFYDI%2BqNwWyFXz%2BR/Kzt7nBqIyCrZHE/Crp2FIz0oEo3fQUvXNe41jeqSAvqsq9oD2NxUdr/pZz0l6fepfX3yXRm9tYQmp6WB6UAgM6bxk416fQK6m3pU5CFBGyCj3QR%2BY7%2B9eCC3f9GbgWYjRe%2B//a0RnF//fV3sjI/x2BO84ESf0IsQAKLzAE5/YgAX833XrwgA2IWjHNwtVdf0fcUvF9z6BcaXf2Zs5xRnxb8vXWpBbx0EF6Ffg24ROCDRq4IQk99OXfa2/J5iT3298tAX3399apbXxABhfLlzHAWAiNz1cedUYDHBlfJhBwBJfZ0GeguLHnyahPfbgM%2B1V3WgIDd6AniScAmAxkE4CF0SQPh1eAjYDF9WAjl3YD8ifnyEDI3fCGVNSLWGmYcBqQgMQRSAytAoCA3KgMQoTBGQMF85AxgM04lAzQLYDqAjgLcCVA/V3UC%2BfYAE98DfIwKmUxAoqQDdVA6sAJQ6An3wUCXA8mC8DdXHwM8C%2BIPXHcC7AgVQrAVfQQMF9J/V80qR13VXXmUAgzTiwgGXDOhVA8AClGdAd3EKj5gEwbQEMRhMWA39dKYVCSX1BQGCB04DQaiX30YuK8DnB/ADIm0JjtQWFaglQZ7X8BLtOWHIxhMIyCVghFay0fJUbKIIYCnAR/0UNn/ELxaowvKRhn8sIOihDRWAT/0UYvsKwDHBlg%2BQOzBS3e912sb6fXUy9A1HL2H9A/SRhttZaerClsDgxy2NtMwQPjUpXvO42FQB9cvVj1CdPY03Jy3JryvofKClCBFwaABVHZvwf4TZhYPat3GBOAHQSwVs/ZumIhlXBWSc9eiMrBsFPsRAOVAIafN02tPDba25si3LECBDu9OPUpNevcEKT8D4H50fgrg9kGL9hnTz3P8TKVmgD8VXGuDZDuEdXw9NaAaP0z89FLENZd/SaEJEA%2Bgdz3JDMAat2pDU7am1xDm/eviD9BrDbTQRZA6IIAUBbJ/1QJ8/bYK6pdg/YLYAjgtRlODQgxwINCRQkQC1U9dEgnuCO0R4Kr8AAw%2Bw5DIySs0D5IA6AMZDFDFf1VCebEGVqD6gujHKhr8WMDaCCwToLMxAGHoNtVxgugEGDVqfmBGCNMMYP6CFwWWBmoxwf/SQN/wWYPTCbfHULxZ9QlYMND6qTv2bpTQ9IHNc3/cAOEDLQw4OIMv/L7B/9zg330dCnzHELYAtVanTuCRgB4MGAIQtOVW83gqQA%2BCrbb4POl5eeAP%2BCSTQELr0I9fVy5Ml/JkMk4Jw%2BlV8I5Q2EKzQxwBEOzQHgZEKrdKQ9oDRCMQmOWFCOQrkKb8pQ9kN5oWQp2DvCA3MUIlCeQwUNmcelNfwJDkQOELHBiQwcKVCVQwhn3D0AGEIVCf/C8KZtQw38PmCRTWXCWCqwi4LWCbDDYPspsHDJDC9mw6Lz2CowA4OtDv/J0DOC0I3sKuD4vEkO9UX2V0NHD3Q8cKT8OQrcz94fVALBgDgw%2BAI89kXNVwydzkTdzWhqg71z5tUI%2B0OrDUbNIBlExwbM0rMzzRclXopIyvnaIUKG%2BnV4GwjD0Kcr3M/iUjNQG0KfMewsMCuDdw5ujpsbgSoX6oVQ3UM%2BlVRZkiv59dYUQBFNvOCL38l3QhisBT%2BG9xS4eBYfkciI8fzwpD4IwhkPsZ/f0J84fItFVGx/IvsIQiPXDV1EjrIwyJrDoyKQBQwZIls1A9ZUBc2WIUMFSMfhqddSM2Cz3RsPLAdgs/lSiT4AfwMiKIoyIDcTIlhiJtzIumysjUKCqLsjfDEgj8jqYBdxcj7YNyN5CPIocz95mBSKIeBoo3qIQiL/V6lCigpYaIiiuo2jGMi7/EGTTMxI9XycDVg6yKpMaLZdTotOImw1dE1IkPyKjcIkqLEwyom9w7DjggCHIjxIi4Jijq/NOwtCiIhiTYj5/DiKDCbDFfzHAqI3JQlN%2BTSvWX8bw1VwekDzNaJEANo5KKspdIwwHSiAkLc3kiBSRSNVE8oi4xr4sIzG35czQyLw/8YYtRm7Caoy4IDdqIyhwACzI2KmajLw4XHqoYY9qLc0DQLqOcjMAyD1H0Y5FsO/FV5eaKiithH6OJipXQhjYh2QViN8JuBAgV8juY2fkwDYo/iJEiFglCMSjCY1Gwqi4YzDlPNso6klyjhyVSMuMMYkW2KjNIqRnZiIACqPxiyIu0PWiHQ36IHCy/MmMaiKYomxaj6qNqJQB7IzqO5imYwKNcjWYtOSNjvIsWNGiARRaL5jJQmOUFiHzdvj95RYygQWiAo5UKpjlopCK592/BWLujffVG0xkOAjk06NuvVskxlUYgqOOjsIrGLOitIyiA/8840iK7okovsJJibY54K5ouqeQFTQCUMOOr5UqAWKdBT%2BRXibi3sdYAmjCGX2KhDfKTMGcMnvHqNTQWYoOMF8eI6WK1Dyw3inBivfA0PTi91TOK7VkLPCxzjGQPOK1j8oo6Lz8TolT1LijYiuK7CzY6uKtipXJP0Hj/SGTQJUvWJwDgCnQKePV8Z4hOPv8EoysNTjNoo0M2iWLYdT2jPo/OP3jdYv21OiDYrqiNiro02KrjCYmuN/9SY%2BuKdh2YwiKcBiIgMI%2BitwriOfjeY6eIS8/ohozlNG9IGNnivbb2MPgtRBfSJBOfWtBysnrV1gTQ7rEGALNXrEqy%2BDWyehNyDMTOCySj3fc2P18krBezbUGAXoEKii40LxLiLo9AE4AIAERNYxrooKnrsk7R6OpsigxQBKDkgkABmjtAJOxSoMEyhGmtREmnjUpboi2OrDQyUhJWijdORLETMYiRIgThYGf24BZE0RM7CAIARnlw7rJuwadJHVRPDdigzQO0SvEyuz0Tkdd6IMTzrIxPzxaAWjF4TxtSxMTiFBT6SiTQEnCKPipE45xsS3ExRM8T6HRh18TXqNRMjdAk3fgu88k%2BGzeioAzBJsTjEmJNMSIYg0IsT34%2BKLliakg%2BPEStgyRPNDd%2BWkBcT5E/SI8S6HegDhsVEwpP8T1EkpJ8oyk4ZPqdQk3XXCTF/NpO%2Bj%2BEpePMT4k5pNljcyOhIGtoyNpNSTi4hxO0ifKGwD6T%2B/E4JiS83JhMUiV%2BKjTGc/E7IICTNEoJO7RmE6axuTbDSpMDDtAJZJMSVkyGKaT6fOKM2Sk4xYOsi5EtePesnLN3Dj5PRfnW1j0Yk0MPjsYo5I1gskhRIuSvQtOyKSNEkZi0TSk2aP0TFkqJOWS4kujgSSP4uWP5saY3oDXjSrQK3dx/zOFL3idYxFI6T9Y81ykTTk7JIxSkEkILus4WL6yvpnPSFMRlEbBWX5SKHAwEiDxk4pKeT8UnRO7QiaT5OqTiU35NJTaUSaMdhrYiCKFSAIokPewSQkCIMBY48CN5DD7DUJwC54ttVugz/dpLsTOkzSPwiKYGRJtTTgNxJ/9lE6uwADsUzQJvjC6BZMZBXUlKm4i/kxpPG034wFJlinaI3SDTC4%2B1PZTywJ1OdAXUnGndSzY7tCBtJU%2BqJrgfUzRL9SAyANIXpbUp%2BJGR6k1ZIuDQyCNJmcgU6NMqNY0u1L1jwEpsLnwy4imGcSg0tNK7pgk8pzrjBQ3NNxT809iIiTtAetJLTYkwmMrT%2BYyNKtSY021P2T7E5tPxR2Y9tNTTron/wrse07NIPh%2B0vXEHTC0kdOLSQ09VMLQq0viJnS60udNZT40ptMTSW09mOOcO0tdLNi7rchyvjvUmVJxTd0j/0JTA0w9JwTQ0tZLo5T0zUNBiL0%2BG3nSHUxdP/B70iAEfSYEjgLIcGHLNKT8d0sAO/SwkqpOHTR0o9InTw0qdOrSo0nPzAzbExtKPik0zAF6S4MyuJBsZkzdJQyP031PQz5kzDMX9sM/9OPTboYDMtTQMuC3rSIMhNLExyMyjNXT4MmdBGSvU3lNQy90ljN/SKknDO/idPIDPwyz0njJ6ts3Pqx2TXaS9K78kUkuPIyTkqjLPiu0l5OuTUBDJAky%2B0hjLzSmM/1Jkyi0uTPYzcMpTJDjPXQjNb87WJblRtXUiFN%2BsoUokUZSFdeFJIywE9JMgSP/QzOXAzY62K3SnYKTJsyC0uzIPSHM0tIAyK0vDJczM6GtKIzP4v5hqBaUr4OctV6QUyCy400jORTW0gnwiyf/aLKT8hCCVM%2BtoyJz2YA5CEVKn8DtUul5D6s40h1T/wwwEJCIAI1P0BgIg1NAj%2B43kLiyIAjDK%2BS2MlLI4yeIgJ2nSyE6giQlOJNn3CgTGX9GESUkqEHz8pEmRLRSBkvNxysM6Q%2Bz7Y9cVDMjJnk%2BgEzS5k2zK%2BSfkupPWzvGSgK5cAUltn4jrU7TPz9yMlNLdSn0ruhytsjCzJDgzsrOSsyB0%2BLKHTWMv9JSzQcl7OoDJ0pO3EdlsmWPwCCocwOICsERbQro/Az3zwZQCc7JlTg2KZlxSJA/V1EChCfgNV8A3fHOeyichGDhybA17MEUTAppxvtzAzBGAQrAnHL0DBfWnOmYik4nIJywcwX1sCvyCnKV9CAAQLxzE%2BYXMFyGcknMJzBfcIPRiLHNJzZR5nYmCxhSYAHFnA56TCNURtcmtABwX9FlPdQjc59H3Yv0OmB1zvObdHowISKGAtzaE5AWtyn0WtEeAUY5wimg/BAIUywtqZGDVB2AK4H%2Bp0AWnGzpxgHtlIBA84AGDzY89UzYBI8gxnGArAcYAjAfKOcFZRmrLiRgxUSZHn4RccmnIzo6sxVPW0X0pDOMprAvnOADec9X3m4CbGKWogZE7IyTsC%2BURlExs0w%2B099p/eVIlSUqDvJ9FCMhvJqAm88lDTp2NXRJslj5NnXbzkATvKxSA3HvKmSEYPvJp4B89iUyph8ggFHzTc2qUnyJOafL51Z8%2BfPuT1fJfMX9V84PHXzM7cCi3zR8q3JXyM0omj5kiVGfK%2BwO86Ny7zF8vFOXyFUnFQqTr8uwU3zJbRvJkSCYUQBfyujY/M/yF8wX3PzpkrGgAK58wfMyoxbF5FLjB0bfOcSW8p/IIAxgD/IXsv8uAp/yL80vP7zkCjfPAo0CjJDvznEvXMJ198yAroMCC54KIKz8kgoQKlUwAqWyqCyZFxsMCxvOcTd8hApuyp8xBQkUWClF1gL2Cq7MQLyC6kKyzqCgQpHznEh/L/yCAUQoPzxC/%2BQuA58mAtPyRAeAsfz/8%2BQpQLeC5yn4LaClnntymCxHUkL77AwpMAOC4wrkK18igpvyzKO/JWA/eekMJ0cC67LZgb%2BNRnsLdnIWm7znC9Qq4L3CoAtvyQCkfO8L6C8ZkYL2FLGl8LtwaAsILpCwwoiLL8nLGiKeCzwriLt87wuEKXCzQsgK0i%2Binfy9CzIscKjCyIqQKFCofKKLqIbwrULkipEUqLgimotYKsipwtkKoipouAKvKRvO8LwC0ABSLgQqAuqKT8sZOIKBixorMLCikYpHzjnI6FdyMi3orqKcisgrcKhi2IpWLt8tYvGKNimYv0K5imQt7zdiq/PyLFaZosOLqIY52%2Bh2AYUW6LZisIu/yFi0wsoLli2SkbzjncYteLNiqQu2KvivYqWKQ4LfIwgZE1vO6KaMxAqvBpwbNPCKjY0TGXokSiEurgoSmRMSKJ83AsNJXtWfPhLo7JEujcUSj/zRLES/Yt%2BLu6GoGhKIAUovULyiub2hUiShuwRLpwUkoXtySsAUpLOS6kshKii%2BkvaL8SmyUJLqi4kqrsuS54J5KCfPkoxKfiwUsOL6S8YpCM4S9kpJLkS7/NRLkAdEoFKsSoUucTW83QslKqSsku1KKS3UqpLMS85ChK6C8fJELn8lks2ETSjUqlKtS4gp1K9Sm0objlSoQtS9HS%2BGxCNXSrrOlLNGWUoRR5S/UttLDS7jHG5AygkrsKrS0Mo9L2Cr0utLFSg0r9LrCtkGDLKSlMvNLPSy0u9LMymMuVKxiq%2Bi6KyiwIqJg2Sgsu5KLS3kqtL%2BSn0tH8hShIodLqyoMuJ1gTI/IlK3Ss0obKiypspLKPCpUr%2BK6SkooDKuyw0i6K6y0vMHKZSxsrlLmyhUrHKsyicoIAMINovjKZymyTnL%2By%2BsqXLhylctHKYimkswLtynMogKeymkz7KQyhcv5LCytMuLKMy9crLLNyjCGOdcShMvRh5y//MXLwy5csjLVy6Mt9LPy450ZL989UqPKgKk8pAqzygovHLaSrcuOcRSgIvAz/yjkrDKCCCMryLEKu4uGKIK68tANDyx8pwrUCPCqjLWyx2ChLjne4FOKHygCqfKhyl8pHK3y88uQrLy%2BipOKUYrCs1Lny7IvTKWy0svAqUKr8uoBhQTACBKyK5iooqQqKitAqaKuipIqZKpiuwrUyoStfKRK98rErLywrDHz9c38slB%2BK90ujcpGV0DgQ742qCSI3PbgoUrgK9YQIqGfLipikMIAyqgrRSkytkqNK8yq6pLK%2BYmsrCVR%2BPsrm6PCsIBnKkGIvK3KgyvQqNComhgryK7NIsr1tIKofi7K24rCrHKiKo4qkKjcvEqDK8YsSq5K5Kv8rUqvC3vjbKvItDDwqruh0rOKlbNZ86XVvFQBC8wX0lJIQfPNQAqcrIPV90eEvIAq4EcvOiZschNBlz5iHqs9968loubyOdWEuBKHCi4uyKwSm4rAq2yh4pxLOypkqdLD81krOLaipav6KrikwvBLRK9as3Kd86cu2ruy3arj0Fq0IsAhwilauqrlKmarjKz/a6sNJbqvxnuqFnQ6vqLci0KqirXKkfLAKe0CYu%2Br0i/aq2L/qnYpOrVqmiqUKrC/wviq8C3QveLHqz4uOrXChGrOrHYJGpaL7Soyr3KtC0hWYKeikEthrnqoGrDCQ4AmoeL/S1/WMrbCiQoprFqj4vmLsawYsRq%2BC1yisK4q5kshrJ%2BNmoeqVkgGuuKXqvGvpqLq5xNVLJi8moxqxauGpxrJa3SvOqUK1op8KNwrIzmrcCoIt%2BrFXUEq5rFivGq8LDKhgq8qKi7Wrfz0a84o5rLi3/MBrMq4GvyrMCzWs8qMKr6tuEDy22oOr7a5auNrvitWtoqWinco%2BqOi72utr7ykIr%2Br/ao6sdqJammsQjXa0YpIqra3sr2rfamGrjrxa%2BGtVrOKlOtWKQ8T3JlE3iu2sxrOahOrzqk6rLLvzji8GsYqY6w2qprA606uDq66ySpeLcog2rVCW6qupVqa6%2B4ouqAS8GrUqm63upzrla7mtNqhSmEr1riq3ytYqtK9ivqq8qj8vErNq4ms%2BqxSm2vzKkqwSqcLhKtcoLr16y8pkSPa1GsTLo65Mv3ql6w%2Bu0rj6ter0q3KmRIFqnS8UvUqBKu%2Bq/SV6x%2BsIqDiz8rBqbC50p%2BqfKr%2BuPK2K08tyr/66KrpKjSvWs/qzK7%2BrQzf6tapDrsyn8pJq8ym%2BpKqD6n%2BqgbV6mBpBqtyxmpNJt6iTnJrTSliogbl6ghr/qXKwupIb3q1smSLKGgcuoa4KyBoQroGhhtPq3K2WvBrsGqhvkqsq%2BCvwqeGl2r4bJyrWozqGQ66v1qwGpBpob761Bteryy82qSLLa28sz1d6nBsXrlG/Bu4bCG3hufrpGi%2BuZKfavetwbkGo%2BrQaoSsOpYatGyxr0bwGzhtoajG%2BhskbTGrcorLgG5xuEbNKlRroa7GoUu/Ktq6CtMrAK3CscrqKmeuVLIKq6oibFGqJsoqYmpSribiKt%2BswrkmjhuiaxG2JvbrQmkioXrXGvJq4bxG4xq8b1a7irgCS65SMibcm1Jvyb0mwpvia4A3itLqGmkRrppFKyKtprGGiSueLpK7upybumnNLSa%2Bm5OqkbUK1SpGbEGlJocrmmyZtrqhSgyswbyGkpqUbNGFKoJQ0qqqqTrYs7KrqrPG/pumb3KhksSavKzZoWbTIsqt2aKqmyqjB86ppvKacqyptObvG85qybay0ZtKrhYAKsfg9mp5oObHYWquWah6gquKaumv5oEQAWxKxMxXcYKoyqaqo5vBb9oRqq6rJqgN1hB%2BgToBGZ%2BgQrH6BSAEwH6BwQIltQAQAfoBKpGMLkB6B1xD6E4AiW54FJbcWzoGEQQAFYBWB2QHuHBBuATgHBA3ATltpAXAEVsdghASlpcAiWwwC4AwnYlspayW0gApb%2BgIlvalwQUgGZayWzoDgBYAGAEQBVZXiCkqyACgE5EDW33xABE6ENDakQIQaGeKowdqTRV5Wols4QQ0EkUpbGWxIRRwiQegHwhaAaWEdbSALAEFBRAdgH9b8ASq1UBZwdqRZbSAI5EKBfwN1qJbw8fFoVb5MDICRBdALAATb1W1EGlb%2BgRls6AaAegCYA2ADgB4B%2BAQQGEAIChA2kAhACA3gBOgREBAV%2BgcYHwglwcYC7ZvCatssIJgY6CiEiAPiDx1WABM2VDKEMMHGAS6nkAIA4zHmQTRxgDCBZhg%2BRCjEw52gbDnajkdmAmAMIK20jziQB%2BFXat2srkuB00VUE3aLNFgE3au26zFKw85PcDnasPadv6oH4AmEwI72r6nGBqxC9sOYDgXokVQ%2BgSOjvbGyarQODpYdtv0BysM8n/A72pKl%2BASAUdlRAKUZAH9A528zRVQw8xtp4hteGYk3bH8S/EJE/wK4GEglUDMGw6wOtaGvww8lkk3bc4KgC7aqOw5HZh223ojwBN2zrBHBGOqq1/4kOjCBXQCBN%2BXGBEQTdq6x3JUQBTznc/LFP9N2/qHHaSAQUCna2sBhHzAYIOdvj947DCDawzqPGV2xE8mDuzBlOkWnyxURKESBFN2vQDDyagJEGDysPEzuvAV0DPLDz3MTIC6lN28NAQwBIOdugI%2BgL1rk7iQTdttBTabYG94lQOdpJxxuMdowhGwHynK452vb347rwZkEs1vCbgE3a4UYADj4agOM3mQPEX8Afg0AZKGS79AVLpikMu9xE8QcujnWi6CutLqnbekLLooZboVjrrtwuyrqK6au0ru8J2gldGXamuwrvS7Wu7Lu8J2ENOwq6eu6rsy62u26GWQDQYbqq7x24BiHaiQViHQAgu7rpm7IzIdrgJlulLpm6ylYgFRA4YOdsoSDujcGYBtsBTkxRbqdDq6xU0GYmW6QweCHw7RiO6lRB59A7qKtMwUrC%2BpN2rc3baG6zduPaohG4Ejz9O7kWvamDFVtetl9LHy0B6gXIBjatAFoEqA4gUgFCAgOmHpCAfAIDoR6YgKoEaAIeugBKA6gPQByBqgPHtSBagMoB%2BhWgHHoUByetHsaByerHraB0QroDpbS2vFspbCWuVujalWw5FpA3AcYGPQ6MUTCxBSSWgGERcQCAFwBCAdOgZaxwMqRu1ewg6HRDLyaQCZbHWrVqQAmVMiONaL8Q1tMBWSEgEEBC2xgDflS2lwFIAf%2Bd9ATb2eglqJaSWhVqValexMNGBee/nsF7gAYXoFx3iMXvaA1ellpk92Wzlu5bOWkPtD7Q%2BtwHFb%2BgSVtIBpWwrDVb7e8lspaVWkADVaNW3FtIBtWvVt1604nXrzk9e6cBupIcTgEdhzobgDKdDkY9FIBbWucEoB7Af1uda02rNrFAvOn1r9bo2wNu0QQ29vpBUigSNv9bY2qqyqC82xNrdxk2oltTaSRDNoGB3W9xFzb82qvr3Vi2kNrLaBAXgEraxASzFra9getsVal9D9SGB8IJLsGBsAXCHkAxMQYF1xL2mzEGAWYaMEVAarRbHB7kgSHrMA6euHosBKexHvR6wgfwDf6UelIEZ7qe762KBaeonoaB8gZ/vx6Gez/ux6kepoEJ6ggWHvgGKeqIC/7me2lt6A2eyPs56E%2BxVspaK%2BwEBjAC%2Bq8GL72QMvqxApeqmDewVgADnl7DW6gbtgVeqQD97NWjPs16nQNvnIBKAbPqqBeAP8Gl6ke43qX6zei3o1AJoYfpt6cB/1sd6PoJLuokCB70HkBiB6cFIGy%2BlgdZarqXfiqBYBfFuj7Y%2B%2BPukGk%2BhQBT71W9XrZaOWrlu4BaQI2GsGeATgBWA3AR2CNhrMSPpWA7ewweVbTB/3oz7dWzPogAkAHgaNbuBvPrNaZqKVRDBhEKvulQa%2Bh1ujaG%2B11uH6PWidiPJW%2BpEFDaf24NoGAFWsNvVoKgmWWjaB%2B%2BNsSGk2/1on702o4ESHZ%2B63oX6i203q4BeAAQBWAhAbRBQBN%2B5jB370O/fpba22jttugr%2BiYHrQPEB%2BB4xLMKjuvAyEBUFJBlOqIS7bHYErAvxb2tTtDN7%2BtkDg6BoAaCPZJOqITu7FAMPIyEfAJ/tyH1AKHp0AwB2HrMBABpHv/7f%2Bs4e/7MemAaZ6IBo4bJ7SgN/uAGoB5oAeGgB0AcQHqgaAdQHYBjoBZ7MBoEfxapB7nvwG%2BegXsBBYDL3oiGJeygZl6aBuXpCHsZD6BWBcQaluYGvB1gf8GQALXsGhc%2B01qqAmh/gapgjexfrqH4gUQat6JB7AfcGIR/oAOglweQahHBe2EdF7xe9QZk908qhEoBzBqwfZBj0YrDD6w%2BiPt0GpWkADj72QcEEKwPAFwG4BHYRwY8BaQWkFlGueh3qMHVWnEfT6/BgIdRGghk1oV6qgFA2L68gavpvBa%2B%2BvuAYEh91ub6Uh31rSH2%2BjIdjysholpyHe%2B/IYVbChofvdaSh6NrKGp%2BrNqqG6RoQapGGhkAHN71%2B1oYsIt%2B9qUgAG2vfo3BKW7oYGGXiHLuWwe2qTv7b2AWcCHa9QEgCoQe259uq6Z2qYYPalOjCHXaNQCYAXbPCcsFfb0uj9rnbvuk4uw7FQd6TQ62gzDrKJph2gA07HO7TqoG52nbts6sAezs06nOudoa72OnoAXY529xDfBPABAFu7QMUDFUA8UdNEg6J2lQAfabgWdowhDu8LvAgUUcRAA6B4ZaxA64UcDsKo/upwAB79gBaGghR2JrVB6giQ4YFINAaHtuG8gC4a%2BGrhjHpSA/%2BwCf8BLhknsgGXhhAeJ7ceiCYJ6UBioEBH6e14Z/Gaez4YBGmezoAwG%2BgUEY56GRzUf6BXe6EZEwxMUgfBB2QdMkl6De4hFl6EQYkeome4TEcsxuRtgfxGOB7XuCG6JyMZjaqJikdqGS21wBpHxB%2BfrBG8JxPqZGPoQEFZG3ewEBQMu4R2BlHyJ7kc6BeR7QZt69ByMfknHYFwBWAjYQrH%2B8QcZwb5aNRsSeT7U%2BswdIBA%2Brlp0mzR2kG/wy%2BkUajHKWtweMm8BzwbT6ZPfFu4BRJ1yaUnSAVMJMAXAIAA%3D%3D
/* -*- Mode: C++; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
* Copyright (C) Flamewing 2011-2018 <flamewing.sonic@gmail.com>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIB_BIGENDIAN_IO_H
#define LIB_BIGENDIAN_IO_H
#include <algorithm>
#include <cstring>
#include <iterator>
#include <type_traits>
// Need to define manually for MSVC.
#if defined(_MSC_VER) || defined(_WIN32)
#ifndef __ORDER_BIG_ENDIAN__
#define __ORDER_BIG_ENDIAN__ 4321
#endif
#ifndef __ORDER_LITTLE_ENDIAN__
#define __ORDER_LITTLE_ENDIAN__ 1234
#endif
#ifndef __BYTE_ORDER__
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#endif
#endif
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define ENDIANIO_LITTLE_ENDIAN 1
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ENDIANIO_BIG_ENDIAN 1
#else
#error "Byte order is neither little endian nor big endian. Do not know how to proceed."
#endif
#if defined(__clang__) || defined(__GNUG__)
#define FORCE_INLINE __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
#define FORCE_INLINE __forceinline
#else
#define FORCE_INLINE inline
#endif
#ifdef __GNUG__
#define ATTR_CONST __attribute__((const))
#define ATTR_PURE __attribute__((pure))
#define CONSTEXPR constexpr
#else
#define ATTR_CONST
#define ATTR_PURE
#define CONSTEXPR
#endif
#ifdef __INTEL_COMPILER
#define assume(x) do {bool const valid = (x); __assume(valid);} while (false)
#elif defined(__GNUG__)
#define assume(x) if (!(x)) __builtin_unreachable()
#elif defined(_MSC_VER)
#define assume(x) __assume((x))
#else
#define assume(x)
#endif
#ifdef _LIBCPP_VERSION
namespace std {
using streamsize = ptrdiff_t;
}
#elif defined(_MSC_VER)
#include <stdlib.h>
#pragma intrinsic(_byteswap_ushort)
#pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64)
#elif defined(__INTEL_COMPILER)
#include <byteswap.h>
#endif
// Note: Opening namespace std and adding stuff is undefined behavior.
// This works with MSVC (MS-STL), g++ (libstdc++), clang (libc++),
// and icc (using any of these libraries).
// Doing this as a compatibility hack with C++17 and newer; when moving
// to a new standard, I can just remove portions of this.
//NOLINTNEXTLINE(cert-dcl58-cpp)
namespace std {
// MS-STL is nonconforming, and has all c++17 stuff available for
// pre-c++17 without any of the feature macros.
#if (defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)) && __cplusplus < 201703L
// _v traits (ported from C++17).
//NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define DEFINE_TRAIT_VARIABLE(trait) template <typename... T> constexpr bool trait ## _v = std::trait<T...>::value
DEFINE_TRAIT_VARIABLE(is_integral);
DEFINE_TRAIT_VARIABLE(is_pointer);
DEFINE_TRAIT_VARIABLE(is_same);
DEFINE_TRAIT_VARIABLE(is_signed);
DEFINE_TRAIT_VARIABLE(is_unsigned);
#undef DEFINE_TRAIT_VARIABLE
#if !defined(__cpp_lib_void_t) || __cpp_lib_void_t < 201411L
// void_t (ported from C++17).
// More complicated than needed due to CWG issue 1558.
namespace __detail {
template <typename... Ts>
struct make_void {
using type = void;
};
} // namespace __detail
template <typename... Ts>
using void_t = typename __detail::make_void<Ts...>::type;
#endif
// bool_constant (ported from C++17).
template <bool B>
using bool_constant = std::integral_constant<bool, B>;
// Negation (ported from C++17).
template <typename B>
struct negation : std::integral_constant<bool, !B::value> {};
template <typename B>
constexpr bool negation_v = negation<B>::value;
// Conjunction (ported from C++17).
template <typename...>
struct conjunction : std::true_type {};
template <typename B1>
struct conjunction<B1> : B1 {};
template <typename B1, typename... Bn>
struct conjunction<B1, Bn...> : std::conditional_t<B1::value, conjunction<Bn...>, B1> {};
template <typename... B>
constexpr bool conjunction_v = conjunction<B...>::value;
// Disjunction (ported from C++17).
template <typename...>
struct disjunction : std::false_type {};
template <typename B1>
struct disjunction<B1> : B1 {};
template <typename B1, typename... Bn>
struct disjunction<B1, Bn...> : std::conditional_t<B1::value, B1, disjunction<Bn...>> {};
template <typename... B>
constexpr bool disjunction_v = disjunction<B...>::value;
#endif
// Type identity (ported from C++20).
template <typename T>
struct type_identity {
using type = T;
};
template <typename T>
using type_identity_t = typename type_identity<T>::type;
// Utility to convert "fancy pointer" to pointer (ported from C++20).
template <typename T>
FORCE_INLINE ATTR_CONST constexpr auto to_address(T* in) noexcept {
return in;
}
template <typename Iter>
FORCE_INLINE ATTR_PURE constexpr auto to_address(Iter in) {
return to_address(in.operator->());
}
// assume_aligned (ported from C++20).
template <size_t N, typename T>
FORCE_INLINE ATTR_CONST constexpr auto assume_aligned(T* ptr) noexcept {
#if defined(__clang__) || defined(__GNUG__)
//NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
return static_cast<T*>(__builtin_assume_aligned(ptr, N));
#elif defined(_MSC_VER)
if ((reinterpret_cast<std::uintptr_t>(ptr) % N) == 0) {
return ptr;
} else {
assume(false);
return nullptr;
}
#else
return ptr;
#endif
}
// is_detected and related (ported from Library Fundamentals v2).
namespace __detail {
template <typename Default, typename AlwaysVoid, template <typename...> class Op, typename... Args>
struct detector {
using value_t = std::false_type;
using type = Default;
};
template <typename Default, template <typename...> class Op, typename... Args>
struct detector<Default, void_t<Op<Args...>>, Op, Args...> {
using value_t = std::true_type;
using type = Op<Args...>;
};
struct nonesuch final {
nonesuch(nonesuch const&) = delete;
nonesuch(nonesuch&&) = delete;
nonesuch() = delete;
~nonesuch() = delete;
auto operator=(nonesuch const&) -> nonesuch& = delete;
auto operator=(nonesuch&&) -> nonesuch& = delete;
};
} // namespace __detail
template <template <typename...> class Op, typename... Args>
using is_detected = typename __detail::detector<__detail::nonesuch, void, Op, Args...>::value_t;
template <template <typename...> class Op, typename... Args >
constexpr bool is_detected_v = is_detected<Op, Args...>::value;
template <template <typename...> class Op, typename... Args>
using detected_t = typename __detail::detector<__detail::nonesuch, void, Op, Args...>::type;
template <typename Default, template <typename...> class Op, typename... Args>
using detected_or = __detail::detector<Default, void, Op, Args...>;
template <typename Default, template <typename...> class Op, typename... Args >
using detected_or_t = typename __detail::detector<Default, void, Op, Args...>::type;
template <typename Expected, template <typename...> class Op, typename... Args>
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
template <typename Expected, template <typename...> class Op, typename... Args>
constexpr bool is_detected_exact_v = is_detected_exact<Expected, Op, Args...>::value;
template <typename To, template <typename...> class Op, typename... Args>
using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>;
template <typename To, template <typename...> class Op, typename... Args>
constexpr bool is_detected_convertible_v = is_detected_convertible<To, Op, Args...>::value;
} // namespace std
namespace detail {
// Meta-programming stuff.
// Utility for finding if a type appears in a list of types.
template <typename Value, typename...>
struct is_any_of : std::false_type {};
template <typename Value, typename B1, typename... Bn>
struct is_any_of<Value, B1, Bn...> : std::bool_constant<
std::is_same_v<Value, B1> || is_any_of<Value, Bn...>::value> {};
template <typename Value, typename... Bs>
constexpr bool is_any_of_v = is_any_of<Value, Bs...>::value;
// Concepts-like syntax. Based on code by Isabella Muerte.
template <bool... Bs>
constexpr bool require = std::conjunction_v<std::bool_constant<Bs>...>;
template <bool... Bs>
constexpr bool either = std::disjunction_v<std::bool_constant<Bs>...>;
template <bool... Bs>
constexpr bool disallow = std::negation_v<std::disjunction<std::bool_constant<Bs>...>>;
template <template <typename...> class Op, typename... Args>
constexpr bool exists = std::is_detected_v<Op, Args...>;
template <typename To, template <typename...> class Op, typename... Args>
constexpr bool converts_to = std::is_detected_convertible_v<To, Op, Args...>;
template <typename Exact, template <typename...> class Op, typename... Args>
constexpr bool identical_to = std::is_detected_exact_v<Exact, Op, Args...>;
namespace functions {
template <typename T>
using push_back = decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()));
template <typename T>
using size = decltype(std::declval<T>().size());
template <typename T>
using resize = decltype(std::declval<T>().resize(std::declval<typename T::size_type>()));
template <typename T>
using data = decltype(std::declval<T>().data());
template <typename T>
using sgetn = decltype(std::declval<T>().sgetn(std::declval<char*>(), std::declval<std::streamsize>()));
template <typename T>
using sputn = decltype(std::declval<T>().sputn(std::declval<char const*>(), std::declval<std::streamsize>()));
template <typename T>
using read = decltype(std::declval<T>().read(std::declval<char*>(), std::declval<std::streamsize>()));
template <typename T>
using write = decltype(std::declval<T>().write(std::declval<char const*>(), std::declval<std::streamsize>()));
template <typename T>
using begin = decltype(std::declval<T>().begin());
template <typename T>
using cbegin = decltype(std::declval<T>().cbegin());
template <typename T>
using end = decltype(std::declval<T>().end());
template <typename T>
using cend = decltype(std::declval<T>().cend());
template <typename T>
using empty = decltype(std::declval<T>().empty());
} // namespace functions
namespace aliases {
//NOLINTNEXTLINE(bugprone-macro-parentheses,cppcoreguidelines-macro-usage)
#define MPL_DEFINE_HAS_ALIAS(alias_name) template <typename T> using alias_name = typename T::alias_name;
MPL_DEFINE_HAS_ALIAS(char_type)
MPL_DEFINE_HAS_ALIAS(value_type)
MPL_DEFINE_HAS_ALIAS(iterator)
MPL_DEFINE_HAS_ALIAS(iterator_type)
MPL_DEFINE_HAS_ALIAS(const_iterator)
MPL_DEFINE_HAS_ALIAS(size_type)
MPL_DEFINE_HAS_ALIAS(difference_type)
MPL_DEFINE_HAS_ALIAS(reference)
MPL_DEFINE_HAS_ALIAS(const_reference)
MPL_DEFINE_HAS_ALIAS(iterator_category)
MPL_DEFINE_HAS_ALIAS(container_type)
MPL_DEFINE_HAS_ALIAS(pointer)
MPL_DEFINE_HAS_ALIAS(const_pointer)
MPL_DEFINE_HAS_ALIAS(streambuf_type)
MPL_DEFINE_HAS_ALIAS(istream_type)
MPL_DEFINE_HAS_ALIAS(ostream_type)
#undef MPL_DEFINE_HAS_ALIAS
} // namespace aliases
namespace traits {
template <typename T>
using iterator_traits = typename std::iterator_traits<T>;
} // namespace traits
namespace ops {
template <class T, class U>
using equal_to = decltype(std::declval<T>() == std::declval<U>());
template <class T, class U>
using not_equal = decltype(std::declval<T>() != std::declval<U>());
template <class T, class U>
using less = decltype(std::declval<T>() < std::declval<U>());
template <class T>
using dereference = decltype(*std::declval<T>());
template <class T>
using arrow = decltype(std::declval<T>().operator->());
template <class T>
using postfix_increment = decltype(std::declval<T>()++);
template <class T>
using prefix_increment = decltype(++std::declval<T>());
} // namespace ops
namespace adl {
using std::swap;
template <class T, class U=T>
using swap_with = decltype(swap(std::declval<T>(), std::declval<U>()));
} // namespace adl
namespace concepts {
template <class T>
constexpr bool DefaultConstructible = std::is_default_constructible<T>::value;
template <class T>
constexpr bool CopyConstructible = std::is_copy_constructible<T>::value;
template <class T>
constexpr bool CopyAssignable = std::is_copy_assignable<T>::value;
template <class T>
constexpr bool Destructible = std::is_destructible<T>::value;
template <class T, class U = T>
constexpr bool EqualityComparable = require<
converts_to<bool, ops::equal_to, T, U>,
converts_to<bool, ops::not_equal, T, U>
>;
template <class T, class U>
constexpr bool SwappableWith = exists<adl::swap_with, T, U>;
template <class T>
constexpr bool Swappable = SwappableWith<T&, T&>;
template <class T>
constexpr bool Pointer = std::is_pointer<T>::value;
template <typename T>
constexpr bool Container = require<
exists<aliases::value_type, T>,
exists<aliases::reference, T>,
exists<aliases::const_reference, T>,
exists<aliases::iterator, T>,
exists<aliases::const_iterator, T>,
exists<aliases::difference_type, T>,
exists<aliases::size_type, T>,
concepts::DefaultConstructible<T>,
concepts::CopyConstructible<T>,
concepts::CopyAssignable<T>,
concepts::Destructible<T>,
concepts::EqualityComparable<T>,
concepts::Swappable<T>,
exists<functions::size, T>,
exists<functions::empty, T>,
either<
identical_to<std::detected_t<aliases::iterator, T>, functions::begin, T>,
identical_to<std::detected_t<aliases::const_iterator, T>, functions::begin, T>
>,
either<
identical_to<std::detected_t<aliases::iterator, T>, functions::end, T>,
identical_to<std::detected_t<aliases::const_iterator, T>, functions::end, T>
>,
identical_to<std::detected_t<aliases::const_iterator, T>, functions::cbegin, T>,
identical_to<std::detected_t<aliases::const_iterator, T>, functions::cend, T>
>;
template <class T>
constexpr bool Iterator = require<
CopyConstructible<T>,
CopyAssignable<T>,
Destructible<T>,
Swappable<T>,
exists<ops::postfix_increment, T>,
exists<ops::prefix_increment, T>,
exists<ops::dereference, T>
>;
} // namespace concepts
template <template <typename...> class Op, typename... Args>
constexpr bool is_character_type_v = is_any_of_v<
std::remove_cv_t<std::detected_t<Op, Args...>>,
#if __cplusplus >= 201703L
std::byte,
#endif
char, unsigned char
>;
template <typename T>
struct is_pointer_like : std::bool_constant<
either<
require<
concepts::Pointer<T>,
is_character_type_v<aliases::value_type, std::detected_t<traits::iterator_traits, T>>
>,
require<
concepts::Iterator<T>,
either<
// For (back_|front_)?insert_iterator:
require<
converts_to<
std::output_iterator_tag,
aliases::iterator_category,
std::detected_t<traits::iterator_traits, T>
>,
is_character_type_v<aliases::value_type, std::detected_t<aliases::container_type, T>>
>,
// For all other iterators:
require<
converts_to<
std::forward_iterator_tag,
aliases::iterator_category,
std::detected_t<traits::iterator_traits, T>
>,
is_character_type_v<aliases::value_type, std::detected_t<traits::iterator_traits, T>>
>
>
>
>
> {};
template <typename T>
struct is_pointer_like<T&> : is_pointer_like<T> {};
template <typename T>
constexpr bool is_pointer_like_v = is_pointer_like<T>::value;
template <typename T>
struct is_contiguous_container : std::bool_constant<
require<
concepts::Container<T>,
exists<functions::resize, T>,
either<
identical_to<std::detected_t<functions::data, T>, aliases::pointer, T>,
identical_to<std::detected_t<functions::data, T>, aliases::const_pointer, T>
>,
is_character_type_v<aliases::value_type, T>
>
> {};
template <typename T>
struct is_contiguous_container<T&> : is_contiguous_container<T> {};
template <typename T>
struct is_push_back_container : std::bool_constant<
require<
concepts::Container<T>,
exists<functions::push_back, T>,
disallow<
exists<functions::data, T>
>,
is_character_type_v<aliases::value_type, T>
>
> {};
template <typename T>
struct is_push_back_container<T&> : is_push_back_container<T> {};
template <template <typename...> class Op, typename... Args>
struct pointer_or_char : std::type_identity<
std::conditional_t<
std::is_pointer_v<std::detected_t<Op, Args...>>,
std::detected_t<Op, Args...>,
char
>
> {};
template <template <typename...> class Op, typename... Args>
using pointer_or_char_t = typename pointer_or_char<Op, Args...>::type;
// Note: fails for stupid stuff like std::reverse_iterator<std::reverse_iterator<T>>.
// This failure is intentional.
template <typename T>
struct is_reverse_iterator : std::false_type {};
template <typename T>
struct is_reverse_iterator<std::reverse_iterator<T>> : std::true_type {};
template <typename T>
struct is_reverse_iterator<const T> : is_reverse_iterator<T> {};
template <typename T>
struct is_reverse_iterator<T&> : is_reverse_iterator<T> {};
template <typename T>
struct is_really_reverse_iterator : std::false_type {};
template <typename T>
struct is_really_reverse_iterator<std::reverse_iterator<T>> : std::bool_constant<
!is_really_reverse_iterator<T>::value
> {};
template <typename T>
struct is_really_reverse_iterator<std::move_iterator<T>> : std::bool_constant<
is_really_reverse_iterator<T>::value
> {};
template <typename T>
struct is_really_reverse_iterator<const T> : is_really_reverse_iterator<T> {};
template <typename T>
struct is_really_reverse_iterator<T&> : is_really_reverse_iterator<T> {};
// Probably unportable assumption: if the iterator is
// the size of a pointer, the only thing it can hold
// is a pointer. So it cannot be a deque iterator.
// This works with MSVC (MS-STL), g++ (libstdc++),
// clang (libc++), and icc (using any of these libraries).
template <typename Iter>
struct is_maybe_contiguous_iterator : std::bool_constant<
require<
converts_to<
std::random_access_iterator_tag,
aliases::iterator_category,
std::detected_t<traits::iterator_traits, Iter>
>,
disallow<
std::is_detected_exact_v<void, aliases::value_type, std::detected_t<traits::iterator_traits, Iter>>
>,
sizeof(Iter) == sizeof(pointer_or_char_t<aliases::pointer, std::detected_t<traits::iterator_traits, Iter>>)
>
> {};
template <typename T>
struct is_maybe_contiguous_iterator<const T> : is_maybe_contiguous_iterator<T> {};
template <typename T>
struct is_maybe_contiguous_iterator<T&> : is_maybe_contiguous_iterator<T> {};
template <typename Iter, bool>
struct is_contiguous_iterator_impl : std::bool_constant<
is_maybe_contiguous_iterator<Iter>::value
> {};
template <typename Iter>
struct is_contiguous_iterator_impl<Iter, true> : std::bool_constant<
is_contiguous_iterator_impl<
std::detected_t<
aliases::iterator_type,
Iter
>,
is_reverse_iterator<
std::detected_t<
aliases::iterator_type,
Iter
>
>::value
>::value
> {};
template <typename Iter>
struct is_contiguous_iterator : std::bool_constant<
is_contiguous_iterator_impl<Iter, is_reverse_iterator<Iter>::value>::value
> {};
template <typename T>
struct is_contiguous_iterator<const T> : is_contiguous_iterator<T> {};
template <typename T>
struct is_contiguous_iterator<T&> : is_contiguous_iterator<T> {};
// Robust SFINAE idiom by Jonathan Boccara
// https://www.fluentcpp.com/2019/08/23/how-to-make-sfinae-pretty-and-robust/
template <typename T>
using has_read_function_t = std::enable_if_t<exists<functions::read, T>, bool>;
template <typename T>
using has_sgetn_function_t = std::enable_if_t<exists<functions::sgetn, T>, bool>;
template <typename T>
using has_write_function_t = std::enable_if_t<exists<functions::write, T>, bool>;
template <typename T>
using has_sputn_function_t = std::enable_if_t<exists<functions::sputn, T>, bool>;
template <typename T>
using is_contiguous_container_t = std::enable_if_t<is_contiguous_container<T>::value, bool>;
template <typename T>
using is_push_back_container_t = std::enable_if_t<is_push_back_container<T>::value, bool>;
template <typename T>
using is_pointer_like_t = std::enable_if_t<is_pointer_like_v<T>, bool>;
template <typename T>
using is_unsigned_integer_t = std::enable_if_t<
require<
std::is_integral_v<T>,
std::is_unsigned_v<T>,
!std::is_same_v<T, bool>
>, bool>;
template <typename T>
using is_signed_integer_t = std::enable_if_t<
require<
std::is_integral_v<T>,
std::is_signed_v<T>
>, bool>;
// base case: just fail
template <size_t Size, typename... >
struct select_unsigned;
// recursive case: check using numeric_limits
template <size_t Size, typename T, typename... Ts>
struct select_unsigned<Size, T, Ts...> : std::conditional_t<
Size == sizeof(T), std::type_identity<T>, select_unsigned<Size, Ts...>> {};
template <uint64_t Size>
using select_unsigned_t = typename select_unsigned<Size, uint8_t, uint16_t, uint32_t, uint64_t>::type;
template <typename T, typename Iter>
FORCE_INLINE ATTR_PURE constexpr auto to_aligned_address(Iter it) {
return std::assume_aligned<sizeof(T)>(std::to_address(it));
}
template <typename T, typename Iter>
FORCE_INLINE ATTR_PURE constexpr auto to_unaligned_address(Iter it) {
#if defined(__GNUG__) || !defined(_MSC_VER)
return std::to_address(it);
#else
_unaligned auto ptr{std::to_address(it)};
return ptr;
#endif
}
FORCE_INLINE ATTR_CONST CONSTEXPR auto bswap(uint8_t val) noexcept -> uint8_t {
return val;
}
FORCE_INLINE ATTR_CONST CONSTEXPR auto bswap(uint16_t val) noexcept -> uint16_t {
#if defined(__GNUG__)
#ifdef __INTEL_COMPILER
if (__builtin_constant_p(val)) {
return __bswap_constant_16(val);
}
#endif
return __builtin_bswap16(val);
#elif defined(_MSC_VER)
return _byteswap_ushort(val);
#else
return ((val & 0xffu) << 8) | ((val >> 8) & 0xffu);
#endif
}
FORCE_INLINE ATTR_CONST CONSTEXPR auto bswap(uint32_t val) noexcept -> uint32_t {
#if defined(__GNUG__)
#ifdef __INTEL_COMPILER
if (__builtin_constant_p(val)) {
return __bswap_constant_32(val);
}
#endif
return __builtin_bswap32(val);
#elif defined(_MSC_VER)
return _byteswap_ulong(val);
#else
val = ((val & 0xffffu) << 16) | ((val >> 16) & 0xffffu);
return ((val & 0xff00ffu) << 8) | ((val >> 8) & 0xff00ffu);
#endif
}
FORCE_INLINE ATTR_CONST CONSTEXPR auto bswap(uint64_t val) noexcept -> uint64_t {
#if defined(__GNUG__)
#ifdef __INTEL_COMPILER
if (__builtin_constant_p(val)) {
return __bswap_constant_64(val);
}
#endif
return __builtin_bswap64(val);
#elif defined(_MSC_VER)
return _byteswap_uint64(val);
#else
val = ((val & 0xffffffffull) << 32) | ((val >> 32) & 0xffffffffull);
val = ((val & 0xffff0000ffffull) << 16) | ((val >> 16) & 0xffff0000ffffull);
return ((val & 0xff00ff00ff00ffull) << 8) | ((val >> 8) & 0xff00ff00ff00ffull);
#endif
}
namespace impl {
template <typename T>
struct ByteIdentity {
FORCE_INLINE ATTR_CONST static constexpr auto Get(T val) noexcept -> T {
return val;
}
};
template <typename T>
struct ByteReverse {
FORCE_INLINE ATTR_CONST static constexpr auto Get(T val) noexcept -> T {
return bswap(val);
}
};
template <bool bigendian, typename T>
class DoEndianByteIO {
FORCE_INLINE ATTR_CONST static constexpr auto calcShift(size_t N) -> size_t {
if (bigendian) {
return (sizeof(T) - 1 - N) * 8;
}
return (N * 8);
}
#if __cplusplus < 201703L
using expander = int[];
#endif
public:
template <typename Iter, size_t... Is>
FORCE_INLINE static constexpr auto Read(Iter in, std::index_sequence<Is...> /*seq*/) {
T val{};
auto getByte = [&](size_t shift) {
auto cc = static_cast<T>(*in) << shift;
++in;
val |= cc;
};
#if __cplusplus >= 201703L
static_cast<void>((getByte(calcShift(Is)), ...));
#else
static_cast<void>(expander{(getByte(calcShift(Is)), 0)...});
#endif
return std::make_pair(in, val);
}
template <typename Iter, size_t... Is>
FORCE_INLINE static constexpr auto Write(Iter out, T val, std::index_sequence<Is...> /*seq*/) {
using uint = std::conditional_t<
exists<aliases::value_type, std::detected_t<aliases::container_type, Iter>>,
std::detected_t<aliases::value_type, std::detected_t<aliases::container_type, Iter>>,
std::detected_or_t<char, aliases::value_type, std::detected_t<traits::iterator_traits, Iter>>>;
auto putByte = [&](size_t shift) {
*out = static_cast<uint>(val >> shift);
++out;
};
#if __cplusplus >= 201703L
static_cast<void>((putByte(calcShift(Is)), ...));
#else
static_cast<void>(expander{(putByte(calcShift(Is)), 0)...});
#endif
return out;
}
};
} // namespace impl
template <typename T>
using BigEndianByteIO = impl::DoEndianByteIO<true, T>;
template <typename T>
using LittleEndianByteIO = impl::DoEndianByteIO<false, T>;
template <template <typename> class Convert,
template <typename> class Preserve,
template <typename> class ByteIO>
struct EndianHandlerBase {
template <typename T>
FORCE_INLINE ATTR_CONST constexpr auto convert(T val) const noexcept -> T {
return Convert<T>::Get(val);
}
template <typename T>
FORCE_INLINE ATTR_CONST constexpr auto keep(T val) const noexcept -> T {
return Preserve<T>::Get(val);
}
template <typename T, typename Iter>
FORCE_INLINE constexpr auto read(Iter&& in) const -> T {
auto ret = ByteIO<T>::Read(std::forward<Iter>(in), std::make_index_sequence<sizeof(T)>());
in = ret.first;
return ret.second;
}
template <typename T, typename Iter>
FORCE_INLINE constexpr void write(Iter&& out, T val) const {
out = ByteIO<T>::Write(std::forward<Iter>(out), val, std::make_index_sequence<sizeof(T)>());
}
};
#ifdef ENDIANIO_LITTLE_ENDIAN
using EndianIdentity = EndianHandlerBase<impl::ByteIdentity, impl::ByteReverse , LittleEndianByteIO>;
using EndianReverse = EndianHandlerBase<impl::ByteReverse , impl::ByteIdentity, BigEndianByteIO >;
#elif defined(ENDIANIO_BIG_ENDIAN)
using EndianIdentity = EndianHandlerBase<impl::ByteIdentity, impl::ByteReverse , BigEndianByteIO >;
using EndianReverse = EndianHandlerBase<impl::ByteReverse , impl::ByteIdentity, LittleEndianByteIO>;
#endif
struct EndianBaseImpl {
private:
// GCC and clang generate optimal code with the other version.
// Need this version for MSVC and ICC.
template <typename T, typename EndianHandler, typename Iter>
FORCE_INLINE static auto ReadInternal(Iter&& in, EndianHandler endian, std::true_type /*tag*/) -> T {
auto ptr{to_unaligned_address<T>(in)};
if (is_really_reverse_iterator<Iter>::value) {
std::advance(ptr, -ptrdiff_t(sizeof(T)-1));
}
T val;
std::memcpy(&val, ptr, sizeof(T));
if (is_really_reverse_iterator<Iter>::value) {
val = endian.keep(val);
} else {
val = endian.convert(val);
}
std::advance(in, sizeof(T));
return val;
}
template <typename T, typename EndianHandler, typename Iter>
FORCE_INLINE static auto ReadInternal(Iter&& in, EndianHandler endian, std::false_type /*tag*/) -> T {
return endian.template read<T>(std::forward<Iter>(in));
}
// GCC generates optimal code with the other version.
// Need this version for clang, MSVC, and ICC.
template <typename T, typename EndianHandler, typename Iter>
FORCE_INLINE static void WriteInternal(Iter&& out, EndianHandler endian, T val, std::true_type /*tag*/) {
auto ptr{to_unaligned_address<T>(out)};
if (is_really_reverse_iterator<Iter>::value) {
std::advance(ptr, -ptrdiff_t(sizeof(T)-1));
val = endian.keep(val);
} else {
val = endian.convert(val);
}
std::memcpy(ptr, &val, sizeof(T));
std::advance(out, sizeof(T));
}
template <typename T, typename EndianHandler, typename Iter>
FORCE_INLINE static void WriteInternal(Iter&& out, EndianHandler endian, T val, std::false_type /*tag*/) {
endian.write(std::forward<Iter>(out), val);
}
public:
template <typename T, typename EndianHandler, typename Stream, has_read_function_t<Stream> = true>
FORCE_INLINE static auto Read(Stream& in, EndianHandler endian) {
alignas(alignof(T)) typename Stream::char_type buffer[sizeof(T)];
in.read(std::begin(buffer), sizeof(T));
return Read<T>(std::begin(buffer), endian);
}
template <typename T, typename EndianHandler, typename Buf, has_sgetn_function_t<Buf> = true>
FORCE_INLINE static auto Read(Buf& in, EndianHandler endian) {
alignas(alignof(T)) typename Buf::char_type buffer[sizeof(T)];
in.sgetn(std::begin(buffer), sizeof(T));
return Read<T>(std::begin(buffer), endian);
}
template <typename T, typename EndianHandler, typename Iter, is_pointer_like_t<Iter> = true>
FORCE_INLINE static auto Read(Iter&& in, EndianHandler endian) {
return ReadInternal<T>(std::forward<Iter>(in), endian, is_contiguous_iterator<Iter>());
}
template <typename T, typename EndianHandler, typename Stream, has_write_function_t<Stream> = true>
FORCE_INLINE static auto Write(Stream& out, EndianHandler endian, T val) {
alignas(alignof(T)) typename Stream::char_type buffer[sizeof(T)];
Write(std::begin(buffer), endian, val);
out.write(std::cbegin(buffer), sizeof(T));
}
template <typename T, typename EndianHandler, typename Buf, has_sputn_function_t<Buf> = true>
FORCE_INLINE static auto Write(Buf& out, EndianHandler endian, T val) {
alignas(alignof(T)) typename Buf::char_type buffer[sizeof(T)];
Write(std::begin(buffer), endian, val);
out.sputn(std::cbegin(buffer), sizeof(T));
}
template <typename T, typename EndianHandler, typename Cont, is_contiguous_container_t<Cont> = true>
FORCE_INLINE static auto Write(Cont& out, EndianHandler endian, T val) {
auto sz = out.size();
out.resize(sz + sizeof(T));
Write(std::addressof(out[sz]), endian, val);
}
template <typename T, typename EndianHandler, typename Cont, is_push_back_container_t<Cont> = true>
FORCE_INLINE static auto Write(Cont& out, EndianHandler endian, T val) {
Write(std::back_inserter(out), endian, val);
}
template <typename T, typename EndianHandler, typename Iter, is_pointer_like_t<Iter> = true>
FORCE_INLINE static auto Write(Iter&& out, EndianHandler endian, T val) {
WriteInternal(std::forward<Iter>(out), endian, val, is_contiguous_iterator<Iter>());
}
};
#undef assume
template <size_t Size>
using uintN_t = select_unsigned_t<Size>;
template <typename EndianHandler>
struct EndianBase {
template <typename Src>
FORCE_INLINE static auto Read1(Src&& in) -> uint8_t {
return EndianBaseImpl::Read<uint8_t>(std::forward<Src>(in), EndianHandler{});
}
template <typename Src>
FORCE_INLINE static auto Read2(Src&& in) -> uint16_t {
return EndianBaseImpl::Read<uint16_t>(std::forward<Src>(in), EndianHandler{});
}
template <typename Src>
FORCE_INLINE static auto Read4(Src&& in) -> uint32_t {
return EndianBaseImpl::Read<uint32_t>(std::forward<Src>(in), EndianHandler{});
}
template <typename Src>
FORCE_INLINE static auto Read8(Src&& in) -> uint64_t {
return EndianBaseImpl::Read<uint64_t>(std::forward<Src>(in), EndianHandler{});
}
template <size_t Size, typename Src>
FORCE_INLINE static auto ReadN(Src&& in) -> uintN_t<Size> {
return EndianBaseImpl::Read<uintN_t<Size>>(std::forward<Src>(in), EndianHandler{});
}
template <typename T, typename Src, is_unsigned_integer_t<T> = true>
FORCE_INLINE static auto Read(Src&& in) {
return EndianBaseImpl::Read<T>(std::forward<Src>(in), EndianHandler{});
}
template <typename T, typename Src, is_signed_integer_t<T> = true>
FORCE_INLINE static auto Read(Src&& in) {
using uint_t = typename std::make_unsigned<T>::type;
uint_t valu = EndianBaseImpl::Read<uint_t>(std::forward<Src>(in), EndianHandler{});
T val;
std::memcpy(&val, &valu, sizeof(T));
return val;
}
template <typename Dst>
FORCE_INLINE static void Write1(Dst&& out, uint8_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write1(Dst&& out, int8_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write2(Dst&& out, uint16_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write2(Dst&& out, int16_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write4(Dst&& out, uint32_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write4(Dst&& out, int32_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write8(Dst&& out, uint64_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename Dst>
FORCE_INLINE static void Write8(Dst&& out, int64_t val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <size_t Size, typename Dst>
FORCE_INLINE static void WriteN(Dst&& out, uintN_t<Size> val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename T, typename Dst, is_unsigned_integer_t<T> = true>
FORCE_INLINE static auto Write(Dst&& out, T val) {
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, val);
}
template <typename T, typename Dst, is_signed_integer_t<T> = true>
FORCE_INLINE static auto Write(Dst&& out, T val) {
using uint_t = typename std::make_unsigned<T>::type;
uint_t valu;
std::memcpy(&valu, &val, sizeof(T));
EndianBaseImpl::Write(std::forward<Dst>(out), EndianHandler{}, valu);
}
};
} // namespace detail
template <typename Src>
FORCE_INLINE auto Read1(Src&& in) -> size_t {
return detail::EndianBaseImpl::template Read<uint8_t>(std::forward<Src>(in), detail::EndianIdentity{});
}
template <typename Dst>
FORCE_INLINE void Write1(Dst&& out, size_t const val) {
detail::EndianBaseImpl::Write(std::forward<Dst>(out), detail::EndianIdentity{}, uint8_t(val));
}
#ifdef ENDIANIO_LITTLE_ENDIAN
using BigEndian = detail::EndianBase<detail::EndianReverse>;
using LittleEndian = detail::EndianBase<detail::EndianIdentity>;
#elif defined(ENDIANIO_BIG_ENDIAN)
using BigEndian = detail::EndianBase<detail::EndianIdentity>;
using LittleEndian = detail::EndianBase<detail::EndianReverse>;
#endif
#endif
#include <vector>
#include <deque>
#include <list>
#include <string>
#include <sstream>
#include <fstream>
//NOLINTNEXTLINE(google-build-using-namespace,google-global-names-in-headers)
using namespace std;
namespace DoBigEndian {
using uint_t = uint32_t;
using Endian = BigEndian;
auto testR1(const uint8_t*& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(vector<uint8_t>::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(deque<uint8_t>::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(list<uint8_t>::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(string::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(const uint8_t* cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(vector<uint8_t>::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(deque<uint8_t>::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(list<uint8_t>::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(string::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(std::reverse_iterator<const uint8_t*>& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(vector<uint8_t>::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(deque<uint8_t>::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(list<uint8_t>::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(string::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(ifstream& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(istringstream& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(filebuf& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(stringbuf& cc) {
return Endian::Read<uint_t>(cc);
}
auto testW1(uint8_t*& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(vector<uint8_t>::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(deque<uint8_t>::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(list<uint8_t>::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(string::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(uint8_t* cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(vector<uint8_t>::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(deque<uint8_t>::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(list<uint8_t>::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(string::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(std::reverse_iterator<uint8_t*>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(vector<uint8_t>::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(deque<uint8_t>::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(list<uint8_t>::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(string::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(vector<uint8_t>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(deque<uint8_t>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(list<uint8_t>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(string& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(ofstream& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(ostringstream& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(filebuf& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(stringbuf& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW5(vector<uint8_t>& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
auto testW5(deque<uint8_t>& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
auto testW5(list<uint8_t>& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
auto testW5(string& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
} // namespace DoBigEndian
namespace DoLittleEndian {
using uint_t = uint32_t;
using Endian = LittleEndian;
auto testR1(const uint8_t*& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(vector<uint8_t>::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(deque<uint8_t>::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(list<uint8_t>::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR1(string::const_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(const uint8_t* cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(vector<uint8_t>::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(deque<uint8_t>::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(list<uint8_t>::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
ATTR_PURE auto testR2(string::const_iterator cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(std::reverse_iterator<const uint8_t*>& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(vector<uint8_t>::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(deque<uint8_t>::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(list<uint8_t>::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR3(string::const_reverse_iterator& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(ifstream& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(istringstream& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(filebuf& cc) {
return Endian::Read<uint_t>(cc);
}
auto testR4(stringbuf& cc) {
return Endian::Read<uint_t>(cc);
}
auto testW1(uint8_t*& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(vector<uint8_t>::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(deque<uint8_t>::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(list<uint8_t>::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW1(string::iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(uint8_t* cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(vector<uint8_t>::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(deque<uint8_t>::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(list<uint8_t>::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW2(string::iterator cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(std::reverse_iterator<uint8_t*>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(vector<uint8_t>::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(deque<uint8_t>::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(list<uint8_t>::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW3(string::reverse_iterator& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(vector<uint8_t>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(deque<uint8_t>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(list<uint8_t>& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(string& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(ofstream& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(ostringstream& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(filebuf& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW4(stringbuf& cc, uint_t vv) {
Endian::Write(cc, vv);
}
auto testW5(vector<uint8_t>& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
auto testW5(deque<uint8_t>& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
auto testW5(list<uint8_t>& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
auto testW5(string& cc, uint_t vv) {
auto it = back_inserter(cc);
Endian::Write(it, vv);
}
} // namespace DoLittleEndian
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment