Skip to content

Commit 6e3c528

Browse files
committed
feat/style: Implement primitive array reading, start work on object arrays
1 parent d519ecc commit 6e3c528

13 files changed

Lines changed: 168 additions & 84 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
cmake_minimum_required(VERSION VERSION 3.30)
2-
project(JavaObjectStreams VERSION 1.0.2)
2+
project(JavaObjectStreams VERSION 1.0.3)
33

44
set(CMAKE_CXX_STANDARD 20)
55

include/JavaObject/EJavaFieldDescriptorType.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
#define JAVAOBJECTSTREAMS_EJAVAFIELDDESCRIPTORTYPE_H
1313

1414
enum EJavaFieldDescriptorType : signed char {
15-
TYPE_BYTE = 'B',
16-
TYPE_CHARACTER = 'C',
17-
TYPE_DOUBLE = 'D',
18-
TYPE_FLOAT = 'F',
19-
TYPE_INT = 'I',
20-
TYPE_LONG = 'J',
21-
TYPE_OBJECT = 'L',
22-
TYPE_SHORT = 'S',
23-
TYPE_BOOLEAN = 'Z',
24-
TYPE_ARRAY = '['
15+
TYPE_BYTE = 'B',
16+
TYPE_CHARACTER = 'C',
17+
TYPE_DOUBLE = 'D',
18+
TYPE_FLOAT = 'F',
19+
TYPE_INT = 'I',
20+
TYPE_LONG = 'J',
21+
TYPE_OBJECT = 'L',
22+
TYPE_SHORT = 'S',
23+
TYPE_BOOLEAN = 'Z',
24+
TYPE_ARRAY = '['
2525
};
2626

27-
#endif // JAVAOBJECTSTREAMS_EJAVAFIELDDESCRIPTORTYPE_H
27+
#endif // JAVAOBJECTSTREAMS_EJAVAFIELDDESCRIPTORTYPE_H

include/JavaObject/EJavaTypeCode.h

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@
1212
#define JAVAOBJECTSTREAMS_EJAVATYPECODE_H
1313

1414
enum EJavaTypeCode : signed char {
15-
TC_NULL = 0x70,
16-
TC_REFERENCE = 0x71,
17-
TC_CLASSDESC = 0x72,
18-
TC_OBJECT = 0x73,
19-
TC_STRING = 0x74,
20-
TC_ARRAY = 0x75,
21-
TC_CLASS = 0x76,
22-
TC_BLOCKDATA = 0x77,
23-
TC_ENDBLOCKDATA = 0x78,
24-
TC_RESET = 0x79,
25-
TC_BLOCKDATALONG = 0x7a,
26-
TC_EXCEPTION = 0x7B,
27-
TC_LONGSTRING = 0x7C,
28-
TC_PROXYCLASSDESC = 0x7D,
29-
TC_ENUM = 0x7E,
15+
TC_NULL = 0x70,
16+
TC_REFERENCE = 0x71,
17+
TC_CLASSDESC = 0x72,
18+
TC_OBJECT = 0x73,
19+
TC_STRING = 0x74,
20+
TC_ARRAY = 0x75,
21+
TC_CLASS = 0x76,
22+
TC_BLOCKDATA = 0x77,
23+
TC_ENDBLOCKDATA = 0x78,
24+
TC_RESET = 0x79,
25+
TC_BLOCKDATALONG = 0x7a,
26+
TC_EXCEPTION = 0x7B,
27+
TC_LONGSTRING = 0x7C,
28+
TC_PROXYCLASSDESC = 0x7D,
29+
TC_ENUM = 0x7E,
3030

31-
TC_BASE = TC_NULL, // lowest value
32-
TC_MAX = TC_ENUM // highest value
31+
TC_BASE = TC_NULL, // lowest value
32+
TC_MAX = TC_ENUM // highest value
3333
};
3434

35-
#endif // JAVAOBJECTSTREAMS_EJAVATYPECODE_H
35+
#endif // JAVAOBJECTSTREAMS_EJAVATYPECODE_H

include/JavaObject/JavaSerializedClassParser.h

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,23 @@ namespace javaobject {
2626
class SerializedField;
2727

2828
struct JavaObject {
29-
SerializedClass& m_class;
29+
SerializedClass &m_class;
3030
};
31-
using JavaArray = std::vector<JavaObject>;
31+
32+
class JavaArray;
3233

3334
// DO NOT RE-ORDER VARIANTS
34-
using JavaValue = std::variant<int64_t, double, int32_t, float, bool, JavaArray, std::shared_ptr<JavaObject>, std::string>;
35+
using JavaValue = std::variant<int64_t, double, int32_t, float, bool, JavaArray, std::shared_ptr<JavaObject>,
36+
std::string>;
37+
38+
class JavaArray : public std::vector<JavaValue> {
39+
public:
40+
JavaArray() = default;
41+
42+
explicit JavaArray(const JavaValue &value) {
43+
this->emplace_back(value);
44+
};
45+
};
3546

3647
class SerializedClass {
3748
public:
@@ -42,29 +53,41 @@ namespace javaobject {
4253

4354
class SerializedField {
4455
public:
45-
const SerializedClass& m_class;
56+
const SerializedClass &m_class;
4657

4758
EJavaFieldDescriptorType type;
4859
std::string name;
4960
std::string desc;
5061
JavaValue value;
5162

52-
explicit SerializedField(const SerializedClass& clazz, const std::string &name, const EJavaFieldDescriptorType type, const std::string &desc) : m_class(clazz), name(name), type(type), desc(desc) {}
63+
explicit SerializedField(const SerializedClass &clazz, const std::string &name,
64+
const EJavaFieldDescriptorType type, std::string &desc) : m_class(clazz), name(name),
65+
type(type), desc(desc) {
66+
}
5367

54-
static SerializedField parseFieldEntry(const SerializedClass& clazz, bio::stream::BinaryInputStream &strm);
55-
static std::string parseSignature(const SerializedClass& clazz, char type, bio::stream::BinaryInputStream &strm);
56-
static JavaValue readFieldValue(JavaSerializedClassParser& parser, const SerializedField &field, bio::stream::BinaryInputStream &strm);
68+
static SerializedField parseFieldEntry(const SerializedClass &clazz, bio::stream::BinaryInputStream &strm);
69+
70+
static std::string parseSignature(const SerializedClass &clazz, char type,
71+
bio::stream::BinaryInputStream &strm);
72+
73+
static JavaValue readFieldValue(JavaSerializedClassParser &parser, SerializedField &field,
74+
bio::stream::BinaryInputStream &strm);
75+
76+
void setDescriptor(const std::string &desc);
5777
};
5878

5979
class JavaSerializedClassParser {
60-
bio::stream::BinaryInputStream& m_stream;
80+
bio::stream::BinaryInputStream &m_stream;
6181
std::vector<SerializedClass> m_serializedClasses;
82+
6283
public:
63-
explicit JavaSerializedClassParser(bio::stream::BinaryInputStream &strm) : m_stream(strm) {};
84+
explicit JavaSerializedClassParser(bio::stream::BinaryInputStream &strm) : m_stream(strm) {
85+
};
6486

6587
std::vector<SerializedClass> parseAllEntries();
88+
6689
SerializedClass parseEntry();
6790
};
6891
} // lodestone::minecraft::common::java::classic::minev3
6992

70-
#endif //JAVAOBJECTSTREAMS_JAVASERIALIZEDCLASSPARSER_H
93+
#endif //JAVAOBJECTSTREAMS_JAVASERIALIZEDCLASSPARSER_H

include/JavaObject/io/Serializable.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ namespace javaobject::io {
1818
virtual ~Serializable() = default;
1919

2020
virtual SerializedClass serializeObject() = 0;
21+
2122
// todo deserialize func too I think?
2223
// or maybe we should be able to create a definition type (just types and names, no values) and pass that into deserializeObject with template to return correct class type
2324
};
2425
}
2526

26-
#endif // JAVAOBJECTSTREAMS_SERIALIZABLE_H
27+
#endif // JAVAOBJECTSTREAMS_SERIALIZABLE_H

include/JavaObject/stream/ObjectInputStream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@ namespace javaobject::stream {
2929
using iobjectstream = ObjectInputStream;
3030
}
3131

32-
#endif // JAVAOBJECTSTREAMS_OBJECTINPUTSTREAM_H
32+
#endif // JAVAOBJECTSTREAMS_OBJECTINPUTSTREAM_H

include/JavaObject/stream/ObjectOutputStream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ namespace javaobject::stream {
2020
using oobjectstream = ObjectOutputStream;
2121
}
2222

23-
#endif // JAVAOBJECTSTREAMS_OBJECTOUTPUTSTREAM_H
23+
#endif // JAVAOBJECTSTREAMS_OBJECTOUTPUTSTREAM_H

src/JavaSerializedClassParser.cpp

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ namespace javaobject {
4343

4444
// Check if descriptor is object or array
4545
if (type == TYPE_OBJECT || type == TYPE_ARRAY) {
46-
char typeCode = strm.readByte();
47-
if (typeCode == TYPE_ARRAY) {
46+
if (const char typeCode = strm.readByte(); typeCode == TYPE_ARRAY) {
4847
// Read primitive array
49-
const char arrayType = strm.readByte();
50-
if (arrayType != TYPE_OBJECT) {
48+
if (const char arrayType = strm.readByte(); arrayType != TYPE_OBJECT) {
5149
descriptor += arrayType;
5250
} else {
5351
descriptor += parseSignature(clazz, arrayType, strm);
@@ -75,7 +73,7 @@ namespace javaobject {
7573
}
7674

7775
JavaValue SerializedField::readFieldValue(JavaSerializedClassParser &parser,
78-
const SerializedField &field,
76+
SerializedField &field,
7977
bio::stream::BinaryInputStream &
8078
strm) {
8179
const auto descriptor = field.desc;
@@ -100,34 +98,75 @@ namespace javaobject {
10098
// which means we need to shift this down to get the
10199
// correct sign and value.
102100
return JavaValue
103-
{static_cast<int32_t>(strm.readBE<uint32_t>() >> 8)};
101+
{static_cast<int32_t>(strm.readBE<uint32_t>() >> 8)};
104102
}
105103
if (field.type == TYPE_LONG) {
106104
return JavaValue
107-
{static_cast<int64_t>(strm.readBE<uint64_t>() >> 8)};
105+
{static_cast<int64_t>(strm.readBE<uint64_t>() >> 8)};
108106
}
109107
if (field.type == TYPE_OBJECT) {
110108
if (descriptor == "Ljava/lang/String;") {
111109
return JavaValue{
112110
std::string(strm.readStringWithLength<char>(
113111
bio::util::ByteOrder::BIG,
114-
bio::util::string::StringLengthEncoding::LENGTH_PREFIX))};
112+
bio::util::string::StringLengthEncoding::LENGTH_PREFIX))
113+
};
115114
}
116115
strm.seekRelative(-1);
117-
int offset = strm.getOffset();
118-
// Object!
116+
117+
// Parse object
119118
SerializedClass clazz = parser.parseEntry();
120119
return JavaValue{std::make_shared<JavaObject>(clazz)};
121120
}
122121
if (field.type == TYPE_ARRAY) {
123-
// Array!
124-
return readFieldValue(parser, field, strm);
122+
// Read TCBlockData as a Java Array is an Object (Block-Like)
123+
strm.seekRelative(1);
124+
auto desc = strm.readStringWithLength<char>(bio::util::ByteOrder::BIG,
125+
bio::util::string::StringLengthEncoding::LENGTH_PREFIX);
126+
127+
JavaArray result;
128+
auto modifiedDesc = std::string(desc);
129+
if (modifiedDesc.starts_with("[")) {
130+
modifiedDesc = modifiedDesc.substr(1);
131+
}
132+
std::ranges::replace(modifiedDesc, '.', '/');
133+
auto originalType = field.type;
134+
auto modifiedType = static_cast<EJavaFieldDescriptorType>(modifiedDesc[0]);
135+
136+
const int64_t uuid = strm.readBE<int64_t>();
137+
int padding = strm.readSignedByte();
138+
strm.seekRelative(padding);
139+
140+
if (const uint16_t tcBlockData = strm.readBE<uint16_t>(); tcBlockData != 0x7870) {
141+
// LOG_ERROR("TCBlockData could not be found after array value was defined.");
142+
std::cout << tcBlockData << std::endl;
143+
}
144+
int32_t fieldCount = strm.readBE<int32_t>();
145+
146+
field.setDescriptor(modifiedDesc);
147+
field.type = modifiedType;
148+
strm.seekRelative(1);
149+
for (int i = 0; i < fieldCount; i++) {
150+
int offset = strm.getOffset();
151+
JavaValue value = readFieldValue(parser, field, strm);
152+
offset = strm.getOffset();
153+
result.push_back(value);
154+
strm.seekRelative(1);
155+
}
156+
field.setDescriptor(desc);
157+
field.type = originalType;
158+
159+
return result;
125160
}
126161

127162
// LOG_DEBUG("Descriptor not yet implemented!");
128163
return {};
129164
}
130165

166+
void SerializedField::setDescriptor(const std::string &desc) {
167+
this->desc = desc;
168+
}
169+
131170
std::vector<SerializedClass> JavaSerializedClassParser::parseAllEntries() {
132171
std::vector<SerializedClass> result;
133172
if (!this->m_stream.getStream().eof()) {
@@ -202,4 +241,4 @@ namespace javaobject {
202241
this->m_serializedClasses.push_back(result);
203242
return result;
204243
}
205-
} // lodestone::minecraft::common::java::classic::minev3
244+
} // lodestone::minecraft::common::java::classic::minev3

src/io/Serializable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111
#include "JavaObject/io/Serializable.h"
1212

1313
namespace javaobject::io {
14-
}
14+
}

src/stream/ObjectInputStream.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
namespace javaobject::stream {
1414
ObjectInputStream::ObjectInputStream(std::istream &input) : m_input(input) {
1515
}
16-
}
16+
}

0 commit comments

Comments
 (0)