java.nio: partial Path/Files/FileSystem/InputStream implementation
This commit is contained in:
parent
e83cf7f092
commit
86e18a0944
2
Makefile
2
Makefile
@ -10,7 +10,7 @@ CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protec
|
||||
CFLAGS += -I$(MAKEFILE_PATH)/
|
||||
CFLAGS += -I$(MAKEFILE_PATH)/c
|
||||
CFLAGS += -DDEBUG
|
||||
CFLAGS += -DDEBUG_PRINT
|
||||
#CFLAGS += -DDEBUG_PRINT
|
||||
LDFLAGS = -lm
|
||||
OPT ?= -O0
|
||||
DEPFLAGS = -MMD -MP
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "native_types.h"
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
struct backtrace_entry {
|
||||
struct class_file * class_file;
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "fatal.h"
|
||||
#include "parse_type.h"
|
||||
#include "find_attribute.h"
|
||||
#include "frame.h"
|
||||
#include "native_types_allocate.h"
|
||||
#include "vm_instance.h"
|
||||
|
||||
|
@ -5,53 +5,7 @@
|
||||
#include "class_file.h"
|
||||
#include "hash_table.h"
|
||||
#include "native_types.h"
|
||||
|
||||
enum initialization_state {
|
||||
CLASS_UNINITIALIZED,
|
||||
CLASS_INITIALIZING,
|
||||
CLASS_INITIALIZED,
|
||||
};
|
||||
|
||||
struct method_entry {
|
||||
struct class_entry * class_entry;
|
||||
struct method_info * method_info;
|
||||
struct Code_attribute * code_attribute;
|
||||
};
|
||||
|
||||
union attribute_entry {
|
||||
struct class_entry * class_entry;
|
||||
struct method_entry * method_entry;
|
||||
struct field_entry * field_entry;
|
||||
struct objectref * string_objectref;
|
||||
};
|
||||
|
||||
struct field_entry {
|
||||
struct class_entry * class_entry;
|
||||
struct field_info * field_info;
|
||||
union {
|
||||
int32_t instance_index;
|
||||
int32_t static_index;
|
||||
};
|
||||
};
|
||||
|
||||
struct class_entry {
|
||||
struct class_file * class_file;
|
||||
enum initialization_state initialization_state;
|
||||
union attribute_entry * attribute_entry;
|
||||
int32_t static_fields_count;
|
||||
int32_t * static_fields;
|
||||
int32_t instance_fields_count;
|
||||
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} fields;
|
||||
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} methods;
|
||||
};
|
||||
#include "vm.h"
|
||||
|
||||
struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buffers,
|
||||
int length,
|
||||
@ -94,3 +48,7 @@ bool class_resolver_instanceof(int class_hash_table_length,
|
||||
struct class_entry * origin_class_entry,
|
||||
const int class_index,
|
||||
struct objectref * objectref);
|
||||
|
||||
struct objectref * class_resolver_lookup_string(struct vm * vm,
|
||||
struct class_entry * class_entry,
|
||||
const int string_index);
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
uint32_t decode_print_instruction(const uint8_t * code, uint32_t pc);
|
||||
void decode_execute_instruction(struct vm * vm, const uint8_t * code, uint32_t pc);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void op_aaload(struct vm * vm);
|
||||
void op_aastore(struct vm * vm);
|
||||
|
@ -1,8 +1,3 @@
|
||||
// declared here due to circular frame.h include in class_resolver.h
|
||||
struct objectref * class_resolver_lookup_string(struct vm * vm,
|
||||
struct class_entry * class_entry,
|
||||
const int string_index);
|
||||
|
||||
static inline struct field_entry * field_entry_from_constant_index(int class_hash_table_length,
|
||||
struct hash_table_entry * class_hash_table,
|
||||
struct class_entry * origin_class_entry,
|
||||
|
@ -1,9 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "vm.h"
|
||||
#include "assert.h"
|
||||
#include "class_file.h"
|
||||
#include "class_resolver.h"
|
||||
#include "native_types.h"
|
||||
|
||||
enum initialization_state {
|
||||
CLASS_UNINITIALIZED,
|
||||
CLASS_INITIALIZING,
|
||||
CLASS_INITIALIZED,
|
||||
};
|
||||
|
||||
struct method_entry {
|
||||
struct class_entry * class_entry;
|
||||
struct method_info * method_info;
|
||||
struct Code_attribute * code_attribute;
|
||||
};
|
||||
|
||||
union attribute_entry {
|
||||
struct class_entry * class_entry;
|
||||
struct method_entry * method_entry;
|
||||
struct field_entry * field_entry;
|
||||
struct objectref * string_objectref;
|
||||
};
|
||||
|
||||
struct field_entry {
|
||||
struct class_entry * class_entry;
|
||||
struct field_info * field_info;
|
||||
union {
|
||||
int32_t instance_index;
|
||||
int32_t static_index;
|
||||
};
|
||||
};
|
||||
|
||||
struct class_entry {
|
||||
struct class_file * class_file;
|
||||
enum initialization_state initialization_state;
|
||||
union attribute_entry * attribute_entry;
|
||||
int32_t static_fields_count;
|
||||
int32_t * static_fields;
|
||||
int32_t instance_fields_count;
|
||||
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} fields;
|
||||
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} methods;
|
||||
};
|
||||
|
||||
struct frame {
|
||||
struct class_entry * class_entry;
|
||||
@ -27,20 +74,6 @@ struct stack {
|
||||
int32_t capacity;
|
||||
};
|
||||
|
||||
struct vm {
|
||||
struct stack frame_stack;
|
||||
struct stack data_stack;
|
||||
struct frame * current_frame;
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} class_hash_table;
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} native_hash_table;
|
||||
};
|
||||
|
||||
static inline struct frame * stack_push_frame(struct stack * stack, int num_frames)
|
||||
{
|
||||
struct frame * frame = &stack->frame[stack->ix];
|
||||
@ -182,17 +215,3 @@ static inline double operand_stack_pop_f64(struct frame * frame)
|
||||
double f = *((double *)&value);
|
||||
return f;
|
||||
}
|
||||
|
||||
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
|
||||
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
||||
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
||||
void vm_method_return(struct vm * vm);
|
||||
void vm_execute(struct vm * vm);
|
||||
struct vm * vm_start(int class_hash_table_length,
|
||||
struct hash_table_entry * class_hash_table,
|
||||
int native_hash_table_length,
|
||||
struct hash_table_entry * native_hash_table,
|
||||
const uint8_t * main_class_name,
|
||||
int main_class_name_length);
|
||||
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type);
|
||||
void vm_exception(struct vm * vm, struct objectref * objectref);
|
4
c/gc.c
4
c/gc.c
@ -1,6 +1,8 @@
|
||||
#include "frame.h"
|
||||
#include "gc.h"
|
||||
#include "memory_allocator.h"
|
||||
#include "printf.h"
|
||||
#include "hash_table.h"
|
||||
#include "native_types.h"
|
||||
|
||||
static void walk_address(void * address);
|
||||
|
||||
|
2
c/gc.h
2
c/gc.h
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void gc_mark(struct vm * vm);
|
||||
void gc_sweep();
|
||||
|
21
c/native.c
21
c/native.c
@ -4,6 +4,7 @@
|
||||
#include "printf.h"
|
||||
#include "native.h"
|
||||
#include "native/class.h"
|
||||
#include "native/libcinputstream.h"
|
||||
#include "native/loader.h"
|
||||
#include "native/math.h"
|
||||
#include "native/memory.h"
|
||||
@ -160,6 +161,26 @@ const static struct native_method native_method[] = {
|
||||
.method_descriptor = "(Ljava/lang/Object;)I",
|
||||
.func = native_java_lang_system_hashcode_1,
|
||||
},
|
||||
#if !defined(__dreamcast__)
|
||||
{
|
||||
.class_name = "jvm/internal/LibcInputStream",
|
||||
.method_name = "_open",
|
||||
.method_descriptor = "([B)I",
|
||||
.func = native_jvm_internal_libcinputstream_open_1,
|
||||
},
|
||||
{
|
||||
.class_name = "jvm/internal/LibcInputStream",
|
||||
.method_name = "_close",
|
||||
.method_descriptor = "(I)V",
|
||||
.func = native_jvm_internal_libcinputstream_close_1,
|
||||
},
|
||||
{
|
||||
.class_name = "jvm/internal/LibcInputStream",
|
||||
.method_name = "_read",
|
||||
.method_descriptor = "(I)I",
|
||||
.func = native_jvm_internal_libcinputstream_read_1,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_method_call(struct vm * vm,
|
||||
struct constant * class_name_constant,
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "class.h"
|
||||
#include "printf.h"
|
||||
#include "vm_instance.h"
|
||||
#include "class_resolver.h"
|
||||
|
||||
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args);
|
||||
void native_java_lang_class_getsuperclass_1(struct vm * vm, uint32_t * args);
|
||||
|
38
c/native/libcinputstream.c
Normal file
38
c/native/libcinputstream.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libcinputstream.h"
|
||||
#include "assert.h"
|
||||
#include "native_types.h"
|
||||
|
||||
void native_jvm_internal_libcinputstream_open_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||
assert(arrayref != nullptr);
|
||||
assert(arrayref->length > 0);
|
||||
assert(arrayref->u8[arrayref->length - 1] == 0);
|
||||
FILE * file = fopen((const char *)arrayref->u8, "rb");
|
||||
assert(file != nullptr);
|
||||
|
||||
operand_stack_push_u32(vm->current_frame, (uint32_t)file);
|
||||
}
|
||||
|
||||
void native_jvm_internal_libcinputstream_close_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
FILE * file = (FILE *)args[0];
|
||||
assert(file != nullptr);
|
||||
int ret = fclose(file);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
void native_jvm_internal_libcinputstream_read_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
FILE * file = (FILE *)args[0];
|
||||
assert(file != nullptr);
|
||||
|
||||
uint8_t buf[1];
|
||||
int32_t size = fread(buf, 1, 1, file);
|
||||
if (size == 0)
|
||||
operand_stack_push_u32(vm->current_frame, (uint32_t)-1);
|
||||
else
|
||||
operand_stack_push_u32(vm->current_frame, (uint32_t)buf[0]);
|
||||
}
|
9
c/native/libcinputstream.h
Normal file
9
c/native/libcinputstream.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
void native_jvm_internal_libcinputstream_open_1(struct vm * vm, uint32_t * args);
|
||||
void native_jvm_internal_libcinputstream_close_1(struct vm * vm, uint32_t * args);
|
||||
void native_jvm_internal_libcinputstream_read_1(struct vm * vm, uint32_t * args);
|
@ -4,6 +4,7 @@
|
||||
#include "malloc.h"
|
||||
#include "loader.h"
|
||||
#include "native.h"
|
||||
#include "class_resolver.h"
|
||||
|
||||
static uint8_t loader_buffer[0x100000] __attribute__ ((aligned (32)));
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_jvm_internal_loader_getbuffer_0(struct vm * vm, uint32_t * args);
|
||||
void native_jvm_internal_loader_load_2(struct vm * vm, uint32_t * args);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_lang_math_sin_1(struct vm * vm, uint32_t * args);
|
||||
void native_java_lang_math_cos_1(struct vm * vm, uint32_t * args);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args);
|
||||
void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "object.h"
|
||||
#include "vm_instance.h"
|
||||
#include "native_types.h"
|
||||
|
||||
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args);
|
||||
|
@ -5,18 +5,22 @@
|
||||
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||
assert(arrayref != nullptr);
|
||||
print_bytes(arrayref->u8, arrayref->length);
|
||||
}
|
||||
|
||||
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
struct arrayref * arrayref = (struct arrayref *)args[0];
|
||||
assert(arrayref != nullptr);
|
||||
print_chars(arrayref->u16, arrayref->length);
|
||||
}
|
||||
|
||||
void native_java_io_printstream_write_s_1(struct vm * vm, uint32_t * args)
|
||||
{
|
||||
struct objectref * objectref = (struct objectref *)args[0];
|
||||
assert(objectref != nullptr);
|
||||
struct arrayref * arrayref = objectref->aref[0];
|
||||
assert(arrayref != nullptr);
|
||||
print_chars(arrayref->u16, arrayref->length);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_io_printstream_write_ba_1(struct vm * vm, uint32_t * args);
|
||||
void native_java_io_printstream_write_ca_1(struct vm * vm, uint32_t * args);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_lang_runtime_freememory_0(struct vm * vm, uint32_t * args);
|
||||
void native_java_lang_runtime_gc_0(struct vm * vm, uint32_t * args);
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
void native_java_lang_system_hashcode_1(struct vm * vm, uint32_t * args);
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "class_resolver.h"
|
||||
#include "memory_allocator.h"
|
||||
|
||||
enum tag_type {
|
||||
|
@ -1,8 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "native_types.h"
|
||||
#include "frame.h"
|
||||
#include "gc.h"
|
||||
#include "vm.h"
|
||||
#include "memory_allocator.h"
|
||||
|
||||
static inline void * gc_memory_allocate(struct vm * vm, int size)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "class_file.h"
|
||||
#include "bytes.h"
|
||||
#include "decode.h"
|
||||
#include "frame.h"
|
||||
#include "class_resolver.h"
|
||||
#include "printf.h"
|
||||
#include "string.h"
|
||||
@ -104,20 +103,26 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
||||
|
||||
for (int j = 0; j < field_info->attributes_count; j++) {
|
||||
if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) {
|
||||
struct attribute_info * attribute = &field_info->attributes[j];
|
||||
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
||||
assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String
|
||||
|
||||
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
||||
assert(name_constant->tag == CONSTANT_Utf8);
|
||||
|
||||
struct field_entry * field_entry = class_resolver_lookup_field(class_entry->fields.length,
|
||||
class_entry->fields.entry,
|
||||
name_constant->utf8.bytes,
|
||||
name_constant->utf8.length);
|
||||
assert(field_entry != nullptr);
|
||||
class_entry->static_fields[field_entry->static_index] = constantvalue->integer.bytes;
|
||||
debugf(" constantvalue: %d\n", constantvalue->integer.bytes);
|
||||
|
||||
struct attribute_info * attribute = &field_info->attributes[j];
|
||||
struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
||||
if (constantvalue->tag == CONSTANT_Integer) {
|
||||
class_entry->static_fields[field_entry->static_index] = constantvalue->integer.bytes;
|
||||
} else if (constantvalue->tag == CONSTANT_String) {
|
||||
struct objectref * objectref = class_resolver_lookup_string(vm,
|
||||
class_entry,
|
||||
attribute->constantvalue->constantvalue_index);
|
||||
class_entry->static_fields[field_entry->static_index] = (int32_t)objectref;
|
||||
} else {
|
||||
assert(!"invalid constantvalue tag");
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
32
c/vm.h
Normal file
32
c/vm.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "frame_stack.h"
|
||||
#include "class_file.h"
|
||||
|
||||
struct vm {
|
||||
struct stack frame_stack;
|
||||
struct stack data_stack;
|
||||
struct frame * current_frame;
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} class_hash_table;
|
||||
struct {
|
||||
int length;
|
||||
struct hash_table_entry * entry;
|
||||
} native_hash_table;
|
||||
};
|
||||
|
||||
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
|
||||
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
||||
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
||||
void vm_method_return(struct vm * vm);
|
||||
void vm_execute(struct vm * vm);
|
||||
struct vm * vm_start(int class_hash_table_length,
|
||||
struct hash_table_entry * class_hash_table,
|
||||
int native_hash_table_length,
|
||||
struct hash_table_entry * native_hash_table,
|
||||
const uint8_t * main_class_name,
|
||||
int main_class_name_length);
|
||||
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type);
|
||||
void vm_exception(struct vm * vm, struct objectref * objectref);
|
@ -1,6 +1,7 @@
|
||||
#include "string.h"
|
||||
#include "native_types_allocate.h"
|
||||
#include "vm_instance.h"
|
||||
#include "class_resolver.h"
|
||||
|
||||
struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "frame.h"
|
||||
#include "vm.h"
|
||||
|
||||
struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
|
||||
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant);
|
||||
|
7
classes/java/io/Closeable.java
Normal file
7
classes/java/io/Closeable.java
Normal file
@ -0,0 +1,7 @@
|
||||
package java.io;
|
||||
|
||||
public interface Closeable
|
||||
extends AutoCloseable {
|
||||
|
||||
void close() throws IOException;
|
||||
}
|
4
classes/java/io/IOException.java
Normal file
4
classes/java/io/IOException.java
Normal file
@ -0,0 +1,4 @@
|
||||
package java.io;
|
||||
|
||||
public class IOException extends Exception {
|
||||
}
|
72
classes/java/io/InputStream.java
Normal file
72
classes/java/io/InputStream.java
Normal file
@ -0,0 +1,72 @@
|
||||
package java.io;
|
||||
|
||||
public abstract class InputStream
|
||||
implements Closeable {
|
||||
|
||||
public InputStream() {
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
}
|
||||
|
||||
public void mark(int readlimit) {
|
||||
}
|
||||
|
||||
public abstract int read() throws IOException;
|
||||
|
||||
public int read(byte[] b) throws IOException {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
public int read(byte[] b,
|
||||
int off,
|
||||
int len) throws IOException {
|
||||
if (off < 0 || len < 0 || len > b.length - off)
|
||||
throw new IndexOutOfBoundsException();
|
||||
|
||||
if (b == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
try {
|
||||
int c = read();
|
||||
boolean endOfStream = c == -1;
|
||||
if (endOfStream) {
|
||||
if (i == 0)
|
||||
return -1;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
b[off + i] = (byte)c;
|
||||
} catch (IOException e) {
|
||||
if (i == 0)
|
||||
throw e;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
public void reset() throws IOException {
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
public long skip(long n)
|
||||
throws IOException {
|
||||
|
||||
long ni = n;
|
||||
while (ni > 0L) {
|
||||
int b = read();
|
||||
if (b < 0)
|
||||
break;
|
||||
ni -= 1;
|
||||
}
|
||||
return n - ni;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package java.lang;
|
||||
|
||||
public final class Class<T> {
|
||||
private Object klass; // struct class_entry *
|
||||
private int class_entry; // is actually struct class_entry *
|
||||
private String name;
|
||||
|
||||
private Class() {
|
||||
|
26
classes/java/nio/file/FileSystem.java
Normal file
26
classes/java/nio/file/FileSystem.java
Normal file
@ -0,0 +1,26 @@
|
||||
package java.nio.file;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
|
||||
public abstract class FileSystem
|
||||
implements Closeable {
|
||||
|
||||
protected FileSystem() {
|
||||
}
|
||||
|
||||
public abstract void close()
|
||||
throws IOException;
|
||||
|
||||
public abstract Path getPath(String first,
|
||||
String... more);
|
||||
|
||||
public abstract String getSeparator();
|
||||
|
||||
public abstract boolean isOpen();
|
||||
|
||||
public abstract boolean isReadOnly();
|
||||
|
||||
public abstract FileSystemProvider provider();
|
||||
}
|
12
classes/java/nio/file/FileSystems.java
Normal file
12
classes/java/nio/file/FileSystems.java
Normal file
@ -0,0 +1,12 @@
|
||||
package java.nio.file;
|
||||
|
||||
import jvm.internal.LibcFileSystem;
|
||||
|
||||
public final class FileSystems {
|
||||
private FileSystems() {
|
||||
}
|
||||
|
||||
public static FileSystem getDefault() {
|
||||
return LibcFileSystem.getLibcFileSystem();
|
||||
}
|
||||
}
|
15
classes/java/nio/file/Files.java
Normal file
15
classes/java/nio/file/Files.java
Normal file
@ -0,0 +1,15 @@
|
||||
package java.nio.file;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public final class Files {
|
||||
|
||||
|
||||
public static InputStream newInputStream(Path path,
|
||||
OpenOption... options)
|
||||
throws IOException {
|
||||
|
||||
return path.getFileSystem().provider().newInputStream(path, options);
|
||||
}
|
||||
}
|
4
classes/java/nio/file/OpenOption.java
Normal file
4
classes/java/nio/file/OpenOption.java
Normal file
@ -0,0 +1,4 @@
|
||||
package java.nio.file;
|
||||
|
||||
public interface OpenOption {
|
||||
}
|
7
classes/java/nio/file/Path.java
Normal file
7
classes/java/nio/file/Path.java
Normal file
@ -0,0 +1,7 @@
|
||||
package java.nio.file;
|
||||
|
||||
public interface Path
|
||||
// extends Comparable<Path>, Iterable<Path>
|
||||
{
|
||||
FileSystem getFileSystem();
|
||||
}
|
18
classes/java/nio/file/spi/FileSystemProvider.java
Normal file
18
classes/java/nio/file/spi/FileSystemProvider.java
Normal file
@ -0,0 +1,18 @@
|
||||
package java.nio.file.spi;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class FileSystemProvider {
|
||||
protected FileSystemProvider() {
|
||||
}
|
||||
|
||||
public InputStream newInputStream(Path path,
|
||||
OpenOption... options)
|
||||
throws IOException {
|
||||
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
43
classes/jvm/internal/LibcFileSystem.java
Normal file
43
classes/jvm/internal/LibcFileSystem.java
Normal file
@ -0,0 +1,43 @@
|
||||
package jvm.internal;
|
||||
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
|
||||
public class LibcFileSystem extends FileSystem {
|
||||
private static final String separator = "/";
|
||||
|
||||
private static LibcFileSystem libcFileSystem = new LibcFileSystem();
|
||||
|
||||
public static LibcFileSystem getLibcFileSystem() {
|
||||
return libcFileSystem;
|
||||
}
|
||||
|
||||
private LibcFileSystem() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public Path getPath(String first, String ... more) {
|
||||
return LibcPath.fromString(first, more);
|
||||
}
|
||||
|
||||
public String getSeparator() {
|
||||
return LibcFileSystem.separator;
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public FileSystemProvider provider() {
|
||||
return LibcFileSystemProvider.getLibcFileSystemProvider();
|
||||
}
|
||||
}
|
26
classes/jvm/internal/LibcFileSystemProvider.java
Normal file
26
classes/jvm/internal/LibcFileSystemProvider.java
Normal file
@ -0,0 +1,26 @@
|
||||
package jvm.internal;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LibcFileSystemProvider extends FileSystemProvider {
|
||||
private static LibcFileSystemProvider libcFileSystemProvider = new LibcFileSystemProvider();
|
||||
|
||||
private LibcFileSystemProvider() {
|
||||
super();
|
||||
}
|
||||
|
||||
public static LibcFileSystemProvider getLibcFileSystemProvider() {
|
||||
return libcFileSystemProvider;
|
||||
}
|
||||
|
||||
public InputStream newInputStream(Path path,
|
||||
OpenOption... options)
|
||||
throws IOException {
|
||||
return new LibcInputStream((LibcPath)path);
|
||||
}
|
||||
}
|
25
classes/jvm/internal/LibcInputStream.java
Normal file
25
classes/jvm/internal/LibcInputStream.java
Normal file
@ -0,0 +1,25 @@
|
||||
package jvm.internal;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class LibcInputStream extends InputStream {
|
||||
private int file; // is actually FILE *
|
||||
|
||||
private static native int _open(byte[] path);
|
||||
|
||||
public LibcInputStream(LibcPath path) {
|
||||
file = _open(path.path);
|
||||
}
|
||||
|
||||
private static native void _close(int file);
|
||||
|
||||
public void close() {
|
||||
_close(file);
|
||||
}
|
||||
|
||||
private static native int _read(int file);
|
||||
|
||||
public int read() {
|
||||
return _read(file);
|
||||
}
|
||||
}
|
43
classes/jvm/internal/LibcPath.java
Normal file
43
classes/jvm/internal/LibcPath.java
Normal file
@ -0,0 +1,43 @@
|
||||
package jvm.internal;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.FileSystem;
|
||||
|
||||
public class LibcPath implements Path {
|
||||
public byte[] path;
|
||||
|
||||
public LibcPath(byte[] path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
private static int copyInto(byte[] dest, int offset, String s) {
|
||||
int length = s.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
dest[offset + i] = (byte)s.charAt(i);
|
||||
}
|
||||
return offset + length;
|
||||
}
|
||||
|
||||
public static LibcPath fromString(String first, String... more) {
|
||||
int length = first.length();
|
||||
for (int i = 0; i < more.length; i++) {
|
||||
length += more[i].length();
|
||||
}
|
||||
length += more.length + 1; // including C string null terminator
|
||||
|
||||
byte[] path = new byte[length];
|
||||
int offset = 0;
|
||||
offset = copyInto(path, offset, first);
|
||||
byte sep = (byte)'/';
|
||||
for (int i = 0; i < more.length; i++) {
|
||||
path[offset++] = sep;
|
||||
offset = copyInto(path, offset, more[i]);
|
||||
}
|
||||
|
||||
return new LibcPath(path);
|
||||
}
|
||||
|
||||
public FileSystem getFileSystem() {
|
||||
return LibcFileSystem.getLibcFileSystem();
|
||||
}
|
||||
}
|
16
classes/test/TestInputStream.java
Normal file
16
classes/test/TestInputStream.java
Normal file
@ -0,0 +1,16 @@
|
||||
package test;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
class TestInputStream {
|
||||
public static void main() throws IOException {
|
||||
Path path = FileSystems.getDefault().getPath("/home/bilbo/source.txt");
|
||||
InputStream is = Files.newInputStream(path);
|
||||
char c = (char)is.read();
|
||||
System.out.println(c);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user