Compare commits
183 Commits
BodgeMaste
...
master
Author | SHA1 | Date |
---|---|---|
BodgeMaster | 53173dd7c7 | |
BodgeMaster | 8482194b01 | |
BodgeMaster | 229392a7fe | |
BodgeMaster | a48c4dcd33 | |
BodgeMaster | a787a89493 | |
BodgeMaster | b9006cc6ea | |
BodgeMaster | eb8db35615 | |
BodgeMaster | 9dd4489141 | |
BodgeMaster | d1c855857c | |
BodgeMaster | 8f8d51f459 | |
BodgeMaster | 8b13f72acc | |
Joca | 6ef1d401bb | |
Joca | 1bcc5eae64 | |
BodgeMaster | 97b844c6d1 | |
BodgeMaster | 20857cb8c5 | |
BodgeMaster | abc5491192 | |
BodgeMaster | ad54f0a012 | |
BodgeMaster | ae71322ba1 | |
BodgeMaster | 01e5f5eaac | |
BodgeMaster | 6112da2e6f | |
BodgeMaster | b07d6e2ff6 | |
BodgeMaster | 4247bd295a | |
BodgeMaster | 4c651d1b6f | |
BodgeMaster | e152c72a04 | |
BodgeMaster | 5d80ca801e | |
BodgeMaster | c245e8a5ca | |
BodgeMaster | 10d8cdae22 | |
BodgeMaster | b08a86f0b8 | |
BodgeMaster | c6ec0f6850 | |
BodgeMaster | 85fc73e015 | |
BodgeMaster | d2861b79ac | |
BodgeMaster | 9403da4ca0 | |
BodgeMaster | ad5bf1c41a | |
BodgeMaster | 7108e71b96 | |
Shwoomple | 26df433dc5 | |
BodgeMaster | 44716a55bb | |
BodgeMaster | fe7c763d06 | |
BodgeMaster | d392e080ca | |
BodgeMaster | 60a8ac9788 | |
Shwoomple | bc2255de6b | |
Shwoomple | e627714b44 | |
Shwoomple | 42b7e40f9d | |
Shwoomple | 9bda607649 | |
Shwoomple | 76dd30c45a | |
BodgeMaster | 78880e1c20 | |
BodgeMaster | 1d899db889 | |
BodgeMaster | 3cc91ae33d | |
Shwoomple | 63e1749ad1 | |
Shwoomple | ea8e806366 | |
BodgeMaster | 18a9517370 | |
BodgeMaster | cd93f4c4c6 | |
Shwoomple | f784948c3e | |
Shwoomple | d794bce288 | |
BodgeMaster | 99c8f562d6 | |
BodgeMaster | 57a86cba47 | |
BodgeMaster | 5ff8a871ad | |
BodgeMaster | e0994e5db8 | |
BodgeMaster | 80c8a46ab2 | |
BodgeMaster | 4abb1f223c | |
BodgeMaster | 4da50d3c6b | |
BodgeMaster | c9b56d4d7f | |
BodgeMaster | 7bccaca7b9 | |
BodgeMaster | f6b965040d | |
BodgeMaster | b5c18cd0de | |
BodgeMaster | a1ba08b7db | |
BodgeMaster | 1d7e98d0b3 | |
BodgeMaster | a7e07d2c3c | |
BodgeMaster | 7ae843039c | |
BodgeMaster | 5574cdb4bf | |
BodgeMaster | 89cfb9d850 | |
BodgeMaster | f681c54c82 | |
BodgeMaster | ee0ebb273c | |
Shwoomple | 8dea1f2d31 | |
Shwoomple | c825c73afd | |
Shwoomple | e7711a3d59 | |
Shwoomple | e7ce6f5cd4 | |
BodgeMaster | ee9b5d4f67 | |
BodgeMaster | b84130344d | |
BodgeMaster | 25d7806f6d | |
Shwoomple | 6e57a86338 | |
Shwoomple | c54eb48887 | |
BodgeMaster | c14504ce0b | |
BodgeMaster | 92cf81c1b4 | |
BodgeMaster | df35243ee9 | |
BodgeMaster | 36dcf0a0f5 | |
BodgeMaster | 93fdcb7b65 | |
BodgeMaster | 8d2f3f2fa5 | |
BodgeMaster | cdc23e7468 | |
BodgeMaster | e9bfb6eeee | |
BodgeMaster | 8b62ec9c88 | |
BodgeMaster | ca0af3306f | |
BodgeMaster | 9b21dfaee5 | |
BodgeMaster | 996154fbbc | |
BodgeMaster | 77dd79398f | |
BodgeMaster | fd5fe3967f | |
BodgeMaster | 374466f26c | |
BodgeMaster | 3b56a52085 | |
BodgeMaster | 7be73f86d4 | |
BodgeMaster | 71834e1018 | |
BodgeMaster | ccce564219 | |
BodgeMaster | 53279c6905 | |
BodgeMaster | f8dd10d301 | |
BodgeMaster | 6672a4f149 | |
BodgeMaster | d5ce50a4a9 | |
BodgeMaster | f0092b78d3 | |
BodgeMaster | b1ba33b39f | |
BodgeMaster | 833c09e2da | |
BodgeMaster | b53999a548 | |
BodgeMaster | 379903d751 | |
BodgeMaster | 17792ec5bf | |
BodgeMaster | 9ce35b5c6b | |
BodgeMaster | be08a97275 | |
BodgeMaster | 6bdf99c897 | |
BodgeMaster | 936def1a65 | |
BodgeMaster | 3cc1222de9 | |
BodgeMaster | ecf3b14b5a | |
BodgeMaster | 8da758becd | |
BodgeMaster | 1e5051b503 | |
BodgeMaster | 3b4c125ca2 | |
BodgeMaster | 4cb1206839 | |
BodgeMaster | 39c5940200 | |
BodgeMaster | f3e03710f6 | |
BodgeMaster | 72fc923839 | |
BodgeMaster | 5059bd0193 | |
BodgeMaster | 8bb633f118 | |
BodgeMaster | ec44ac9531 | |
BodgeMaster | 341b4c187e | |
BodgeMaster | 79650e390e | |
BodgeMaster | 2d2b67373c | |
BodgeMaster | 4c4366f7e6 | |
BodgeMaster | 4ef1d2c44f | |
Shwoomple | 5920d1d004 | |
Shwoomple | 056c1e6b11 | |
BodgeMaster | 8b1491c311 | |
BodgeMaster | fc2caf3bc0 | |
BodgeMaster | 89baeebc65 | |
Shwoomple | c204aa7d76 | |
BodgeMaster | 09503d3dc7 | |
BodgeMaster | 9fb06c998e | |
BodgeMaster | aa97154474 | |
BodgeMaster | 9abfd9e5a9 | |
Shwoomple | 150ce826ba | |
Shwoomple | 3449e3b9c4 | |
Charlie Root | 213d28a9b8 | |
Shwoomple | c1d7801436 | |
Shwoomple | 9610f4a4a2 | |
BodgeMaster | 434c976cc5 | |
BodgeMaster | 47fd1f8970 | |
BodgeMaster | 10b1d9fa0c | |
Shwoomple | e8d41efeef | |
Shwoomple | 508b5e67e7 | |
BodgeMaster | 398321e415 | |
BodgeMaster | 53878c3e2b | |
BodgeMaster | ad291ee77d | |
BodgeMaster | 6149418f52 | |
BodgeMaster | ac12bcf865 | |
BodgeMaster | 8b92d24ab9 | |
BodgeMaster | aab91a2523 | |
BodgeMaster | 58b1199e38 | |
Shwoomple | 48f8a7dcf2 | |
BodgeMaster | 209d0828b4 | |
BodgeMaster | b4d4ce77b2 | |
BodgeMaster | ee5048331c | |
BodgeMaster | 629c999336 | |
BodgeMaster | cdd17045d1 | |
BodgeMaster | bb40f6553e | |
BodgeMaster | a9759e3bc2 | |
BodgeMaster | ab1164557d | |
BodgeMaster | 1b8819ffe5 | |
BodgeMaster | 4934a78aaa | |
BodgeMaster | 327ad9a9b5 | |
BodgeMaster | bddab2e9f8 | |
BodgeMaster | 017c8a61f8 | |
BodgeMaster | 5272636cb8 | |
BodgeMaster | 91d16ea451 | |
BodgeMaster | a1fc0ce4b4 | |
Shwoomple | ca7b121c4d | |
BodgeMaster | 25bec4c587 | |
BodgeMaster | 589cf1ddaf | |
BodgeMaster | 884a5239c6 | |
BodgeMaster | 9190cad80d | |
BodgeMaster | a862590370 | |
BodgeMaster | 3995e97f03 |
|
@ -14,12 +14,20 @@
|
|||
# ignore endianness check
|
||||
/.endianness
|
||||
/resources/check_endianness
|
||||
/resources/check_endianness.exe
|
||||
|
||||
# Java bytecode
|
||||
*.class
|
||||
# Maven's build files
|
||||
/resources/java/netty-tests/target/
|
||||
|
||||
# ignore nano's temp files
|
||||
*.swp
|
||||
|
||||
# Ignore sublime text project files.
|
||||
*.sublime-*
|
||||
|
||||
#vscode
|
||||
.vscode
|
||||
|
||||
writeTest
|
||||
|
|
12
Makefile
12
Makefile
|
@ -1,12 +0,0 @@
|
|||
all: build
|
||||
build:
|
||||
bash ./scripts/build.sh
|
||||
clean:
|
||||
bash ./scripts/clean.sh
|
||||
mrproper:
|
||||
bash ./scripts/clean.sh
|
||||
bash ./scripts/clean_dependencies.sh
|
||||
setup:
|
||||
bash ./scripts/setup_project.sh
|
||||
test:
|
||||
bash ./scripts/test.sh
|
|
@ -14,8 +14,8 @@ Immediate goals:
|
|||
- [ ] send a surface to stand on
|
||||
- [ ] handle chat
|
||||
- NBT library
|
||||
- [ ] parse NBT
|
||||
- [ ] decode and encode data
|
||||
- [x] parse NBT
|
||||
- [x] decode and encode data
|
||||
|
||||
|
||||
## Project Setup Instructions
|
||||
|
@ -26,6 +26,7 @@ Build dependencies:
|
|||
|
||||
- bash
|
||||
- a C++ 20 compiler
|
||||
- GLFW with headers
|
||||
|
||||
Setup dependencies:
|
||||
|
||||
|
|
|
@ -22,10 +22,8 @@ each file.
|
|||
Don't use excessive comments, use descriptive names instead.
|
||||
There is no such thing as too long names (within reason, of course).
|
||||
|
||||
Don't have comments that go beyond 80 characters per line, preferably
|
||||
slightly less.
|
||||
|
||||
Put comments on their own lines.
|
||||
Format comments to improve readability, don't have long single-line comments.
|
||||
|
||||
Indent by four spaces.
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
Copyright <year>, FOSS-VG Developers and Contributers
|
||||
|
||||
Author(s):
|
||||
<names or pseudonyms here>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, version 3.
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,122 @@
|
|||
[0: Compound]:
|
||||
|–Header: 3 bytes
|
||||
|–Payload: 232 bytes
|
||||
|–Total: 235 bytes
|
||||
|–Length: 4
|
||||
|
|
||||
|–[3: List] int8 arrays:
|
||||
| |–Header: 14 bytes
|
||||
| |–Payload: 29 bytes
|
||||
| |–Total: 43 bytes
|
||||
| |–Contained Type: Array of 8 Bit Integers
|
||||
| |–Length: 3
|
||||
| |
|
||||
| |–[22: Array of 8 Bit Integers]:
|
||||
| | |–Payload: 8 bytes
|
||||
| | |–Total: 8 bytes
|
||||
| | |–Length: 4
|
||||
| | '–Values:
|
||||
| | |–13
|
||||
| | |–37
|
||||
| | |–52
|
||||
| | '–81
|
||||
| |
|
||||
| |–[30: Array of 8 Bit Integers]:
|
||||
| | |–Payload: 8 bytes
|
||||
| | |–Total: 8 bytes
|
||||
| | |–Length: 4
|
||||
| | '–Values:
|
||||
| | |–80
|
||||
| | |–0
|
||||
| | |–81
|
||||
| | '–35
|
||||
| |
|
||||
| '–[38: Array of 8 Bit Integers]:
|
||||
| |–Payload: 8 bytes
|
||||
| |–Total: 8 bytes
|
||||
| |–Length: 4
|
||||
| '–Values:
|
||||
| |–0
|
||||
| |–0
|
||||
| |–34
|
||||
| '–-65
|
||||
|
|
||||
|
|
||||
|–[46: List] int32 arrays:
|
||||
| |–Header: 15 bytes
|
||||
| |–Payload: 97 bytes
|
||||
| |–Total: 112 bytes
|
||||
| |–Contained Type: Array of 32 Bit Integers
|
||||
| |–Length: 3
|
||||
| |
|
||||
| |–[66: Array of 32 Bit Integers]:
|
||||
| | |–Payload: 16 bytes
|
||||
| | |–Total: 16 bytes
|
||||
| | |–Length: 3
|
||||
| | '–Values:
|
||||
| | |–13859
|
||||
| | |–7677676
|
||||
| | '–1337
|
||||
| |
|
||||
| |–[82: Array of 32 Bit Integers]:
|
||||
| | |–Payload: 68 bytes
|
||||
| | |–Total: 68 bytes
|
||||
| | |–Length: 16
|
||||
| | '–Values:
|
||||
| | |–1
|
||||
| | |–2
|
||||
| | |–4
|
||||
| | |–8
|
||||
| | |–16
|
||||
| | |–32
|
||||
| | |–64
|
||||
| | |–128
|
||||
| | |–256
|
||||
| | |–512
|
||||
| | |–1024
|
||||
| | |–2048
|
||||
| | |–4096
|
||||
| | |–8192
|
||||
| | |–16384
|
||||
| | '–32768
|
||||
| |
|
||||
| '–[150: Array of 32 Bit Integers]:
|
||||
| |–Payload: 8 bytes
|
||||
| |–Total: 8 bytes
|
||||
| |–Length: 1
|
||||
| '–Values:
|
||||
| '–-100000
|
||||
|
|
||||
|
|
||||
|–[158: List] int64 arrays:
|
||||
| |–Header: 15 bytes
|
||||
| |–Payload: 61 bytes
|
||||
| |–Total: 76 bytes
|
||||
| |–Contained Type: Array of 64 Bit Integers
|
||||
| |–Length: 2
|
||||
| |
|
||||
| |–[178: Array of 64 Bit Integers]:
|
||||
| | |–Payload: 28 bytes
|
||||
| | |–Total: 28 bytes
|
||||
| | |–Length: 3
|
||||
| | '–Values:
|
||||
| | |–9999999998
|
||||
| | |–0
|
||||
| | '–77777666666666
|
||||
| |
|
||||
| '–[206: Array of 64 Bit Integers]:
|
||||
| |–Payload: 28 bytes
|
||||
| |–Total: 28 bytes
|
||||
| |–Length: 3
|
||||
| '–Values:
|
||||
| |–-2141414141414141
|
||||
| |–7680
|
||||
| '–900
|
||||
|
|
||||
|
|
||||
'–[234: End]:
|
||||
|–Header: 1 byte
|
||||
|–Payload: 0 bytes
|
||||
'–Total: 1 byte
|
||||
|
||||
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
[0: 64 Bit Integer] test:
|
||||
|–Header: 7 bytes
|
||||
|–Payload: 8 bytes
|
||||
|–Total: 15 bytes
|
||||
'–Value: 9223372036854775807
|
||||
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
|||
[0: 64 Bit Integer] test:
|
||||
|–Header: 7 bytes
|
||||
|–Payload: 8 bytes
|
||||
|–Total: 15 bytes
|
||||
'–Value: 9223372036854775807
|
||||
|
||||
[15: 32 Bit Integer] int32:
|
||||
|–Header: 8 bytes
|
||||
|–Payload: 4 bytes
|
||||
|–Total: 12 bytes
|
||||
'–Value: 1866009202
|
||||
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,592 @@
|
|||
[0: Compound]:
|
||||
|–Header: 3 bytes
|
||||
|–Payload: 792 bytes
|
||||
|–Total: 795 bytes
|
||||
|–Length: 3
|
||||
|
|
||||
|–[3: List] 60:
|
||||
| |–Header: 5 bytes
|
||||
| |–Payload: 222 bytes
|
||||
| |–Total: 227 bytes
|
||||
| |–Contained Type: List
|
||||
| |–Length: 5
|
||||
| |
|
||||
| |–[13: List]:
|
||||
| | |–Payload: 81 bytes
|
||||
| | |–Total: 81 bytes
|
||||
| | |–Contained Type: String
|
||||
| | |–Length: 3
|
||||
| | |
|
||||
| | |–[18: String]:
|
||||
| | | |–Payload: 18 bytes
|
||||
| | | |–Total: 18 bytes
|
||||
| | | '–Value: Du bist so dumm,
|
||||
| | |
|
||||
| | |–[36: String]:
|
||||
| | | |–Payload: 38 bytes
|
||||
| | | |–Total: 38 bytes
|
||||
| | | '–Value: Du wirfst ’nen Stein auf’n Boden
|
||||
| | |
|
||||
| | '–[74: String]:
|
||||
| | |–Payload: 20 bytes
|
||||
| | |–Total: 20 bytes
|
||||
| | '–Value: und triffst nicht.
|
||||
| |
|
||||
| |
|
||||
| |–[94: List]:
|
||||
| | |–Payload: 12 bytes
|
||||
| | |–Total: 12 bytes
|
||||
| | |–Contained Type: 8 Bit Integer
|
||||
| | |–Length: 7
|
||||
| | |
|
||||
| | |–[99: 8 Bit Integer]:
|
||||
| | | |–Payload: 1 byte
|
||||
| | | |–Total: 1 byte
|
||||
| | | '–Value: 115
|
||||
| | |
|
||||
| | |–[100: 8 Bit Integer]:
|
||||
| | | |–Payload: 1 byte
|
||||
| | | |–Total: 1 byte
|
||||
| | | '–Value: 35
|
||||
| | |
|
||||
| | |–[101: 8 Bit Integer]:
|
||||
| | | |–Payload: 1 byte
|
||||
| | | |–Total: 1 byte
|
||||
| | | '–Value: 7
|
||||
| | |
|
||||
| | |–[102: 8 Bit Integer]:
|
||||
| | | |–Payload: 1 byte
|
||||
| | | |–Total: 1 byte
|
||||
| | | '–Value: -3
|
||||
| | |
|
||||
| | |–[103: 8 Bit Integer]:
|
||||
| | | |–Payload: 1 byte
|
||||
| | | |–Total: 1 byte
|
||||
| | | '–Value: 56
|
||||
| | |
|
||||
| | |–[104: 8 Bit Integer]:
|
||||
| | | |–Payload: 1 byte
|
||||
| | | |–Total: 1 byte
|
||||
| | | '–Value: 105
|
||||
| | |
|
||||
| | '–[105: 8 Bit Integer]:
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 1 byte
|
||||
| | '–Value: 125
|
||||
| |
|
||||
| |
|
||||
| |–[106: List]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | |–Contained Type: End
|
||||
| | '–Length: 0
|
||||
| |
|
||||
| |–[111: List]:
|
||||
| | |–Payload: 77 bytes
|
||||
| | |–Total: 77 bytes
|
||||
| | |–Contained Type: Compound
|
||||
| | |–Length: 3
|
||||
| | |
|
||||
| | |–[116: Compound]:
|
||||
| | | |–Payload: 6 bytes
|
||||
| | | |–Total: 6 bytes
|
||||
| | | |–Length: 2
|
||||
| | | |
|
||||
| | | |–[116: 8 Bit Integer] 3:
|
||||
| | | | |–Header: 4 bytes
|
||||
| | | | |–Payload: 1 byte
|
||||
| | | | |–Total: 5 bytes
|
||||
| | | | '–Value: 105
|
||||
| | | |
|
||||
| | | '–[121: End]:
|
||||
| | | |–Header: 1 byte
|
||||
| | | |–Payload: 0 bytes
|
||||
| | | '–Total: 1 byte
|
||||
| | |
|
||||
| | |
|
||||
| | |–[122: Compound]:
|
||||
| | | |–Payload: 38 bytes
|
||||
| | | |–Total: 38 bytes
|
||||
| | | |–Length: 3
|
||||
| | | |
|
||||
| | | |–[122: String] 600:
|
||||
| | | | |–Header: 6 bytes
|
||||
| | | | |–Payload: 5 bytes
|
||||
| | | | |–Total: 11 bytes
|
||||
| | | | '–Value: 800
|
||||
| | | |
|
||||
| | | |–[133: List] cookie:
|
||||
| | | | |–Header: 9 bytes
|
||||
| | | | |–Payload: 17 bytes
|
||||
| | | | |–Total: 26 bytes
|
||||
| | | | |–Contained Type: String
|
||||
| | | | |–Length: 3
|
||||
| | | | |
|
||||
| | | | |–[147: String]:
|
||||
| | | | | |–Payload: 5 bytes
|
||||
| | | | | |–Total: 5 bytes
|
||||
| | | | | '–Value: eat
|
||||
| | | | |
|
||||
| | | | |–[152: String]:
|
||||
| | | | | |–Payload: 4 bytes
|
||||
| | | | | |–Total: 4 bytes
|
||||
| | | | | '–Value: it
|
||||
| | | | |
|
||||
| | | | '–[156: String]:
|
||||
| | | | |–Payload: 3 bytes
|
||||
| | | | |–Total: 3 bytes
|
||||
| | | | '–Value: !
|
||||
| | | |
|
||||
| | | |
|
||||
| | | '–[159: End]:
|
||||
| | | |–Header: 1 byte
|
||||
| | | |–Payload: 0 bytes
|
||||
| | | '–Total: 1 byte
|
||||
| | |
|
||||
| | |
|
||||
| | '–[160: Compound]:
|
||||
| | |–Payload: 28 bytes
|
||||
| | |–Total: 28 bytes
|
||||
| | |–Length: 2
|
||||
| | |
|
||||
| | |–[160: Compound]:
|
||||
| | | |–Header: 3 bytes
|
||||
| | | |–Payload: 24 bytes
|
||||
| | | |–Total: 27 bytes
|
||||
| | | |–Length: 2
|
||||
| | | |
|
||||
| | | |–[163: Compound] e:
|
||||
| | | | |–Header: 4 bytes
|
||||
| | | | |–Payload: 19 bytes
|
||||
| | | | |–Total: 23 bytes
|
||||
| | | | |–Length: 3
|
||||
| | | | |
|
||||
| | | | |–[167: 32 Bit Integer] a:
|
||||
| | | | | |–Header: 4 bytes
|
||||
| | | | | |–Payload: 4 bytes
|
||||
| | | | | |–Total: 8 bytes
|
||||
| | | | | '–Value: 544502633
|
||||
| | | | |
|
||||
| | | | |–[175: Compound] f:
|
||||
| | | | | |–Header: 4 bytes
|
||||
| | | | | |–Payload: 6 bytes
|
||||
| | | | | |–Total: 10 bytes
|
||||
| | | | | |–Length: 2
|
||||
| | | | | |
|
||||
| | | | | |–[179: Compound] o:
|
||||
| | | | | | |–Header: 4 bytes
|
||||
| | | | | | |–Payload: 1 byte
|
||||
| | | | | | |–Total: 5 bytes
|
||||
| | | | | | |–Length: 1
|
||||
| | | | | | |
|
||||
| | | | | | '–[183: End]:
|
||||
| | | | | | |–Header: 1 byte
|
||||
| | | | | | |–Payload: 0 bytes
|
||||
| | | | | | '–Total: 1 byte
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | | | '–[184: End]:
|
||||
| | | | | |–Header: 1 byte
|
||||
| | | | | |–Payload: 0 bytes
|
||||
| | | | | '–Total: 1 byte
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | '–[185: End]:
|
||||
| | | | |–Header: 1 byte
|
||||
| | | | |–Payload: 0 bytes
|
||||
| | | | '–Total: 1 byte
|
||||
| | | |
|
||||
| | | |
|
||||
| | | '–[186: End]:
|
||||
| | | |–Header: 1 byte
|
||||
| | | |–Payload: 0 bytes
|
||||
| | | '–Total: 1 byte
|
||||
| | |
|
||||
| | |
|
||||
| | '–[187: End]:
|
||||
| | |–Header: 1 byte
|
||||
| | |–Payload: 0 bytes
|
||||
| | '–Total: 1 byte
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| '–[188: List]:
|
||||
| |–Payload: 42 bytes
|
||||
| |–Total: 42 bytes
|
||||
| |–Contained Type: List
|
||||
| |–Length: 2
|
||||
| |
|
||||
| |–[193: List]:
|
||||
| | |–Payload: 20 bytes
|
||||
| | |–Total: 20 bytes
|
||||
| | |–Contained Type: String
|
||||
| | |–Length: 5
|
||||
| | |
|
||||
| | |–[198: String]:
|
||||
| | | |–Payload: 3 bytes
|
||||
| | | |–Total: 3 bytes
|
||||
| | | '–Value: a
|
||||
| | |
|
||||
| | |–[201: String]:
|
||||
| | | |–Payload: 3 bytes
|
||||
| | | |–Total: 3 bytes
|
||||
| | | '–Value: b
|
||||
| | |
|
||||
| | |–[204: String]:
|
||||
| | | |–Payload: 3 bytes
|
||||
| | | |–Total: 3 bytes
|
||||
| | | '–Value: c
|
||||
| | |
|
||||
| | |–[207: String]:
|
||||
| | | |–Payload: 3 bytes
|
||||
| | | |–Total: 3 bytes
|
||||
| | | '–Value: d
|
||||
| | |
|
||||
| | '–[210: String]:
|
||||
| | |–Payload: 3 bytes
|
||||
| | |–Total: 3 bytes
|
||||
| | '–Value: e
|
||||
| |
|
||||
| |
|
||||
| '–[213: List]:
|
||||
| |–Payload: 17 bytes
|
||||
| |–Total: 17 bytes
|
||||
| |–Contained Type: 32 Bit Integer
|
||||
| |–Length: 3
|
||||
| |
|
||||
| |–[218: 32 Bit Integer]:
|
||||
| | |–Payload: 4 bytes
|
||||
| | |–Total: 4 bytes
|
||||
| | '–Value: 457829
|
||||
| |
|
||||
| |–[222: 32 Bit Integer]:
|
||||
| | |–Payload: 4 bytes
|
||||
| | |–Total: 4 bytes
|
||||
| | '–Value: 300
|
||||
| |
|
||||
| '–[226: 32 Bit Integer]:
|
||||
| |–Payload: 4 bytes
|
||||
| |–Total: 4 bytes
|
||||
| '–Value: 60
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|–[230: Compound] compound_level_1:
|
||||
| |–Header: 19 bytes
|
||||
| |–Payload: 545 bytes
|
||||
| |–Total: 564 bytes
|
||||
| |–Length: 5
|
||||
| |
|
||||
| |–[249: List] 100:
|
||||
| | |–Header: 6 bytes
|
||||
| | |–Payload: 291 bytes
|
||||
| | |–Total: 297 bytes
|
||||
| | |–Contained Type: Compound
|
||||
| | |–Length: 4
|
||||
| | |
|
||||
| | |–[260: Compound]:
|
||||
| | | |–Payload: 6 bytes
|
||||
| | | |–Total: 6 bytes
|
||||
| | | |–Length: 2
|
||||
| | | |
|
||||
| | | |–[260: 8 Bit Integer] 3:
|
||||
| | | | |–Header: 4 bytes
|
||||
| | | | |–Payload: 1 byte
|
||||
| | | | |–Total: 5 bytes
|
||||
| | | | '–Value: 3
|
||||
| | | |
|
||||
| | | '–[265: End]:
|
||||
| | | |–Header: 1 byte
|
||||
| | | |–Payload: 0 bytes
|
||||
| | | '–Total: 1 byte
|
||||
| | |
|
||||
| | |
|
||||
| | |–[266: Compound]:
|
||||
| | | |–Payload: 125 bytes
|
||||
| | | |–Total: 125 bytes
|
||||
| | | |–Length: 4
|
||||
| | | |
|
||||
| | | |–[266: Array of 8 Bit Integers] 600:
|
||||
| | | | |–Header: 6 bytes
|
||||
| | | | |–Payload: 16 bytes
|
||||
| | | | |–Total: 22 bytes
|
||||
| | | | |–Length: 12
|
||||
| | | | '–Values:
|
||||
| | | | |–69
|
||||
| | | | |–36
|
||||
| | | | |–67
|
||||
| | | | |–66
|
||||
| | | | |–40
|
||||
| | | | |–-121
|
||||
| | | | |–98
|
||||
| | | | |–-46
|
||||
| | | | |–21
|
||||
| | | | |–101
|
||||
| | | | |–104
|
||||
| | | | '–97
|
||||
| | | |
|
||||
| | | |–[288: 64 Bit Integer] eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:
|
||||
| | | | |–Header: 85 bytes
|
||||
| | | | |–Payload: 8 bytes
|
||||
| | | | |–Total: 93 bytes
|
||||
| | | | '–Value: 317827579944
|
||||
| | | |
|
||||
| | | |–[381: 16 Bit Integer] nose:
|
||||
| | | | |–Header: 7 bytes
|
||||
| | | | |–Payload: 2 bytes
|
||||
| | | | |–Total: 9 bytes
|
||||
| | | | '–Value: 12547
|
||||
| | | |
|
||||
| | | '–[390: End]:
|
||||
| | | |–Header: 1 byte
|
||||
| | | |–Payload: 0 bytes
|
||||
| | | '–Total: 1 byte
|
||||
| | |
|
||||
| | |
|
||||
| | |–[391: Compound]:
|
||||
| | | |–Payload: 154 bytes
|
||||
| | | |–Total: 154 bytes
|
||||
| | | |–Length: 3
|
||||
| | | |
|
||||
| | | |–[391: List] 681:
|
||||
| | | | |–Header: 6 bytes
|
||||
| | | | |–Payload: 8 bytes
|
||||
| | | | |–Total: 14 bytes
|
||||
| | | | |–Contained Type: 8 Bit Integer
|
||||
| | | | |–Length: 3
|
||||
| | | | |
|
||||
| | | | |–[402: 8 Bit Integer]:
|
||||
| | | | | |–Payload: 1 byte
|
||||
| | | | | |–Total: 1 byte
|
||||
| | | | | '–Value: 3
|
||||
| | | | |
|
||||
| | | | |–[403: 8 Bit Integer]:
|
||||
| | | | | |–Payload: 1 byte
|
||||
| | | | | |–Total: 1 byte
|
||||
| | | | | '–Value: 3
|
||||
| | | | |
|
||||
| | | | '–[404: 8 Bit Integer]:
|
||||
| | | | |–Payload: 1 byte
|
||||
| | | | |–Total: 1 byte
|
||||
| | | | '–Value: 5
|
||||
| | | |
|
||||
| | | |
|
||||
| | | |–[405: Compound] moar:
|
||||
| | | | |–Header: 7 bytes
|
||||
| | | | |–Payload: 132 bytes
|
||||
| | | | |–Total: 139 bytes
|
||||
| | | | |–Length: 2
|
||||
| | | | |
|
||||
| | | | |–[412: Compound] nesting:
|
||||
| | | | | |–Header: 10 bytes
|
||||
| | | | | |–Payload: 121 bytes
|
||||
| | | | | |–Total: 131 bytes
|
||||
| | | | | |–Length: 2
|
||||
| | | | | |
|
||||
| | | | | |–[422: Compound] go:
|
||||
| | | | | | |–Header: 5 bytes
|
||||
| | | | | | |–Payload: 115 bytes
|
||||
| | | | | | |–Total: 120 bytes
|
||||
| | | | | | |–Length: 2
|
||||
| | | | | | |
|
||||
| | | | | | |–[427: Compound] brrrrr:
|
||||
| | | | | | | |–Header: 9 bytes
|
||||
| | | | | | | |–Payload: 105 bytes
|
||||
| | | | | | | |–Total: 114 bytes
|
||||
| | | | | | | |–Length: 7
|
||||
| | | | | | | |
|
||||
| | | | | | | |–[436: 16 Bit Integer] anyway:
|
||||
| | | | | | | | |–Header: 9 bytes
|
||||
| | | | | | | | |–Payload: 2 bytes
|
||||
| | | | | | | | |–Total: 11 bytes
|
||||
| | | | | | | | '–Value: 12547
|
||||
| | | | | | | |
|
||||
| | | | | | | |–[447: List] data:
|
||||
| | | | | | | | |–Header: 7 bytes
|
||||
| | | | | | | | |–Payload: 21 bytes
|
||||
| | | | | | | | |–Total: 28 bytes
|
||||
| | | | | | | | |–Contained Type: 32 Bit Integer
|
||||
| | | | | | | | |–Length: 4
|
||||
| | | | | | | | |
|
||||
| | | | | | | | |–[459: 32 Bit Integer]:
|
||||
| | | | | | | | | |–Payload: 4 bytes
|
||||
| | | | | | | | | |–Total: 4 bytes
|
||||
| | | | | | | | | '–Value: 10
|
||||
| | | | | | | | |
|
||||
| | | | | | | | |–[463: 32 Bit Integer]:
|
||||
| | | | | | | | | |–Payload: 4 bytes
|
||||
| | | | | | | | | |–Total: 4 bytes
|
||||
| | | | | | | | | '–Value: 808464643
|
||||
| | | | | | | | |
|
||||
| | | | | | | | |–[467: 32 Bit Integer]:
|
||||
| | | | | | | | | |–Payload: 4 bytes
|
||||
| | | | | | | | | |–Total: 4 bytes
|
||||
| | | | | | | | | '–Value: 645
|
||||
| | | | | | | | |
|
||||
| | | | | | | | '–[471: 32 Bit Integer]:
|
||||
| | | | | | | | |–Payload: 4 bytes
|
||||
| | | | | | | | |–Total: 4 bytes
|
||||
| | | | | | | | '–Value: 1337
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |–[475: 8 Bit Integer] here:
|
||||
| | | | | | | | |–Header: 7 bytes
|
||||
| | | | | | | | |–Payload: 1 byte
|
||||
| | | | | | | | |–Total: 8 bytes
|
||||
| | | | | | | | '–Value: 3
|
||||
| | | | | | | |
|
||||
| | | | | | | |–[483: Double] is:
|
||||
| | | | | | | | |–Header: 5 bytes
|
||||
| | | | | | | | |–Payload: 8 bytes
|
||||
| | | | | | | | |–Total: 13 bytes
|
||||
| | | | | | | | '–Value: 7.29293e-304
|
||||
| | | | | | | |
|
||||
| | | | | | | |–[496: 32 Bit Integer] so:
|
||||
| | | | | | | | |–Header: 5 bytes
|
||||
| | | | | | | | |–Payload: 4 bytes
|
||||
| | | | | | | | |–Total: 9 bytes
|
||||
| | | | | | | | '–Value: 808464643
|
||||
| | | | | | | |
|
||||
| | | | | | | |–[505: Array of 32 Bit Integers] some:
|
||||
| | | | | | | | |–Header: 7 bytes
|
||||
| | | | | | | | |–Payload: 28 bytes
|
||||
| | | | | | | | |–Total: 35 bytes
|
||||
| | | | | | | | |–Length: 6
|
||||
| | | | | | | | '–Values:
|
||||
| | | | | | | | |–3865431
|
||||
| | | | | | | | |–230597146
|
||||
| | | | | | | | |–2147483647
|
||||
| | | | | | | | |–-1870208349
|
||||
| | | | | | | | |–-1195067710
|
||||
| | | | | | | | '–-2031966525
|
||||
| | | | | | | |
|
||||
| | | | | | | '–[540: End]:
|
||||
| | | | | | | |–Header: 1 byte
|
||||
| | | | | | | |–Payload: 0 bytes
|
||||
| | | | | | | '–Total: 1 byte
|
||||
| | | | | | |
|
||||
| | | | | | |
|
||||
| | | | | | '–[541: End]:
|
||||
| | | | | | |–Header: 1 byte
|
||||
| | | | | | |–Payload: 0 bytes
|
||||
| | | | | | '–Total: 1 byte
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | | | '–[542: End]:
|
||||
| | | | | |–Header: 1 byte
|
||||
| | | | | |–Payload: 0 bytes
|
||||
| | | | | '–Total: 1 byte
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | | | '–[543: End]:
|
||||
| | | | |–Header: 1 byte
|
||||
| | | | |–Payload: 0 bytes
|
||||
| | | | '–Total: 1 byte
|
||||
| | | |
|
||||
| | | |
|
||||
| | | '–[544: End]:
|
||||
| | | |–Header: 1 byte
|
||||
| | | |–Payload: 0 bytes
|
||||
| | | '–Total: 1 byte
|
||||
| | |
|
||||
| | |
|
||||
| | '–[545: Compound]:
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 1 byte
|
||||
| | |–Length: 1
|
||||
| | |
|
||||
| | '–[545: End]:
|
||||
| | |–Header: 1 byte
|
||||
| | |–Payload: 0 bytes
|
||||
| | '–Total: 1 byte
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |–[546: Compound] compound_level_2a:
|
||||
| | |–Header: 20 bytes
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 21 bytes
|
||||
| | |–Length: 1
|
||||
| | |
|
||||
| | '–[566: End]:
|
||||
| | |–Header: 1 byte
|
||||
| | |–Payload: 0 bytes
|
||||
| | '–Total: 1 byte
|
||||
| |
|
||||
| |
|
||||
| |–[567: Compound] compound_level_2b:
|
||||
| | |–Header: 20 bytes
|
||||
| | |–Payload: 191 bytes
|
||||
| | |–Total: 211 bytes
|
||||
| | |–Length: 3
|
||||
| | |
|
||||
| | |–[587: Float] 300:
|
||||
| | | |–Header: 6 bytes
|
||||
| | | |–Payload: 4 bytes
|
||||
| | | |–Total: 10 bytes
|
||||
| | | '–Value: 1.89896e+28
|
||||
| | |
|
||||
| | |–[597: List] 900:
|
||||
| | | |–Header: 6 bytes
|
||||
| | | |–Payload: 174 bytes
|
||||
| | | |–Total: 180 bytes
|
||||
| | | |–Contained Type: String
|
||||
| | | |–Length: 6
|
||||
| | | |
|
||||
| | | |–[608: String]:
|
||||
| | | | |–Payload: 7 bytes
|
||||
| | | | |–Total: 7 bytes
|
||||
| | | | '–Value: aaaaa
|
||||
| | | |
|
||||
| | | |–[615: String]:
|
||||
| | | | |–Payload: 30 bytes
|
||||
| | | | |–Total: 30 bytes
|
||||
| | | | '–Value: bbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
| | | |
|
||||
| | | |–[645: String]:
|
||||
| | | | |–Payload: 6 bytes
|
||||
| | | | |–Total: 6 bytes
|
||||
| | | | '–Value: nose
|
||||
| | | |
|
||||
| | | |–[651: String]:
|
||||
| | | | |–Payload: 13 bytes
|
||||
| | | | |–Total: 13 bytes
|
||||
| | | | '–Value: hello there
|
||||
| | | |
|
||||
| | | |–[664: String]:
|
||||
| | | | |–Payload: 37 bytes
|
||||
| | | | |–Total: 37 bytes
|
||||
| | | | '–Value: Eat more bricks, they’re healthy.
|
||||
| | | |
|
||||
| | | '–[701: String]:
|
||||
| | | |–Payload: 76 bytes
|
||||
| | | |–Total: 76 bytes
|
||||
| | | '–Value: ŧ€æ ̣←¶ĸæ↓ŧŧþ€ł„ ̣€æ€“¢↓ø→ł¶€¶„ŋ
|
||||
| | |
|
||||
| | |
|
||||
| | '–[777: End]:
|
||||
| | |–Header: 1 byte
|
||||
| | |–Payload: 0 bytes
|
||||
| | '–Total: 1 byte
|
||||
| |
|
||||
| |
|
||||
| |–[778: List] eeeeeee:
|
||||
| | |–Header: 10 bytes
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 15 bytes
|
||||
| | |–Contained Type: End
|
||||
| | '–Length: 0
|
||||
| |
|
||||
| '–[793: End]:
|
||||
| |–Header: 1 byte
|
||||
| |–Payload: 0 bytes
|
||||
| '–Total: 1 byte
|
||||
|
|
||||
|
|
||||
'–[794: End]:
|
||||
|–Header: 1 byte
|
||||
|–Payload: 0 bytes
|
||||
'–Total: 1 byte
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
[0: Compound]:
|
||||
|–Header: 3 bytes
|
||||
|–Payload: 2395 bytes
|
||||
|–Total: 2398 bytes
|
||||
|–Length: 2
|
||||
|
|
||||
|–[3: List] servers:
|
||||
| |–Header: 10 bytes
|
||||
| |–Payload: 2384 bytes
|
||||
| |–Total: 2394 bytes
|
||||
| |–Contained Type: Compound
|
||||
| |–Length: 2
|
||||
| |
|
||||
| |–[18: Compound]:
|
||||
| | |–Payload: 1184 bytes
|
||||
| | |–Total: 1184 bytes
|
||||
| | |–Length: 4
|
||||
| | |
|
||||
| | |–[18: String] ip:
|
||||
| | | |–Header: 5 bytes
|
||||
| | | |–Payload: 14 bytes
|
||||
| | | |–Total: 19 bytes
|
||||
| | | '–Value: minecraft.ip
|
||||
| | |
|
||||
| | |–[37: String] name:
|
||||
| | | |–Header: 7 bytes
|
||||
| | | |–Payload: 20 bytes
|
||||
| | | |–Total: 27 bytes
|
||||
| | | '–Value: Survival0 Internal
|
||||
| | |
|
||||
| | |–[64: String] icon:
|
||||
| | | |–Header: 7 bytes
|
||||
| | | |–Payload: 1130 bytes
|
||||
| | | |–Total: 1137 bytes
|
||||
| | | '–Value: iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAADFUlEQVR4Xt2bPW4UQRCFx9qUA+wBkJB8ElIkbmAJn4GYhNQ38AmcEBORcA8OQdjQbfeq9pvq6und/pv9pCeL/qv3amakHS9elsY45w7ucg48bxcwRS1YZyr++7uj4Ybcsf4wvBm668jYRtDNKOirOTQwC/TZBBadDfqtCovNCn1XgUVmh/6vgofvBea4CB66N5inCB62V5hrEzwk4qdaqSVLCdwsCdN/f1RXpmwVmDMJN0bClGK+lozSVWBOFW6ShGlhtpZ6NcCzWLjMi01Y8mb0829XTfLcDqRfoLiShCVKAyIMtlXy3B6cp37DXXj1NRjwbP2f90Ecl+d3YH0XcAUJS5QGlGqSBqzvAi4gYUlhAyIc1yTP78FF4a0G3L8cT5LhI1xPsUYPihuQCq81ICdJHJN1elClATI4xbUMLhnWAJf5vX00dW0DPNxLsVYHDtkqNCUDeRiaDSAMPbgBLltFu/1JHH/69G4Vylovdf/1GNT9MeAA0RqQUqoBmmLgqOcvH4KmagBvSZqWyjWA62NgijVbY1agGZqVYkCK61NizdaYFeTtSKMt1fMxMCvM2AA/VioLczYaiWZ6yXoE5PwWaWdIzNnSYrWlmY+e2DRNqTMk5uzMDeA6GZpzFuYsOzpCJIwpzaL8J9GrG5DCH/rr5/dqypmUbG1AVO5sdZZXYQZd481CnQ2blG6OEkMwoKUcfsXqdTg24PHh4ybRcKkeH76d/Ts+vy/H9XPMgFtk8Prf8DgahhSjoyQtlnpT4p0I4a0G8EqnxKK1pTXA/8yJe0kI71EmViZGSlrUvDE051KcGuDBRNjMK50Si9aWtKeF1JT7HHAW3oPJ6SS9MawluVeyEJf4asxP8YNLD71aWuPHS6Ww/mrMw1UePzxKKbjOksaSwiXughtDv/oRrr41mFeFm24F5kzCjbcCc5pw895hvk3wkL3CXEXwsL3BPBfBQ/cCc1wFD58d+q8Ci8wKfVeFxWaDfpvAorNAn82hgVHQV1fc2Bco+8WmJ94M3TVknuAadFsL1tkFTvneoYDmfz7/D2WFu2nv97K8AAAAAElFTkSuQmCC
|
||||
| | |
|
||||
| | '–[1201: End]:
|
||||
| | |–Header: 1 byte
|
||||
| | |–Payload: 0 bytes
|
||||
| | '–Total: 1 byte
|
||||
| |
|
||||
| |
|
||||
| '–[1202: Compound]:
|
||||
| |–Payload: 1195 bytes
|
||||
| |–Total: 1195 bytes
|
||||
| |–Length: 4
|
||||
| |
|
||||
| |–[1202: String] ip:
|
||||
| | |–Header: 5 bytes
|
||||
| | |–Payload: 25 bytes
|
||||
| | |–Total: 30 bytes
|
||||
| | '–Value: lostcave.ddnss.de:45539
|
||||
| |
|
||||
| |–[1232: String] name:
|
||||
| | |–Header: 7 bytes
|
||||
| | |–Payload: 20 bytes
|
||||
| | |–Total: 27 bytes
|
||||
| | '–Value: Survival0 External
|
||||
| |
|
||||
| |–[1259: String] icon:
|
||||
| | |–Header: 7 bytes
|
||||
| | |–Payload: 1130 bytes
|
||||
| | |–Total: 1137 bytes
|
||||
| | '–Value: iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAADFUlEQVR4Xt2bPW4UQRCFx9qUA+wBkJB8ElIkbmAJn4GYhNQ38AmcEBORcA8OQdjQbfeq9pvq6und/pv9pCeL/qv3amakHS9elsY45w7ucg48bxcwRS1YZyr++7uj4Ybcsf4wvBm668jYRtDNKOirOTQwC/TZBBadDfqtCovNCn1XgUVmh/6vgofvBea4CB66N5inCB62V5hrEzwk4qdaqSVLCdwsCdN/f1RXpmwVmDMJN0bClGK+lozSVWBOFW6ShGlhtpZ6NcCzWLjMi01Y8mb0829XTfLcDqRfoLiShCVKAyIMtlXy3B6cp37DXXj1NRjwbP2f90Ecl+d3YH0XcAUJS5QGlGqSBqzvAi4gYUlhAyIc1yTP78FF4a0G3L8cT5LhI1xPsUYPihuQCq81ICdJHJN1elClATI4xbUMLhnWAJf5vX00dW0DPNxLsVYHDtkqNCUDeRiaDSAMPbgBLltFu/1JHH/69G4Vylovdf/1GNT9MeAA0RqQUqoBmmLgqOcvH4KmagBvSZqWyjWA62NgijVbY1agGZqVYkCK61NizdaYFeTtSKMt1fMxMCvM2AA/VioLczYaiWZ6yXoE5PwWaWdIzNnSYrWlmY+e2DRNqTMk5uzMDeA6GZpzFuYsOzpCJIwpzaL8J9GrG5DCH/rr5/dqypmUbG1AVO5sdZZXYQZd481CnQ2blG6OEkMwoKUcfsXqdTg24PHh4ybRcKkeH76d/Ts+vy/H9XPMgFtk8Prf8DgahhSjoyQtlnpT4p0I4a0G8EqnxKK1pTXA/8yJe0kI71EmViZGSlrUvDE051KcGuDBRNjMK50Si9aWtKeF1JT7HHAW3oPJ6SS9MawluVeyEJf4asxP8YNLD71aWuPHS6Ww/mrMw1UePzxKKbjOksaSwiXughtDv/oRrr41mFeFm24F5kzCjbcCc5pw895hvk3wkL3CXEXwsL3BPBfBQ/cCc1wFD58d+q8Ci8wKfVeFxWaDfpvAorNAn82hgVHQV1fc2Bco+8WmJ94M3TVknuAadFsL1tkFTvneoYDmfz7/D2WFu2nv97K8AAAAAElFTkSuQmCC
|
||||
| |
|
||||
| '–[2396: End]:
|
||||
| |–Header: 1 byte
|
||||
| |–Payload: 0 bytes
|
||||
| '–Total: 1 byte
|
||||
|
|
||||
|
|
||||
|
|
||||
'–[2397: End]:
|
||||
|–Header: 1 byte
|
||||
|–Payload: 0 bytes
|
||||
'–Total: 1 byte
|
||||
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
[0: Compound]:
|
||||
|–Header: 3 bytes
|
||||
|–Payload: 475 bytes
|
||||
|–Total: 478 bytes
|
||||
|–Length: 15
|
||||
|
|
||||
|–[3: String] Spaces and special characters are allowed in tag names, right?:
|
||||
| |–Header: 65 bytes
|
||||
| |–Payload: 24 bytes
|
||||
| |–Total: 89 bytes
|
||||
| '–Value: Idk. Let’s find out.
|
||||
|
|
||||
|–[92: Compound] compound:
|
||||
| |–Header: 11 bytes
|
||||
| |–Payload: 45 bytes
|
||||
| |–Total: 56 bytes
|
||||
| |–Length: 3
|
||||
| |
|
||||
| |–[103: 32 Bit Integer] some_number:
|
||||
| | |–Header: 14 bytes
|
||||
| | |–Payload: 4 bytes
|
||||
| | |–Total: 18 bytes
|
||||
| | '–Value: -754506943
|
||||
| |
|
||||
| |–[121: String] some_text:
|
||||
| | |–Header: 12 bytes
|
||||
| | |–Payload: 14 bytes
|
||||
| | |–Total: 26 bytes
|
||||
| | '–Value: eat a cookie
|
||||
| |
|
||||
| '–[147: End]:
|
||||
| |–Header: 1 byte
|
||||
| |–Payload: 0 bytes
|
||||
| '–Total: 1 byte
|
||||
|
|
||||
|
|
||||
|–[148: Double] double:
|
||||
| |–Header: 9 bytes
|
||||
| |–Payload: 8 bytes
|
||||
| |–Total: 17 bytes
|
||||
| '–Value: 623594
|
||||
|
|
||||
|–[165: Float] float:
|
||||
| |–Header: 8 bytes
|
||||
| |–Payload: 4 bytes
|
||||
| |–Total: 12 bytes
|
||||
| '–Value: 35.2678
|
||||
|
|
||||
|–[177: 16 Bit Integer] int16:
|
||||
| |–Header: 8 bytes
|
||||
| |–Payload: 2 bytes
|
||||
| |–Total: 10 bytes
|
||||
| '–Value: 2000
|
||||
|
|
||||
|–[187: 32 Bit Integer] int32:
|
||||
| |–Header: 8 bytes
|
||||
| |–Payload: 4 bytes
|
||||
| |–Total: 12 bytes
|
||||
| '–Value: 10101010
|
||||
|
|
||||
|–[199: Array of 32 Bit Integers] int32_array:
|
||||
| |–Header: 14 bytes
|
||||
| |–Payload: 20 bytes
|
||||
| |–Total: 34 bytes
|
||||
| |–Length: 4
|
||||
| '–Values:
|
||||
| |–398452796
|
||||
| |–43259
|
||||
| |–2147483647
|
||||
| '–1634890337
|
||||
|
|
||||
|–[233: 64 Bit Integer] int64:
|
||||
| |–Header: 8 bytes
|
||||
| |–Payload: 8 bytes
|
||||
| |–Total: 16 bytes
|
||||
| '–Value: 810001800766
|
||||
|
|
||||
|–[249: Array of 64 Bit Integers] int64_array:
|
||||
| |–Header: 14 bytes
|
||||
| |–Payload: 44 bytes
|
||||
| |–Total: 58 bytes
|
||||
| |–Length: 5
|
||||
| '–Values:
|
||||
| |–239865
|
||||
| |–23586749
|
||||
| |–9223372036854775807
|
||||
| |–188944201329624
|
||||
| '–3116157694992754
|
||||
|
|
||||
|–[307: 8 Bit Integer] int8:
|
||||
| |–Header: 7 bytes
|
||||
| |–Payload: 1 byte
|
||||
| |–Total: 8 bytes
|
||||
| '–Value: 100
|
||||
|
|
||||
|–[315: Array of 8 Bit Integers] int8_array:
|
||||
| |–Header: 13 bytes
|
||||
| |–Payload: 12 bytes
|
||||
| |–Total: 25 bytes
|
||||
| |–Length: 8
|
||||
| '–Values:
|
||||
| |–113
|
||||
| |–53
|
||||
| |–119
|
||||
| |–98
|
||||
| |–84
|
||||
| |–100
|
||||
| |–-11
|
||||
| '–50
|
||||
|
|
||||
|–[340: List] list_int8:
|
||||
| |–Header: 12 bytes
|
||||
| |–Payload: 10 bytes
|
||||
| |–Total: 22 bytes
|
||||
| |–Contained Type: 8 Bit Integer
|
||||
| |–Length: 5
|
||||
| |
|
||||
| |–[357: 8 Bit Integer]:
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 1 byte
|
||||
| | '–Value: 65
|
||||
| |
|
||||
| |–[358: 8 Bit Integer]:
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 1 byte
|
||||
| | '–Value: 96
|
||||
| |
|
||||
| |–[359: 8 Bit Integer]:
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 1 byte
|
||||
| | '–Value: 78
|
||||
| |
|
||||
| |–[360: 8 Bit Integer]:
|
||||
| | |–Payload: 1 byte
|
||||
| | |–Total: 1 byte
|
||||
| | '–Value: 127
|
||||
| |
|
||||
| '–[361: 8 Bit Integer]:
|
||||
| |–Payload: 1 byte
|
||||
| |–Total: 1 byte
|
||||
| '–Value: -6
|
||||
|
|
||||
|
|
||||
|–[362: List] list_strings:
|
||||
| |–Header: 15 bytes
|
||||
| |–Payload: 77 bytes
|
||||
| |–Total: 92 bytes
|
||||
| |–Contained Type: String
|
||||
| |–Length: 12
|
||||
| |
|
||||
| |–[382: String]:
|
||||
| | |–Payload: 8 bytes
|
||||
| | |–Total: 8 bytes
|
||||
| | '–Value: Pacman
|
||||
| |
|
||||
| |–[390: String]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | '–Value: ate
|
||||
| |
|
||||
| |–[395: String]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | '–Value: all
|
||||
| |
|
||||
| |–[400: String]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | '–Value: the
|
||||
| |
|
||||
| |–[405: String]:
|
||||
| | |–Payload: 6 bytes
|
||||
| | |–Total: 6 bytes
|
||||
| | '–Value: dots
|
||||
| |
|
||||
| |–[411: String]:
|
||||
| | |–Payload: 4 bytes
|
||||
| | |–Total: 4 bytes
|
||||
| | '–Value: so
|
||||
| |
|
||||
| |–[415: String]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | '–Value: now
|
||||
| |
|
||||
| |–[420: String]:
|
||||
| | |–Payload: 8 bytes
|
||||
| | |–Total: 8 bytes
|
||||
| | '–Value: he’s
|
||||
| |
|
||||
| |–[428: String]:
|
||||
| | |–Payload: 8 bytes
|
||||
| | |–Total: 8 bytes
|
||||
| | '–Value: coming
|
||||
| |
|
||||
| |–[436: String]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | '–Value: for
|
||||
| |
|
||||
| |–[441: String]:
|
||||
| | |–Payload: 5 bytes
|
||||
| | |–Total: 5 bytes
|
||||
| | '–Value: the
|
||||
| |
|
||||
| '–[446: String]:
|
||||
| |–Payload: 8 bytes
|
||||
| |–Total: 8 bytes
|
||||
| '–Value: words.
|
||||
|
|
||||
|
|
||||
|–[454: String] string:
|
||||
| |–Header: 9 bytes
|
||||
| |–Payload: 14 bytes
|
||||
| |–Total: 23 bytes
|
||||
| '–Value: Hello World!
|
||||
|
|
||||
'–[477: End]:
|
||||
|–Header: 1 byte
|
||||
|–Payload: 0 bytes
|
||||
'–Total: 1 byte
|
||||
|
||||
|
|
@ -1,33 +1,67 @@
|
|||
# Tests
|
||||
# Resources
|
||||
|
||||
Data used for testing and understanding the internals of Minecraft/FOSS-VG,
|
||||
also contains code to produce such data
|
||||
|
||||
|
||||
## java/
|
||||
|
||||
Programs to produce data for figuring out how to interact
|
||||
with Java-specific things
|
||||
|
||||
- `JavaStringGenerator.java`: A simple tool that reads from stdin and outputs Java-style UTF-8 to stdout
|
||||
- `netty-tests/`: Figure out how Netty operates
|
||||
|
||||
|
||||
## NBT_data/
|
||||
|
||||
Data used to test the NBT library
|
||||
|
||||
`bare_int64_tag`: What the name says
|
||||
`bare_int64_tag_and_int32_tag`: What the name says
|
||||
`simple_nbt`: A simple NBT file containing all tag types
|
||||
`nested_compounds_and_lists`: A combination of nested compound and list tags (parser stress test)
|
||||
`servers.dat`: Pulled from my Minecraft installation
|
||||
`servers.dat_nbt_decoded.txt`: The same data manually decoded (This was done to get a better understanding how NBT works, might come in handy.)
|
||||
`level.dat`: Pulled from one of my world saves (gzip-compressed)
|
||||
`level.dat_decompressed`: The same data decompressed
|
||||
|
||||
|
||||
## network_capture/
|
||||
|
||||
Network captures used to get an understanding of the protocol
|
||||
|
||||
`ping.pcapng`: WireShark capture of the multipayer screen server ping
|
||||
`ping_decoded.txt`: Extracted TCP payloads from the network capture annotated with what’s happening
|
||||
|
||||
|
||||
## unicode_data/
|
||||
|
||||
This directory contains two files with unicode data. One is in Java format, the other is normal UTF-8.
|
||||
Files with unicode data
|
||||
|
||||
- Bare ("normal") UTF-8
|
||||
- Java format
|
||||
|
||||
|
||||
## all_bytes
|
||||
|
||||
Every possible 8-bit byte in ascending order
|
||||
|
||||
## check_endianness.cpp
|
||||
|
||||
A simple tool to determine the endianness of the system and write the endianness header for FOSS-VG
|
||||
A simple tool to determine the endianness of the system and write
|
||||
the endianness header for FOSS-VG
|
||||
|
||||
Supports: Little Endian, Big Endian, PDP Endian, Honeywell Endian
|
||||
|
||||
Note that, while it can detect PDP and Honeywell endianness, the FOSS-VG project itself does not support these.
|
||||
Usage: `check_endianness > header_file`
|
||||
|
||||
Usage example: `check_endianness > header_file`
|
||||
Note that, while this tool should in theory be able to detect
|
||||
PDP and Honeywell-316-style endianness, the FOSS-VG project itself
|
||||
does not support these.
|
||||
|
||||
## region_files
|
||||
|
||||
## JavaStringGenerator.java
|
||||
|
||||
A simple tool written in Java that takes an input as UTF-8 and outputs it in Java-style UTF-8.
|
||||
|
||||
Usage example: `echo -ne "\x00" | java JavaStringGenerator > output_file`
|
||||
|
||||
|
||||
## NBT_data
|
||||
|
||||
Data used to test the NBT library.
|
||||
|
||||
`servers.dat`: My current servers.dat as pulled from my Minecraft installation
|
||||
`servers.dat_nbt_decoded.txt`: The same file manually decoded (I did this to get a better understanding how NBT works, might come in handy in the future.)
|
||||
`simple_nbt`: A simple NBT file containing all tags
|
||||
`nested_compounds_and_lists`: A combination of nested compound and list tags intended to be challenging to parse
|
||||
Exactly what the name says. At this point just a random region file I grabbed
|
||||
from Minecraft, will probably contain synthetic files for test cases in the
|
||||
future as well.
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
# Netty Testing
|
||||
|
||||
This sub-project is used to learn how Netty works
|
||||
|
||||
Build with Maven (`mvn compile`). Run with the build scripts.
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>foss_vg</groupId>
|
||||
<artifactId>netty-tests</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<name>netty-tests</name>
|
||||
<url>https://lostcave.ddnss.de/git/BodgeMaster/FOSS-VG</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.84.Final</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<!--
|
||||
Removed all the bloat bc we don't need it.
|
||||
Maven will probably choose a default version for the things I removed.
|
||||
I don't care as targets other than compile and clean aren't needed here.
|
||||
-->
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
</project>
|
|
@ -1,7 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright 2022, FOSS-VG Developers and Contributers
|
||||
#
|
||||
# Author(s):
|
||||
# BodgeMaster
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, version 3.
|
||||
|
@ -15,9 +16,7 @@
|
|||
# version 3 along with this program.
|
||||
# If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
echo "################################################################################
|
||||
Testing hexnet
|
||||
################################################################################"
|
||||
set -e
|
||||
|
||||
echo "Test not yet implemented."
|
||||
#TODO: implement unit test after merging back with master
|
||||
cd target/classes
|
||||
java foss_vg.NettyClient
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright 2022, FOSS-VG Developers and Contributers
|
||||
#
|
||||
# Author(s):
|
||||
# BodgeMaster
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, version 3.
|
||||
#
|
||||
# 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 Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# version 3 along with this program.
|
||||
# If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
set -e
|
||||
|
||||
cd target/classes
|
||||
java foss_vg.NettyServer
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
package foss_vg;
|
||||
|
||||
public class NettyClient {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
package foss_vg;
|
||||
|
||||
public class NettyServer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
}
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,90 @@
|
|||
if [ "$1" = "-v" ]; then
|
||||
VERBOSE=true
|
||||
shift
|
||||
else
|
||||
VERBOSE=false
|
||||
fi
|
||||
|
||||
if [ "$1" = "-n" ]; then
|
||||
DECOMPRESS=false
|
||||
shift
|
||||
else
|
||||
DECOMPRESS=true
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f "$1" ]; then
|
||||
echo "Usage: $0 [-v] [-n] FILE"
|
||||
echo " -v display raw content and NBT dump"
|
||||
echo " -n don't decompress"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# pointer data
|
||||
OFFSET_HEX="0x$(dd bs=1 if="$1" count=3 2>/dev/null | hexdump -e '3/1 "%02x" "\n"')"
|
||||
OFFSET="$(baseconvert -d $OFFSET_HEX)"
|
||||
echo " offset: $OFFSET ($OFFSET_HEX)"
|
||||
LENGTH_HEX="0x$(dd bs=1 if="$1" count=1 skip=3 2>/dev/null | hexdump -e '1/1 "%02x" "\n"')"
|
||||
LENGTH="$(baseconvert -d $LENGTH_HEX)"
|
||||
echo " length: $LENGTH ($LENGTH_HEX)"
|
||||
|
||||
#TODO: last modified
|
||||
|
||||
# chunk
|
||||
DATA="$(dd if="$1" bs=4096 count=$LENGTH skip=$OFFSET 2>/dev/null | hexdump -v -e '16/1 "%02x" "\n"' | tr -d '
|
||||
')"
|
||||
|
||||
# blob header
|
||||
# bs=2 because each byte is two digits hex
|
||||
COMPRESSED_LENGTH_HEX="0x$(dd bs=2 count=4 2> /dev/null <<< $DATA)"
|
||||
COMPRESSED_LENGTH="$(baseconvert -d $COMPRESSED_LENGTH_HEX)"
|
||||
echo " compressed length in bytes: $COMPRESSED_LENGTH ($COMPRESSED_LENGTH_HEX)"
|
||||
FORMAT_HEX="0x$(dd bs=2 skip=4 count=1 2> /dev/null <<< $DATA)"
|
||||
case $FORMAT_HEX in
|
||||
"0x01")
|
||||
FORMAT="gzip"
|
||||
function UNCOMPRESS {
|
||||
gzip -dc
|
||||
}
|
||||
;;
|
||||
"0x02")
|
||||
FORMAT="zlib"
|
||||
function UNCOMPRESS {
|
||||
cat > /tmp/chunk_zlib_decompress
|
||||
python3 <<< "
|
||||
import zlib,sys
|
||||
a = open('/tmp/chunk_zlib_decompress', 'rb')
|
||||
data = a.read()
|
||||
a.close()
|
||||
sys.stdout.buffer.write(zlib.decompress(data))
|
||||
sys.stdout.buffer.flush()
|
||||
"
|
||||
rm /tmp/chunk_zlib_decompress
|
||||
}
|
||||
;;
|
||||
*)
|
||||
FORMAT="unknown"
|
||||
function UNCOMPRESS {
|
||||
false
|
||||
}
|
||||
;;
|
||||
esac
|
||||
echo " format: $FORMAT ($FORMAT_HEX)"
|
||||
|
||||
|
||||
if $DECOMPRESS; then
|
||||
dd if="$1" bs=4096 count=$LENGTH skip=$OFFSET 2>/dev/null | dd bs=1 skip=5 count=$(($COMPRESSED_LENGTH-1)) 2>/dev/null | UNCOMPRESS > /tmp/chunk_uncompressed_nbt
|
||||
else
|
||||
dd if="$1" bs=4096 count=$LENGTH skip=$OFFSET 2>/dev/null | dd bs=1 skip=5 count=$(($COMPRESSED_LENGTH-1)) 2>/dev/null > /tmp/chunk_compressed_nbt
|
||||
fi
|
||||
|
||||
if $VERBOSE; then
|
||||
echo "Raw chunk data:"
|
||||
echo "$DATA"
|
||||
echo "NBT dump:"
|
||||
|
||||
#TODO: use pipes instead of a file
|
||||
#TODO: fix this up to work with both compressed and uncompressed NBT
|
||||
dumpnbt /tmp/chunk_uncompressed_nbt
|
||||
rm /tmp/chunk_uncompressed_nbt
|
||||
fi
|
Binary file not shown.
|
@ -35,10 +35,19 @@ fi
|
|||
# dynamically linked libraries.
|
||||
echo ">>> Building libs..."
|
||||
create_directory bin/lib
|
||||
for lib in $(find ./src/lib -name "*.cpp"); do
|
||||
COMPILE_COMMAND="$CXX_WITH_FLAGS -I ./include -fPIC -shared -o $(sed -e 's/^.\/src/.\/bin/;s/cpp$/so/' <<< $lib) $lib"
|
||||
echo $COMPILE_COMMAND
|
||||
$COMPILE_COMMAND &
|
||||
COMPILE_COMMANDS=(
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/net/connection.so ./src/lib/net/connection.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/cli.so ./src/lib/cli.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/file.so ./src/lib/file.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/game/block.so ./src/lib/game/block.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/game/entity.so ./src/lib/game/entity.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/nbt.so ./src/lib/nbt.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -o ./bin/lib/region.so ./src/lib/region.cpp"
|
||||
"$CXX_WITH_FLAGS -I ./include -fPIC -shared -l:libz.so -o ./bin/lib/zlibutil.so ./src/lib/zlibutil.cpp"
|
||||
)
|
||||
for command in ${!COMPILE_COMMANDS[@]}; do
|
||||
echo "${COMPILE_COMMANDS[command]}"
|
||||
${COMPILE_COMMANDS[command]} &
|
||||
$WAIT_ANYWAY
|
||||
done
|
||||
|
||||
|
@ -55,12 +64,17 @@ wait
|
|||
# How to run a tool: specify the library path to use for the dynamic linker
|
||||
# when running a program
|
||||
# Example: LD_LIBRARY_PATH=bin/lib bin/tools/dumpnbt
|
||||
echo ">>> Building tools..."
|
||||
echo ">>> Building programs..."
|
||||
create_directory bin/tools
|
||||
# add compile commands to this array
|
||||
COMPILE_COMMANDS=(
|
||||
"$CXX_WITH_FLAGS src/tools/dumpnbt.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/tools/dumpnbt"
|
||||
"$CXX_WITH_FLAGS src/tools/hexnet.cpp -I./include -Lbin/lib -l:cli.so -l:libsockpp.so -o bin/tools/hexnet"
|
||||
"$CXX_WITH_FLAGS src/tools/dumpnbt.cpp -I./include -Lbin/lib -l:nbt.so -l:cli.so -o bin/tools/dumpnbt"
|
||||
"$CXX_WITH_FLAGS src/tools/arraydump.cpp -I./include -Lbin/lib -l:file.so -l:cli.so -o bin/tools/arraydump"
|
||||
"$CXX_WITH_FLAGS src/tools/baseconvert.cpp -I./include -Lbin/lib -l:cli.so -o bin/tools/baseconvert"
|
||||
"$CXX_WITH_FLAGS src/tools/zlibutil.cpp -I./include -Lbin/lib -l:cli.so -l:file.so -l:zlibutil.so -l:libz.so -o bin/tools/zlibutil"
|
||||
"$CXX_WITH_FLAGS -pthread src/tools/hexnet.cpp -I./include -Lbin/lib -l:cli.so -l:libsockpp.so -o bin/tools/hexnet"
|
||||
"$CXX_WITH_FLAGS -DFOSSVG_DEBUG src/fossvg.cpp -I./include -Lbin/lib -l:file.so -l:cli.so -lglfw -lvulkan -o bin/fossvg"
|
||||
"$CXX_WITH_FLAGS src/fossvgd.cpp -I./include -Lbin/lib -l:cli.so -o bin/fossvgd"
|
||||
)
|
||||
for command in ${!COMPILE_COMMANDS[@]}; do
|
||||
echo "${COMPILE_COMMANDS[command]}"
|
||||
|
@ -69,3 +83,21 @@ for command in ${!COMPILE_COMMANDS[@]}; do
|
|||
done
|
||||
|
||||
wait
|
||||
|
||||
echo ">>> Compiling shaders..."
|
||||
create_directory bin/shaders
|
||||
for shader in $(find ./src/shaders -name "*.vsh"); do
|
||||
COMPILE_COMMAND="dependencies/shaderc/bin/glslc -o $(sed -e 's/^.\/src/.\/bin/;s/vsh$/vsh.spv/' <<< $shader) -fshader-stage=vertex $shader"
|
||||
echo $COMPILE_COMMAND
|
||||
$COMPILE_COMMAND &
|
||||
$WAIT_ANYWAY
|
||||
done
|
||||
|
||||
for shader in $(find ./src/shaders -name "*.fsh"); do
|
||||
COMPILE_COMMAND="dependencies/shaderc/bin/glslc -o $(sed -e 's/^.\/src/.\/bin/;s/fsh$/fsh.spv/' <<< $shader) -fshader-stage=fragment $shader"
|
||||
echo $COMPILE_COMMAND
|
||||
$COMPILE_COMMAND &
|
||||
$WAIT_ANYWAY
|
||||
done
|
||||
|
||||
wait
|
||||
|
|
|
@ -25,14 +25,21 @@ remove .endianness
|
|||
remove resources/check_endianness
|
||||
create_directory ./bin
|
||||
create_directory ./bin/lib
|
||||
create_directory ./bin/lib/net
|
||||
create_directory ./include
|
||||
|
||||
ln -vs ../../dependencies/sockpp-0.7.1/build/libsockpp.so bin/lib/
|
||||
ln -vs ../../dependencies/sockpp-0.7.1/build/libsockpp.so.0 bin/lib/
|
||||
ln -vs ../../dependencies/sockpp-0.7.1/build/libsockpp.so.0.7.1 bin/lib/
|
||||
if uname -s | tr [:upper:] [:lower:] | grep cygwin >/dev/null; then
|
||||
ln -vs ../../dependencies/sockpp-0.8.1/build/cygsockpp-0.dll bin/lib/libsockpp.so
|
||||
ln -vs ../../dependencies/sockpp-0.8.1/build/cygsockpp-0.dll bin/lib/
|
||||
else
|
||||
ln -vs ../../dependencies/sockpp-0.8.1/build/libsockpp.so bin/lib/
|
||||
ln -vs ../../dependencies/sockpp-0.8.1/build/libsockpp.so.0 bin/lib/
|
||||
ln -vs ../../dependencies/sockpp-0.8.1/build/libsockpp.so.0.8.1 bin/lib/
|
||||
fi
|
||||
|
||||
ln -vs ../dependencies/sockpp-0.7.1/include/sockpp/ ./include/
|
||||
ln -vs ../dependencies/sockpp-0.8.1/include/sockpp/ ./include/
|
||||
ln -vs ../dependencies/tiny-utf8-4.4.3/include/tinyutf8/ ./include/
|
||||
ln -vs ../dependencies/zlib-1.3.1/ ./include/zlib
|
||||
|
||||
create_file ./bin/.placeholder
|
||||
create_file ./include/.placeholder
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
source scripts/lib.sh
|
||||
|
||||
#TODO: move this to download.sh
|
||||
echo ">>> Checking download cache for unneeded or corrupted files..."
|
||||
for file in $(ls .download_cache); do
|
||||
#TODO: remove if unknown shasum
|
||||
|
@ -35,6 +36,6 @@ done
|
|||
echo "
|
||||
>>> Cleaning dependencies..."
|
||||
|
||||
remove ./dependencies
|
||||
remove -f ./dependencies
|
||||
create_directory ./dependencies
|
||||
create_file ./dependencies/.placeholder
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
if [ "$#" -lt 3 -o "$#" -gt 3 ]; then
|
||||
echo "Usage: $0 URL DESTINATION SHA256SUM"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source scripts/lib.sh
|
||||
|
||||
URL="$1"
|
||||
DESTINATION="$2"
|
||||
SHA256SUM="$3"
|
||||
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
USE_WGET=yes
|
||||
else
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
USE_WGET=no
|
||||
else
|
||||
echo "Found neither wget nor curl. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -d .download_cache ]; then
|
||||
echo "Cache directory missing."
|
||||
create_directory .download_cache
|
||||
fi
|
||||
|
||||
#TODO: keep track of which cached file is downloaded to which destination
|
||||
#TODO: when downloading a file with a new hash to the same destination, mark the old one as no longer in use
|
||||
#TODO: if there is an even older one for the same download path, delete it
|
||||
#TODO: remove cache maintenance from clean_dependencies
|
||||
|
||||
if [ -f ".download_cache/$SHA256SUM" ]; then
|
||||
if check_sha256 ".download_cache/$SHA256SUM" "$SHA256SUM"; then
|
||||
echo "Using locally cached file for $DESTINATION"
|
||||
cp ".download_cache/$SHA256SUM" "$DESTINATION"
|
||||
exit 0
|
||||
else
|
||||
echo "Locally cached file for $DESTINATION is corrupted."
|
||||
rm ".download_cache/$SHA256SUM"
|
||||
$0 "$URL" "$DESTINATION" "$SHA256SUM"
|
||||
exit $?
|
||||
fi
|
||||
else
|
||||
echo -n "Downloading $URL to $DESTINATION... "
|
||||
if [ $USE_WGET = yes ]; then
|
||||
wget -O ".download_cache/$SHA256SUM" "$URL" >/dev/null 2>&1
|
||||
else
|
||||
curl -L "$URL" --output ".download_cache/$SHA256SUM" >/dev/null 2>&1
|
||||
fi
|
||||
if check_sha256 ".download_cache/$SHA256SUM" "$SHA256SUM"; then
|
||||
cp ".download_cache/$SHA256SUM" "$DESTINATION"
|
||||
echo "done."
|
||||
exit 0
|
||||
else
|
||||
echo "error."
|
||||
echo "Checksum verification failed. Your download is either corrupted or the file has been altered. Removing file."
|
||||
rm ".download_cache/$SHA256SUM"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
|
@ -57,11 +57,18 @@ fi
|
|||
# `rm -v` only prints the names of the removed things instead of a more
|
||||
# comprehensible message like "removing NAME".
|
||||
function remove {
|
||||
echo "Removing $1..."
|
||||
if [ -d "$1" ]; then
|
||||
rm -rv "$1"
|
||||
local USE_FORCE=""
|
||||
if [ "$1" = "-f" ]; then
|
||||
USE_FORCE="f"
|
||||
shift
|
||||
echo "Forcefully removing $1..."
|
||||
else
|
||||
rm -v "$1"
|
||||
echo "Removing $1..."
|
||||
fi;
|
||||
if [ -d "$1" ]; then
|
||||
rm -"$USE_FORCE"rv "$1"
|
||||
else
|
||||
rm -"$USE_FORCE"v "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
@ -17,68 +17,19 @@
|
|||
|
||||
source scripts/lib.sh
|
||||
|
||||
echo -n "Wget or curl? "
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
USE_WGET=yes
|
||||
echo "wget"
|
||||
else
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
USE_WGET=no
|
||||
echo "curl"
|
||||
else
|
||||
echo "Found neither wget nor curl. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
function download {
|
||||
URL="$1"
|
||||
DESTINATION="$2"
|
||||
SHA256SUM="$3"
|
||||
|
||||
if [ ! -d .download_cache ]; then
|
||||
echo "Cache directory missing."
|
||||
create_directory .download_cache
|
||||
fi
|
||||
|
||||
if [ -f ".download_cache/$SHA256SUM" ]; then
|
||||
if check_sha256 ".download_cache/$SHA256SUM" "$SHA256SUM"; then
|
||||
echo "Using locally cached file for $DESTINATION"
|
||||
cp ".download_cache/$SHA256SUM" "$DESTINATION"
|
||||
return 0
|
||||
else
|
||||
echo "Locally cached file for $DESTINATION is corrupted."
|
||||
rm ".download_cache/$SHA256SUM"
|
||||
download "$URL" "$DESTINATION" "$SHA256SUM"
|
||||
return $?
|
||||
fi
|
||||
else
|
||||
echo -n "Downloading $URL to $DESTINATION... "
|
||||
if [ $USE_WGET = yes ]; then
|
||||
wget -O ".download_cache/$SHA256SUM" "$URL" >/dev/null 2>&1
|
||||
else
|
||||
curl -L "$URL" --output ".download_cache/$SHA256SUM" >/dev/null 2>&1
|
||||
fi
|
||||
if check_sha256 ".download_cache/$SHA256SUM" "$SHA256SUM"; then
|
||||
cp ".download_cache/$SHA256SUM" "$DESTINATION"
|
||||
echo "done."
|
||||
return 0
|
||||
else
|
||||
echo "error."
|
||||
echo "Checksum verification failed. Your download is either corrupted or the file has been altered. Removing file."
|
||||
rm ".download_cache/$SHA256SUM"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
scripts/clean.sh
|
||||
scripts/clean_dependencies.sh
|
||||
|
||||
set -e # failures are not acceptable here
|
||||
create_directory dependencies/tmp
|
||||
download https://github.com/DuffsDevice/tiny-utf8/archive/refs/tags/v4.4.3.tar.gz dependencies/tmp/tiny-utf8.tar.gz 8e3f61651909c9f3105d3501932a96aa65733127fb6e7cf94cb1b0a2dff42c8f
|
||||
download https://github.com/fpagliughi/sockpp/archive/refs/tags/v0.7.1.tar.gz dependencies/tmp/sockpp.tar.gz 2e023528bebbd2ac083fc91fbe6d5c4158c3336bedbcff48f594f3b28f53b940
|
||||
scripts/download.sh https://github.com/DuffsDevice/tiny-utf8/archive/refs/tags/v4.4.3.tar.gz dependencies/tmp/tiny-utf8.tar.gz 8e3f61651909c9f3105d3501932a96aa65733127fb6e7cf94cb1b0a2dff42c8f
|
||||
scripts/download.sh https://github.com/fpagliughi/sockpp/archive/refs/tags/v0.8.1.tar.gz dependencies/tmp/sockpp.tar.gz a8aedff8bd8c1da530b91be650352008fddabc9f1df0d19701d76cbc359c8651
|
||||
scripts/download.sh https://www.zlib.net/zlib-1.3.1.tar.xz dependencies/tmp/zlib.tar.xz 38ef96b8dfe510d42707d9c781877914792541133e1870841463bfa73f883e32
|
||||
|
||||
#TODO: figure out how to cache shaderc
|
||||
#also TODO: target a specific commit
|
||||
git clone --branch known-good https://github.com/google/shaderc.git dependencies/tmp/shaderc
|
||||
#scripts/download.sh https://github.com/google/shaderc/archive/refs/tags/v2023.7.tar.gz dependencies/tmp/shaderc.tar.gz 681e1340726a0bf46bea7e31f10cbfe78e01e4446a35d90fedc2b78d400fcdeb
|
||||
|
||||
echo -n ">>> Extracting tiny-utf8... "
|
||||
gzip -d dependencies/tmp/tiny-utf8.tar.gz
|
||||
|
@ -90,11 +41,60 @@ gzip -d dependencies/tmp/sockpp.tar.gz
|
|||
tar -xf dependencies/tmp/sockpp.tar -C dependencies
|
||||
echo "done"
|
||||
|
||||
echo ">>> Building sockpp... "
|
||||
pushd dependencies/sockpp-0.7.1/ >/dev/null 2>&1
|
||||
cmake -Bbuild .
|
||||
cmake --build build
|
||||
echo -n ">>> Extracting zlib... "
|
||||
xz -d dependencies/tmp/zlib.tar.xz
|
||||
tar -xf dependencies/tmp/zlib.tar -C dependencies
|
||||
echo "done"
|
||||
|
||||
echo ">>> Building sockpp..."
|
||||
pushd dependencies/sockpp-0.8.1/ >/dev/null 2>&1
|
||||
if uname -s | tr [:upper:] [:lower:] | grep cygwin >/dev/null; then
|
||||
echo "Adding Cygwin workaound for building sockpp."
|
||||
|
||||
#for FILE in "$(find ./ -type f)"; do
|
||||
# sed -i -e 's/_WIN32/PLEASE_DO_NOT_DEFINE_THIS_MACRO/g' $FILE
|
||||
#done
|
||||
#mv ./include/sockpp/socket.h ./include/sockpp/socket.h_original
|
||||
#echo '#include <sys/time.h>
|
||||
##include "socket.h_original"' > ./include/sockpp/socket.h
|
||||
sed -i -e 's/SO_REUSEPORT/SO_REUSEADDR/g' ./src/acceptor.cpp
|
||||
|
||||
#CFLAGS="-D_XOPEN_SOURCE=700" CXXFLAGS="-D_XOPEN_SOURCE=700" cmake -Bbuild
|
||||
#CFLAGS="-D_XOPEN_SOURCE=700" CXXFLAGS="-D_XOPEN_SOURCE=700" cmake --build build
|
||||
cmake -Bbuild .
|
||||
cmake --build build
|
||||
else
|
||||
cmake -Bbuild .
|
||||
cmake --build build
|
||||
fi
|
||||
popd >/dev/null 2>&1
|
||||
echo ">>> done"
|
||||
|
||||
echo ">>> Dealing with shaderc shenanigans..."
|
||||
pushd dependencies/tmp/shaderc
|
||||
echo "Getting sources using the provided script..."
|
||||
./update_shaderc_sources.py
|
||||
SHADERC_BUILD="build-$(dd if=/dev/urandom bs=1 count=5 2>/dev/null | base32)"
|
||||
echo "Creating and entering directory $SHADERC_BUILD."
|
||||
mkdir "$SHADERC_BUILD"
|
||||
cd "$SHADERC_BUILD"
|
||||
echo "Running CMake..."
|
||||
CXXFLAGS="-Wno-error" cmake -GNinja -DCMAKE_BUILD_TYPE=Release ../src/
|
||||
echo "Running Ninja..."
|
||||
ninja
|
||||
popd >/dev/null 2>&1
|
||||
#if needed copy more relevant files to dependencies/shaderc
|
||||
echo "Copying binary to dependencies/shaderc/bin..."
|
||||
mkdir -vp dependencies/shaderc/bin
|
||||
cp -v "dependencies/tmp/shaderc/$SHADERC_BUILD/glslc/glslc" dependencies/shaderc/bin
|
||||
echo ">>> done"
|
||||
|
||||
echo ">>> Building zlib..."
|
||||
pushd dependencies/zlib-1.3.1/
|
||||
./configure
|
||||
make
|
||||
popd
|
||||
echo "done"
|
||||
|
||||
echo ">>> Cleaning up..."
|
||||
remove dependencies/tmp
|
||||
remove -f dependencies/tmp
|
||||
|
|
|
@ -33,12 +33,13 @@ echo ">>> Building tests..."
|
|||
|
||||
# add compile commands to this array
|
||||
COMPILE_COMMANDS=(
|
||||
"$CXX_WITH_FLAGS src/test/nbt_read_write_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_read_write_helpers"
|
||||
"$CXX_WITH_FLAGS src/test/nbt_read_write_helpers.cpp -I./include -Lbin/lib -l:nbt.so -o bin/test/nbt_read_write_helpers"
|
||||
"$CXX_WITH_FLAGS src/test/cli_argument_parser.cpp -Lbin/lib -l:cli.so -o bin/test/cli_argument_parser"
|
||||
"$CXX_WITH_FLAGS src/test/javacompat.cpp -I./include -Lbin/lib -l:javacompat.so -o bin/test/javacompat"
|
||||
"$CXX_WITH_FLAGS src/test/nbt_write_string_failure_mode.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_write_string_failure_mode"
|
||||
"$CXX_WITH_FLAGS src/test/nbt_tags.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_tags"
|
||||
"$CXX_WITH_FLAGS src/test/nbt_size_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_size_helpers"
|
||||
"$CXX_WITH_FLAGS src/test/javacompat.cpp -I./include -Lbin/lib -o bin/test/javacompat"
|
||||
"$CXX_WITH_FLAGS src/test/nbt_tags.cpp -I./include -Lbin/lib -l:nbt.so -o bin/test/nbt_tags"
|
||||
"$CXX_WITH_FLAGS src/test/nbt_size_helpers.cpp -I./include -Lbin/lib -l:nbt.so -o bin/test/nbt_size_helpers"
|
||||
"$CXX_WITH_FLAGS src/test/file.cpp -I./include -Lbin/lib -l:file.so -o bin/test/file"
|
||||
"$CXX_WITH_FLAGS src/test/varint.cpp -I./include -Lbin/lib -o bin/test/varint"
|
||||
)
|
||||
for command in ${!COMPILE_COMMANDS[@]}; do
|
||||
echo "${COMPILE_COMMANDS[command]}"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "================================================================================"
|
||||
echo -n "Testing \`arraydump\`... "
|
||||
[ -x bin/tools/arraydump ] \
|
||||
&& [ "$(bin/tools/arraydump resources/all_bytes)" = "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}" ] \
|
||||
&& [ "$(bin/tools/arraydump --hexadecimal resources/all_bytes)" = "{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}" ] \
|
||||
&& [ "$(bin/tools/arraydump --octal resources/all_bytes)" = "{0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377}" ] \
|
||||
&& [ "$(bin/tools/arraydump --binary resources/all_bytes)" = "{0b00000000, 0b00000001, 0b00000010, 0b00000011, 0b00000100, 0b00000101, 0b00000110, 0b00000111, 0b00001000, 0b00001001, 0b00001010, 0b00001011, 0b00001100, 0b00001101, 0b00001110, 0b00001111, 0b00010000, 0b00010001, 0b00010010, 0b00010011, 0b00010100, 0b00010101, 0b00010110, 0b00010111, 0b00011000, 0b00011001, 0b00011010, 0b00011011, 0b00011100, 0b00011101, 0b00011110, 0b00011111, 0b00100000, 0b00100001, 0b00100010, 0b00100011, 0b00100100, 0b00100101, 0b00100110, 0b00100111, 0b00101000, 0b00101001, 0b00101010, 0b00101011, 0b00101100, 0b00101101, 0b00101110, 0b00101111, 0b00110000, 0b00110001, 0b00110010, 0b00110011, 0b00110100, 0b00110101, 0b00110110, 0b00110111, 0b00111000, 0b00111001, 0b00111010, 0b00111011, 0b00111100, 0b00111101, 0b00111110, 0b00111111, 0b01000000, 0b01000001, 0b01000010, 0b01000011, 0b01000100, 0b01000101, 0b01000110, 0b01000111, 0b01001000, 0b01001001, 0b01001010, 0b01001011, 0b01001100, 0b01001101, 0b01001110, 0b01001111, 0b01010000, 0b01010001, 0b01010010, 0b01010011, 0b01010100, 0b01010101, 0b01010110, 0b01010111, 0b01011000, 0b01011001, 0b01011010, 0b01011011, 0b01011100, 0b01011101, 0b01011110, 0b01011111, 0b01100000, 0b01100001, 0b01100010, 0b01100011, 0b01100100, 0b01100101, 0b01100110, 0b01100111, 0b01101000, 0b01101001, 0b01101010, 0b01101011, 0b01101100, 0b01101101, 0b01101110, 0b01101111, 0b01110000, 0b01110001, 0b01110010, 0b01110011, 0b01110100, 0b01110101, 0b01110110, 0b01110111, 0b01111000, 0b01111001, 0b01111010, 0b01111011, 0b01111100, 0b01111101, 0b01111110, 0b01111111, 0b10000000, 0b10000001, 0b10000010, 0b10000011, 0b10000100, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10001001, 0b10001010, 0b10001011, 0b10001100, 0b10001101, 0b10001110, 0b10001111, 0b10010000, 0b10010001, 0b10010010, 0b10010011, 0b10010100, 0b10010101, 0b10010110, 0b10010111, 0b10011000, 0b10011001, 0b10011010, 0b10011011, 0b10011100, 0b10011101, 0b10011110, 0b10011111, 0b10100000, 0b10100001, 0b10100010, 0b10100011, 0b10100100, 0b10100101, 0b10100110, 0b10100111, 0b10101000, 0b10101001, 0b10101010, 0b10101011, 0b10101100, 0b10101101, 0b10101110, 0b10101111, 0b10110000, 0b10110001, 0b10110010, 0b10110011, 0b10110100, 0b10110101, 0b10110110, 0b10110111, 0b10111000, 0b10111001, 0b10111010, 0b10111011, 0b10111100, 0b10111101, 0b10111110, 0b10111111, 0b11000000, 0b11000001, 0b11000010, 0b11000011, 0b11000100, 0b11000101, 0b11000110, 0b11000111, 0b11001000, 0b11001001, 0b11001010, 0b11001011, 0b11001100, 0b11001101, 0b11001110, 0b11001111, 0b11010000, 0b11010001, 0b11010010, 0b11010011, 0b11010100, 0b11010101, 0b11010110, 0b11010111, 0b11011000, 0b11011001, 0b11011010, 0b11011011, 0b11011100, 0b11011101, 0b11011110, 0b11011111, 0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100, 0b11100101, 0b11100110, 0b11100111, 0b11101000, 0b11101001, 0b11101010, 0b11101011, 0b11101100, 0b11101101, 0b11101110, 0b11101111, 0b11110000, 0b11110001, 0b11110010, 0b11110011, 0b11110100, 0b11110101, 0b11110110, 0b11110111, 0b11111000, 0b11111001, 0b11111010, 0b11111011, 0b11111100, 0b11111101, 0b11111110, 0b11111111}" ] \
|
||||
&& echo "PASS" \
|
||||
|| echo "FAIL"
|
||||
echo "================================================================================"
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "================================================================================"
|
||||
echo -n "Testing \`baseconvert\`... "
|
||||
|
||||
[ $(baseconvert -d "0xFFFFFFFFFFFFFFFF") = "18446744073709551615" ] \
|
||||
&& [ $(baseconvert -x "0xFFFFFFFFFFFFFFFF") = "0xffffffffffffffff" ] \
|
||||
&& [ $(baseconvert -o "0xFFFFFFFFFFFFFFFF") = "01777777777777777777777" ] \
|
||||
&& [ $(baseconvert -b "0xFFFFFFFFFFFFFFFF") = "0b1111111111111111111111111111111111111111111111111111111111111111" ] \
|
||||
&& [ $(baseconvert -x "0XFFFFFFFFFFFFFFFF") = "0xffffffffffffffff" ] \
|
||||
&& [ $(baseconvert -d "0") = "0" ] \
|
||||
&& [ $(baseconvert -x "0") = "0x0" ] \
|
||||
&& [ $(baseconvert -o "0") = "0" ] \
|
||||
&& [ $(baseconvert -b "0") = "0b0" ] \
|
||||
&& [ $(baseconvert -b "4") = "0b100" ] \
|
||||
&& [ $(baseconvert -x "07777" ) = "0xfff" ] \
|
||||
&& [ $(baseconvert -x "0o7777" ) = "0xfff" ] \
|
||||
&& [ $(baseconvert -x "0O7777" ) = "0xfff" ] \
|
||||
&& [ $(baseconvert -o "0b1000" ) = "010" ] \
|
||||
&& [ $(baseconvert -o "0B1000" ) = "010" ] \
|
||||
&& echo "PASS" \
|
||||
|| echo "FAIL"
|
||||
echo "================================================================================"
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "================================================================================"
|
||||
echo -n "Testing \`dumpnbt\`... "
|
||||
|
||||
[ "$(dumpnbt resources/NBT_data/bare_int64_tag)" = "$(cat resources/NBT_data/bare_int64_tag.dumpnbt_out)" ] \
|
||||
&& [ "$(dumpnbt resources/NBT_data/bare_int64_tag_and_int32_tag)" = "$(cat resources/NBT_data/bare_int64_tag_and_int32_tag.dumpnbt_out)" ] \
|
||||
&& [ "$(dumpnbt resources/NBT_data/servers.dat)" = "$(cat resources/NBT_data/servers.dat.dumpnbt_out)" ] \
|
||||
&& [ "$(dumpnbt resources/NBT_data/simple_nbt)" = "$(cat resources/NBT_data/simple_nbt.dumpnbt_out)" ] \
|
||||
&& [ "$(dumpnbt resources/NBT_data/nested_compounds_and_lists)" = "$(cat resources/NBT_data/nested_compounds_and_lists.dumpnbt_out)" ] \
|
||||
&& [ "$(dumpnbt resources/NBT_data/level.dat_decompressed)" = "$(cat resources/NBT_data/level.dat_decompressed.dumpnbt_out)" ] \
|
||||
&& [ "$(dumpnbt resources/NBT_data/arrays_inside_lists)" = "$(cat resources/NBT_data/arrays_inside_lists.dumpnbt_out)" ] \
|
||||
&& echo "PASS" \
|
||||
|| echo "FAIL"
|
||||
echo "================================================================================"
|
||||
|
||||
#TODO: test with compressed NBT files
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env bash
|
||||
echo "================================================================================"
|
||||
echo "Testing \`zlibutil\`:"
|
||||
echo "--------------------------------------------------------------------------------"
|
||||
|
||||
TMPDIR="$(mktemp -d -t fossvg-zlibutil-XXXXX)"
|
||||
TMPDATA="$(dd if=/dev/urandom bs=33 count=1 2>/dev/null | base64)"
|
||||
|
||||
echo -n "Compression test... "
|
||||
|
||||
echo -n "$TMPDATA" >> "$TMPDIR/compress"
|
||||
zlibutil "$TMPDIR/compress"
|
||||
|
||||
python3 <<< "
|
||||
import zlib, sys
|
||||
tmpfile = open('$TMPDIR/compress.zz', 'rb')
|
||||
data = tmpfile.read()
|
||||
tmpfile.close()
|
||||
try:
|
||||
if zlib.decompress(data)==b'$TMPDATA':
|
||||
print('PASS')
|
||||
else:
|
||||
print('FAIL: Wrong data.')
|
||||
except:
|
||||
print('FAIL: Exception.')
|
||||
"
|
||||
|
||||
echo -n "Decompression test... "
|
||||
#TODO: create a compressed file using another implementation (Python)
|
||||
python3 <<< "
|
||||
import zlib
|
||||
tmpfile = open('$TMPDIR/decompress.zz', 'wb')
|
||||
tmpfile.write(zlib.compress(b'$TMPDATA'))
|
||||
tmpfile.close()
|
||||
"
|
||||
|
||||
zlibutil -d "$TMPDIR/decompress.zz"
|
||||
if [ "$(cat "$TMPDIR/decompress")" = "$TMPDATA" ]; then
|
||||
echo "PASS"
|
||||
else
|
||||
echo "FAIL"
|
||||
fi
|
||||
|
||||
rm -r "$TMPDIR"
|
||||
|
||||
echo "================================================================================"
|
|
@ -13,9 +13,15 @@
|
|||
# version 3 along with this program.
|
||||
# If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
echo -n "Loading shell environment for FOSS-VG development... "
|
||||
echo ">>> Loading shell environment for FOSS-VG development..."
|
||||
|
||||
PROJECT_BASE_DIR="$( cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 ; pwd -P )"
|
||||
export PROJECT_BASE_DIR="$( cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 ; pwd -P )"
|
||||
echo "Project base directory is $PROJECT_BASE_DIR"
|
||||
|
||||
if [ -f "$PROJECT_BASE_DIR/.localenv.bashrc" ]; then
|
||||
source "$PROJECT_BASE_DIR/.localenv.bashrc"
|
||||
echo "Applied local environment customizations."
|
||||
fi
|
||||
|
||||
alias clean="pushd \"$PROJECT_BASE_DIR\" >/dev/null 2>&1; scripts/clean.sh; popd >/dev/null 2>&1"
|
||||
alias clean_dependencies="pushd \"$PROJECT_BASE_DIR\" >/dev/null 2>&1; scripts/clean_dependencies.sh; popd >/dev/null 2>&1"
|
||||
|
@ -33,15 +39,79 @@ function build {
|
|||
popd >/dev/null 2>&1
|
||||
}
|
||||
|
||||
echo "Added aliases and functions."
|
||||
|
||||
export PATH="$PROJECT_BASE_DIR/bin:$PROJECT_BASE_DIR/bin/tools:$PROJECT_BASE_DIR/scripts/tools:$PATH"
|
||||
if uname -s | tr [:upper:] [:lower:] | grep cygwin >/dev/null; then
|
||||
echo "Adding Cygwin workaound for library path."
|
||||
export PATH="$PROJECT_BASE_DIR/bin/lib:$PATH"
|
||||
fi
|
||||
echo "PATH is $PATH"
|
||||
|
||||
if [ -z "$LD_LIBRARY_PATH" ]; then
|
||||
export LD_LIBRARY_PATH="$PROJECT_BASE_DIR"/bin/lib
|
||||
else
|
||||
export LD_LIBRARY_PATH="$PROJECT_BASE_DIR"/bin/lib:"$LD_LIBRARY_PATH"
|
||||
fi
|
||||
echo "LD_LIBRARY_PATH is $LD_LIBRARY_PATH"
|
||||
|
||||
if [ -f "$PROJECT_BASE_DIR/.localenv.bashrc" ]; then
|
||||
source "$PROJECT_BASE_DIR/.localenv.bashrc"
|
||||
echo ">>> Checking for dependencies..."
|
||||
MISSING_DEPS=0
|
||||
|
||||
if command -v wget > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
if command -v curl > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
echo "WARNING: \`wget\` or \`curl\` is needed to download some additional dependencies."
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "done."
|
||||
if command -v sha256sum > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
if command -v sha256 > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
echo "WARNING: Coreutils \`sha256sum\` or a \`sha256\` as found on NetBSD is needed to verify downloaded files."
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v gzip > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
echo "WARNING: \`gzip\` is needed to decompress downloaded dependencies."
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if command -v tar > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
echo "WARNING: \`tar\` is needed to unpack downloaded dependencies."
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if command -v cmake > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
echo "WARNING: \`cmake\` is needed to build downloaded dependencies."
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
|
||||
if [ -z "$CXX" ]; then
|
||||
if command -v c++ > /dev/null 2>&1; then
|
||||
true
|
||||
else
|
||||
echo "WARNING: Your system does not appear to have a standard C++ compiler. If you have a C++ compiler installed, but not linked to \`c++\` on your PATH, set it manually using \`CXX=/path/to/your/compiler\`."
|
||||
MISSING_DEPS=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$MISSING_DEPS" -eq 0 ]; then
|
||||
echo "All set."
|
||||
fi
|
||||
|
||||
unset MISSING_DEPS
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
extern "C" {
|
||||
#include <GLFW/glfw3.h>
|
||||
}
|
||||
|
||||
#include "./lib/cli.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
|
||||
uint32_t windowWidth = 1366;
|
||||
uint32_t windowHeight = 768;
|
||||
|
||||
//TODO: check the TODO above glfwInit() in void main()
|
||||
// #### Callbacks ##############################################################
|
||||
void cursorPositionCallback([[maybe_unused]] GLFWwindow* window, [[maybe_unused]] double x, [[maybe_unused]] double y) {
|
||||
}
|
||||
|
||||
void keyCallback([[maybe_unused]] GLFWwindow* window, [[maybe_unused]] int32_t key, [[maybe_unused]] int32_t scancode, [[maybe_unused]] int32_t action, [[maybe_unused]] int32_t mods) {
|
||||
}
|
||||
|
||||
void textInputCallback([[maybe_unused]] GLFWwindow* window, [[maybe_unused]] uint32_t codepoint) {
|
||||
}
|
||||
|
||||
void cursorEnterLeaveCallback([[maybe_unused]] GLFWwindow* window, [[maybe_unused]] int32_t entered) {
|
||||
}
|
||||
|
||||
void mouseButtonCallback([[maybe_unused]] GLFWwindow* window, [[maybe_unused]] int32_t button, [[maybe_unused]] int32_t action, [[maybe_unused]] int32_t mods) {
|
||||
}
|
||||
|
||||
void scrollCallback([[maybe_unused]] GLFWwindow* window, [[maybe_unused]] double x, [[maybe_unused]] double y) {
|
||||
}
|
||||
// #### End Callbacks ##########################################################
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('h', "help", "print help and exit"));
|
||||
flags.push_back(CLI::Flag('l', "license", "print license information and exit"));
|
||||
std::vector<CLI::Option> options;
|
||||
options.push_back(CLI::Option('x', "window-width", "PIXELS", "window width on startup"));
|
||||
options.push_back(CLI::Option('y', "window-height", "PIXELS", "window height on startup"));
|
||||
std::vector<CLI::Argument> arguments;
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "FOSS-VG Client");
|
||||
|
||||
if (cliParser.getFlag("help").value) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.getFlag("license").value){
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
<< "This program is free software: you can redistribute it and/or modify it\n"
|
||||
<< "under the terms of the GNU Affero General Public License as published\n"
|
||||
<< "by the Free Software Foundation, version 3.\n"
|
||||
<< "\n"
|
||||
<< "This program is distributed in the hope that it will be useful,\n"
|
||||
<< "but WITHOUT ANY WARRANTY; without even the implied\n"
|
||||
<< "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
<< "See the GNU Affero General Public License for more details.\n"
|
||||
<< "\n"
|
||||
<< "You should have received a copy of the GNU Affero General Public License\n"
|
||||
<< "version 3 along with this program.\n"
|
||||
<< "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
if (cliParser.getOption("window-width").errorCode != ErrorCodes::NOT_PRESENT) {
|
||||
windowWidth = std::stoi(cliParser.getOption("window-width").value);
|
||||
}
|
||||
|
||||
if (cliParser.getOption("window-height").errorCode != ErrorCodes::NOT_PRESENT) {
|
||||
windowHeight = std::stoi(cliParser.getOption("window-height").value);
|
||||
}
|
||||
|
||||
|
||||
// TODO: Find a better place for this
|
||||
// Ideally, the window management and rendering portion of FOSS-VG should
|
||||
// live in a library so it can be easily reloaded/restarted for things like
|
||||
// switching from/to fullscreen. For now, I am going to put it here because
|
||||
// I want to get it going before making it pretty.
|
||||
{
|
||||
if (!glfwInit()) {
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
// do not create OpenGL context
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
//TODO: add a version macro
|
||||
// (for example Git commit hash passed on the compiler command line)
|
||||
std::string windowTitle = "FOSS-VG";
|
||||
|
||||
// Apparently, this also allows to set things like whether the window is full-screen
|
||||
GLFWwindow* window = glfwCreateWindow(windowWidth, windowHeight, windowTitle.c_str(), nullptr, nullptr);
|
||||
|
||||
if (window == nullptr) {
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
glfwSetCursorPosCallback(window, cursorPositionCallback);
|
||||
glfwSetKeyCallback(window, keyCallback);
|
||||
glfwSetCharCallback(window, textInputCallback);
|
||||
glfwSetCursorEnterCallback(window, cursorEnterLeaveCallback);
|
||||
glfwSetMouseButtonCallback(window, mouseButtonCallback);
|
||||
glfwSetScrollCallback(window, scrollCallback);
|
||||
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "./lib/cli.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('h', "help", "print help and exit"));
|
||||
flags.push_back(CLI::Flag('l', "license", "print license information and exit"));
|
||||
std::vector<CLI::Option> options;
|
||||
std::vector<CLI::Argument> arguments;
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "FOSS-VG Server");
|
||||
|
||||
if (cliParser.getFlag("help").value) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.getFlag("license").value){
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
<< "This program is free software: you can redistribute it and/or modify it\n"
|
||||
<< "under the terms of the GNU Affero General Public License as published\n"
|
||||
<< "by the Free Software Foundation, version 3.\n"
|
||||
<< "\n"
|
||||
<< "This program is distributed in the hope that it will be useful,\n"
|
||||
<< "but WITHOUT ANY WARRANTY; without even the implied\n"
|
||||
<< "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
<< "See the GNU Affero General Public License for more details.\n"
|
||||
<< "\n"
|
||||
<< "You should have received a copy of the GNU Affero General Public License\n"
|
||||
<< "version 3 along with this program.\n"
|
||||
<< "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster, Shwoomple
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
|
@ -199,7 +202,6 @@ namespace CLI {
|
|||
}
|
||||
|
||||
ArgumentsParser::~ArgumentsParser() {
|
||||
//TODO: check that this actually runs
|
||||
for (auto const& [shortName, flag]: this->flagsByShortName) {
|
||||
delete flag;
|
||||
}
|
||||
|
@ -318,6 +320,10 @@ namespace CLI {
|
|||
}
|
||||
}
|
||||
|
||||
if (this->additionalInfo != "") {
|
||||
usageString += "\nAdditional Info:\n\n\t" + this->additionalInfo + "\n";
|
||||
}
|
||||
|
||||
return usageString;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,43 +17,54 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
//TODO: needed macros:
|
||||
// TRY: takes a variable, a function call, and the ErrorOr return type of the calling function - intended to automatically unwrap the ErrorOr data type or propagate the error upwards
|
||||
// RAISE: takes an error code and optionally a message to produce something like `return ErrorOr<T>(true, errorCode, file, lineNumber, message)`
|
||||
|
||||
template <typename T>
|
||||
struct ErrorOr {
|
||||
bool isError;
|
||||
uint8_t errorCode;
|
||||
T value;
|
||||
|
||||
ErrorOr();
|
||||
ErrorOr(T);
|
||||
ErrorOr(bool, uint8_t);
|
||||
ErrorOr(bool, uint8_t, T);
|
||||
ErrorOr() {
|
||||
this->isError = false;
|
||||
this->errorCode = 0;
|
||||
}
|
||||
|
||||
ErrorOr(T value) {
|
||||
this->isError = false;
|
||||
this->errorCode = 0;
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
ErrorOr(bool isError, uint8_t errorCode) {
|
||||
this->isError = isError;
|
||||
this->errorCode = errorCode;
|
||||
}
|
||||
|
||||
ErrorOr(bool isError, uint8_t errorCode, T value) {
|
||||
this->isError = isError;
|
||||
this->errorCode = errorCode;
|
||||
this->value = value;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
ErrorOr<T>::ErrorOr() {
|
||||
this->isError = false;
|
||||
this->errorCode = 0;
|
||||
}
|
||||
struct ErrorOrVoid {
|
||||
bool isError;
|
||||
uint8_t errorCode;
|
||||
|
||||
template <typename T>
|
||||
ErrorOr<T>::ErrorOr(T value) {
|
||||
this->isError = false;
|
||||
this->errorCode = 0;
|
||||
this->value = value;
|
||||
}
|
||||
ErrorOrVoid() {
|
||||
this->isError = false;
|
||||
this->errorCode = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ErrorOr<T>::ErrorOr(bool isError, uint8_t errorCode) {
|
||||
this->isError = isError;
|
||||
this->errorCode = errorCode;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ErrorOr<T>::ErrorOr(bool isError, uint8_t errorCode, T value) {
|
||||
this->isError = isError;
|
||||
this->errorCode = errorCode;
|
||||
this->value = value;
|
||||
}
|
||||
ErrorOrVoid(bool isError, uint8_t errorCode) {
|
||||
this->isError = isError;
|
||||
this->errorCode = errorCode;
|
||||
}
|
||||
};
|
||||
|
||||
namespace ErrorCodes {
|
||||
// These are all arbitrary values used to assign error codes to different
|
||||
|
@ -64,13 +75,10 @@ namespace ErrorCodes {
|
|||
// Ahh yes, very useful.
|
||||
const uint8_t SUCCESS = 0;
|
||||
|
||||
// IndexOutOfRangeException equivalent
|
||||
const uint8_t OUT_OF_RANGE = 1;
|
||||
|
||||
// when going out of bounds in a non-predetermined way
|
||||
// like OUT_OF_RANGE but when going out of bounds in a non-predetermined way
|
||||
const uint8_t OVERRUN = 2;
|
||||
|
||||
// when checking for presence of something, for example CLI arguments
|
||||
const uint8_t NOT_PRESENT = 3;
|
||||
|
||||
const uint8_t WRONG_USAGE = 4;
|
||||
|
@ -83,6 +91,23 @@ namespace ErrorCodes {
|
|||
|
||||
const uint8_t NOT_YET_KNOWN = 7;
|
||||
|
||||
const uint8_t INVALID_TYPE = 8;
|
||||
|
||||
const uint8_t FILE_NOT_OPEN = 9;
|
||||
const uint8_t FILE_NOT_FOUND = 10;
|
||||
|
||||
// when performing an operation that would technically be valid but must
|
||||
// never be performed (like deleting an end tag from an NBT compound)
|
||||
const uint8_t NOT_ALLOWED = 11;
|
||||
|
||||
const uint8_t MIXED_TYPES = 12;
|
||||
|
||||
// when too much data is available
|
||||
const uint8_t OVERFLOW = 13;
|
||||
|
||||
const uint8_t COMPRESSION = 14;
|
||||
const uint8_t DECOMPRESSION = 15;
|
||||
|
||||
const uint8_t UNIMPLEMENTED = 254;
|
||||
|
||||
const uint8_t UNKNOWN = 255;
|
||||
|
|
|
@ -0,0 +1,326 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// Bodgemaster, Shwoomple
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "tinyutf8/tinyutf8.h"
|
||||
#include "file.hpp"
|
||||
|
||||
File::File(std::string path, char mode, uint64_t cursorPosition): mode(mode), path(path), cursorPosition(cursorPosition){
|
||||
std::filesystem::path filePath = path;
|
||||
if(this->mode == 'w' || (this->mode == 'a' && !std::filesystem::exists(filePath))){
|
||||
this->size = ErrorOr<uint64_t>(0);
|
||||
}else{
|
||||
this->size = ErrorOr<uint64_t>(std::filesystem::file_size(filePath));
|
||||
}
|
||||
this->open();
|
||||
}
|
||||
|
||||
File::~File() {
|
||||
if (this->isOpen) {
|
||||
this->fileStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
void File::open(){
|
||||
switch(this->mode){
|
||||
case 'w':
|
||||
this->fileStream.open(this->path, std::fstream::out | std::fstream::binary);
|
||||
break;
|
||||
case 'm':
|
||||
this->fileStream.open(this->path, std::fstream::out | std::fstream::in | std::fstream::binary);
|
||||
break;
|
||||
case 'r':
|
||||
this->fileStream.open(this->path, std::fstream::in | std::fstream::binary);
|
||||
break;
|
||||
case 'a':
|
||||
this->fileStream.open(this->path, std::fstream::app | std::fstream::binary);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::filesystem::path filePath = this->path;
|
||||
this->size = ErrorOr<uint64_t>(std::filesystem::file_size(filePath));
|
||||
this->isOpen = this->fileStream.is_open();
|
||||
}
|
||||
|
||||
void File::close(){
|
||||
this->fileStream.close();
|
||||
std::filesystem::path filePath = this->path;
|
||||
this->size = ErrorOr<uint64_t>(std::filesystem::file_size(filePath));
|
||||
this->isOpen = false;
|
||||
}
|
||||
|
||||
bool File::eof() {
|
||||
return !this->size.isError && this->cursorPosition >= this->size.value;
|
||||
}
|
||||
|
||||
ErrorOr<uint8_t> File::readByte(){
|
||||
if (!this->isOpen) {
|
||||
return ErrorOr<uint8_t>(true, ErrorCodes::FILE_NOT_OPEN);
|
||||
}
|
||||
if (!this->size.isError && this->cursorPosition >= this->size.value) {
|
||||
return ErrorOr<uint8_t>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
uint8_t* nextPointer = new uint8_t;
|
||||
uint8_t nextByte;
|
||||
bool failure = false;
|
||||
|
||||
try {
|
||||
this->fileStream.seekg(this->cursorPosition);
|
||||
this->fileStream.read(reinterpret_cast<char*>(nextPointer), 1);
|
||||
nextByte = *nextPointer;
|
||||
this->cursorPosition++;
|
||||
|
||||
} catch (std::exception& e) {
|
||||
failure = true;
|
||||
}
|
||||
|
||||
delete nextPointer;
|
||||
return failure? ErrorOr<uint8_t>(true, ErrorCodes::UNKNOWN) : ErrorOr<uint8_t>(nextByte);
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> File::read(uint64_t bytes){
|
||||
if (!this->isOpen) {
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::FILE_NOT_OPEN);
|
||||
}
|
||||
if (!this->size.isError && this->cursorPosition >= this->size.value+bytes) {
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
uint8_t* buffer = new uint8_t[bytes];
|
||||
std::vector<uint8_t> data;
|
||||
bool failure = false;
|
||||
|
||||
try {
|
||||
this->fileStream.seekg(this->cursorPosition);
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), bytes);
|
||||
data = std::vector<uint8_t>(buffer, buffer+bytes);
|
||||
this->cursorPosition += bytes;
|
||||
|
||||
} catch (std::exception& e) {
|
||||
failure = true;
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
return failure? ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::UNKNOWN) : ErrorOr<std::vector<uint8_t>>(data);
|
||||
}
|
||||
|
||||
ErrorOr<tiny_utf8::string> File::readString(uint64_t bytes){
|
||||
ErrorOr<std::vector<uint8_t>> data = this->read(bytes);
|
||||
if(data.isError){
|
||||
return ErrorOr<tiny_utf8::string>(true, data.errorCode);
|
||||
}
|
||||
std::string s;
|
||||
for(auto byte: data.value){
|
||||
s.push_back(byte);
|
||||
}
|
||||
return ErrorOr<tiny_utf8::string>(tiny_utf8::string(s));
|
||||
}
|
||||
|
||||
ErrorOrVoid File::writeByte(uint8_t byte){
|
||||
|
||||
bool failure = false;
|
||||
|
||||
try{
|
||||
this->fileStream << byte;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
|
||||
return failure ? ErrorOrVoid(true, ErrorCodes::UNKNOWN) : ErrorOrVoid();
|
||||
}
|
||||
|
||||
ErrorOrVoid File::write(std::vector<uint8_t> data){
|
||||
bool failure = false;
|
||||
|
||||
try{
|
||||
this->fileStream << std::string(data.begin(), data.end());
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
|
||||
return failure ? ErrorOrVoid(true, ErrorCodes::UNKNOWN) : ErrorOrVoid();
|
||||
}
|
||||
|
||||
ErrorOrVoid File::writeString(tiny_utf8::string data){
|
||||
bool failure = false;
|
||||
|
||||
try{
|
||||
this->fileStream << data;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
return failure ? ErrorOrVoid(true, ErrorCodes::UNKNOWN) : ErrorOrVoid();
|
||||
}
|
||||
|
||||
// Naive implementation of insertByte
|
||||
ErrorOrVoid File::insertByte(uint8_t byte){
|
||||
bool failure = false;
|
||||
|
||||
try{
|
||||
uint8_t* buffer = new uint8_t[this->size.value];
|
||||
std::vector<uint8_t> readData;
|
||||
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), this->size.value);
|
||||
readData = std::vector<uint8_t>(buffer, buffer+this->size.value);
|
||||
|
||||
readData.insert(readData.begin()+this->cursorPosition, byte);
|
||||
this->fileStream.seekg(0);
|
||||
this->write(readData);
|
||||
this->cursorPosition++;
|
||||
delete[] buffer;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
return failure ? ErrorOrVoid(true, ErrorCodes::UNKNOWN) : ErrorOrVoid();
|
||||
}
|
||||
|
||||
|
||||
ErrorOrVoid File::insert(std::vector<uint8_t> data){
|
||||
bool failure = false;
|
||||
|
||||
try{
|
||||
uint8_t* buffer = new uint8_t[this->size.value];
|
||||
std::vector<uint8_t> readData;
|
||||
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), this->size.value);
|
||||
readData = std::vector<uint8_t>(buffer, buffer+this->size.value);
|
||||
|
||||
readData.insert(readData.begin()+this->cursorPosition, data.begin(), data.end());
|
||||
this->fileStream.seekg(0);
|
||||
this->write(readData);
|
||||
this->cursorPosition += data.size();
|
||||
delete[] buffer;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
return failure ? ErrorOrVoid(true, ErrorCodes::UNKNOWN) : ErrorOrVoid();
|
||||
}
|
||||
|
||||
ErrorOrVoid File::insertString(tiny_utf8::string string){
|
||||
bool failure = false;
|
||||
|
||||
try{
|
||||
uint8_t* buffer = new uint8_t[this->size.value];
|
||||
tiny_utf8::string readData;
|
||||
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), this->size.value);
|
||||
|
||||
readData = tiny_utf8::string((char *) buffer, 0, this->size.value);
|
||||
readData.insert(readData.begin()+this->cursorPosition, string);
|
||||
|
||||
this->fileStream.seekg(0);
|
||||
|
||||
this->writeString(readData);
|
||||
this->cursorPosition += string.size();
|
||||
delete[] buffer;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
return failure ? ErrorOrVoid(true, ErrorCodes::UNKNOWN) : ErrorOrVoid();
|
||||
}
|
||||
|
||||
ErrorOr<uint8_t> File::cutByte(){
|
||||
bool failure = false;
|
||||
uint8_t byte;
|
||||
try{
|
||||
uint8_t* buffer = new uint8_t[this->size.value];
|
||||
std::vector<uint8_t> readData;
|
||||
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), this->size.value);
|
||||
readData = std::vector<uint8_t>(buffer, buffer+this->size.value);
|
||||
|
||||
byte = readData[this->cursorPosition];
|
||||
readData.erase(readData.begin() + this->cursorPosition);
|
||||
|
||||
std::filesystem::resize_file(this->path, readData.size());
|
||||
this->fileStream.seekg(0);
|
||||
this->write(readData);
|
||||
//this->cursorPosition++;
|
||||
delete[] buffer;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
return failure ? ErrorOr<uint8_t>(true, ErrorCodes::UNKNOWN) : ErrorOr<uint8_t>(byte);
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> File::cut(uint64_t length){
|
||||
bool failure = false;
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
try{
|
||||
uint8_t* buffer = new uint8_t[this->size.value];
|
||||
std::vector<uint8_t> readData;
|
||||
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), this->size.value);
|
||||
readData = std::vector<uint8_t>(buffer, buffer+this->size.value);
|
||||
|
||||
bytes = std::vector<uint8_t>(readData.begin() + this->cursorPosition, readData.begin() + (this->cursorPosition + length));
|
||||
readData.erase(readData.begin() + this->cursorPosition, readData.begin() + (this->cursorPosition + length));
|
||||
|
||||
std::filesystem::resize_file(this->path, readData.size());
|
||||
this->fileStream.seekg(0);
|
||||
this->write(readData);
|
||||
//this->cursorPosition += length;
|
||||
delete[] buffer;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
|
||||
return failure ? ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::UNKNOWN) :ErrorOr<std::vector<uint8_t>>(bytes);
|
||||
}
|
||||
|
||||
ErrorOr<tiny_utf8::string> File::cutString(uint64_t length){
|
||||
bool failure = false;
|
||||
tiny_utf8::string cutString;
|
||||
try{
|
||||
uint8_t* buffer = new uint8_t[this->size.value];
|
||||
tiny_utf8::string readData;
|
||||
|
||||
this->fileStream.read(reinterpret_cast<char*>(buffer), this->size.value);
|
||||
readData = tiny_utf8::string((char *) buffer, 0, this->size.value);
|
||||
|
||||
cutString = readData.substr(this->cursorPosition, length);
|
||||
|
||||
std::filesystem::resize_file(this->path, readData.size()-cutString.size());
|
||||
this->fileStream.seekg(0);
|
||||
this->writeString(readData.substr(this->cursorPosition+length));
|
||||
//this->cursorPosition += length;
|
||||
delete[] buffer;
|
||||
}catch(std::exception& e){
|
||||
failure = true;
|
||||
}
|
||||
|
||||
return failure ? ErrorOr<tiny_utf8::string>(true, ErrorCodes::UNKNOWN) : ErrorOr<tiny_utf8::string>(cutString);
|
||||
}
|
||||
|
||||
ErrorOr<File*> File::open(std::string path, char mode, uint64_t startPosition){
|
||||
if (!std::filesystem::exists(path) && (mode == 'r' || mode == 'm')) {
|
||||
return ErrorOr<File*>(true, ErrorCodes::FILE_NOT_FOUND, nullptr);
|
||||
}
|
||||
|
||||
//TODO: check access perms
|
||||
|
||||
return ErrorOr<File*>(new File(path, mode, startPosition));
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster, Shwoomple
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <tinyutf8/tinyutf8.h>
|
||||
|
||||
#include "error.hpp"
|
||||
|
||||
|
||||
class File {
|
||||
private:
|
||||
//TODO: add other necessary internals to this section as needed
|
||||
char mode;
|
||||
std::fstream fileStream;
|
||||
//TODO: add other necessary details to the constructor as needed
|
||||
// For example, the fstream (or whatever mechanism is used) needs
|
||||
// to be handed over from File::open() to the File object.
|
||||
//
|
||||
// Remember to add a destructor to the public section if pointers
|
||||
// are to be used.
|
||||
File(std::string path, char mode, uint64_t cursorPosition);
|
||||
public:
|
||||
bool isOpen;
|
||||
std::string path;
|
||||
uint64_t cursorPosition;
|
||||
// may be error if not a regular file or size cannot be determined
|
||||
ErrorOr<uint64_t> size;
|
||||
|
||||
File() {};
|
||||
~File();
|
||||
|
||||
void open();
|
||||
void close();
|
||||
|
||||
bool eof();
|
||||
|
||||
// only applicable to read and edit modes
|
||||
// moves the cursor to the right of the read section
|
||||
ErrorOr<uint8_t> readByte();
|
||||
ErrorOr<std::vector<uint8_t>> read(uint64_t bytes);
|
||||
ErrorOr<tiny_utf8::string> readString(uint64_t bytes);
|
||||
|
||||
// only applicable to write, modify, append, and edit modes
|
||||
// in modify and edit modes, overwrite whatever is at the
|
||||
// cursor position if there is anything there
|
||||
// moves the cursor to the right of the written section
|
||||
ErrorOrVoid writeByte(uint8_t byte);
|
||||
ErrorOrVoid write(std::vector<uint8_t> data);
|
||||
ErrorOrVoid writeString(tiny_utf8::string string);
|
||||
|
||||
// only applicable to modify and edit modes
|
||||
// insert at cursor position and move other contents to the right
|
||||
// moves the cursor to the right of the inserted section
|
||||
ErrorOrVoid insertByte(uint8_t byte);
|
||||
ErrorOrVoid insert(std::vector<uint8_t> data);
|
||||
ErrorOrVoid insertString(tiny_utf8::string string);
|
||||
|
||||
// only applicable to edit mode
|
||||
// return the cut section, remove cut section from file
|
||||
// moves the cursor to the right of where it happened
|
||||
ErrorOr<uint8_t> cutByte();
|
||||
ErrorOr<std::vector<uint8_t>> cut(uint64_t length);
|
||||
ErrorOr<tiny_utf8::string> cutString(uint64_t length);
|
||||
|
||||
// modes:
|
||||
// r (read)
|
||||
// w (write: overwrite file deleting its previous contents)
|
||||
// a (append: write to end of file)
|
||||
// m (modify: write to file modifying its previous contents)
|
||||
//
|
||||
// A startPosition of 0xFFFFFFFF is considered to be the end of
|
||||
// the file whatever its size.
|
||||
static ErrorOr<File*> open(std::string path, char mode, uint64_t startPosition=0);
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace block {
|
||||
|
||||
// For internal use only. These are examples, we will probably need
|
||||
// a different way of assigning IDs in the future but a list should
|
||||
// be fine for now, I guess.
|
||||
// I don’t know how Minecraft assigns its IDs or if it even matters
|
||||
// given that it has used string IDs for a while now. We just need an
|
||||
// internal way to distinguish between classes.
|
||||
namespace ids {
|
||||
const uint16_t AIR = 0;
|
||||
const uint16_t STONE = 1;
|
||||
}
|
||||
|
||||
// These are intended to be combined using bitwise OR.
|
||||
namespace collisionBehavior {
|
||||
// Let the block handle it.
|
||||
// A function on the relevant block class will deal with it.
|
||||
const uint8_t UNKNOWN = 0b00000000;
|
||||
|
||||
// Collision box inhibits movement?
|
||||
// (stone or stone slab)
|
||||
const uint8_t SOLID = 0b00000001;
|
||||
|
||||
// Does collision box fill entire block?
|
||||
// (stone or grass block)
|
||||
//
|
||||
// The shape of the collision box is part of the relevant block class
|
||||
// when this bit is unset.
|
||||
const uint8_t FULL_BLOCK = 0b00000010;
|
||||
|
||||
const uint8_t SOLID_FULL_BLOCK = SOLID | FULL_BLOCK;
|
||||
|
||||
// Slow down entities when inside the block?
|
||||
// (vines or soulsand)
|
||||
//
|
||||
// Entities are considered to be inside a given block when rounding
|
||||
// their coordinates results in the coordinates of the block.
|
||||
//
|
||||
// The amount of slowdown is controlled by a function on the relevant
|
||||
// block class.
|
||||
const uint8_t SLOWDOWN = 0b00000100;
|
||||
|
||||
// Slow down entities when touching the collision box of the block?
|
||||
// (honey block)
|
||||
//
|
||||
// The amount of slowdown is controlled by a function on the relevant
|
||||
// block class.
|
||||
const uint8_t SURFACE_SLOWDOWN = 0b00001000;
|
||||
|
||||
// Deal damage when entities are inside it?
|
||||
// (berry bush)
|
||||
//
|
||||
// Entities are considered to be inside a given block when rounding
|
||||
// their coordinates results in the coordinates of the block.
|
||||
//
|
||||
// The amount of damage is controlled by a function on the relevant
|
||||
// block class.
|
||||
const uint8_t DAMAGE = 0b00010000;
|
||||
|
||||
// Deal damage when entities touch the collision box?
|
||||
// (magma block)
|
||||
//
|
||||
// The amount of damage is controlled by a function on the relevant
|
||||
// block class.
|
||||
const uint8_t SURFACE_DAMAGE = 0b00010000;
|
||||
|
||||
// Is the block bouncy?
|
||||
// (bed or slime block)
|
||||
//
|
||||
// The bounciness of the block is handled by the relevant block class.
|
||||
const uint8_t BOUNCY = 0b00100000;
|
||||
}
|
||||
|
||||
class Generic {
|
||||
private:
|
||||
public:
|
||||
virtual uint16_t id() = 0;
|
||||
virtual uint8_t collisionBehavior() = 0;
|
||||
|
||||
//TODO: (not pure) virtual functions for collision box, slowdown, damage, bounciness, etc.
|
||||
|
||||
//TODO: (not pure) virtual function for hitbox (defaults to full block)
|
||||
}
|
||||
|
||||
class Air {
|
||||
public:
|
||||
uint16_t id() {
|
||||
return ids::AIR;
|
||||
}
|
||||
uint8_t collisionBehavior() {
|
||||
// is a full block but doesn't collide or anything else
|
||||
return collisionBehavior::FULL_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
BlockGeneric* getNewBlockFromID(uint16_t id) {
|
||||
//TODO
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
//Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify it
|
||||
//under the terms of the GNU Affero General Public License as published
|
||||
//by the Free Software Foundation, version 3.
|
||||
//
|
||||
//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 Affero General Public License for more details.
|
||||
//
|
||||
//You should have received a copy of the GNU Affero General Public License
|
||||
//version 3 along with this program.
|
||||
//If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <tinyutf8/tinyutf8.h>
|
||||
#include <string>
|
||||
#include "error.hpp"
|
||||
#include "javacompat.hpp"
|
||||
#include "../../.endianness"
|
||||
|
||||
#ifdef FOSSVG_ENDIAN_BIG_WORD
|
||||
#error "Honeywell-316-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||
#endif
|
||||
#ifdef FOSSVG_ENDIAN_LITTLE_WORD
|
||||
#error "PDP-11-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||
#endif
|
||||
#ifdef FOSSVG_ENDIAN_UNKNOWN
|
||||
#error "The endianness of your system could not be determined. Please set it manually. FOSS-VG is currently implemented using some endian-specific functions."
|
||||
#endif
|
||||
|
||||
namespace JavaCompat {
|
||||
ErrorOr<tiny_utf8::string> importJavaString(uint8_t data[], uint16_t size) {
|
||||
std::string stdString;
|
||||
uint16_t encodedSize = static_cast<uint16_t>(data[0])<<8 | static_cast<uint16_t>(data[1]);
|
||||
|
||||
if(encodedSize != size){
|
||||
return ErrorOr<tiny_utf8::string>(true, ErrorCodes::MISMATCHEDSIZE);
|
||||
}
|
||||
|
||||
for(uint8_t i=2; i<size+2; i++){
|
||||
if(i != 0){
|
||||
if(data[i] == 0x80 && data[i-1] == 0xc0){
|
||||
stdString[stdString.length() - 1] = '\0';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
stdString.push_back((char) data[i]);
|
||||
}
|
||||
return ErrorOr<tiny_utf8::string>(tiny_utf8::string(stdString));
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> exportJavaString(tiny_utf8::string data) {
|
||||
uint16_t* size = new uint16_t;
|
||||
uint8_t* sizeBytes = reinterpret_cast<uint8_t*>(size);
|
||||
std::vector<uint8_t> output = std::vector<uint8_t>();
|
||||
std::string stdString = data.cpp_str();
|
||||
|
||||
if(stdString.size() > 0xFFFF){
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
*size = (uint16_t) stdString.size();
|
||||
|
||||
//placeholder size bytes
|
||||
output.push_back(0x00);
|
||||
output.push_back(0x00);
|
||||
for(uint16_t i=0; i<stdString.size(); i++){
|
||||
if((uint8_t) stdString[i] == 0x00){
|
||||
*size += 1;
|
||||
output.push_back(0xc0);
|
||||
output.push_back(0x80);
|
||||
continue;
|
||||
}
|
||||
output.push_back(stdString[i]);
|
||||
}
|
||||
|
||||
#ifdef FOSSVG_BIG_ENDIAN
|
||||
output[0] = *sizeBytes;
|
||||
output[1] = *(sizeBytes+1);
|
||||
#else
|
||||
#ifdef FOSSVG_LITTLE_ENDIAN
|
||||
output[0] = *(sizeBytes+1);
|
||||
output[1] = *sizeBytes;
|
||||
#else
|
||||
#error "NBT::helper::writeInt16: An implementation for your endianness is unavailable."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ErrorOr(output);
|
||||
}
|
||||
|
||||
}
|
|
@ -13,11 +13,83 @@
|
|||
//version 3 along with this program.
|
||||
//If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <vector>
|
||||
#pragma once
|
||||
|
||||
#include <tinyutf8/tinyutf8.h>
|
||||
#include <string>
|
||||
#include "error.hpp"
|
||||
#include "../../.endianness"
|
||||
|
||||
#ifdef FOSSVG_ENDIAN_BIG_WORD
|
||||
#error "Honeywell-316-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||
#endif
|
||||
#ifdef FOSSVG_ENDIAN_LITTLE_WORD
|
||||
#error "PDP-11-style endianness is not supported. If you feel like it should, feel free to participate in the project to maintain it."
|
||||
#endif
|
||||
#ifdef FOSSVG_ENDIAN_UNKNOWN
|
||||
#error "The endianness of your system could not be determined. Please set it manually. FOSS-VG is currently implemented using some endian-specific functions."
|
||||
#endif
|
||||
|
||||
namespace JavaCompat {
|
||||
ErrorOr<tiny_utf8::string> importJavaString(uint8_t data[], uint16_t size);
|
||||
ErrorOr<std::vector<uint8_t>> exportJavaString(tiny_utf8::string data);
|
||||
ErrorOr<tiny_utf8::string> importJavaString(uint8_t data[], uint16_t size) {
|
||||
std::string stdString;
|
||||
uint16_t encodedSize = static_cast<uint16_t>(data[0])<<8 | static_cast<uint16_t>(data[1]);
|
||||
|
||||
if(encodedSize != size){
|
||||
return ErrorOr<tiny_utf8::string>(true, ErrorCodes::MISMATCHEDSIZE);
|
||||
}
|
||||
|
||||
for(uint16_t i=2; i<size+2; i++){
|
||||
if(i != 0){
|
||||
if(data[i] == 0x80 && data[i-1] == 0xc0){
|
||||
stdString[stdString.length() - 1] = '\0';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
stdString.push_back((char) data[i]);
|
||||
}
|
||||
return ErrorOr<tiny_utf8::string>(tiny_utf8::string(stdString));
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> exportJavaString(tiny_utf8::string data) {
|
||||
uint16_t* size = new uint16_t;
|
||||
uint8_t* sizeBytes = reinterpret_cast<uint8_t*>(size);
|
||||
std::vector<uint8_t> output = std::vector<uint8_t>();
|
||||
std::string stdString = data.cpp_str();
|
||||
|
||||
if(stdString.size() > 0xFFFF){
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
*size = (uint16_t) stdString.size();
|
||||
|
||||
//placeholder size bytes
|
||||
output.push_back(0x00);
|
||||
output.push_back(0x00);
|
||||
for(uint16_t i=0; i<stdString.size(); i++){
|
||||
if((uint8_t) stdString[i] == 0x00){
|
||||
*size += 1;
|
||||
output.push_back(0xc0);
|
||||
output.push_back(0x80);
|
||||
continue;
|
||||
}
|
||||
output.push_back(stdString[i]);
|
||||
}
|
||||
|
||||
//FIXME: endian-dependent implementation
|
||||
#ifdef FOSSVG_BIG_ENDIAN
|
||||
output[0] = *sizeBytes;
|
||||
output[1] = *(sizeBytes+1);
|
||||
#else
|
||||
#ifdef FOSSVG_LITTLE_ENDIAN
|
||||
output[0] = *(sizeBytes+1);
|
||||
output[1] = *sizeBytes;
|
||||
#else
|
||||
#error "JavaCompat::exportJavaString: An implementation for your endianness is unavailable."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ErrorOr(output);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
1462
src/lib/nbt.cpp
1462
src/lib/nbt.cpp
File diff suppressed because it is too large
Load Diff
296
src/lib/nbt.hpp
296
src/lib/nbt.hpp
|
@ -19,29 +19,31 @@
|
|||
// NBT tags have a type, optionally a name which consists of the name size and the name string, optionally content type, and optionally a payload which can consist of optionally content type, optionally a content size,
|
||||
// and the stored content. The format in which they are stored is as follows: <type><name size><name><payload>. All numbers are stored in big endian representation.
|
||||
// All tag types:
|
||||
// generic representation: Tag(uint8:tag_type, String:name, uint16:name_size, byte[]:content, int32:size)
|
||||
// None (compound end): Tag( 0, "", 0, None, 0) => used to determine the end of a compound tag, only the type gets stored
|
||||
// int8: Tag( 1, String:name, uint16:name_size, int8:content, 1) => a single signed byte, size not stored
|
||||
// int16: Tag( 2, String:name, uint16:name_size, int16:content, 2) => 16 bit signed integer, size not stored
|
||||
// int32: Tag( 3, String:name, uint16:name_size, int32:content, 4) => 32 bit signed integer, size not stored
|
||||
// int64: Tag( 4, String:name, uint16:name_size, int64:content, 8) => 64 bit signed integer, size not stored
|
||||
// float: Tag( 5, String:name, uint16:name_size, float:content, 4) => 32 bit IEEE754 floating point number, size not stored
|
||||
// double: Tag( 6, String:name, uint16:name_size, double:content, 8) => 64 bit IEEE754 floating point number, size not stored
|
||||
// int8[]: Tag( 7, String:name, uint16:name_size, int8[]:content, int32:size) => content stored prefixed with size
|
||||
// String: Tag( 8, String:name, uint16:name_size, String:content, uint16:size) => Java style modified UTF-8 string, content stored prefixed with size
|
||||
// Tag[] (list): Tag<Tag:type>( 9, String:name, uint16:name_size, Tag[]:content, int32:size) => list of tags of the same type with tag type and name information omitted prefixed by (in order) content type and size
|
||||
// Tag[] (compound): Tag(10, String:name, uint16:name_size, Tag[]:content, int32:size) => list of tags, last tag is always an end tag, size not stored
|
||||
// int32[]: Tag(11, String:name, uint16:name_size, int32[]:content,int32:size) => list of 32 bit signed integers prefixed with its size, endianness not verified at this point
|
||||
// int64[]: Tag(12, String:name, uint16:name_size, int64[]:content,int32:size) => list of 64 bit signed integers prefixed with its size, endianness not verified at this point
|
||||
// Generic: Tag(uint8:tag_type, String:name, uint16:name_size, byte[]:content, int32:size)
|
||||
// End: Tag( 0, "", 0, None, 0) => used to determine the end of a compound tag, only the type gets stored
|
||||
// Int8: Tag( 1, String:name, uint16:name_size, int8:content, 1) => a single signed byte, size not stored
|
||||
// Int16: Tag( 2, String:name, uint16:name_size, int16:content, 2) => 16 bit signed integer, size not stored
|
||||
// Int32: Tag( 3, String:name, uint16:name_size, int32:content, 4) => 32 bit signed integer, size not stored
|
||||
// Int64: Tag( 4, String:name, uint16:name_size, int64:content, 8) => 64 bit signed integer, size not stored
|
||||
// Float: Tag( 5, String:name, uint16:name_size, float:content, 4) => 32 bit IEEE754 floating point number, size not stored
|
||||
// Double: Tag( 6, String:name, uint16:name_size, double:content, 8) => 64 bit IEEE754 floating point number, size not stored
|
||||
// Int8Array: Tag( 7, String:name, uint16:name_size, int8[]:content, int32:length) => content stored prefixed with size
|
||||
// String: Tag( 8, String:name, uint16:name_size, String:content, uint16:size) => Java style modified UTF-8 string, content stored prefixed with size
|
||||
// List: Tag<Tag:type>( 9, String:name, uint16:name_size, Tag[]:content, int32:length) => list of tags of the same type with tag type and name information omitted prefixed by (in order) content type and length
|
||||
// Compound: Tag(10, String:name, uint16:name_size, Tag[]:content, int32:length) => list of tags, last tag is always an end tag, size not stored
|
||||
// Int32Array: Tag(11, String:name, uint16:name_size, int32[]:content,int32:length) => list of 32 bit signed integers prefixed with its size
|
||||
// Int64Array: Tag(12, String:name, uint16:name_size, int64[]:content,int32:length) => list of 64 bit signed integers prefixed with its size
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <tinyutf8/tinyutf8.h>
|
||||
#include <mutex>
|
||||
|
||||
#include "error.hpp"
|
||||
|
||||
namespace NBT {
|
||||
namespace helper {
|
||||
namespace Helper {
|
||||
ErrorOr<int8_t> readInt8(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
|
||||
ErrorOr<int16_t> readInt16(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
|
||||
ErrorOr<int32_t> readInt32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
|
||||
|
@ -61,7 +63,7 @@ namespace NBT {
|
|||
void writeDouble(std::vector<uint8_t>* destination, double data);
|
||||
void writeInt8Array(std::vector<uint8_t>* destination, std::vector<int8_t> data);
|
||||
void writeInt8Array(std::vector<uint8_t>* destination, int8_t data[], uint32_t dataSize);
|
||||
void writeString(std::vector<uint8_t>* destination, tiny_utf8::string data);
|
||||
ErrorOrVoid writeString(std::vector<uint8_t>* destination, tiny_utf8::string data);
|
||||
void writeInt32Array(std::vector<uint8_t>* destination, std::vector<int32_t> data);
|
||||
void writeInt32Array(std::vector<uint8_t>* destination, int32_t data[], uint32_t dataSize);
|
||||
void writeInt64Array(std::vector<uint8_t>* destination, std::vector<int64_t> data);
|
||||
|
@ -72,46 +74,236 @@ namespace NBT {
|
|||
}
|
||||
|
||||
namespace TagType {
|
||||
const uint8_t END = 0;
|
||||
const uint8_t INT8 = 1;
|
||||
const uint8_t INT16 = 2;
|
||||
const uint8_t INT32 = 3;
|
||||
const uint8_t INT64 = 4;
|
||||
const uint8_t FLOAT = 5;
|
||||
const uint8_t DOUBLE = 6;
|
||||
const uint8_t INT8_ARRAY = 7;
|
||||
const uint8_t STRING = 8;
|
||||
const uint8_t LIST = 9;
|
||||
const uint8_t COMPOUND = 10;
|
||||
const uint8_t INT32_ARRAY= 11;
|
||||
const uint8_t INT64_ARRAY= 12;
|
||||
const uint8_t END = 0;
|
||||
const uint8_t INT8 = 1;
|
||||
const uint8_t INT16 = 2;
|
||||
const uint8_t INT32 = 3;
|
||||
const uint8_t INT64 = 4;
|
||||
const uint8_t FLOAT = 5;
|
||||
const uint8_t DOUBLE = 6;
|
||||
const uint8_t INT8_ARRAY = 7;
|
||||
const uint8_t STRING = 8;
|
||||
const uint8_t LIST = 9;
|
||||
const uint8_t COMPOUND = 10;
|
||||
const uint8_t INT32_ARRAY= 11;
|
||||
const uint8_t INT64_ARRAY= 12;
|
||||
// This is a workaround that's not part of the spec.
|
||||
const uint8_t INVALID = 255;
|
||||
}
|
||||
|
||||
//Generic parent class to make declaration easier
|
||||
template <typename T>
|
||||
class Tag{
|
||||
public:
|
||||
uint8_t tagType;
|
||||
tiny_utf8::string name;
|
||||
uint16_t nameSize;
|
||||
T content;
|
||||
int32_t size;
|
||||
namespace Tag {
|
||||
|
||||
Tag(){}
|
||||
Tag(uint8_t tagType, tiny_utf8::string name, uint16_t nameSize, T content, uint32_t size);
|
||||
};
|
||||
class Generic {
|
||||
protected:
|
||||
std::mutex mutex;
|
||||
uint8_t type;
|
||||
public:
|
||||
tiny_utf8::string name;
|
||||
|
||||
class End: public Tag<uint8_t>{
|
||||
public:
|
||||
End();
|
||||
};
|
||||
Generic();
|
||||
virtual ~Generic();
|
||||
|
||||
class Byte: public Tag<int8_t>{
|
||||
public:
|
||||
Byte(tiny_utf8::string name, uint16_t nameSize, int8_t content);
|
||||
Byte(uint8_t data[]);
|
||||
bool validate(uint8_t data[]);
|
||||
};
|
||||
virtual ErrorOrVoid serialize(std::vector<uint8_t>* rawData);
|
||||
virtual ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData);
|
||||
uint8_t getTagType();
|
||||
};
|
||||
|
||||
bool validateRawNBTData(uint8_t data[], int length, uint64_t initialPosition=0);
|
||||
class End: public Generic {
|
||||
public:
|
||||
End();
|
||||
|
||||
// This needs a separate serializer because
|
||||
// END tags have a special header.
|
||||
ErrorOrVoid serialize(std::vector<uint8_t>* rawData) override;
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
};
|
||||
|
||||
class Int8: public Generic {
|
||||
private:
|
||||
int8_t value;
|
||||
public:
|
||||
Int8();
|
||||
Int8(tiny_utf8::string name, int8_t value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
int8_t getValue();
|
||||
void setValue(int8_t value);
|
||||
};
|
||||
|
||||
class Int16: public Generic {
|
||||
private:
|
||||
int16_t value;
|
||||
public:
|
||||
Int16();
|
||||
Int16(tiny_utf8::string name, int16_t value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
int16_t getValue();
|
||||
void setValue(int16_t value);
|
||||
};
|
||||
|
||||
class Int32: public Generic {
|
||||
private:
|
||||
int32_t value;
|
||||
public:
|
||||
Int32();
|
||||
Int32(tiny_utf8::string name, int32_t value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
int32_t getValue();
|
||||
void setValue(int32_t value);
|
||||
};
|
||||
|
||||
class Int64: public Generic {
|
||||
private:
|
||||
int64_t value;
|
||||
public:
|
||||
Int64();
|
||||
Int64(tiny_utf8::string name, int64_t value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
int64_t getValue();
|
||||
void setValue(int64_t value);
|
||||
};
|
||||
|
||||
class Float: public Generic {
|
||||
private:
|
||||
float value;
|
||||
public:
|
||||
Float();
|
||||
Float(tiny_utf8::string name, float value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
float getValue();
|
||||
void setValue(float value);
|
||||
};
|
||||
|
||||
class Double: public Generic {
|
||||
private:
|
||||
double value;
|
||||
public:
|
||||
Double();
|
||||
Double(tiny_utf8::string name, double value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
double getValue();
|
||||
void setValue(double value);
|
||||
};
|
||||
|
||||
class Int8Array: public Generic {
|
||||
private:
|
||||
std::vector<int8_t> data;
|
||||
public:
|
||||
Int8Array();
|
||||
Int8Array(tiny_utf8::string name, std::vector<int8_t> data);
|
||||
Int8Array(tiny_utf8::string name, uint64_t length, int8_t data[]);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
|
||||
std::vector<int8_t> getData();
|
||||
ErrorOr<int8_t> getValue(uint64_t position);
|
||||
void setData(std::vector<int8_t> newData);
|
||||
ErrorOrVoid setValue(uint64_t position, int8_t value);
|
||||
uint64_t length();
|
||||
void addElement(int8_t element);
|
||||
ErrorOrVoid removeElement(uint64_t position);
|
||||
};
|
||||
|
||||
class String: public Generic {
|
||||
private:
|
||||
tiny_utf8::string value;
|
||||
public:
|
||||
String();
|
||||
String(tiny_utf8::string name, tiny_utf8::string value);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
tiny_utf8::string getValue();
|
||||
void setValue(tiny_utf8::string value);
|
||||
};
|
||||
|
||||
class List: public Generic {
|
||||
private:
|
||||
std::vector<Generic*> tags;
|
||||
uint8_t containedType;
|
||||
List(tiny_utf8::string name, std::vector<Generic*> data);
|
||||
public:
|
||||
List();
|
||||
List(tiny_utf8::string name, uint8_t type);
|
||||
|
||||
~List() override;
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
|
||||
uint8_t getContainedType();
|
||||
ErrorOr<Generic*> getElementPointer(uint64_t position);
|
||||
ErrorOrVoid setElementPointerAt(uint64_t position, Generic* pointer);
|
||||
ErrorOrVoid appendPointer(Generic* pointer);
|
||||
ErrorOrVoid deleteElement(uint64_t position);
|
||||
uint64_t length();
|
||||
static ErrorOr<List*> constructWithData(tiny_utf8::string name, std::vector<Generic*> data);
|
||||
};
|
||||
|
||||
class Compound: public Generic {
|
||||
private:
|
||||
std::vector<Generic*> tags;
|
||||
// built-in end tag
|
||||
End* endPointer;
|
||||
Compound(tiny_utf8::string name, std::vector<Generic*> data);
|
||||
public:
|
||||
Compound();
|
||||
Compound(tiny_utf8::string name);
|
||||
|
||||
~Compound() override;
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
|
||||
ErrorOr<Generic*> getElementPointer(uint64_t position);
|
||||
ErrorOrVoid setElementPointerAt(uint64_t position, Generic* pointer);
|
||||
ErrorOrVoid appendPointer(Generic* pointer);
|
||||
ErrorOrVoid deleteElement(uint64_t position);
|
||||
uint64_t length();
|
||||
static ErrorOr<Compound*> constructWithData(tiny_utf8::string name, std::vector<Generic*> data);
|
||||
};
|
||||
|
||||
class Int32Array: public Generic {
|
||||
private:
|
||||
std::vector<int32_t> data;
|
||||
public:
|
||||
Int32Array();
|
||||
Int32Array(tiny_utf8::string name, std::vector<int32_t> data);
|
||||
Int32Array(tiny_utf8::string name, uint64_t length, int32_t data[]);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
|
||||
std::vector<int32_t> getData();
|
||||
ErrorOr<int32_t> getValue(uint64_t position);
|
||||
void setData(std::vector<int32_t> newData);
|
||||
ErrorOrVoid setValue(uint64_t position, int32_t value);
|
||||
uint64_t length();
|
||||
void addElement(int32_t element);
|
||||
ErrorOrVoid removeElement(uint64_t position);
|
||||
};
|
||||
|
||||
class Int64Array: public Generic {
|
||||
private:
|
||||
std::vector<int64_t> data;
|
||||
public:
|
||||
Int64Array();
|
||||
Int64Array(tiny_utf8::string name, std::vector<int64_t> data);
|
||||
Int64Array(tiny_utf8::string name, uint64_t length, int64_t data[]);
|
||||
|
||||
ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData) override;
|
||||
|
||||
std::vector<int64_t> getData();
|
||||
ErrorOr<int64_t> getValue(uint64_t position);
|
||||
void setData(std::vector<int64_t> newData);
|
||||
ErrorOrVoid setValue(uint64_t position, int64_t value);
|
||||
uint64_t length();
|
||||
void addElement(int64_t element);
|
||||
ErrorOrVoid removeElement(uint64_t position);
|
||||
};
|
||||
}
|
||||
|
||||
ErrorOr<std::vector<Tag::Generic*>> deserialize(uint8_t data[], uint64_t dataSize, uint64_t initialPosition=0, uint64_t* processedDataSize=nullptr);
|
||||
bool validateRawNBTData(uint8_t data[], uint64_t dataSize, uint64_t initialPosition=0, uint64_t* processedDataSize=nullptr);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "../error.hpp"
|
||||
|
||||
namespace network {
|
||||
struct Connection {
|
||||
}
|
||||
|
||||
// host could be a hostname or address
|
||||
ErrorOr<Connection> connect(std::string host);
|
||||
void disconnect(Connection);
|
||||
|
||||
// start listening for incoming connections
|
||||
ErrorOrVoid startListening();
|
||||
// stop listening for new incoming connections but keep existing
|
||||
// connections open
|
||||
void stopListening();
|
||||
// stop listening for incoming connections and disconnect all
|
||||
void stopCommunication();
|
||||
|
||||
ErrorOr<Connection> acceptNextIncoming();
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "../../error.hpp"
|
||||
|
||||
namespace Position {
|
||||
struct Location {
|
||||
// 26 bit integer
|
||||
int32_t x;
|
||||
// 12 bit integer
|
||||
int16_t y;
|
||||
// 26 bit integer
|
||||
int32_t z;
|
||||
}
|
||||
|
||||
Location fromPosition(uint64_t position) {
|
||||
Location location;
|
||||
|
||||
location.x = (int32_t) ((0xFFFFFFC000000000 & position) >> 38);
|
||||
if (location.x >= 0x02000000) {
|
||||
location.x -= 0x04000000;
|
||||
}
|
||||
|
||||
location.y = (int16_t) ((0x0000000000000FFF & position));
|
||||
if (location.y >= 0x0800) {
|
||||
location.y -= 0x1000;
|
||||
}
|
||||
|
||||
location.z = (int32_t) ((0x0000003FFFFFF000 & position) >> 12);
|
||||
if (location.z >= 0x02000000) {
|
||||
location.z -= 0x04000000;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<Location> fromPosition(std::vector data, uint64_t initialPosition=0) {
|
||||
if (inititalPosition >= data.size()) {
|
||||
return ErrorOr<Location>(true, ErrorCodes::OUT_OF_BOUNDS);
|
||||
}
|
||||
if (initialPosition+7 >= data.size()) {
|
||||
return ErrorOr<Location>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
uint64_t deserialized = 0;
|
||||
for (uint8_t i=0; i<8; i++) {
|
||||
deserialized += (uint64_t) data[initialPosition+i] << i*8;
|
||||
}
|
||||
|
||||
return ErrorOr<Location>(fromPosition(deserialized));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster, Shwoomple
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "../../error.hpp"
|
||||
|
||||
namespace VarInt {
|
||||
|
||||
// up to 5 bytes, least significant byte first, most significant bit
|
||||
// indicates whether the next byte is still part of the number
|
||||
ErrorOr<int32_t> fromVar32(std::vector<uint8_t> data, uint64_t initialPosition=0, uint8_t* processedBytes=nullptr) {
|
||||
if (initialPosition >= data.size()) {
|
||||
return ErrorOr<int32_t>(true, ErrorCodes::OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
int32_t returnValue = 0;
|
||||
uint64_t currentPosition = initialPosition;
|
||||
uint8_t bits = 0;
|
||||
while (data[currentPosition] & 0b10000000 && currentPosition < initialPosition+4) {
|
||||
returnValue = returnValue + (((int32_t) 0b01111111 & data[currentPosition]) << bits);
|
||||
|
||||
(*processedBytes)++;
|
||||
bits += 7;
|
||||
currentPosition++;
|
||||
// check after increasing so we don't need to check outside the loop
|
||||
if (currentPosition >= data.size()) {
|
||||
return ErrorOr<int32_t>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
}
|
||||
if (data[currentPosition] & 0b10000000) {
|
||||
return ErrorOr<int32_t>(true, ErrorCodes::OVERFLOW);
|
||||
}
|
||||
returnValue = returnValue + (((int32_t) 0b01111111 & data[currentPosition]) << bits);
|
||||
(*processedBytes)++;
|
||||
|
||||
return ErrorOr<int32_t>(returnValue);
|
||||
}
|
||||
|
||||
// up to 10 bytes, least significant byte first, most significant bit
|
||||
// indicates whether the next byte is still part of the number
|
||||
ErrorOr<int64_t> fromVar64(std::vector<uint8_t> data, uint64_t initialPosition=0, uint8_t* processedBytes=nullptr) {
|
||||
if (initialPosition >= data.size()) {
|
||||
return ErrorOr<int64_t>(true, ErrorCodes::OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
int64_t returnValue = 0;
|
||||
uint64_t currentPosition = initialPosition;
|
||||
uint8_t bits = 0;
|
||||
while (data[currentPosition] & 0b10000000 && currentPosition < initialPosition+9) {
|
||||
returnValue = returnValue + (((int64_t) 0b01111111 & data[currentPosition]) << bits);
|
||||
|
||||
(*processedBytes)++;
|
||||
bits += 7;
|
||||
currentPosition++;
|
||||
// check after increasing so we don't need to check outside the loop
|
||||
if (currentPosition >= data.size()) {
|
||||
return ErrorOr<int64_t>(true, ErrorCodes::OVERRUN);
|
||||
}
|
||||
}
|
||||
if (data[currentPosition] & 0b10000000) {
|
||||
return ErrorOr<int64_t>(true, ErrorCodes::OVERFLOW);
|
||||
}
|
||||
returnValue = returnValue + (((int64_t) 0b01111111 & data[currentPosition]) << bits);
|
||||
(*processedBytes)++;
|
||||
|
||||
return ErrorOr<int64_t>(returnValue);
|
||||
}
|
||||
|
||||
// appends to the vector
|
||||
void toVar32(int32_t value, std::vector<uint8_t> &data) {
|
||||
uint8_t nextByte;
|
||||
uint8_t shift = 0;
|
||||
// do something else after the 4th shift
|
||||
while (shift < 4) {
|
||||
if (shift>0 && value==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nextByte = value & 0b01111111;
|
||||
|
||||
value = (value >> 7) & 0x01FFFFFF;
|
||||
shift++;
|
||||
|
||||
|
||||
if (value>0) {
|
||||
nextByte = nextByte + 0b10000000;
|
||||
}
|
||||
data.push_back(nextByte);
|
||||
|
||||
}
|
||||
if (value>0) {
|
||||
data.push_back(value & 0b00001111);
|
||||
}
|
||||
}
|
||||
|
||||
// appends to the vector
|
||||
void toVar64(int64_t value, std::vector<uint8_t> &data) {
|
||||
uint8_t nextByte;
|
||||
uint8_t shift = 0;
|
||||
// do something else after the 4th shift
|
||||
while (shift < 9) {
|
||||
if (shift>0 && value==0) {
|
||||
return;
|
||||
}
|
||||
|
||||
nextByte = value & 0b01111111;
|
||||
|
||||
value = (value >> 7) & 0x01FFFFFFFFFFFFFF;
|
||||
shift++;
|
||||
|
||||
if (value>0) {
|
||||
nextByte = nextByte + 0b10000000;
|
||||
}
|
||||
data.push_back(nextByte);
|
||||
|
||||
}
|
||||
if (value>0) {
|
||||
data.push_back(value & 0b00000001);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Packet {
|
||||
struct DataContainer {
|
||||
uint32_t typeID;
|
||||
std::vector<uint8_t> payload;
|
||||
}
|
||||
|
||||
namespace TypeID {
|
||||
// These are guessed names for what the package IDs could mean.
|
||||
// Some package IDs are used multiple times. I assume the different
|
||||
// connection states (handshaking, status, login, and play) play a role
|
||||
// in identifying what kind of package has been received.
|
||||
|
||||
// State: handshaking
|
||||
const uint32_t HANDSHAKE = 0;
|
||||
|
||||
// State: status
|
||||
const uint32_t STATUS = 0;
|
||||
const uint32_t PING = 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2023, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2023, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
|
||||
// File structure:
|
||||
// 4K table of uint32_t: pointing to chunks
|
||||
// -> 24bit offset, 8 bit length
|
||||
// -> both offset and length are multiplied by 4096 to get the real value
|
||||
// -> lowest valid offset = 2
|
||||
// -> chunk is not present if pointer=0
|
||||
// -> chunk calculation: ((x % 32) + (z % 32) * 32) * 4
|
||||
// -> what about negative chunks?
|
||||
// 4k table of uint32_t: last modified timestamps
|
||||
// individual chunks
|
||||
// -> 5 byte header
|
||||
// -> 4 byte length
|
||||
// -> 1 byte compression type: 0?? 1->gzip 2->zlib
|
||||
// -> extension idea: support for other compression algorithms
|
||||
// - lzma
|
||||
// - xz
|
||||
// - lz4
|
||||
// - zstd
|
||||
// -> compressed NBT data
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Region {
|
||||
uint32_t storagePointers[1024];
|
||||
uint32_t lastModifiedTimestamps[1024];
|
||||
|
||||
// Chunk coordinates are uint8_t here bc they are 0<=x<32.
|
||||
uint32_t* coordsToStoragePointer(uint8_t x, uint8_t z) {
|
||||
return &storagePointers[z*32 + x];
|
||||
}
|
||||
|
||||
// Chunk coordinates are uint8_t here bc they are 0<=x<32.
|
||||
uint32_t* coordsToLastModified(uint8_t x, uint8_t z) {
|
||||
return &lastModifiedTimestamps[z*32 + x];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// Jocadbz
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
// includes vector and error.hpp
|
||||
#include "zlibutil.hpp"
|
||||
|
||||
#include <zlib/zlib.h>
|
||||
#include <cstring>
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
|
||||
#define CHUNK_SIZE 16384 // Chunk size
|
||||
|
||||
namespace zlib {
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> compressData(std::vector<uint8_t> data) {
|
||||
// I, too, love the fact that raw bytes are signed and therefore can have negative values. -_-
|
||||
std::vector<int8_t> signedData = std::vector<int8_t>(data.begin(), data.end());
|
||||
|
||||
z_stream zs;
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
if (deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK) {
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::COMPRESSION);
|
||||
//TODO: include error message once implemented
|
||||
//throw(std::runtime_error("deflateInit failed while compressing."));
|
||||
}
|
||||
|
||||
zs.next_in = reinterpret_cast<Bytef*>(reinterpret_cast<char*>(signedData.data()));
|
||||
zs.avail_in = signedData.size();
|
||||
|
||||
int ret;
|
||||
char outbuffer[CHUNK_SIZE];
|
||||
std::vector<char> compressedData;
|
||||
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = CHUNK_SIZE;
|
||||
|
||||
ret = deflate(&zs, Z_FINISH);
|
||||
|
||||
if (compressedData.size() < zs.total_out)
|
||||
compressedData.insert(compressedData.end(), outbuffer, outbuffer + CHUNK_SIZE - zs.avail_out);
|
||||
} while (ret == Z_OK);
|
||||
|
||||
deflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) {
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::COMPRESSION);
|
||||
//TODO: include error message once implemented
|
||||
//throw(std::runtime_error("Error while compressing: " + std::to_string(ret)));
|
||||
}
|
||||
|
||||
return ErrorOr<std::vector<uint8_t>>(std::vector<uint8_t>(compressedData.begin(), compressedData.end()));
|
||||
}
|
||||
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> decompressData(std::vector<uint8_t> data) {
|
||||
// I, too, love the fact that raw bytes are signed and therefore can have negative values. -_-
|
||||
std::vector<int8_t> signedData = std::vector<int8_t>(data.begin(), data.end());
|
||||
|
||||
z_stream zs;
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
if (inflateInit(&zs) != Z_OK) {
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::DECOMPRESSION);
|
||||
//TODO: include error message once implemented
|
||||
//throw(std::runtime_error("inflateInit failed while decompressing."));
|
||||
}
|
||||
|
||||
zs.next_in = reinterpret_cast<Bytef*>(reinterpret_cast<char*>(signedData.data()));
|
||||
zs.avail_in = signedData.size();
|
||||
|
||||
int ret;
|
||||
char outbuffer[CHUNK_SIZE];
|
||||
std::vector<char> decompressedData;
|
||||
|
||||
do {
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
|
||||
zs.avail_out = CHUNK_SIZE;
|
||||
|
||||
ret = inflate(&zs, 0);
|
||||
|
||||
if (decompressedData.size() < zs.total_out)
|
||||
decompressedData.insert(decompressedData.end(), outbuffer, outbuffer + CHUNK_SIZE - zs.avail_out);
|
||||
} while (ret == Z_OK);
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
if (ret != Z_STREAM_END) {
|
||||
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::DECOMPRESSION);
|
||||
//TODO: include error message once implemented
|
||||
//throw(std::runtime_error("Error while decompressing: " + std::to_string(ret)));
|
||||
}
|
||||
|
||||
return ErrorOr<std::vector<uint8_t>>(std::vector<uint8_t>(decompressedData.begin(), decompressedData.end()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2024, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// Jocadbz
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "error.hpp"
|
||||
|
||||
namespace zlib {
|
||||
ErrorOr<std::vector<uint8_t>> compressData(std::vector<uint8_t> data);
|
||||
ErrorOr<std::vector<uint8_t>> decompressData(std::vector<uint8_t> data);
|
||||
}
|
|
@ -746,5 +746,19 @@ int main() {
|
|||
ASSERT(noCLIParser.getUsage() == "Help: universecreator\n\n\tCreate a universe with a banana and an apple.\n\nUsage: universecreator \n");
|
||||
std::cout << "Passed no CLI input usage test." << std::endl;
|
||||
|
||||
// additional info test ############################################
|
||||
std::vector<CLI::Flag> additionalInfoCLIFlags;
|
||||
|
||||
std::vector<CLI::Option> additionalInfoCLIOptions;
|
||||
|
||||
std::vector<CLI::Argument> additionalInfoCLIArguments;
|
||||
|
||||
const char** additionalInfoCLICommand = new const char*[1];
|
||||
additionalInfoCLICommand[0] = "universecreator";
|
||||
CLI::ArgumentsParser additionalInfoCLIParser = CLI::ArgumentsParser(1, additionalInfoCLICommand, additionalInfoCLIFlags, additionalInfoCLIOptions, additionalInfoCLIArguments, "Create a universe with a banana and an apple.", "Rick Astley was here.");
|
||||
|
||||
ASSERT(additionalInfoCLIParser.getUsage() == "Help: universecreator\n\n\tCreate a universe with a banana and an apple.\n\nUsage: universecreator \n\nAdditional Info:\n\n\tRick Astley was here.\n");
|
||||
std::cout << "Passed additional info test." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <vector>
|
||||
#include "assert.hpp"
|
||||
#include "tinyutf8/tinyutf8.h"
|
||||
#include "../lib/file.hpp"
|
||||
|
||||
int main(){
|
||||
std::cout << "################################################################################" << std::endl;
|
||||
std::cout << "File tests" << std::endl;
|
||||
std::cout << "################################################################################" << std::endl;
|
||||
File* file;
|
||||
|
||||
//readByte test
|
||||
file = File::open("resources/unicode_data/normal_utf-8", 'r').value;
|
||||
uint8_t byte = file->readByte().value;
|
||||
ASSERT(byte == 'T');
|
||||
std::cout << "Passed read byte test." << std::endl;
|
||||
|
||||
//read test
|
||||
std::vector<uint8_t> bytes = file->read(5).value;
|
||||
//cursorPosition has already moved forward by one
|
||||
ASSERT(bytes == std::vector<uint8_t>({'e', 's', 't', ' ', 's'}));
|
||||
std::cout << "Passed read test." << std::endl;
|
||||
|
||||
//readString test
|
||||
tiny_utf8::string data = file->readString(5).value;
|
||||
ASSERT(data == "tring");
|
||||
std::cout << "Passed read string test." << std::endl;
|
||||
file->close();
|
||||
delete file;
|
||||
|
||||
//Write Tests
|
||||
File *writeFile;
|
||||
File *readFile;
|
||||
|
||||
//writeByte test
|
||||
writeFile = File::open("resources/writeTest", 'w').value;
|
||||
writeFile->writeByte('a');
|
||||
writeFile->close();
|
||||
|
||||
readFile = File::open("resources/writeTest", 'r').value;
|
||||
uint8_t testByte = readFile->readByte().value;
|
||||
readFile->close();
|
||||
ASSERT(testByte == 'a');
|
||||
std::cout << "Passed write byte test." << std::endl;
|
||||
|
||||
//write test
|
||||
writeFile->open();
|
||||
writeFile->write(std::vector<uint8_t>({'a', 'b', 'c'}));
|
||||
writeFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string testBytes = readFile->readString(3).value;
|
||||
readFile->close();
|
||||
ASSERT(testBytes == "abc");
|
||||
std::cout << "Passed write test." << std::endl;
|
||||
|
||||
writeFile->open();
|
||||
writeFile->writeString(tiny_utf8::string("Hallo"));
|
||||
writeFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string testString = readFile->readString(5).value;
|
||||
readFile->close();
|
||||
ASSERT(testString == "Hallo");
|
||||
std::cout << "Passed write string test." << std::endl;
|
||||
|
||||
delete writeFile;
|
||||
|
||||
File *appendFile;
|
||||
|
||||
appendFile = File::open("resources/writeTest", 'a').value;
|
||||
appendFile->writeByte(',');
|
||||
appendFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string appendByteString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(appendByteString == "Hallo,");
|
||||
std::cout << "Passed append byte test." << std::endl;
|
||||
|
||||
appendFile->open();
|
||||
appendFile->write(std::vector<uint8_t>({' ', 'I', 'c', 'h'}));
|
||||
appendFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string appendBytesString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(appendBytesString == "Hallo, Ich");
|
||||
std::cout << "Passed append test" << std::endl;
|
||||
|
||||
appendFile->open();
|
||||
appendFile->writeString(" bin Shwoomple.");
|
||||
appendFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string appendString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(appendString == "Hallo, Ich bin Shwoomple.");
|
||||
std::cout << "Passed append string test" << std::endl;
|
||||
|
||||
delete appendFile;
|
||||
|
||||
//test insert functions
|
||||
File *modifyFile;
|
||||
|
||||
modifyFile = File::open("resources/writeTest", 'm').value;
|
||||
|
||||
modifyFile->cursorPosition = 5;
|
||||
modifyFile->insertByte(',');
|
||||
modifyFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string modifyByteString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(modifyByteString == "Hallo,, Ich bin Shwoomple.");
|
||||
std::cout << "Passed modify byte test" << std::endl;
|
||||
|
||||
modifyFile->open();
|
||||
modifyFile->cursorPosition = 6;
|
||||
modifyFile->insert(std::vector<uint8_t>({' ', 'H', 'i'}));
|
||||
modifyFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string modifyBytesString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(modifyBytesString == "Hallo, Hi, Ich bin Shwoomple.");
|
||||
std::cout << "Passed modify test" << std::endl;
|
||||
|
||||
modifyFile->open();
|
||||
modifyFile->cursorPosition = 9;
|
||||
modifyFile->insertString(" THE CAKE IS A LIE");
|
||||
modifyFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string modifyString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(modifyString == "Hallo, Hi THE CAKE IS A LIE, Ich bin Shwoomple.");
|
||||
std::cout << "Passed modify string test" << std::endl;
|
||||
|
||||
//test cut functions
|
||||
modifyFile->open();
|
||||
modifyFile->cursorPosition = modifyFile->size.value-1;
|
||||
ErrorOr<uint8_t> cutByte = modifyFile->cutByte();
|
||||
modifyFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string cutByteString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(modifyFile->cursorPosition == modifyFile->size.value);
|
||||
ASSERT(cutByte.value == '.');
|
||||
ASSERT(cutByteString == "Hallo, Hi THE CAKE IS A LIE, Ich bin Shwoomple");
|
||||
std::cout << "Passed cut byte test." << std::endl;
|
||||
|
||||
modifyFile->open();
|
||||
modifyFile->cursorPosition = 9;
|
||||
ErrorOr<std::vector<uint8_t>> cutBytes = modifyFile->cut(18);
|
||||
modifyFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string cutBytesString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
|
||||
ASSERT(modifyFile->cursorPosition == 9);
|
||||
ASSERT(cutBytes.value == std::vector<uint8_t>({' ', 'T', 'H', 'E', ' ', 'C', 'A', 'K', 'E', ' ', 'I', 'S', ' ','A', ' ', 'L', 'I', 'E'}))
|
||||
ASSERT(cutBytesString == "Hallo, Hi, Ich bin Shwoomple");
|
||||
std::cout << "Passed cut test." << std::endl;
|
||||
|
||||
modifyFile->open();
|
||||
modifyFile->cursorPosition = 0;
|
||||
ErrorOr<tiny_utf8::string> cutString = modifyFile->cutString(7);
|
||||
modifyFile->close();
|
||||
|
||||
readFile->open();
|
||||
readFile->cursorPosition = 0;
|
||||
tiny_utf8::string cutReadString = readFile->readString(readFile->size.value).value;
|
||||
readFile->close();
|
||||
|
||||
ASSERT(modifyFile->cursorPosition == 0);
|
||||
ASSERT(cutString.value == "Hallo, ");
|
||||
ASSERT(cutReadString == "Hi, Ich bin Shwoomple");
|
||||
std::cout << "Passed cutString test." << std::endl;
|
||||
}
|
|
@ -75,7 +75,16 @@ int main(){
|
|||
|
||||
tiny_utf8::string normalString = tiny_utf8::string(normalStdString);
|
||||
|
||||
// check for normal operation
|
||||
ASSERT(normalString == importedString);
|
||||
|
||||
// check for mismatched size error
|
||||
std::string javaStdStringCopy = javaStdString;
|
||||
javaStdStringCopy[0]='b';
|
||||
ErrorOr<tiny_utf8::string> errorString = JavaCompat::importJavaString(reinterpret_cast<uint8_t*>(javaStdStringCopy.data()), 0x75);
|
||||
ASSERT(errorString.isError);
|
||||
ASSERT(errorString.errorCode == ErrorCodes::MISMATCHEDSIZE);
|
||||
|
||||
std::cout << "Passed Import Java string test." << std::endl;
|
||||
|
||||
//using normalString from when we read the file earlier
|
||||
|
@ -91,5 +100,5 @@ int main(){
|
|||
std::cout << "Passed Export Java string test." << std::endl;
|
||||
delete nextChar;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,32 +29,41 @@ int main(){
|
|||
std::cout << "NBT read/write helper tests" << std::endl;
|
||||
std::cout << "################################################################################" << std::endl;
|
||||
|
||||
uint8_t validNBTDataBlob[] = {0x0a, 0x00, 0x00, 0x08, 0x00, 0x3e, 0x53, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x61, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x61, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2c, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3f, 0x00, 0x16, 0x49, 0x64, 0x6b, 0x2e, 0x20, 0x4c, 0x65, 0x74, 0xe2, 0x80, 0x99, 0x73, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x0a, 0x00, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x03, 0x00, 0x0b, 0x73, 0x6f, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xd3, 0x07, 0x23, 0x41, 0x08, 0x00, 0x09, 0x73, 0x6f, 0x6d, 0x65, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x00, 0x0c, 0x65, 0x61, 0x74, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x00, 0x06, 0x00, 0x06, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x41, 0x23, 0x07, 0xd3, 0x4e, 0xfd, 0x07, 0xf1, 0x05, 0x00, 0x05, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x42, 0x0d, 0x12, 0x43, 0x02, 0x00, 0x05, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x07, 0xd0, 0x03, 0x00, 0x05, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x00, 0x9a, 0x21, 0x12, 0x0b, 0x00, 0x0b, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x00, 0x04, 0x17, 0xbf, 0xe8, 0x3c, 0x00, 0x00, 0xa8, 0xfb, 0x7f, 0xff, 0xff, 0xff, 0x61, 0x72, 0x72, 0x61, 0x04, 0x00, 0x05, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x00, 0x00, 0x00, 0xbc, 0x97, 0xde, 0x9e, 0x3e, 0x0c, 0x00, 0x0b, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xa8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x67, 0xe7, 0xbd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xab, 0xd8, 0x00, 0x00, 0xab, 0xd8, 0x00, 0x0b, 0x12, 0x21, 0x00, 0x79, 0x61, 0x72, 0x01, 0x00, 0x04, 0x69, 0x6e, 0x74, 0x38, 0x64, 0x07, 0x00, 0x0a, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x00, 0x00, 0x00, 0x08, 0x71, 0x35, 0x77, 0x62, 0x54, 0x64, 0xf5, 0x32, 0x09, 0x00, 0x09, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x38, 0x01, 0x00, 0x00, 0x00, 0x05, 0x41, 0x60, 0x4e, 0x7f, 0xfa, 0x09, 0x00, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x50, 0x61, 0x63, 0x6d, 0x61, 0x6e, 0x00, 0x03, 0x61, 0x74, 0x65, 0x00, 0x03, 0x61, 0x6c, 0x6c, 0x00, 0x03, 0x74, 0x68, 0x65, 0x00, 0x04, 0x64, 0x6f, 0x74, 0x73, 0x00, 0x02, 0x73, 0x6f, 0x00, 0x03, 0x6e, 0x6f, 0x77, 0x00, 0x06, 0x68, 0x65, 0xe2, 0x80, 0x99, 0x73, 0x00, 0x06, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x00, 0x03, 0x66, 0x6f, 0x72, 0x00, 0x03, 0x74, 0x68, 0x65, 0x00, 0x06, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x08, 0x00, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x00};
|
||||
uint64_t validNBTDataBlobSize = 478;
|
||||
uint64_t currentPositionInBlob;
|
||||
|
||||
// used for all integer tests
|
||||
uint8_t dataForIntTest[] = {30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
|
||||
uint64_t dataSize = 10;
|
||||
uint64_t currentPosition;
|
||||
|
||||
// int8 ############################################################
|
||||
// read successfully
|
||||
uint64_t currentPosition = 5;
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 35);
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
currentPosition = 5;
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 35);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// begin of data
|
||||
currentPosition = 0;
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 30);
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 30);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// end of data
|
||||
currentPosition = 9;
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 39);
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 39);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// out of bounds
|
||||
currentPosition = 10;
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0x13A;
|
||||
ASSERT(NBT::Helper::readInt8(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt8(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == 100);
|
||||
|
||||
std::cout << "Passed readInt8 NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* writeInt8TestResult = new std::vector<uint8_t>();
|
||||
NBT::helper::writeInt8(writeInt8TestResult, (int8_t) 8);
|
||||
NBT::Helper::writeInt8(writeInt8TestResult, (int8_t) 8);
|
||||
std::vector<uint8_t> dereferencedWriteInt8TestResult = *writeInt8TestResult;
|
||||
delete writeInt8TestResult;
|
||||
ASSERT(dereferencedWriteInt8TestResult.back() == (uint8_t) 8);
|
||||
|
@ -64,29 +73,33 @@ int main(){
|
|||
// int16 ###########################################################
|
||||
// read successfully
|
||||
currentPosition = 5;
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).value == 8996);
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).value == 8996);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// begin of data
|
||||
currentPosition = 0;
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).value == 7711);
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).value == 7711);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// end of data
|
||||
currentPosition = 8;
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).value == 9767);
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).value == 9767);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// partially out of bounds
|
||||
currentPosition = 9;
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// fully out of bounds
|
||||
currentPosition = 10;
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0xb9;
|
||||
ASSERT(NBT::Helper::readInt16(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt16(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == 2000);
|
||||
|
||||
std::cout << "Passed readInt16 NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* writeInt16TestResult = new std::vector<uint8_t>();
|
||||
NBT::helper::writeInt16(writeInt16TestResult, (int16_t) 0xABCD);
|
||||
NBT::Helper::writeInt16(writeInt16TestResult, (int16_t) 0xABCD);
|
||||
std::vector<uint8_t> dereferencedWriteInt16TestResult = *writeInt16TestResult;
|
||||
delete writeInt16TestResult;
|
||||
ASSERT(dereferencedWriteInt16TestResult[0] == (uint8_t) 0xAB && dereferencedWriteInt16TestResult[1] == (uint8_t) 0xCD);
|
||||
|
@ -96,29 +109,34 @@ int main(){
|
|||
// int32 ###########################################################
|
||||
// read successfully
|
||||
currentPosition = 5;
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).value == 589571366);
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).value == 589571366);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// begin of data
|
||||
currentPosition = 0;
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).value == 505356321);
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).value == 505356321);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// end of data
|
||||
currentPosition = 6;
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).value == 606414375);
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).value == 606414375);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// partially out of bounds
|
||||
currentPosition = 7;
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// fully out of bounds
|
||||
currentPosition = 10;
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0xc3;
|
||||
ASSERT(NBT::Helper::readInt32(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == 10101010);
|
||||
|
||||
std::cout << "Passed readInt32 NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* writeInt32TestResult = new std::vector<uint8_t>();
|
||||
NBT::helper::writeInt32(writeInt32TestResult, (int32_t) 0x12345678);
|
||||
NBT::Helper::writeInt32(writeInt32TestResult, (int32_t) 0x12345678);
|
||||
// delete before checking assertions so we don't leak
|
||||
std::vector<uint8_t> dereferencedWriteInt32TestResult = *writeInt32TestResult;
|
||||
delete writeInt32TestResult;
|
||||
ASSERT(
|
||||
|
@ -133,29 +151,34 @@ int main(){
|
|||
// int64 ###########################################################
|
||||
// read successfully
|
||||
currentPosition = 1;
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).value == 2242829044932683046);
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).value == 2242829044932683046);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// begin of data
|
||||
currentPosition = 0;
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).value == 2170488872094606373);
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).value == 2170488872094606373);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// end of data
|
||||
currentPosition = 2;
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).value == 2315169217770759719);
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).value == 2315169217770759719);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == false);
|
||||
// partially out of bounds
|
||||
currentPosition = 3;
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// fully out of bounds
|
||||
currentPosition = 10;
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0xf1;
|
||||
ASSERT(NBT::Helper::readInt64(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == 810001800766);
|
||||
|
||||
std::cout << "Passed readInt64 NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* writeInt64TestResult = new std::vector<uint8_t>();
|
||||
NBT::helper::writeInt64(writeInt64TestResult, (int64_t) 0x0123456789ABCDEF);
|
||||
NBT::Helper::writeInt64(writeInt64TestResult, (int64_t) 0x0123456789ABCDEF);
|
||||
// delete before checking assertions so we don't leak
|
||||
std::vector<uint8_t> dereferencedWriteInt64TestResult = *writeInt64TestResult;
|
||||
delete writeInt64TestResult;
|
||||
ASSERT(
|
||||
|
@ -190,30 +213,34 @@ int main(){
|
|||
// int8 "array" ####################################################
|
||||
// read successfully
|
||||
currentPosition = 0;
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int8_t>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}));
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int8_t>({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}));
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
// read empty
|
||||
currentPosition = 112;
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int8_t>());
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int8_t>());
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
// read overrun
|
||||
currentPosition = 20;
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read with size partially out of bounds
|
||||
currentPosition = 114;
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read out of bounds
|
||||
currentPosition = 200;
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0x148;
|
||||
ASSERT(NBT::Helper::readInt8Array(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt8Array(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == std::vector<int8_t>({(int8_t) 0x71, (int8_t) 0x35, (int8_t) 0x77, (int8_t) 0x62, (int8_t) 0x54, (int8_t) 0x64, (int8_t) 0xf5, (int8_t) 0x32}));
|
||||
|
||||
std::cout << "Passed readInt8Array NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* int8ArrayTestOutput = new std::vector<uint8_t>();
|
||||
int8_t writeDataTest[] = {1,2,3,4};
|
||||
NBT::helper::writeInt8Array(int8ArrayTestOutput, writeDataTest, (uint32_t)4);
|
||||
NBT::Helper::writeInt8Array(int8ArrayTestOutput, writeDataTest, (uint32_t)4);
|
||||
ASSERT(
|
||||
int8ArrayTestOutput->at(0) == 0 &&
|
||||
int8ArrayTestOutput->at(1) == 0 &&
|
||||
|
@ -225,7 +252,7 @@ int main(){
|
|||
int8ArrayTestOutput->at(7) == 4
|
||||
);
|
||||
int8ArrayTestOutput->clear();
|
||||
NBT::helper::writeInt8Array(int8ArrayTestOutput, std::vector<int8_t>({1,2,3,4}));
|
||||
NBT::Helper::writeInt8Array(int8ArrayTestOutput, std::vector<int8_t>({1,2,3,4}));
|
||||
ASSERT(
|
||||
int8ArrayTestOutput->at(0) == 0 &&
|
||||
int8ArrayTestOutput->at(1) == 0 &&
|
||||
|
@ -242,30 +269,34 @@ int main(){
|
|||
// int32 "array" ###################################################
|
||||
// read successfully
|
||||
currentPosition = 68;
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int32_t>({1027489600, 1094861636, 1162233672, 1229605708, 1296977744, 1364349780, 1431721816, 1499093852, 1566465888, 1633837924}));
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int32_t>({1027489600, 1094861636, 1162233672, 1229605708, 1296977744, 1364349780, 1431721816, 1499093852, 1566465888, 1633837924}));
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
// read empty
|
||||
currentPosition = 112;
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int32_t>());
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int32_t>());
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
// read overrun
|
||||
currentPosition = 20;
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read with size partially out of bounds
|
||||
currentPosition = 114;
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read out of bounds
|
||||
currentPosition = 200;
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0xd5;
|
||||
ASSERT(NBT::Helper::readInt32Array(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt32Array(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == std::vector<int32_t>({(int32_t) 0x17bfe83c, (int32_t) 0xa8fb, (int32_t) 0x7fffffff, (int32_t) 0x61727261}));
|
||||
|
||||
std::cout << "Passed readInt32Array NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* int32ArrayTestOutput = new std::vector<uint8_t>();
|
||||
int32_t input32[] = {0x01234567, 0x01234567};
|
||||
NBT::helper::writeInt32Array(int32ArrayTestOutput, input32, 2);
|
||||
NBT::Helper::writeInt32Array(int32ArrayTestOutput, input32, 2);
|
||||
ASSERT(
|
||||
int32ArrayTestOutput->at(0) == 0x00 &&
|
||||
int32ArrayTestOutput->at(1) == 0x00 &&
|
||||
|
@ -281,7 +312,7 @@ int main(){
|
|||
int32ArrayTestOutput->at(11) == 0x67
|
||||
);
|
||||
int32ArrayTestOutput->clear();
|
||||
NBT::helper::writeInt32Array(int32ArrayTestOutput, std::vector<int32_t>({0x01234567, 0x01234567}));
|
||||
NBT::Helper::writeInt32Array(int32ArrayTestOutput, std::vector<int32_t>({0x01234567, 0x01234567}));
|
||||
ASSERT(
|
||||
int32ArrayTestOutput->at(0) == 0x00 &&
|
||||
int32ArrayTestOutput->at(1) == 0x00 &&
|
||||
|
@ -303,30 +334,34 @@ int main(){
|
|||
// int64 "array" ###################################################
|
||||
// read successfully
|
||||
currentPosition = 44;
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int64_t>({2966230773313449776, 3544952156018063160, 4123673537695186954, 4413034230074983236, 4991755612779596620}));
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int64_t>({2966230773313449776, 3544952156018063160, 4123673537695186954, 4413034230074983236, 4991755612779596620}));
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
// read empty
|
||||
currentPosition = 112;
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int64_t>());
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).value == std::vector<int64_t>());
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == false);
|
||||
// read overrun
|
||||
currentPosition = 20;
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read with size partially out of bounds
|
||||
currentPosition = 114;
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read out of bounds
|
||||
currentPosition = 200;
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0x107;
|
||||
ASSERT(NBT::Helper::readInt64Array(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readInt64Array(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == std::vector<int64_t>({(int64_t) 239865, (int64_t) 23586749, (int64_t) 9223372036854775807, (int64_t) 188944201329624, (int64_t) 3116157694992754}));
|
||||
|
||||
std::cout << "Passed readInt64Array NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* int64ArrayTestOutput = new std::vector<uint8_t>();
|
||||
int64_t input64[] = {0x0123456789ABCDEF, 0x0123456789ABCDEF};
|
||||
NBT::helper::writeInt64Array(int64ArrayTestOutput, input64, 2);
|
||||
NBT::Helper::writeInt64Array(int64ArrayTestOutput, input64, 2);
|
||||
ASSERT(
|
||||
int64ArrayTestOutput->at(0) == 0x00 &&
|
||||
int64ArrayTestOutput->at(1) == 0x00 &&
|
||||
|
@ -350,7 +385,7 @@ int main(){
|
|||
int64ArrayTestOutput->at(19) == 0xEF
|
||||
);
|
||||
int64ArrayTestOutput->clear();
|
||||
NBT::helper::writeInt64Array(int64ArrayTestOutput, std::vector<int64_t>({0x0123456789ABCDEF, 0x0123456789ABCDEF}));
|
||||
NBT::Helper::writeInt64Array(int64ArrayTestOutput, std::vector<int64_t>({0x0123456789ABCDEF, 0x0123456789ABCDEF}));
|
||||
ASSERT(
|
||||
int64ArrayTestOutput->at(0) == 0x00 &&
|
||||
int64ArrayTestOutput->at(1) == 0x00 &&
|
||||
|
@ -383,21 +418,25 @@ int main(){
|
|||
dataSize = 4;
|
||||
currentPosition = 0;
|
||||
// read successfully
|
||||
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).value == -63351.46484375f);
|
||||
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readFloat(dataForFloatTest, dataSize, currentPosition).value == -63351.46484375f);
|
||||
ASSERT(NBT::Helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == false);
|
||||
// read overrun
|
||||
currentPosition = 1;
|
||||
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::Helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read out of bounds
|
||||
currentPosition = 4;
|
||||
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0xad;
|
||||
ASSERT(NBT::Helper::readFloat(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readFloat(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == 35.2678337097168);
|
||||
|
||||
std::cout << "Passed readFloat NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* writeFloatTestResult = new std::vector<uint8_t>();
|
||||
NBT::helper::writeFloat(writeFloatTestResult, (float) -63351.46484375f);
|
||||
NBT::Helper::writeFloat(writeFloatTestResult, (float) -63351.46484375f);
|
||||
std::vector<uint8_t> dereferencedWriteFloatTestResult = *writeFloatTestResult;
|
||||
delete writeFloatTestResult;
|
||||
ASSERT(
|
||||
|
@ -414,21 +453,25 @@ int main(){
|
|||
dataSize = 8;
|
||||
currentPosition = 0;
|
||||
// read successfully
|
||||
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).value == -20.015625476837158203125);
|
||||
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == false);
|
||||
ASSERT(NBT::Helper::readDouble(dataForDoubleTest, dataSize, currentPosition).value == -20.015625476837158203125);
|
||||
ASSERT(NBT::Helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == false);
|
||||
// read overrun
|
||||
currentPosition = 1;
|
||||
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::Helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
|
||||
// read out of bounds
|
||||
currentPosition = 8;
|
||||
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
ASSERT(NBT::Helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
|
||||
ASSERT(NBT::Helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
// read from a bigger blob
|
||||
currentPositionInBlob = 0x9d;
|
||||
ASSERT(NBT::Helper::readDouble(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readDouble(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == 623593.6542742235);
|
||||
|
||||
std::cout << "Passed readDouble NBT helper test" << std::endl;
|
||||
|
||||
std::vector<uint8_t>* writeDoubleTestResult = new std::vector<uint8_t>();
|
||||
NBT::helper::writeDouble(writeDoubleTestResult, (double) -20.015625476837158203125);
|
||||
NBT::Helper::writeDouble(writeDoubleTestResult, (double) -20.015625476837158203125);
|
||||
std::vector<uint8_t> dereferencedWriteDoubleTestResult = *writeDoubleTestResult;
|
||||
delete writeDoubleTestResult;
|
||||
ASSERT(
|
||||
|
@ -487,15 +530,22 @@ int main(){
|
|||
std::cerr << "Failed to open file: " << normalFilePath << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
tiny_utf8::string normalString = tiny_utf8::string(normalStdString);
|
||||
|
||||
ASSERT(normalString == NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0x75, 0).value)
|
||||
ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0xFFFFF, 0).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0xF, 0).errorCode == ErrorCodes::MISMATCHEDSIZE);
|
||||
std::cout << "Passed readString NBT helper test." << std::endl;
|
||||
delete nextChar;
|
||||
|
||||
ASSERT(normalString == NBT::Helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), javaStdString.size(), 0).value)
|
||||
|
||||
javaStdString[0] = '1';
|
||||
ASSERT(NBT::Helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), javaStdString.size(), 0).errorCode == ErrorCodes::OVERRUN);
|
||||
ASSERT(NBT::Helper::readString(reinterpret_cast<uint8_t*>(javaStdString.data()), javaStdString.size(), javaStdString.size()).errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
|
||||
//reading data from the blob at the top of this file
|
||||
currentPositionInBlob = 0x1cf;
|
||||
ASSERT(NBT::Helper::readString(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).isError == false);
|
||||
ASSERT(NBT::Helper::readString(validNBTDataBlob, validNBTDataBlobSize, currentPositionInBlob).value == "Hello World!");
|
||||
|
||||
std::cout << "Passed readString NBT helper test." << std::endl;
|
||||
|
||||
char* nextChar1 = new char;
|
||||
|
||||
//reading data from the java modified utf8 file
|
||||
|
@ -517,11 +567,17 @@ int main(){
|
|||
std::cerr << "Failed to open file: " << javaFilePath1 << std::endl;
|
||||
return 2;
|
||||
}
|
||||
delete nextChar1;
|
||||
|
||||
std::vector<uint8_t>* exportedString = new std::vector<uint8_t>();
|
||||
NBT::helper::writeString(exportedString, normalString);
|
||||
NBT::Helper::writeString(exportedString, normalString);
|
||||
ASSERT(javaStdString1 == *exportedString);
|
||||
|
||||
//check that we get an error when trying to write a string that is too long
|
||||
std::string overrunString = std::string(0x10000, '.');
|
||||
ASSERT(NBT::Helper::writeString(exportedString, tiny_utf8::string(overrunString)).isError);
|
||||
ASSERT(NBT::Helper::writeString(exportedString, tiny_utf8::string(overrunString)).errorCode == ErrorCodes::OVERRUN);
|
||||
|
||||
std::cout << "Passed writeString NBT helper test." << std::endl;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -101,16 +101,16 @@ int main() {
|
|||
// Basic valid data tests
|
||||
//##################################################################
|
||||
// const uint8_t END = 0;
|
||||
ErrorOr<uint64_t> totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x93);
|
||||
ErrorOr<int32_t> dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x93);
|
||||
ErrorOr<uint64_t> totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x93);
|
||||
ErrorOr<int32_t> dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x93);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 1);
|
||||
ASSERT(!dataLength.isError);
|
||||
ASSERT(dataLength.value == 0);
|
||||
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 477);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 477);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 477);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 477);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 1);
|
||||
|
@ -118,8 +118,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 0);
|
||||
|
||||
//const uint8_t INT8 = 1;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x133);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x133);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x133);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x133);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 8);
|
||||
|
@ -127,8 +127,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 1);
|
||||
|
||||
//const uint8_t INT16 = 2;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xb1);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xb1);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xb1);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xb1);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 10);
|
||||
|
@ -136,16 +136,16 @@ int main() {
|
|||
ASSERT(dataLength.value == 1);
|
||||
|
||||
//const uint8_t INT32 = 3;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xbb);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xbb);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xbb);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xbb);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 12);
|
||||
ASSERT(!dataLength.isError);
|
||||
ASSERT(dataLength.value == 1);
|
||||
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x67);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x67);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x67);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x67);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 18);
|
||||
|
@ -153,8 +153,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 1);
|
||||
|
||||
//const uint8_t INT64 = 4;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xe9);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xe9);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xe9);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xe9);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 16);
|
||||
|
@ -162,8 +162,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 1);
|
||||
|
||||
//const uint8_t FLOAT = 5;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xa5);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xa5);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xa5);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xa5);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 12);
|
||||
|
@ -171,8 +171,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 1);
|
||||
|
||||
//const uint8_t DOUBLE = 6;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x94);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x94);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x94);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x94);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 17);
|
||||
|
@ -180,8 +180,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 1);
|
||||
|
||||
//const uint8_t INT8_ARRAY = 7;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x13b);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x13b);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x13b);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x13b);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 25);
|
||||
|
@ -189,16 +189,16 @@ int main() {
|
|||
ASSERT(dataLength.value == 8);
|
||||
|
||||
//const uint8_t STRING = 8;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x1c6);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x1c6);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x1c6);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x1c6);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 23);
|
||||
ASSERT(!dataLength.isError);
|
||||
ASSERT(dataLength.value == 12);
|
||||
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x79);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x79);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x79);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x79);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 26);
|
||||
|
@ -206,16 +206,16 @@ int main() {
|
|||
ASSERT(dataLength.value == 12);
|
||||
|
||||
//const uint8_t LIST = 9;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x154);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x154);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x154);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x154);
|
||||
|
||||
ASSERT(totalSize.isError);
|
||||
ASSERT(totalSize.errorCode == ErrorCodes::NOT_YET_KNOWN);
|
||||
ASSERT(!dataLength.isError);
|
||||
ASSERT(dataLength.value == 5);
|
||||
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x16a);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x16a);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x16a);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x16a);
|
||||
|
||||
ASSERT(totalSize.isError);
|
||||
ASSERT(totalSize.errorCode == ErrorCodes::NOT_YET_KNOWN);
|
||||
|
@ -223,8 +223,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 12);
|
||||
|
||||
//const uint8_t COMPOUND = 10;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x5c);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x5c);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0x5c);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0x5c);
|
||||
|
||||
ASSERT(totalSize.isError);
|
||||
ASSERT(totalSize.errorCode == ErrorCodes::NOT_YET_KNOWN);
|
||||
|
@ -232,8 +232,8 @@ int main() {
|
|||
ASSERT(dataLength.errorCode == ErrorCodes::NOT_YET_KNOWN);
|
||||
|
||||
//const uint8_t INT32_ARRAY= 11;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xc7);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xc7);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xc7);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xc7);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 34);
|
||||
|
@ -241,8 +241,8 @@ int main() {
|
|||
ASSERT(dataLength.value == 4);
|
||||
|
||||
//const uint8_t INT64_ARRAY= 12;
|
||||
totalSize = NBT::helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xf9);
|
||||
dataLength = NBT::helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xf9);
|
||||
totalSize = NBT::Helper::totalTagSize(simpleNBTData, simpleNBTDataSize, 0xf9);
|
||||
dataLength = NBT::Helper::containedDataLength(simpleNBTData, simpleNBTDataSize, 0xf9);
|
||||
|
||||
ASSERT(!totalSize.isError);
|
||||
ASSERT(totalSize.value == 58);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +0,0 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include "../lib/nbt.hpp"
|
||||
#include "../lib/error.hpp"
|
||||
#include "../lib/javacompat.hpp"
|
||||
|
||||
int main() {
|
||||
std::cout << "================================================================================" << std::endl;
|
||||
std::cout << "NBT write string helper failure mode test" << std::endl;
|
||||
std::cout << "================================================================================" << std::endl;
|
||||
std::cout << "This is supposed to abort." << std::endl;
|
||||
std::vector<uint8_t>* exportedString = new std::vector<uint8_t>();
|
||||
std::string overrunString = std::string(0xFFFFF, '.');
|
||||
NBT::helper::writeString(exportedString, tiny_utf8::string(overrunString));
|
||||
}
|
|
@ -0,0 +1,287 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster, Shwoomple
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "assert.hpp"
|
||||
#include "../lib/error.hpp"
|
||||
#include "../lib/net/conversion/varint.hpp"
|
||||
|
||||
int main() {
|
||||
|
||||
std::cout << "################################################################################" << std::endl;
|
||||
std::cout << "VarInt tests" << std::endl;
|
||||
std::cout << "################################################################################" << std::endl;
|
||||
// examples for numbers
|
||||
//
|
||||
// 32 Bit
|
||||
// 0000 0000 0000 0000 0000 0000 0000 0000 = 0 -> 0000 0000
|
||||
// 1111 1111 1111 1111 1111 1111 1111 1111 = -1 (unsigned int32 max) -> 1111 1111 1111 1111 1111 1111 1111 1111 0000 1111
|
||||
// 0000 0000 0010 0100 0011 1101 1011 1101 = 2375101 -> 1011 1101 1111 1011 1001 0000 0000 0001
|
||||
// 0000 0000 0000 0000 0001 0001 0001 0001 = 4369 -> 1001 0001 0010 0010
|
||||
//
|
||||
// 64 Bit
|
||||
// 0010 0000 0001 0000 0000 0000 1010 0010 1010 1000 0010 0000 1101 0000 1001 0011 = 2310347307446489235 -> 1101 0011 1010 0001 1000 0011 1100 0001 1010 1010 1001 0100 1000 0000 1000 1000 0010 0000
|
||||
// 1000 0000 0100 0000 0010 0000 0001 0000 0000 1000 0000 0100 0000 0010 0000 0001 = -9205322385119247871 -> 1000 0001 1000 0100 1001 0000 1100 0000 1000 0000 1000 0010 1000 1000 1010 0000 1000 0000 0000 0001
|
||||
// 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 = -1 (unsigned int64 max) -> 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0001
|
||||
|
||||
{
|
||||
std::vector<uint8_t> data = std::vector<uint8_t>();
|
||||
uint8_t processedBytes;
|
||||
ErrorOr<int32_t> result = VarInt::fromVar32(data, 0, &processedBytes);
|
||||
ASSERT(result.isError);
|
||||
ASSERT(result.errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<uint8_t> data = { 0x84 };
|
||||
uint8_t processedBytes;
|
||||
ErrorOr<int32_t> result = VarInt::fromVar32(data, 0, &processedBytes);
|
||||
ASSERT(result.isError);
|
||||
ASSERT(result.errorCode == ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<uint8_t> data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x01 };
|
||||
uint8_t processedBytes;
|
||||
ErrorOr<int32_t> result = VarInt::fromVar32(data, 0, &processedBytes);
|
||||
ASSERT(result.isError);
|
||||
ASSERT(result.errorCode == ErrorCodes::OVERFLOW);
|
||||
}
|
||||
|
||||
uint8_t zeroProcessedBytes = 0;
|
||||
std::vector<uint8_t> zeroData;
|
||||
zeroData.push_back(0);
|
||||
ErrorOr<int32_t> zero = VarInt::fromVar32(zeroData, 0, &zeroProcessedBytes);
|
||||
ASSERT(!zero.isError);
|
||||
ASSERT(zero.value == 0);
|
||||
ASSERT(zeroProcessedBytes == 1);
|
||||
|
||||
uint8_t minusOneProcessedBytes = 0;
|
||||
std::vector<uint8_t> minusOneData;
|
||||
minusOneData.push_back(255);
|
||||
minusOneData.push_back(255);
|
||||
minusOneData.push_back(255);
|
||||
minusOneData.push_back(255);
|
||||
minusOneData.push_back(15);
|
||||
ErrorOr<int32_t> minusOne = VarInt::fromVar32(minusOneData, 0, &minusOneProcessedBytes);
|
||||
ASSERT(!minusOne.isError);
|
||||
ASSERT(minusOne.value == -1);
|
||||
ASSERT(minusOneProcessedBytes == 5);
|
||||
|
||||
uint8_t smallProcessedBytes = 0;
|
||||
std::vector<uint8_t> smallData;
|
||||
// offset data by 3 to test initialPosition feature
|
||||
smallData.push_back(0b10010001);
|
||||
smallData.push_back(0b10010001);
|
||||
smallData.push_back(0b10010001);
|
||||
smallData.push_back(0b10010001);
|
||||
smallData.push_back(0b00100010);
|
||||
ErrorOr<int32_t> small = VarInt::fromVar32(smallData, 3, &smallProcessedBytes);
|
||||
ASSERT(!small.isError);
|
||||
ASSERT(small.value == 4369);
|
||||
ASSERT(smallProcessedBytes == 2);
|
||||
|
||||
uint8_t bigProcessedBytes = 0;
|
||||
std::vector<uint8_t> bigData;
|
||||
bigData.push_back(0b10111101);
|
||||
bigData.push_back(0b11111011);
|
||||
bigData.push_back(0b10010000);
|
||||
bigData.push_back(0b00000001);
|
||||
ErrorOr<int32_t> big = VarInt::fromVar32(bigData, 0, &bigProcessedBytes);
|
||||
ASSERT(!big.isError);
|
||||
ASSERT(big.value == 2375101);
|
||||
ASSERT(bigProcessedBytes == 4);
|
||||
|
||||
//TODO: test error conditions
|
||||
|
||||
std::cout << "Passed fromVar32 test." << std::endl;
|
||||
|
||||
{
|
||||
std::vector<uint8_t> data = std::vector<uint8_t>();
|
||||
uint8_t processedBytes;
|
||||
ErrorOr<int64_t> result = VarInt::fromVar64(data, 0, &processedBytes);
|
||||
ASSERT(result.isError);
|
||||
ASSERT(result.errorCode == ErrorCodes::OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<uint8_t> data = { 0x84 };
|
||||
uint8_t processedBytes;
|
||||
ErrorOr<int64_t> result = VarInt::fromVar64(data, 0, &processedBytes);
|
||||
ASSERT(result.isError);
|
||||
ASSERT(result.errorCode == ErrorCodes::OVERRUN);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<uint8_t> data = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01 };
|
||||
uint8_t processedBytes;
|
||||
ErrorOr<int64_t> result = VarInt::fromVar64(data, 0, &processedBytes);
|
||||
ASSERT(result.isError);
|
||||
ASSERT(result.errorCode == ErrorCodes::OVERFLOW);
|
||||
}
|
||||
|
||||
uint8_t zero64ProcessedBytes = 0;
|
||||
std::vector<uint8_t> zero64Data;
|
||||
zero64Data.push_back(0);
|
||||
ErrorOr<int64_t> zero64 = VarInt::fromVar64(zero64Data, 0, &zero64ProcessedBytes);
|
||||
ASSERT(!zero64.isError);
|
||||
ASSERT(zero64.value == 0);
|
||||
ASSERT(zero64ProcessedBytes == 1);
|
||||
|
||||
uint8_t minusOne64ProcessedBytes = 0;
|
||||
std::vector<uint8_t> minusOne64Data;
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(255);
|
||||
minusOne64Data.push_back(1);
|
||||
ErrorOr<int64_t> minusOne64 = VarInt::fromVar64(minusOne64Data, 0, &minusOne64ProcessedBytes);
|
||||
ASSERT(!minusOne64.isError);
|
||||
ASSERT(minusOne64.value == -1);
|
||||
ASSERT(minusOne64ProcessedBytes == 10);
|
||||
|
||||
// 0010 0000 0001 0000 0000 0000 1010 0010 1010 1000 0010 0000 1101 0000 1001 0011 = 2310347307446489235 -> 1101 0011 1010 0001 1000 0011 1100 0001 1010 1010 1001 0100 1000 0000 1000 1000 0010 0000
|
||||
uint8_t small64ProcessedBytes = 0;
|
||||
std::vector<uint8_t> small64Data;
|
||||
// offset data by 3 to test initialPosition feature
|
||||
small64Data.push_back(0b11010011);
|
||||
small64Data.push_back(0b11010011);
|
||||
small64Data.push_back(0b11010011);
|
||||
small64Data.push_back(0b10010011);
|
||||
small64Data.push_back(0b10100001);
|
||||
small64Data.push_back(0b10000011);
|
||||
small64Data.push_back(0b11000001);
|
||||
small64Data.push_back(0b10101010);
|
||||
small64Data.push_back(0b10010100);
|
||||
small64Data.push_back(0b10000000);
|
||||
small64Data.push_back(0b10001000);
|
||||
small64Data.push_back(0b00100000);
|
||||
ErrorOr<int64_t> small64 = VarInt::fromVar64(small64Data, 3, &small64ProcessedBytes);
|
||||
ASSERT(!small64.isError);
|
||||
ASSERT(small64.value == 2310347307446489235);
|
||||
ASSERT(small64ProcessedBytes == 9);
|
||||
|
||||
// 1000 0000 0100 0000 0010 0000 0001 0000 0000 1000 0000 0100 0000 0010 0000 0001 = -9205322385119247871 -> 1000 0001 1000 0100 1001 0000 1100 0000 1000 0000 1000 0010 1000 1000 1010 0000 1000 0000 0000 0001
|
||||
uint8_t big64ProcessedBytes = 0;
|
||||
std::vector<uint8_t> big64Data;
|
||||
big64Data.push_back(0b10000001);
|
||||
big64Data.push_back(0b10000100);
|
||||
big64Data.push_back(0b10010000);
|
||||
big64Data.push_back(0b11000000);
|
||||
big64Data.push_back(0b10000000);
|
||||
big64Data.push_back(0b10000010);
|
||||
big64Data.push_back(0b10001000);
|
||||
big64Data.push_back(0b10100000);
|
||||
big64Data.push_back(0b10000000);
|
||||
big64Data.push_back(0b00000001);
|
||||
ErrorOr<int64_t> big64 = VarInt::fromVar64(big64Data, 0, &big64ProcessedBytes);
|
||||
ASSERT(!big64.isError);
|
||||
ASSERT(big64.value == -9205322385119247871);
|
||||
ASSERT(big64ProcessedBytes == 10);
|
||||
|
||||
//TODO: Test error conditions
|
||||
|
||||
std::cout << "Passed fromVar64 test." << std::endl;
|
||||
|
||||
// reversing all the previous tests
|
||||
std::vector<uint8_t> dataDump;
|
||||
|
||||
VarInt::toVar32(0, dataDump);
|
||||
ASSERT(dataDump[0] == 0);
|
||||
|
||||
VarInt::toVar32(-1, dataDump);
|
||||
ASSERT(
|
||||
dataDump[1]==255 &&
|
||||
dataDump[2]==255 &&
|
||||
dataDump[3]==255 &&
|
||||
dataDump[4]==255 &&
|
||||
dataDump[5]==15
|
||||
);
|
||||
|
||||
VarInt::toVar32(4369, dataDump);
|
||||
ASSERT(
|
||||
dataDump[6]==0b10010001 &&
|
||||
dataDump[7]==0b00100010
|
||||
);
|
||||
|
||||
VarInt::toVar32(2375101, dataDump);
|
||||
ASSERT(
|
||||
dataDump[8]==0b10111101 &&
|
||||
dataDump[9]==0b11111011 &&
|
||||
dataDump[10]==0b10010000 &&
|
||||
dataDump[11]==0b00000001
|
||||
);
|
||||
|
||||
std::cout << "Passed toVar32 test." << std::endl;
|
||||
|
||||
VarInt::toVar64(0, dataDump);
|
||||
ASSERT(dataDump[12]==0);
|
||||
|
||||
VarInt::toVar64(-1, dataDump);
|
||||
ASSERT(
|
||||
dataDump[13]==255 &&
|
||||
dataDump[14]==255 &&
|
||||
dataDump[15]==255 &&
|
||||
dataDump[16]==255 &&
|
||||
dataDump[17]==255 &&
|
||||
dataDump[18]==255 &&
|
||||
dataDump[19]==255 &&
|
||||
dataDump[20]==255 &&
|
||||
dataDump[21]==255 &&
|
||||
dataDump[22]==1
|
||||
);
|
||||
|
||||
VarInt::toVar64(2310347307446489235, dataDump);
|
||||
ASSERT(
|
||||
dataDump[23]==0b10010011 &&
|
||||
dataDump[24]==0b10100001 &&
|
||||
dataDump[25]==0b10000011 &&
|
||||
dataDump[26]==0b11000001 &&
|
||||
dataDump[27]==0b10101010 &&
|
||||
dataDump[28]==0b10010100 &&
|
||||
dataDump[29]==0b10000000 &&
|
||||
dataDump[30]==0b10001000 &&
|
||||
dataDump[31]==0b00100000
|
||||
);
|
||||
|
||||
VarInt::toVar64(-9205322385119247871, dataDump);
|
||||
ASSERT(
|
||||
dataDump[32]==0b10000001 &&
|
||||
dataDump[33]==0b10000100 &&
|
||||
dataDump[34]==0b10010000 &&
|
||||
dataDump[35]==0b11000000 &&
|
||||
dataDump[36]==0b10000000 &&
|
||||
dataDump[37]==0b10000010 &&
|
||||
dataDump[38]==0b10001000 &&
|
||||
dataDump[39]==0b10100000 &&
|
||||
dataDump[40]==0b10000000 &&
|
||||
dataDump[41]==0b00000001
|
||||
)
|
||||
|
||||
std::cout << "Passed toVar64 test." << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <bitset>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../lib/cli.hpp"
|
||||
#include "../lib/file.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('x', "hexadecimal", "write output as hexadecimal numbers"));
|
||||
flags.push_back(CLI::Flag('o', "octal", "write output as octal numbers"));
|
||||
flags.push_back(CLI::Flag('b', "binary", "write output as binary numbers"));
|
||||
flags.push_back(CLI::Flag('h', "help", "print help and exit"));
|
||||
flags.push_back(CLI::Flag('l', "license", "print license information and exit"));
|
||||
std::vector<CLI::Option> options;
|
||||
std::vector<CLI::Argument> arguments;
|
||||
arguments.push_back(CLI::Argument("FILE", "path of the file to dump"));
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Dump files as C++ array literals");
|
||||
|
||||
if (cliParser.getFlag("help").value) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.getFlag("license").value){
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
<< "ArrayDump is part of the FOSS-VG development tool suite.\n"
|
||||
<< "\n"
|
||||
<< "This program is free software: you can redistribute it and/or modify it\n"
|
||||
<< "under the terms of the GNU Affero General Public License as published\n"
|
||||
<< "by the Free Software Foundation, version 3.\n"
|
||||
<< "\n"
|
||||
<< "This program is distributed in the hope that it will be useful,\n"
|
||||
<< "but WITHOUT ANY WARRANTY; without even the implied\n"
|
||||
<< "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
<< "See the GNU Affero General Public License for more details.\n"
|
||||
<< "\n"
|
||||
<< "You should have received a copy of the GNU Affero General Public License\n"
|
||||
<< "version 3 along with this program.\n"
|
||||
<< "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
ErrorOr<File*> filePointer = File::open(cliParser.getArgument(0).value, 'r');
|
||||
if (filePointer.isError) {
|
||||
std::cout << "Failed to open file: " << cliParser.getArgument(0).value << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
File* file = filePointer.value;
|
||||
|
||||
std::cout << "{";
|
||||
if (cliParser.getFlag("hexadecimal").value) {
|
||||
if (!file->eof()) {
|
||||
std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << (int) file->readByte().value;
|
||||
}
|
||||
while (!file->eof()) {
|
||||
std::cout << ", 0x" << std::setw(2) << std::setfill('0') << std::hex << (int) file->readByte().value;
|
||||
}
|
||||
} else if (cliParser.getFlag("octal").value) {
|
||||
if (!file->eof()) {
|
||||
std::cout << "0" << std::setw(3) << std::setfill('0') << std::oct << (int) file->readByte().value;
|
||||
}
|
||||
while (!file->eof()) {
|
||||
std::cout << ", 0" << std::setw(3) << std::setfill('0') << std::oct << (int) file->readByte().value;
|
||||
}
|
||||
} else if (cliParser.getFlag("binary").value) {
|
||||
if (!file->eof()) {
|
||||
std::cout << "0b" << std::bitset<8>((int) file->readByte().value);
|
||||
}
|
||||
while (!file->eof()) {
|
||||
std::cout << ", 0b" << std::bitset<8>((int) file->readByte().value);
|
||||
}
|
||||
} else {
|
||||
if (!file->eof()) {
|
||||
std::cout << (int) file->readByte().value;
|
||||
}
|
||||
while (!file->eof()) {
|
||||
std::cout << ", " << (int) file->readByte().value;
|
||||
}
|
||||
}
|
||||
std::cout << "}" << std::endl;
|
||||
|
||||
delete file;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
// Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "../lib/cli.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('x', "hexadecimal", "base 16"));
|
||||
flags.push_back(CLI::Flag('o', "octal", "base 8"));
|
||||
flags.push_back(CLI::Flag('b', "binary", "base 2"));
|
||||
flags.push_back(CLI::Flag('d', "decimal", "base 10"));
|
||||
flags.push_back(CLI::Flag('h', "help", "print help and exit"));
|
||||
flags.push_back(CLI::Flag('l', "license", "print license information and exit"));
|
||||
std::vector<CLI::Option> options;
|
||||
std::vector<CLI::Argument> arguments;
|
||||
arguments.push_back(CLI::Argument("NUMBER", "the number to convert"));
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Convert numbers between predefined bases", "This only works for unsigned numbers.\n\tBaseConvert understands the prefixes 0x, 0b, 0o, and 0 in input numbers.");
|
||||
|
||||
if (cliParser.getFlag("help").value) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.getFlag("license").value){
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
<< "BaseConvert is part of the FOSS-VG development tool suite.\n"
|
||||
<< "\n"
|
||||
<< "This program is free software: you can redistribute it and/or modify it\n"
|
||||
<< "under the terms of the GNU Affero General Public License as published\n"
|
||||
<< "by the Free Software Foundation, version 3.\n"
|
||||
<< "\n"
|
||||
<< "This program is distributed in the hope that it will be useful,\n"
|
||||
<< "but WITHOUT ANY WARRANTY; without even the implied\n"
|
||||
<< "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
<< "See the GNU Affero General Public License for more details.\n"
|
||||
<< "\n"
|
||||
<< "You should have received a copy of the GNU Affero General Public License\n"
|
||||
<< "version 3 along with this program.\n"
|
||||
<< "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
std::string numberString = cliParser.getArgument(0).value;
|
||||
uint8_t base = 10;
|
||||
uint64_t* number = new uint64_t;
|
||||
|
||||
if (numberString == "") {
|
||||
std::cerr << "Empty string is not a valid number." << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
if (numberString[0] == '0') {
|
||||
if (numberString.substr(0, 2)=="0x" || numberString.substr(0, 2)=="0X") {
|
||||
base = 16;
|
||||
numberString = numberString.substr(2, numberString.length()-2);
|
||||
} else if (numberString.substr(0, 2)=="0b" || numberString.substr(0, 2)=="0B") {
|
||||
base = 2;
|
||||
numberString = numberString.substr(2, numberString.length()-2);
|
||||
} else if (numberString.substr(0, 2)=="0o" || numberString.substr(0, 2)=="0O") {
|
||||
base = 8;
|
||||
numberString = numberString.substr(2, numberString.length()-2);
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
|
||||
*number = std::stoull(numberString, nullptr, base);
|
||||
|
||||
if (cliParser.getFlag("hexadecimal").value) {
|
||||
std::cout << "0x" << std::hex << *number << std::endl;
|
||||
} else if (cliParser.getFlag("octal").value) {
|
||||
*number==0? std::cout << "0" << std::endl : std::cout << "0" << std::oct << *number << std::endl;
|
||||
} else if (cliParser.getFlag("binary").value) {
|
||||
std::bitset<64> bitset = std::bitset<64>(*number);
|
||||
bool foundFirstBit = false;
|
||||
std::cout << "0b";
|
||||
for (uint8_t i=0; i<64; i++) {
|
||||
if (bitset[63-i]) {
|
||||
std::cout << "1";
|
||||
foundFirstBit = true;
|
||||
} else if (foundFirstBit) {
|
||||
std::cout << "0";
|
||||
}
|
||||
}
|
||||
if (!foundFirstBit) {
|
||||
std::cout << "0";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
} else if (cliParser.getFlag("decimal").value) {
|
||||
std::cout << *number << std::endl;
|
||||
} else {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
delete number;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -13,8 +13,359 @@
|
|||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <tinyutf8/tinyutf8.h>
|
||||
|
||||
#include "../lib/nbt.hpp"
|
||||
#include "../lib/cli.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
#define EXIT_UNIMPLEMENTED 3
|
||||
|
||||
void printTagTypeName(NBT::Tag::Generic* tag, uint64_t offsetBytes) {
|
||||
std::cout << "[" << offsetBytes << ": ";
|
||||
switch (tag->getTagType()) {
|
||||
case NBT::TagType::END:
|
||||
std::cout << "End";
|
||||
break;
|
||||
case NBT::TagType::INT8:
|
||||
std::cout << "8 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::INT16:
|
||||
std::cout << "16 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::INT32:
|
||||
std::cout << "32 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::INT64:
|
||||
std::cout << "64 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::FLOAT:
|
||||
std::cout << "Float";
|
||||
break;
|
||||
case NBT::TagType::DOUBLE:
|
||||
std::cout << "Double";
|
||||
break;
|
||||
case NBT::TagType::INT8_ARRAY:
|
||||
std::cout << "Array of 8 Bit Integers";
|
||||
break;
|
||||
case NBT::TagType::STRING:
|
||||
std::cout << "String";
|
||||
break;
|
||||
case NBT::TagType::LIST:
|
||||
std::cout << "List";
|
||||
break;
|
||||
case NBT::TagType::COMPOUND:
|
||||
std::cout << "Compound";
|
||||
break;
|
||||
case NBT::TagType::INT32_ARRAY:
|
||||
std::cout << "Array of 32 Bit Integers";
|
||||
break;
|
||||
case NBT::TagType::INT64_ARRAY:
|
||||
std::cout << "Array of 64 Bit Integers";
|
||||
break;
|
||||
default:
|
||||
// WTF? How'd you even get here?
|
||||
std::cout << "Unknown Type";
|
||||
}
|
||||
std::cout << "]";
|
||||
if (tag->name == "") {
|
||||
std::cout << ":";
|
||||
} else {
|
||||
std::cout << " " << tag->name << ":";
|
||||
}
|
||||
}
|
||||
|
||||
void printNBytes(uint64_t bytes) {
|
||||
std::cout << bytes << (bytes==1? " byte":" bytes");
|
||||
}
|
||||
|
||||
void drawTree(NBT::Tag::Generic* tag, tiny_utf8::string prefix, uint64_t offsetBytes, bool listMode=false) {
|
||||
std::vector<uint8_t> serialized;
|
||||
uint64_t headerSize = 0;
|
||||
if (listMode) {
|
||||
tag->serializeWithoutHeader(&serialized);
|
||||
|
||||
std::cout << prefix << "|–Payload: ";
|
||||
printNBytes(serialized.size());
|
||||
std::cout << std::endl;
|
||||
} else {
|
||||
tag->serialize(&serialized);
|
||||
if (tag->getTagType() == NBT::TagType::END) {
|
||||
headerSize = 1;
|
||||
} else {
|
||||
headerSize = (uint64_t) NBT::Helper::readInt16(serialized.data(), serialized.size(), 1).value+3;
|
||||
}
|
||||
|
||||
std::cout << prefix << "|–Header: ";
|
||||
printNBytes(headerSize);
|
||||
std::cout << std::endl;
|
||||
std::cout << prefix << "|–Payload: ";
|
||||
printNBytes(serialized.size() - headerSize);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
if (tag->getTagType() == NBT::TagType::END) {
|
||||
std::cout << prefix << "'–Total: ";
|
||||
} else {
|
||||
std::cout << prefix << "|–Total: ";
|
||||
}
|
||||
printNBytes(serialized.size());
|
||||
std::cout << std::endl;
|
||||
|
||||
switch (tag->getTagType()) {
|
||||
case NBT::TagType::END:
|
||||
break;
|
||||
case NBT::TagType::INT8:
|
||||
std::cout << prefix << "'–Value: " << (int32_t) reinterpret_cast<NBT::Tag::Int8*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::INT16:
|
||||
std::cout << prefix << "'–Value: " << (int32_t) reinterpret_cast<NBT::Tag::Int16*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::INT32:
|
||||
std::cout << prefix << "'–Value: " << reinterpret_cast<NBT::Tag::Int32*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::INT64:
|
||||
std::cout << prefix << "'–Value: " << reinterpret_cast<NBT::Tag::Int64*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::FLOAT:
|
||||
std::cout << prefix << "'–Value: " << reinterpret_cast<NBT::Tag::Float*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::DOUBLE:
|
||||
std::cout << prefix << "'–Value: " << reinterpret_cast<NBT::Tag::Double*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::INT8_ARRAY: {
|
||||
NBT::Tag::Int8Array* array = reinterpret_cast<NBT::Tag::Int8Array*>(tag);
|
||||
std::cout << prefix << "|–Length: " << array->length() << std::endl;
|
||||
std::cout << prefix << "'–Values: " << std::endl;
|
||||
for (uint64_t i=0; i<array->length(); i++) {
|
||||
if (i == array->length()-1) {
|
||||
std::cout << prefix << " '–" << (int64_t) array->getValue(i).value << std::endl;
|
||||
} else {
|
||||
std::cout << prefix << " |–" << (int64_t) array->getValue(i).value << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NBT::TagType::STRING:
|
||||
std::cout << prefix << "'–Value: " << reinterpret_cast<NBT::Tag::String*>(tag)->getValue() << std::endl;
|
||||
break;
|
||||
case NBT::TagType::LIST: {
|
||||
NBT::Tag::List* list = reinterpret_cast<NBT::Tag::List*>(tag);
|
||||
|
||||
std::cout << prefix << "|–Contained Type: ";
|
||||
switch (list->getContainedType()) {
|
||||
case NBT::TagType::END:
|
||||
std::cout << "End";
|
||||
break;
|
||||
case NBT::TagType::INT8:
|
||||
std::cout << "8 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::INT16:
|
||||
std::cout << "16 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::INT32:
|
||||
std::cout << "32 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::INT64:
|
||||
std::cout << "64 Bit Integer";
|
||||
break;
|
||||
case NBT::TagType::FLOAT:
|
||||
std::cout << "Float";
|
||||
break;
|
||||
case NBT::TagType::DOUBLE:
|
||||
std::cout << "Double";
|
||||
break;
|
||||
case NBT::TagType::INT8_ARRAY:
|
||||
std::cout << "Array of 8 Bit Integers";
|
||||
break;
|
||||
case NBT::TagType::STRING:
|
||||
std::cout << "String";
|
||||
break;
|
||||
case NBT::TagType::LIST:
|
||||
std::cout << "List";
|
||||
break;
|
||||
case NBT::TagType::COMPOUND:
|
||||
std::cout << "Compound";
|
||||
break;
|
||||
case NBT::TagType::INT32_ARRAY:
|
||||
std::cout << "Array of 32 Bit Integers";
|
||||
break;
|
||||
case NBT::TagType::INT64_ARRAY:
|
||||
std::cout << "Array of 64 Bit Integers";
|
||||
break;
|
||||
default:
|
||||
// WTF? How'd you even get here?
|
||||
std::cout << "Unknown Type";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
if (list->length() > 0) {
|
||||
std::cout << prefix << "|–Length: " << list->length() << std::endl;
|
||||
std::cout << prefix << "|" << std::endl;
|
||||
} else {
|
||||
std::cout << prefix << "'–Length: " << list->length() << std::endl;
|
||||
}
|
||||
|
||||
offsetBytes = offsetBytes + headerSize + 5;
|
||||
for (uint64_t i=0; i<list->length(); i++) {
|
||||
if (i == list->length()-1) {
|
||||
std::cout << prefix << "'–";
|
||||
printTagTypeName(list->getElementPointer(i).value, offsetBytes);
|
||||
std::cout << std::endl;
|
||||
drawTree(list->getElementPointer(i).value, prefix+" ", offsetBytes, true);
|
||||
} else {
|
||||
std::cout << prefix << "|–";
|
||||
printTagTypeName(list->getElementPointer(i).value, offsetBytes);
|
||||
std::cout << std::endl;
|
||||
drawTree(list->getElementPointer(i).value, prefix+"| ", offsetBytes, true);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> serializedElement;
|
||||
list->getElementPointer(i).value->serializeWithoutHeader(&serializedElement);
|
||||
offsetBytes += serializedElement.size();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NBT::TagType::COMPOUND: {
|
||||
NBT::Tag::Compound* compound = reinterpret_cast<NBT::Tag::Compound*>(tag);
|
||||
|
||||
std::cout << prefix << "|–Length: " << compound->length() << std::endl;
|
||||
std::cout << prefix << "|" << std::endl;
|
||||
|
||||
offsetBytes = offsetBytes + headerSize;
|
||||
for (uint64_t i=0; i<compound->length(); i++) {
|
||||
if (i == compound->length()-1) {
|
||||
std::cout << prefix << "'–";
|
||||
printTagTypeName(compound->getElementPointer(i).value, offsetBytes);
|
||||
std::cout << std::endl;
|
||||
drawTree(compound->getElementPointer(i).value, prefix+" ", offsetBytes);
|
||||
} else {
|
||||
std::cout << prefix << "|–";
|
||||
printTagTypeName(compound->getElementPointer(i).value, offsetBytes);
|
||||
std::cout << std::endl;
|
||||
drawTree(compound->getElementPointer(i).value, prefix+"| ", offsetBytes);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> serializedElement;
|
||||
compound->getElementPointer(i).value->serialize(&serializedElement);
|
||||
offsetBytes += serializedElement.size();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NBT::TagType::INT32_ARRAY: {
|
||||
NBT::Tag::Int32Array* array = reinterpret_cast<NBT::Tag::Int32Array*>(tag);
|
||||
std::cout << prefix << "|–Length: " << array->length() << std::endl;
|
||||
std::cout << prefix << "'–Values: " << std::endl;
|
||||
for (uint64_t i=0; i<array->length(); i++) {
|
||||
if (i == array->length()-1) {
|
||||
std::cout << prefix << " '–" << array->getValue(i).value << std::endl;
|
||||
} else {
|
||||
std::cout << prefix << " |–" << array->getValue(i).value << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NBT::TagType::INT64_ARRAY: {
|
||||
NBT::Tag::Int64Array* array = reinterpret_cast<NBT::Tag::Int64Array*>(tag);
|
||||
std::cout << prefix << "|–Length: " << array->length() << std::endl;
|
||||
std::cout << prefix << "'–Values: " << std::endl;
|
||||
for (uint64_t i=0; i<array->length(); i++) {
|
||||
if (i == array->length()-1) {
|
||||
std::cout << prefix << " '–" << array->getValue(i).value << std::endl;
|
||||
} else {
|
||||
std::cout << prefix << " |–" << array->getValue(i).value << std::endl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// WTF? How'd you even get here?
|
||||
std::cout << prefix << "'–???" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << prefix << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return 0;
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('h', "help", "print help and exit"));
|
||||
flags.push_back(CLI::Flag('l', "license", "print license information and exit"));
|
||||
std::vector<CLI::Option> options;
|
||||
std::vector<CLI::Argument> arguments;
|
||||
arguments.push_back(CLI::Argument("FILE", "path of the file to dump"));
|
||||
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Present NBT in human or machine readable formats");
|
||||
|
||||
if (cliParser.getFlag("help").value){
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (cliParser.getFlag("license").value){
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
<< "DumpNBT is part of the FOSS-VG development tool suite.\n"
|
||||
<< "\n"
|
||||
<< "This program is free software: you can redistribute it and/or modify it\n"
|
||||
<< "under the terms of the GNU Affero General Public License as published\n"
|
||||
<< "by the Free Software Foundation, version 3.\n"
|
||||
<< "\n"
|
||||
<< "This program is distributed in the hope that it will be useful,\n"
|
||||
<< "but WITHOUT ANY WARRANTY; without even the implied\n"
|
||||
<< "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
<< "See the GNU Affero General Public License for more details.\n"
|
||||
<< "\n"
|
||||
<< "You should have received a copy of the GNU Affero General Public License\n"
|
||||
<< "version 3 along with this program.\n"
|
||||
<< "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cerr << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
std::ifstream fileStream;
|
||||
fileStream.open(cliParser.getArgument(0).value, std::ios::in | std::ios::binary | std::ios::ate);
|
||||
if (!fileStream.is_open()) {
|
||||
std::cerr << argv[0] << ": Could not open file: " << cliParser.getArgument(0).value << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
uint64_t fileSize = fileStream.tellg();
|
||||
fileStream.seekg(0, std::ios::beg);
|
||||
|
||||
uint8_t data[fileSize];
|
||||
uint8_t* nextByte = new uint8_t;
|
||||
|
||||
for (uint64_t i=0; i<fileSize; i++) {
|
||||
fileStream.read(reinterpret_cast<char*>(nextByte), 1);
|
||||
data[i] = *nextByte;
|
||||
}
|
||||
fileStream.close();
|
||||
|
||||
ErrorOr<std::vector<NBT::Tag::Generic*>> tags = NBT::deserialize(data, fileSize);
|
||||
if (tags.isError) {
|
||||
std::cerr << "Invalid data." << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
uint64_t offsetBytes = 0;
|
||||
for (uint64_t i=0; i<tags.value.size(); i++) {
|
||||
printTagTypeName(tags.value[i], offsetBytes);
|
||||
std::cout << std::endl;
|
||||
drawTree(tags.value[i], "", offsetBytes);
|
||||
|
||||
std::vector<uint8_t> serialized;
|
||||
tags.value[i]->serialize(&serialized);
|
||||
offsetBytes += serialized.size();
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
//Copyright 2022, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// BodgeMaster, Shwoomple
|
||||
//
|
||||
//This program is free software: you can redistribute it and/or modify it
|
||||
//under the terms of the GNU Affero General Public License as published
|
||||
//by the Free Software Foundation, version 3.
|
||||
|
@ -13,167 +16,260 @@
|
|||
//version 3 along with this program.
|
||||
//If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <sockpp/tcp_acceptor.h>
|
||||
#include <sockpp/tcp6_acceptor.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <sockpp/tcp_acceptor.h>
|
||||
#include <sockpp/tcp_connector.h>
|
||||
#include <sockpp/tcp6_acceptor.h>
|
||||
#include <sockpp/tcp6_connector.h>
|
||||
#include <sockpp/udp_socket.h>
|
||||
#include <sockpp/udp6_socket.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "../lib/error.hpp"
|
||||
#include "../lib/cli.hpp"
|
||||
#include "../lib/error.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
#define EXIT_UNIMPLEMENTED 3
|
||||
#define EXIT_SIGNAL 4
|
||||
|
||||
bool ipv4 = true;
|
||||
bool ipv6 = true;
|
||||
bool tcp = true;
|
||||
bool udp = true;
|
||||
bool listenMode = false;
|
||||
int64_t mtu = 1500;
|
||||
std::string host;
|
||||
in_port_t port;
|
||||
sockpp::tcp_socket* tcpSocket;
|
||||
sockpp::tcp6_socket* tcp6Socket;
|
||||
// TCP v4 server
|
||||
sockpp::tcp_socket tcpSocket;
|
||||
sockpp::tcp_acceptor tcpAcceptor;
|
||||
// TCP v4 client
|
||||
sockpp::tcp_connector tcpConnector;
|
||||
// TCP v6 server
|
||||
sockpp::tcp6_socket tcp6Socket;
|
||||
sockpp::tcp6_acceptor tcp6Acceptor;
|
||||
std::mutex tcpSocketMutex;
|
||||
std::mutex tcp6SocketMutex;
|
||||
std::mutex consoleMutex;
|
||||
// used for coordinated graceful exit across threads
|
||||
// TCP v6 client
|
||||
sockpp::tcp6_connector tcp6Connector;
|
||||
// UDP v4 server and client
|
||||
sockpp::udp_socket udpSocket;
|
||||
// UDP v6 server and client
|
||||
sockpp::udp6_socket udp6Socket;
|
||||
|
||||
bool exitProgram = false;
|
||||
|
||||
bool ipv4 = false;
|
||||
bool ipv6 = false;
|
||||
bool tcp = false;
|
||||
bool udp = false;
|
||||
bool outgoing = false;
|
||||
std::string host;
|
||||
in_port_t port;
|
||||
|
||||
// This is probably bigger than the MTU on any given network.
|
||||
// This should allow us to read entire packets at once when they arrive
|
||||
// slowly enough to be read individually.
|
||||
const uint32_t bufferSize = 2048;
|
||||
uint8_t networkBuffer[bufferSize];
|
||||
|
||||
std::string readByteFromStdin() {
|
||||
std::string input = "";
|
||||
// read 2 characters from stdin
|
||||
char characterInput;
|
||||
bool readByte = false;
|
||||
uint16_t iterationsSinceLastInput = 0;
|
||||
while (input.length() < 2 && !exitProgram) {
|
||||
if (std::cin.good()) {
|
||||
std::cin.get(characterInput);
|
||||
readByte = true;
|
||||
} else {
|
||||
readByte = false;
|
||||
}
|
||||
// ignore space, tabs, and newlines
|
||||
if (readByte && characterInput!=' ' && characterInput!='\n' && characterInput!='\r' && characterInput!='\t') {
|
||||
input.push_back(characterInput);
|
||||
}
|
||||
|
||||
iterationsSinceLastInput++;
|
||||
if (readByte) {
|
||||
iterationsSinceLastInput = 0;
|
||||
}
|
||||
if (iterationsSinceLastInput>1024) {
|
||||
// prevent integer overflow
|
||||
iterationsSinceLastInput = 1024;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
}
|
||||
return exitProgram? "" : std::string(1, (char) std::stoi(input, nullptr, 16));
|
||||
}
|
||||
|
||||
void signalHandler(int signal) {
|
||||
// shut down gracefully
|
||||
exitProgram = true;
|
||||
// if still waiting for incoming connection, stop waiting
|
||||
tcpAcceptor.shutdown();
|
||||
tcp6Acceptor.shutdown();
|
||||
|
||||
// tell sockpp to close TCP socket if open because it blocks when trying
|
||||
// to read and there is no data
|
||||
|
||||
if (tcpSocket != nullptr && *tcpSocket) {
|
||||
// Intentionally not using the mutex here
|
||||
std::cout << "test\n";
|
||||
tcpSocket->shutdown(SHUT_RD);
|
||||
tcpAcceptor.shutdown();
|
||||
if (tcpSocket) {
|
||||
tcpSocket.shutdown(SHUT_RD);
|
||||
}
|
||||
|
||||
if (tcp6Socket != nullptr && *tcp6Socket) {
|
||||
// Intentionally not using the mutex here
|
||||
tcp6Socket->shutdown(SHUT_RD);
|
||||
if (tcpConnector) {
|
||||
tcpConnector.shutdown(SHUT_RD);
|
||||
}
|
||||
//TODO: figure out if - and how - this applies to UDP
|
||||
|
||||
// Priority is to finish up all unfinished business that can be finished up.
|
||||
// If something has the console mutex locked, that should not prevent
|
||||
// other threads from winding down. This is why logging happens last.
|
||||
consoleMutex.lock();
|
||||
std::cerr << "Received signal " << signal << ", shutting down." << std::endl;
|
||||
consoleMutex.unlock();
|
||||
std::exit(signal);
|
||||
if (tcp6Socket) {
|
||||
tcp6Socket.shutdown(SHUT_RD);
|
||||
}
|
||||
|
||||
if (tcp6Connector) {
|
||||
tcp6Connector.shutdown(SHUT_RD);
|
||||
}
|
||||
|
||||
if (udpSocket) {
|
||||
udpSocket.shutdown(SHUT_RD);
|
||||
}
|
||||
|
||||
if (udp6Socket) {
|
||||
udp6Socket.shutdown(SHUT_RD);
|
||||
}
|
||||
|
||||
std::cerr << "Received signal " << signal << ", bye!" << std::endl;
|
||||
std::exit(EXIT_SIGNAL);
|
||||
}
|
||||
|
||||
void readFromTCPSocket(sockpp::tcp_socket* socket, int64_t mtu) {
|
||||
ssize_t numBytes;
|
||||
uint8_t buffer[mtu];
|
||||
tcpSocketMutex.lock();
|
||||
while (!exitProgram && (numBytes = socket->read(buffer, sizeof(buffer))) > 0) {
|
||||
tcpSocketMutex.unlock();
|
||||
consoleMutex.lock();
|
||||
for (ssize_t i=0; i<numBytes; i++) {
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i];
|
||||
void readFromTCP() {
|
||||
ssize_t byteCount;
|
||||
while (!exitProgram && (outgoing? (byteCount = tcpConnector.read(networkBuffer, bufferSize)) > 0 : (byteCount = tcpSocket.read(networkBuffer, bufferSize)) > 0)) {
|
||||
for (ssize_t i=0; i<byteCount; i++) {
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) networkBuffer[i] << " ";
|
||||
}
|
||||
std::cout.flush();
|
||||
consoleMutex.unlock();
|
||||
tcpSocketMutex.lock();
|
||||
}
|
||||
tcpSocketMutex.unlock();
|
||||
consoleMutex.lock();
|
||||
std::cerr << std::endl << "Connection closed." << std::endl;
|
||||
consoleMutex.unlock();
|
||||
}
|
||||
|
||||
void readFromTCP6Socket(sockpp::tcp6_socket* socket, int64_t mtu){
|
||||
ssize_t numBytes;
|
||||
uint8_t buffer[mtu];
|
||||
tcp6SocketMutex.lock();
|
||||
while (!exitProgram && (numBytes = socket->read(buffer, sizeof(buffer))) > 0) {
|
||||
tcp6SocketMutex.unlock();
|
||||
consoleMutex.lock();
|
||||
for (ssize_t i=0; i<numBytes; i++) {
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) buffer[i];
|
||||
void writeToTCP() {
|
||||
while (!exitProgram) {
|
||||
if (outgoing) {
|
||||
if (tcpConnector.write(readByteFromStdin()) == -1 && !exitProgram) {
|
||||
exitProgram = true;
|
||||
tcpConnector.shutdown(SHUT_RD);
|
||||
std::cerr << "Error while sending data: " << tcpConnector.last_error_str() << std::endl;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (tcpSocket.write(readByteFromStdin()) == -1 && !exitProgram) {
|
||||
exitProgram = true;
|
||||
tcpSocket.shutdown(SHUT_RD);
|
||||
std::cerr << "Error while sending data: " << tcpSocket.last_error_str() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readFromTCP6() {
|
||||
ssize_t byteCount;
|
||||
while (!exitProgram && (outgoing? (byteCount = tcp6Connector.read(networkBuffer, bufferSize)) > 0 : (byteCount = tcp6Socket.read(networkBuffer, bufferSize)) > 0)) {
|
||||
for (ssize_t i=0; i<byteCount; i++) {
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) networkBuffer[i] << " ";
|
||||
}
|
||||
std::cout.flush();
|
||||
consoleMutex.unlock();
|
||||
tcp6SocketMutex.lock();
|
||||
}
|
||||
tcp6SocketMutex.unlock();
|
||||
consoleMutex.lock();
|
||||
std::cerr << std::endl << "Connection closed." << std::endl;
|
||||
consoleMutex.unlock();
|
||||
}
|
||||
|
||||
void writeToTCPSocket(sockpp::tcp_socket* socket){
|
||||
void writeToTCP6() {
|
||||
while (!exitProgram) {
|
||||
//TODO: Implement locking/unlocking/threading shenanigans
|
||||
if (outgoing) {
|
||||
if (tcp6Connector.write(readByteFromStdin()) == -1 && !exitProgram) {
|
||||
exitProgram = true;
|
||||
tcp6Connector.shutdown(SHUT_RD);
|
||||
std::cerr << "Error while sending data: " << tcp6Connector.last_error_str() << std::endl;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (tcp6Socket.write(readByteFromStdin()) == -1 && !exitProgram) {
|
||||
exitProgram = true;
|
||||
tcp6Socket.shutdown(SHUT_RD);
|
||||
std::cerr << "Error while sending data: " << tcp6Socket.last_error_str() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
consoleMutex.lock();
|
||||
std::cerr << std::endl << "Connection closed." << std::endl;
|
||||
consoleMutex.unlock();
|
||||
}
|
||||
|
||||
void writeToTCP6Socket(sockpp::tcp6_socket* socket){
|
||||
void readFromUDP() {
|
||||
ssize_t byteCount;
|
||||
sockpp::udp_socket::addr_t peer;
|
||||
while ((byteCount = udpSocket.recv_from(networkBuffer, bufferSize, &peer)) > 0) {
|
||||
std::cout << peer << ": ";
|
||||
for (ssize_t i=0; i<byteCount; i++) {
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) networkBuffer[i] << " ";
|
||||
}
|
||||
std::cout << std::dec << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void writeToUDP(sockpp::udp_socket::addr_t peer) {
|
||||
while (!exitProgram) {
|
||||
//TODO: Implement locking/unlocking/threading shenanigans
|
||||
if (udpSocket.send_to(readByteFromStdin(), peer) == -1 && !exitProgram) {
|
||||
exitProgram = true;
|
||||
udpSocket.shutdown(SHUT_RD);
|
||||
std::cerr << "Error while sending data: " << udpSocket.last_error_str() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
consoleMutex.lock();
|
||||
std::cerr << std::endl << "Connection closed." << std::endl;
|
||||
consoleMutex.unlock();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
void readFromUDP6() {
|
||||
ssize_t byteCount;
|
||||
sockpp::udp6_socket::addr_t peer;
|
||||
while ((byteCount = udp6Socket.recv_from(networkBuffer, bufferSize, &peer)) > 0) {
|
||||
std::cout << peer << ": ";
|
||||
for (ssize_t i=0; i<byteCount; i++) {
|
||||
std::cout << std::hex << std::setfill('0') << std::setw(2) << (short) networkBuffer[i] << " ";
|
||||
}
|
||||
std::cout << std::dec << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void writeToUDP6(sockpp::udp6_socket::addr_t peer) {
|
||||
while (!exitProgram) {
|
||||
if (udp6Socket.send_to(readByteFromStdin(), peer) == -1 && !exitProgram) {
|
||||
exitProgram = true;
|
||||
udp6Socket.shutdown(SHUT_RD);
|
||||
std::cerr << "Error while sending data: " << udp6Socket.last_error_str() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::signal(SIGINT, signalHandler);
|
||||
std::signal(SIGTERM, signalHandler);
|
||||
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('4', "ipv4", "use IPv4, defaults to both when -4 and -6 are omitted, otherwise uses what is specified"));
|
||||
flags.push_back(CLI::Flag('6', "ipv6", "use IPv6, defaults to both when -4 and -6 are omitted, otherwise uses what is specified"));
|
||||
flags.push_back(CLI::Flag('t', "tcp", "use TCP, defaults to both when -t and -u are omitted, otherwise uses what is specified"));
|
||||
flags.push_back(CLI::Flag('u', "udp", "use UDP, defaults to both when -t and -u are omitted, otherwise uses what is specified"));
|
||||
flags.push_back(CLI::Flag('n', "no-color", "disable coloring the output (intended for terminals that don't work well with color escape sequences)"));
|
||||
flags.push_back(CLI::Flag('e', "echo-back", "echo input back to stdout"));
|
||||
flags.push_back(CLI::Flag('4', "ipv4", "use IPv4, either this or IPv6 has to be specified"));
|
||||
flags.push_back(CLI::Flag('6', "ipv6", "use IPv6, either this or IPv4 has to be specified"));
|
||||
flags.push_back(CLI::Flag('t', "tcp", "use TCP, either this or UDP has to be specified"));
|
||||
flags.push_back(CLI::Flag('u', "udp", "use UDP, either this or TCP has to be specified"));
|
||||
flags.push_back(CLI::Flag('h', "help", "print this information and exit"));
|
||||
flags.push_back(CLI::Flag('l', "license", "print license information and exit"));
|
||||
|
||||
std::vector<CLI::Option> options;
|
||||
options.push_back(CLI::Option('c', "connect", "HOST", "connect to HOST, listen for incoming connections if omitted"));
|
||||
options.push_back(CLI::Option('m', "mtu-optimize", "MTU", "Optimize for a specific maximum transfer unit by reading MTU bytes at a time."));
|
||||
options.push_back(CLI::Option(
|
||||
'p', "print-prefixes", "TCPin:UDPin:TCPout:UDPout",
|
||||
"override default prefixes for output (defaults to spaces + coloring the output or \"t:u:T:U\" in no-color mode)"
|
||||
));
|
||||
options.push_back(CLI::Option(
|
||||
'i', "input-prefixes", "TCP:UDP",
|
||||
"override default prefixes for input (defaults to \"t:u\")"
|
||||
));
|
||||
options.push_back(CLI::Option('c', "connect", "HOST", "make an outgoing connection to HOST instead of listening for an incoming connection"));
|
||||
options.push_back(CLI::Option('b', "bind", "ADDRESS", "(UDP only) bind to ADDRESS instead of localhost"));
|
||||
|
||||
std::vector<CLI::Argument> arguments;
|
||||
arguments.push_back(CLI::Argument("PORT", "the port to use"));
|
||||
arguments.push_back(CLI::Argument("PORT", "the port to lsiten on (or connect to)"));
|
||||
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Arbitrary tcp/udp connections in hex format.");
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Arbitrary TCP/UDP connections in hex format", "Spaces, tabs, newlines, and carriage returns in the input are ignored.\n\tYou may want to disable input echoing using `stty -echo` (reenable using `stty echo`).\n\tNote that many terminals do line buffering on the input by default.");
|
||||
|
||||
if (cliParser.getFlag("help").value){
|
||||
if (cliParser.getFlag("help").value) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if (cliParser.getFlag("license").value){
|
||||
if (cliParser.getFlag("license").value) {
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
|
@ -194,99 +290,205 @@ int main(int argc, char* argv[]){
|
|||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
if (cliParser.getFlag("ipv4").value || cliParser.getFlag("ipv6").value) {
|
||||
ipv4 = cliParser.getFlag("ipv4").value;
|
||||
ipv6 = cliParser.getFlag("ipv4").value;
|
||||
|
||||
ipv4 = cliParser.getFlag("ipv4").value;
|
||||
ipv6 = cliParser.getFlag("ipv6").value;
|
||||
tcp = cliParser.getFlag("tcp").value;
|
||||
udp = cliParser.getFlag("udp").value;
|
||||
|
||||
if (cliParser.getOption("connect").errorCode != ErrorCodes::NOT_PRESENT) {
|
||||
outgoing = true;
|
||||
host = cliParser.getOption("connect").value;
|
||||
}
|
||||
if (cliParser.getFlag("tcp").value || cliParser.getFlag("udp").value) {
|
||||
tcp = cliParser.getFlag("tcp").value;
|
||||
udp = cliParser.getFlag("udp").value;
|
||||
|
||||
if (!(ipv4 || ipv6) || (ipv4 && ipv6) || !(tcp || udp) || (tcp && udp)) {
|
||||
std::cout << "Please specify which protocols to use (one of IPv4/IPv6, one of TCP/UDP)." << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
if (cliParser.getOption('c').errorCode == ErrorCodes::NOT_PRESENT) {
|
||||
listenMode = true;
|
||||
}
|
||||
if (cliParser.getOption("mtu-optimize").errorCode == ErrorCodes::SUCCESS) {
|
||||
mtu = std::stol(cliParser.getOption("mtu-optimize").value);
|
||||
}
|
||||
host = cliParser.getOption("connect").value;
|
||||
//FIXME: use a function that returns a fixed-width data type instead,
|
||||
// ensure that the given value is a valid port
|
||||
|
||||
port = (in_port_t) std::stoi(cliParser.getArgument(0).value);
|
||||
|
||||
if (listenMode) {
|
||||
if (udp) {
|
||||
std::cerr << "UDP support is not implemented yet." << std::endl;
|
||||
return EXIT_UNIMPLEMENTED;
|
||||
if (outgoing) {
|
||||
if (tcp) {
|
||||
std::cerr << "Connecting to " << host << " on port " << (int) port << " (TCP)..." << std::endl;
|
||||
if (ipv4) {
|
||||
// TCP v4 out
|
||||
tcpConnector = sockpp::tcp_connector({host, port});
|
||||
if (!tcpConnector) {
|
||||
std::cerr << "Error connecting to " << host << " on port " << port << std::endl;
|
||||
std::cerr << tcpConnector.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::thread threadReadFromTCP = std::thread(readFromTCP);
|
||||
std::thread threadWriteToTCP = std::thread(writeToTCP);
|
||||
|
||||
threadReadFromTCP.join();
|
||||
threadWriteToTCP.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
// TCP v6 out
|
||||
tcp6Connector = sockpp::tcp6_connector({host, port});
|
||||
if (!tcp6Connector) {
|
||||
std::cerr << "Error connecting to " << host << " on port " << port << std::endl;
|
||||
std::cerr << tcp6Connector.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::thread threadReadFromTCP6 = std::thread(readFromTCP6);
|
||||
std::thread threadWriteToTCP6 = std::thread(writeToTCP6);
|
||||
|
||||
threadReadFromTCP6.join();
|
||||
threadWriteToTCP6.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
std::cerr << "Talking to " << host << " on port " << (int) port << " (UDP)..." << std::endl;
|
||||
if (ipv4) {
|
||||
// UDP v4 out
|
||||
if (!udpSocket) {
|
||||
std::cerr << "Error creating UDP socket: " << udpSocket.last_error_str() << std::endl;
|
||||
}
|
||||
// Btw: Did you know that UDP has no concept of a connection?
|
||||
sockpp::udp_socket::addr_t peer = sockpp::inet_address(host, port);
|
||||
if (!udpSocket.connect(peer)) {
|
||||
std::cerr << "Error associating socket with " << host << " port " << port << std::endl;
|
||||
std::cerr << udpSocket.last_error_str() << std::endl;
|
||||
}
|
||||
|
||||
std::thread threadReadFromUDP = std::thread(readFromUDP);
|
||||
std::thread threadWriteToUDP = std::thread(writeToUDP, peer);
|
||||
|
||||
threadReadFromUDP.join();
|
||||
threadWriteToUDP.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
// UDP v6 out
|
||||
if (!udp6Socket) {
|
||||
std::cerr << "Error creating UDP socket: " << udp6Socket.last_error_str() << std::endl;
|
||||
}
|
||||
// Btw: Did you know that UDP has no concept of a connection?
|
||||
sockpp::udp6_socket::addr_t peer = sockpp::inet6_address(host, port);
|
||||
if (!udp6Socket.connect(peer)) {
|
||||
std::cerr << "Error associating socket with " << host << " port " << port << std::endl;
|
||||
std::cerr << udp6Socket.last_error_str() << std::endl;
|
||||
}
|
||||
|
||||
std::thread threadReadFromUDP6 = std::thread(readFromUDP6);
|
||||
std::thread threadWriteToUDP6 = std::thread(writeToUDP6, peer);
|
||||
|
||||
threadReadFromUDP6.join();
|
||||
threadWriteToUDP6.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (ipv6) {
|
||||
//std::cerr << "IPv6 support is not implented yet." << std::endl;
|
||||
//return EXIT_UNIMPLEMENTED;
|
||||
std::cerr << "Listening on port " << port << "." << std::endl;
|
||||
sockpp::socket_initializer socketInitializer;
|
||||
tcp6Acceptor = sockpp::tcp6_acceptor(port);
|
||||
|
||||
if(!tcp6Acceptor){
|
||||
std::cerr << "Error while creating TCP6 acceptor: " << tcp6Acceptor.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
sockpp::inet6_address peer;
|
||||
tcp6Socket = new sockpp::tcp6_socket();
|
||||
*tcp6Socket = tcp6Acceptor.accept(&peer);
|
||||
|
||||
std::cerr << "Incoming connection from " << peer << std::endl;
|
||||
|
||||
if (!(*tcp6Socket)) {
|
||||
std::cerr << "Error on incoming connection: " << tcp6Acceptor.last_error_str() << std::endl;
|
||||
delete tcp6Socket;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::thread threadReadFromTCP6 = std::thread(readFromTCP6Socket, tcp6Socket, mtu);
|
||||
threadReadFromTCP6.join();
|
||||
|
||||
delete tcp6Socket;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if(ipv4){
|
||||
std::cerr << "Listening on port " << port << "." << std::endl;
|
||||
|
||||
sockpp::socket_initializer socketInitializer;
|
||||
tcpAcceptor = sockpp::tcp_acceptor(port);
|
||||
|
||||
if (!tcpAcceptor) {
|
||||
std::cerr << "Error while creating TCP acceptor: " << tcpAcceptor.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
sockpp::inet_address peer;
|
||||
tcpSocket = new sockpp::tcp_socket();
|
||||
*tcpSocket = tcpAcceptor.accept(&peer);
|
||||
|
||||
std::cerr << "Incoming connection from " << peer << std::endl;
|
||||
|
||||
if (!(*tcpSocket)) {
|
||||
std::cerr << "Error on incoming connection: " << tcpAcceptor.last_error_str() << std::endl;
|
||||
delete tcpSocket;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::thread threadReadFromTCP = std::thread(readFromTCPSocket, tcpSocket, mtu);
|
||||
threadReadFromTCP.join();
|
||||
|
||||
delete tcpSocket;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
} else {
|
||||
std::cerr << "Client mode is not implemented yet." << std::endl;
|
||||
return EXIT_UNIMPLEMENTED;
|
||||
if (tcp) {
|
||||
std::cerr << "Listening on port " << (int) port << " (TCP)..." << std::endl;
|
||||
if (ipv4) {
|
||||
// TCP v4 in
|
||||
tcpAcceptor = sockpp::tcp_acceptor(port);
|
||||
if (!tcpAcceptor) {
|
||||
std::cerr << "Error while creating TCP acceptor: " << tcpAcceptor.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
sockpp::inet_address peer;
|
||||
tcpSocket = tcpAcceptor.accept(&peer);
|
||||
std::cerr << "Incoming connection from " << peer << std::endl;
|
||||
if (!tcpSocket) {
|
||||
std::cerr << "Error on incoming connection: " << tcpAcceptor.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::thread threadReadFromTCP = std::thread(readFromTCP);
|
||||
std::thread threadWriteToTCP = std::thread(writeToTCP);
|
||||
|
||||
threadReadFromTCP.join();
|
||||
threadWriteToTCP.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
// TCP v6 in
|
||||
tcp6Acceptor = sockpp::tcp6_acceptor(port);
|
||||
if (!tcp6Acceptor) {
|
||||
std::cerr << "Error while creating TCP acceptor: " << tcp6Acceptor.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
sockpp::inet6_address peer;
|
||||
tcp6Socket = tcp6Acceptor.accept(&peer);
|
||||
std::cerr << "Incoming connection from " << peer << std::endl;
|
||||
if (!tcp6Socket) {
|
||||
std::cerr << "Error on incoming connection: " << tcp6Acceptor.last_error_str() << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::thread threadReadFromTCP6 = std::thread(readFromTCP6);
|
||||
std::thread threadWriteToTCP6 = std::thread(writeToTCP6);
|
||||
|
||||
threadReadFromTCP6.join();
|
||||
threadWriteToTCP6.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
std::string address = "localhost";
|
||||
if (cliParser.getOption("bind").errorCode != ErrorCodes::NOT_PRESENT) {
|
||||
address = cliParser.getOption("bind").value;
|
||||
}
|
||||
std::cerr << "Listening on " << address << " port " << (int) port << " (UDP)..." << std::endl;
|
||||
if (ipv4) {
|
||||
// UDP v4 in
|
||||
if (!udpSocket) {
|
||||
std::cerr << "Error creating UDP socket: " << udpSocket.last_error_str() << std::endl;
|
||||
}
|
||||
if (!udpSocket.bind(sockpp::inet_address(address, port))) {
|
||||
std::cerr << "Error binding UDP socket to " << address << " port " << port << ": " << udpSocket.last_error_str() << std::endl;
|
||||
}
|
||||
|
||||
std::thread threadReadFromUDP = std::thread(readFromUDP);
|
||||
// Can't send bc we have no idea where to send to.
|
||||
//std::thread threadWriteToUDP = std::thread(writeToUDP);
|
||||
|
||||
threadReadFromUDP.join();
|
||||
//threadWriteToUDP.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
// UDP v6 in
|
||||
if (!udp6Socket) {
|
||||
std::cerr << "Error creating UDP socket: " << udp6Socket.last_error_str() << std::endl;
|
||||
}
|
||||
if (!udp6Socket.bind(sockpp::inet6_address(address, port))) {
|
||||
std::cerr << "Error binding UDP socket to " << address << " port " << port << ": " << udp6Socket.last_error_str() << std::endl;
|
||||
}
|
||||
|
||||
std::thread threadReadFromUDP6 = std::thread(readFromUDP6);
|
||||
// Can't send bc we have no idea where to send to.
|
||||
//std::thread threadWriteToUDP6 = std::thread(writeToUDP6);
|
||||
|
||||
threadReadFromUDP6.join();
|
||||
//threadWriteToUDP6.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
// Copyright 2024, FOSS-VG Developers and Contributers
|
||||
//
|
||||
// Author(s):
|
||||
// Jocadbz
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// version 3 along with this program.
|
||||
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
#include <bitset>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <tinyutf8/tinyutf8.h>
|
||||
#include <zlib/zlib.h>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
#include "../lib/cli.hpp"
|
||||
#include "../lib/file.hpp"
|
||||
#include "../lib/zlibutil.hpp"
|
||||
#include "../lib/error.hpp"
|
||||
|
||||
#define EXIT_SUCCESS 0
|
||||
#define EXIT_RUNTIME 1
|
||||
#define EXIT_USAGE 2
|
||||
|
||||
#define CHUNK_SIZE 16384 // Chunk size
|
||||
|
||||
/*
|
||||
Finally, the main file
|
||||
⠀⠀⠀⠀⠀⠀⠀⢠⣤⣄⣀⣠⣤⣶⣿⣯⣿⣽⣾⣷⣶⣶⡦⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⢀⣿⣟⣯⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣟⣦⣄⠀⠀⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣾⡷⣄⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣾⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣳⡀⠀⠀⠀
|
||||
⠀⠀⢠⣿⣿⣽⣿⢿⣿⣿⣿⣿⡿⣿⣿⣿⣿⢿⡿⣽⣿⣿⡿⣿⣿⣏⣿⣿⣿⣟⣿⣳⡄⠀⠀
|
||||
⠀⠀⣾⣿⣿⣽⣾⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⢿⣿⣾⢿⣷⡿⣿⣿⣷⢿⣿⣿⣷⡿⣷⠀⠀
|
||||
⠀⢸⣿⣿⣿⣿⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣳⣿⣟⣿⣿⣿⣻⣽⣿⣿⡽⡇⠀
|
||||
⠀⡿⣿⣿⣿⣿⣾⣿⣿⣿⣿⢿⣿⣿⣿⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⡀
|
||||
⢸⣿⣿⣿⣿⣿⣿⣿⣏⠀⠈⠀⣿⣿⣿⣿⣿⣿⣟⣿⣿⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿⣿⢿⡇
|
||||
⢨⣿⣿⣿⣿⣽⣿⣿⣇⣀⡤⠤⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣿⣿⣿⣿⠎⠀
|
||||
⢰⣿⡿⣿⣿⣿⣿⣿⠃⠀⠀⠐⠃⠘⠙⢹⠿⡘⣿⠟⠉⢹⡂⠿⡞⣿⣿⣿⣿⣿⣿⣿⣿⠂⠀
|
||||
⠀⣿⣿⣿⣿⣿⣿⡞⠅⣀⣀⣀⣀⠉⠓⠚⠀⠁⡏⠀⢛⠋⢀⣀⣀⣋⠸⣿⣿⣿⣿⣿⣿⠃⠀
|
||||
⠀⣷⣟⣿⣿⣿⣿⣆⠠⡟⣿⣿⣿⡿⠦⠀⠀⠀⠀⠀⠠⢿⣿⣿⣿⠻⢇⣿⣿⣿⣿⣿⣿⠀⠀
|
||||
⠀⠈⢸⣻⣿⣿⣿⢯⡃⢀⠹⣿⡿⠗⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⠏⣈⠈⣿⣿⣿⣿⣿⣿⠀⠀
|
||||
⠀⠀⠈⣿⣿⣿⣿⣇⡗⠈⠉⠉⠉⠉⠀⠀⢐⡀⠀⠀⠀⠈⠉⠉⠉⠑⢸⣸⣿⡟⣿⣿⡟⠀⠀
|
||||
⠀⠀⠀⢻⣿⣽⣿⡏⢿⡆⠀⠀⠀⠀⠀⠀⠸⢆⡄⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⡿⠇⠀⠀
|
||||
⠀⠀⠀⠈⠿⣿⢿⡇⠀⠙⢦⡀⠀⠀⠀⠐⠲⠤⠔⠂⠀⠀⠀⢀⣴⣾⣿⣿⣿⣿⣿⡟⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠘⣿⣇⠀⠀⠀⠙⠢⣄⡀⠀⠀⠀⠀⣀⣐⣺⣵⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠙⠋⠀⠀⠀⠀⠀⢹⢨⠑⠲⠤⠞⠋⠉⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡼⠈⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀
|
||||
⠀⠀⠀⠀⠀⠀⢀⣀⣠⢤⡠⠒⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀
|
||||
⠀⠀⣠⠔⠒⠉⠁⠀⠀⠘⠶⣲⠄⠀⠀⠈⠀⠀⠀⢠⢀⠀⠀⣀⠤⢻⣿⣿⣿⡏⠐⠲⣄⠀⠀
|
||||
⠀⢰⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠓⠒⠚⢕⡀⠀⠀⣠⠖⠒⠚⠁⠀⢾⣿⣿⣿⡁⠀⠀⠨⡆⠀
|
||||
⠀⢸⠀⠀⠀⠒⠒⠒⠒⠒⠂⠀⠐⠚⠑⠆⠀⠀⠒⠓⠀⠀⠀⠀⠀⣿⣿⣿⣿⡆⠀⠀⠀⣇⠀
|
||||
⠀⠈⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠁⠀
|
||||
*/
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
std::vector<CLI::Flag> flags;
|
||||
flags.push_back(CLI::Flag('d', "decompress", "descompress a file"));
|
||||
std::vector<CLI::Option> options;
|
||||
std::vector<CLI::Argument> arguments;
|
||||
arguments.push_back(CLI::Argument("FILE", "path of the file to compress/decompress"));
|
||||
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Compress or decompress files using zlib");
|
||||
|
||||
if (cliParser.getFlag("help").value) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.getFlag("license").value){
|
||||
std::cout
|
||||
<< "Copyright 2022, FOSS-VG Developers and Contributers\n"
|
||||
<< "\n"
|
||||
<< "ZlibUtil is part of the FOSS-VG development tool suite.\n"
|
||||
<< "\n"
|
||||
<< "This program is free software: you can redistribute it and/or modify it\n"
|
||||
<< "under the terms of the GNU Affero General Public License as published\n"
|
||||
<< "by the Free Software Foundation, version 3.\n"
|
||||
<< "\n"
|
||||
<< "This program is distributed in the hope that it will be useful,\n"
|
||||
<< "but WITHOUT ANY WARRANTY; without even the implied\n"
|
||||
<< "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||
<< "See the GNU Affero General Public License for more details.\n"
|
||||
<< "\n"
|
||||
<< "You should have received a copy of the GNU Affero General Public License\n"
|
||||
<< "version 3 along with this program.\n"
|
||||
<< "If not, see https://www.gnu.org/licenses/agpl-3.0.en.html"
|
||||
<< std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (cliParser.wrongUsage) {
|
||||
std::cout << cliParser.getUsage() << std::endl;
|
||||
return EXIT_USAGE;
|
||||
}
|
||||
|
||||
std::string filename = cliParser.getArgument(0).value;
|
||||
|
||||
ErrorOr<File*> filePointer = File::open(filename, 'r');
|
||||
if (filePointer.isError) {
|
||||
std::cout << "Failed to open file: " << filename << std::endl;
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
File* file = filePointer.value;
|
||||
File* writeFile;
|
||||
|
||||
if (cliParser.getFlag("decompress").value) {
|
||||
std::vector<uint8_t> bytes = file->read(file->size.value).value;
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> decompressed = zlib::decompressData(bytes);
|
||||
if (decompressed.isError) {
|
||||
std::cout << "Error: Failed to decompress: " << filename << std::endl;
|
||||
delete file;
|
||||
// not cleaning up writeFile here bc it hasn't been created
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
|
||||
std::string outFilename;
|
||||
if (filename.length() > 3 && filename.rfind(".zz") == filename.length()-3) {
|
||||
outFilename = filename.substr(0, filename.length()-3);
|
||||
} else {
|
||||
outFilename = filename + ".uncompressed";
|
||||
}
|
||||
writeFile = File::open(outFilename, 'w').value;
|
||||
writeFile->write(decompressed.value);
|
||||
writeFile->close();
|
||||
} else {
|
||||
std::vector<uint8_t> bytes = file->read(file->size.value).value;
|
||||
|
||||
ErrorOr<std::vector<uint8_t>> compressed = zlib::compressData(bytes);
|
||||
if (compressed.isError) {
|
||||
std::cout << "Error: Failed to compress: " << filename << std::endl;
|
||||
delete file;
|
||||
// not cleaning up writeFile here bc it hasn't been created
|
||||
return EXIT_RUNTIME;
|
||||
}
|
||||
writeFile = File::open(filename + ".zz", 'w').value;
|
||||
writeFile->write(compressed.value);
|
||||
writeFile->close();
|
||||
}
|
||||
|
||||
delete file;
|
||||
delete writeFile;
|
||||
}
|
Loading…
Reference in New Issue