Compare commits

..

No commits in common. "master" and "BodgeMaster-unfinished" have entirely different histories.

86 changed files with 749 additions and 15361 deletions

8
.gitignore vendored
View File

@ -14,20 +14,12 @@
# 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 Normal file
View File

@ -0,0 +1,12 @@
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

View File

@ -14,8 +14,8 @@ Immediate goals:
- [ ] send a surface to stand on
- [ ] handle chat
- NBT library
- [x] parse NBT
- [x] decode and encode data
- [ ] parse NBT
- [ ] decode and encode data
## Project Setup Instructions
@ -26,7 +26,6 @@ Build dependencies:
- bash
- a C++ 20 compiler
- GLFW with headers
Setup dependencies:

View File

@ -22,8 +22,10 @@ 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.

View File

@ -1,8 +1,5 @@
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.

View File

@ -1,122 +0,0 @@
[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.

View File

@ -1,6 +0,0 @@
[0: 64 Bit Integer] test:
|Header: 7 bytes
|Payload: 8 bytes
|Total: 15 bytes
'Value: 9223372036854775807

View File

@ -1,12 +0,0 @@
[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.

File diff suppressed because it is too large Load Diff

View File

@ -1,592 +0,0 @@
[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 aufn 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, theyre 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

View File

@ -1,78 +0,0 @@
[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

View File

@ -1,223 +0,0 @@
[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. Lets 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: hes
| |
| |[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

View File

@ -1,67 +1,33 @@
# 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 whats happening
# Tests
## unicode_data/
Files with unicode data
This directory contains two files with unicode data. One is in Java format, the other is normal UTF-8.
- 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
Usage: `check_endianness > header_file`
Note that, while it can detect PDP and Honeywell endianness, the FOSS-VG project itself does not support these.
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.
Usage example: `check_endianness > header_file`
## region_files
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.
## 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

Binary file not shown.

View File

@ -1,5 +0,0 @@
# Netty Testing
This sub-project is used to learn how Netty works
Build with Maven (`mvn compile`). Run with the build scripts.

View File

@ -1,48 +0,0 @@
<?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>

View File

@ -1,22 +0,0 @@
# 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

View File

@ -1,25 +0,0 @@
// 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) {
}
}

View File

@ -1,25 +0,0 @@
// 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) {
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,90 +0,0 @@
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.

View File

@ -35,19 +35,10 @@ fi
# dynamically linked libraries.
echo ">>> Building libs..."
create_directory bin/lib
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]} &
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 &
$WAIT_ANYWAY
done
@ -64,17 +55,12 @@ 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 programs..."
echo ">>> Building tools..."
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: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"
"$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"
)
for command in ${!COMPILE_COMMANDS[@]}; do
echo "${COMPILE_COMMANDS[command]}"
@ -83,21 +69,3 @@ 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

View File

@ -25,21 +25,14 @@ remove .endianness
remove resources/check_endianness
create_directory ./bin
create_directory ./bin/lib
create_directory ./bin/lib/net
create_directory ./include
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/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/
ln -vs ../dependencies/sockpp-0.8.1/include/sockpp/ ./include/
ln -vs ../dependencies/sockpp-0.7.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

View File

@ -17,7 +17,6 @@
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
@ -36,6 +35,6 @@ done
echo "
>>> Cleaning dependencies..."
remove -f ./dependencies
remove ./dependencies
create_directory ./dependencies
create_file ./dependencies/.placeholder

View File

@ -1,61 +0,0 @@
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

13
scripts/lib.sh Executable file → Normal file
View File

@ -57,18 +57,11 @@ fi
# `rm -v` only prints the names of the removed things instead of a more
# comprehensible message like "removing NAME".
function remove {
local USE_FORCE=""
if [ "$1" = "-f" ]; then
USE_FORCE="f"
shift
echo "Forcefully removing $1..."
else
echo "Removing $1..."
fi;
echo "Removing $1..."
if [ -d "$1" ]; then
rm -"$USE_FORCE"rv "$1"
rm -rv "$1"
else
rm -"$USE_FORCE"v "$1"
rm -v "$1"
fi
}

View File

@ -17,19 +17,68 @@
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
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
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
echo -n ">>> Extracting tiny-utf8... "
gzip -d dependencies/tmp/tiny-utf8.tar.gz
@ -41,60 +90,11 @@ gzip -d dependencies/tmp/sockpp.tar.gz
tar -xf dependencies/tmp/sockpp.tar -C dependencies
echo "done"
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
echo ">>> Building sockpp... "
pushd dependencies/sockpp-0.7.1/ >/dev/null 2>&1
cmake -Bbuild .
cmake --build build
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 -f dependencies/tmp
remove dependencies/tmp

View File

@ -33,13 +33,12 @@ 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 -o bin/test/nbt_read_write_helpers"
"$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/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 -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"
"$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"
)
for command in ${!COMPILE_COMMANDS[@]}; do
echo "${COMPILE_COMMANDS[command]}"

View File

@ -1,11 +0,0 @@
#!/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 "================================================================================"

View File

@ -1,22 +0,0 @@
#!/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 "================================================================================"

View File

@ -1,16 +0,0 @@
#!/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

View File

@ -1,8 +1,7 @@
#!/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.
@ -16,7 +15,9 @@
# version 3 along with this program.
# If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
set -e
echo "################################################################################
Testing hexnet
################################################################################"
cd target/classes
java foss_vg.NettyClient
echo "Test not yet implemented."
#TODO: implement unit test after merging back with master

View File

@ -1,46 +0,0 @@
#!/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 "================================================================================"

View File

@ -13,15 +13,9 @@
# version 3 along with this program.
# If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
echo ">>> Loading shell environment for FOSS-VG development..."
echo -n "Loading shell environment for FOSS-VG development... "
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
PROJECT_BASE_DIR="$( cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 ; pwd -P )"
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"
@ -39,79 +33,15 @@ 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"
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
if [ -f "$PROJECT_BASE_DIR/.localenv.bashrc" ]; then
source "$PROJECT_BASE_DIR/.localenv.bashrc"
fi
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
echo "done."

View File

@ -1,150 +0,0 @@
// 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;
}

View File

@ -1,67 +0,0 @@
// 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;
}

View File

@ -1,8 +1,5 @@
// 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.
@ -202,6 +199,7 @@ namespace CLI {
}
ArgumentsParser::~ArgumentsParser() {
//TODO: check that this actually runs
for (auto const& [shortName, flag]: this->flagsByShortName) {
delete flag;
}
@ -320,10 +318,6 @@ namespace CLI {
}
}
if (this->additionalInfo != "") {
usageString += "\nAdditional Info:\n\n\t" + this->additionalInfo + "\n";
}
return usageString;
}
}

View File

@ -17,54 +17,43 @@
#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() {
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;
}
ErrorOr();
ErrorOr(T);
ErrorOr(bool, uint8_t);
ErrorOr(bool, uint8_t, T);
};
struct ErrorOrVoid {
bool isError;
uint8_t errorCode;
template <typename T>
ErrorOr<T>::ErrorOr() {
this->isError = false;
this->errorCode = 0;
}
ErrorOrVoid() {
this->isError = false;
this->errorCode = 0;
}
template <typename T>
ErrorOr<T>::ErrorOr(T value) {
this->isError = false;
this->errorCode = 0;
this->value = value;
}
ErrorOrVoid(bool isError, uint8_t errorCode) {
this->isError = isError;
this->errorCode = errorCode;
}
};
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;
}
namespace ErrorCodes {
// These are all arbitrary values used to assign error codes to different
@ -75,10 +64,13 @@ namespace ErrorCodes {
// Ahh yes, very useful.
const uint8_t SUCCESS = 0;
// IndexOutOfRangeException equivalent
const uint8_t OUT_OF_RANGE = 1;
// like OUT_OF_RANGE but when going out of bounds in a non-predetermined way
// 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;
@ -91,23 +83,6 @@ 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;

View File

@ -1,326 +0,0 @@
// 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));
}

View File

@ -1,94 +0,0 @@
// 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);
};

View File

View File

@ -1,103 +0,0 @@
#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 dont 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
}
}

93
src/lib/javacompat.cpp Normal file
View File

@ -0,0 +1,93 @@
//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);
}
}

View File

@ -13,83 +13,11 @@
//version 3 along with this program.
//If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#pragma once
#include <vector>
#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) {
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);
}
ErrorOr<tiny_utf8::string> importJavaString(uint8_t data[], uint16_t size);
ErrorOr<std::vector<uint8_t>> exportJavaString(tiny_utf8::string data);
}

File diff suppressed because it is too large Load Diff

View File

@ -19,31 +19,29 @@
// 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: 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
// 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
#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);
@ -63,7 +61,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);
ErrorOrVoid writeString(std::vector<uint8_t>* destination, tiny_utf8::string data);
void 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);
@ -74,236 +72,46 @@ 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;
// This is a workaround that's not part of the spec.
const uint8_t INVALID = 255;
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;
}
namespace Tag {
//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;
class Generic {
protected:
std::mutex mutex;
uint8_t type;
public:
tiny_utf8::string name;
Tag(){}
Tag(uint8_t tagType, tiny_utf8::string name, uint16_t nameSize, T content, uint32_t size);
};
Generic();
virtual ~Generic();
class End: public Tag<uint8_t>{
public:
End();
};
virtual ErrorOrVoid serialize(std::vector<uint8_t>* rawData);
virtual ErrorOrVoid serializeWithoutHeader(std::vector<uint8_t>* rawData);
uint8_t getTagType();
};
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[]);
};
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);
bool validateRawNBTData(uint8_t data[], int length, uint64_t initialPosition=0);
}

View File

@ -1,16 +0,0 @@
// 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

View File

@ -1,42 +0,0 @@
// 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();
}

View File

@ -1,70 +0,0 @@
// 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));
}
}

View File

@ -1,141 +0,0 @@
// 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);
}
}
}

View File

@ -1,43 +0,0 @@
// 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;
}
}

View File

@ -1,16 +0,0 @@
// 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

View File

@ -1,16 +0,0 @@
// 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

View File

@ -1,16 +0,0 @@
// 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

View File

@ -1,16 +0,0 @@
// 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

View File

@ -1,17 +0,0 @@
// 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

View File

@ -1,57 +0,0 @@
// 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];
}
}

View File

@ -1,116 +0,0 @@
// 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()));
}
}

View File

@ -1,27 +0,0 @@
// 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);
}

View File

View File

@ -746,19 +746,5 @@ 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;
}

View File

@ -1,215 +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 <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;
}

View File

@ -75,16 +75,7 @@ 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
@ -100,5 +91,5 @@ int main(){
std::cout << "Passed Export Java string test." << std::endl;
delete nextChar;
return 0;
return 0;
}

View File

@ -29,41 +29,32 @@ 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
currentPosition = 5;
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).value == 35);
ASSERT(NBT::Helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == false);
uint64_t 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);
// 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);
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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);
@ -73,33 +64,29 @@ 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::OVERRUN);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// 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);
// 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);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt16(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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);
@ -109,34 +96,29 @@ 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::OVERRUN);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// 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);
// 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);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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);
// delete before checking assertions so we don't leak
NBT::helper::writeInt32(writeInt32TestResult, (int32_t) 0x12345678);
std::vector<uint8_t> dereferencedWriteInt32TestResult = *writeInt32TestResult;
delete writeInt32TestResult;
ASSERT(
@ -151,34 +133,29 @@ 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::OVERRUN);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// 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);
// 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);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64(dataForIntTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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);
// delete before checking assertions so we don't leak
NBT::helper::writeInt64(writeInt64TestResult, (int64_t) 0x0123456789ABCDEF);
std::vector<uint8_t> dereferencedWriteInt64TestResult = *writeInt64TestResult;
delete writeInt64TestResult;
ASSERT(
@ -213,34 +190,30 @@ 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::OVERRUN);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// 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);
// 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}));
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt8Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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 &&
@ -252,7 +225,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 &&
@ -269,34 +242,30 @@ 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::OVERRUN);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// 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);
// 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}));
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt32Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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 &&
@ -312,7 +281,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 &&
@ -334,34 +303,30 @@ 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::OVERRUN);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
// 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);
// 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}));
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readInt64Array(dataForIntArrayTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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 &&
@ -385,7 +350,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 &&
@ -418,25 +383,21 @@ 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);
// 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);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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(
@ -453,25 +414,21 @@ 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);
// 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);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
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(
@ -530,21 +487,14 @@ int main(){
std::cerr << "Failed to open file: " << normalFilePath << std::endl;
return 2;
}
tiny_utf8::string normalString = tiny_utf8::string(normalStdString);
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!");
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;
char* nextChar1 = new char;
@ -567,17 +517,11 @@ 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;

View File

@ -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

View File

@ -0,0 +1,31 @@
// 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));
}

View File

@ -1,287 +0,0 @@
// 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;
}

View File

@ -1,116 +0,0 @@
// 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;
}

View File

@ -1,130 +0,0 @@
// 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;
}

View File

@ -13,359 +13,8 @@
// 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[]) {
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;
return 0;
}

View File

@ -1,8 +1,5 @@
//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.
@ -16,260 +13,167 @@
//version 3 along with this program.
//If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include <chrono>
#include <csignal>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <iomanip>
#include <string>
#include <cstdint>
#include <cctype>
#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 <mutex>
#include <csignal>
#include "../lib/cli.hpp"
#include "../lib/error.hpp"
#include "../lib/cli.hpp"
#define EXIT_SUCCESS 0
#define EXIT_RUNTIME 1
#define EXIT_USAGE 2
#define EXIT_UNIMPLEMENTED 3
#define EXIT_SIGNAL 4
// 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;
// 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;
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;
// 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));
}
sockpp::tcp_socket* tcpSocket;
sockpp::tcp6_socket* tcp6Socket;
sockpp::tcp_acceptor tcpAcceptor;
sockpp::tcp6_acceptor tcp6Acceptor;
std::mutex tcpSocketMutex;
std::mutex tcp6SocketMutex;
std::mutex consoleMutex;
// used for coordinated graceful exit across threads
bool exitProgram = false;
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
tcpAcceptor.shutdown();
if (tcpSocket) {
tcpSocket.shutdown(SHUT_RD);
if (tcpSocket != nullptr && *tcpSocket) {
// Intentionally not using the mutex here
std::cout << "test\n";
tcpSocket->shutdown(SHUT_RD);
}
if (tcpConnector) {
tcpConnector.shutdown(SHUT_RD);
if (tcp6Socket != nullptr && *tcp6Socket) {
// Intentionally not using the mutex here
tcp6Socket->shutdown(SHUT_RD);
}
//TODO: figure out if - and how - this applies to UDP
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);
// 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);
}
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] << " ";
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];
}
std::cout.flush();
consoleMutex.unlock();
tcpSocketMutex.lock();
}
tcpSocketMutex.unlock();
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
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] << " ";
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];
}
std::cout.flush();
consoleMutex.unlock();
tcp6SocketMutex.lock();
}
tcp6SocketMutex.unlock();
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
void writeToTCP6() {
void writeToTCPSocket(sockpp::tcp_socket* socket){
while (!exitProgram) {
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;
}
}
//TODO: Implement locking/unlocking/threading shenanigans
}
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
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) {
void writeToTCP6Socket(sockpp::tcp6_socket* socket){
while (!exitProgram) {
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;
}
//TODO: Implement locking/unlocking/threading shenanigans
}
consoleMutex.lock();
std::cerr << std::endl << "Connection closed." << std::endl;
consoleMutex.unlock();
}
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;
}
}
int main(int argc, char* argv[]){
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, 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('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('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", "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"));
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\")"
));
std::vector<CLI::Argument> arguments;
arguments.push_back(CLI::Argument("PORT", "the port to lsiten on (or connect to)"));
arguments.push_back(CLI::Argument("PORT", "the port to use"));
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.");
CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, options, arguments, "Arbitrary tcp/udp connections in hex format.");
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"
@ -290,205 +194,99 @@ int main(int argc, char* argv[]) {
<< std::endl;
return EXIT_SUCCESS;
}
if (cliParser.wrongUsage) {
std::cout << cliParser.getUsage() << std::endl;
return EXIT_USAGE;
}
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("ipv4").value || cliParser.getFlag("ipv6").value) {
ipv4 = cliParser.getFlag("ipv4").value;
ipv6 = cliParser.getFlag("ipv4").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.getFlag("tcp").value || cliParser.getFlag("udp").value) {
tcp = cliParser.getFlag("tcp").value;
udp = cliParser.getFlag("udp").value;
}
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 (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 (listenMode) {
if (udp) {
std::cerr << "UDP support is not implemented yet." << std::endl;
return EXIT_UNIMPLEMENTED;
}
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 {
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;
}
}
std::cerr << "Client mode is not implemented yet." << std::endl;
return EXIT_UNIMPLEMENTED;
}
}

View File

@ -1,155 +0,0 @@
// 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;
}