/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package malik.emulator.io.cloud;
import java.io.*;
import malik.emulator.util.*;
public class FileInputStream extends InputStream
{
private static final int OPEN_ERROR_NO_ERROR = 0;
private static final int OPEN_ERROR_FILE_NAME_NOT_SPECIFIED = 1;
private static final int OPEN_ERROR_FILE_ACCESS_DENIED = 2;
private int handle;
private int openError;
private long position;
private long size;
private Object lock;
private String fileName;
private DataDescriptor descriptor;
public FileInputStream(String fileName)
{
int h;
char[] fn;
if(fileName == null || (h = fileName.length()) == 0)
{
this.handle = 0;
this.openError = OPEN_ERROR_FILE_NAME_NOT_SPECIFIED;
this.position = 0L;
this.size = 0L;
this.lock = new Object();
this.fileName = fileName;
this.descriptor = null;
return;
}
fileName.getChars(0, h, fn = new char[h + 1], 0);
if((h = (int) MalikSystem.syscall(Array.getFirstElementAddress(fn), 1, 0x0010)) == 0)
{
this.handle = 0;
this.openError = OPEN_ERROR_FILE_ACCESS_DENIED;
this.position = 0L;
this.size = 0L;
this.lock = new Object();
this.fileName = fileName;
this.descriptor = null;
return;
}
this.handle = h;
this.openError = OPEN_ERROR_NO_ERROR;
this.position = 0L;
this.size = MalikSystem.syscall((long) h, 0x0015);
this.lock = new Object();
this.fileName = fileName;
this.descriptor = new DataDescriptor();
}
public String toString()
{
return (handle != 0 ? "Открытый для чтения файл " : "Закрытый файл ").concat(fileName);
}
public void checkOpenError()
throws IOException
{
switch(openError)
{
default:
if(handle != 0)
{
return;
}
throw new IOException("FileInputStream: " +
"файл " + fileName + " был закрыт.");
case OPEN_ERROR_FILE_NAME_NOT_SPECIFIED:
throw new IOException("FileInputStream: " +
"имя файла не задано.");
case OPEN_ERROR_FILE_ACCESS_DENIED:
throw new IOException("FileInputStream: " +
"файл " + fileName + " недоступен для чтения.");
}
}
public boolean hasOpenError()
{
return openError != OPEN_ERROR_NO_ERROR || handle == 0;
}
public final void close()
throws IOException
{
int h;
int error = 0;
synchronized(lock)
{
label0:
{
if((h = handle) == 0)
{
error = 1;
break label0;
}
MalikSystem.syscall((long) h, 0x0011);
handle = 0;
}
}
if(error == 1)
{
throw new IOException("FileInputStream: " +
"файл " + fileName + " был закрыт.");
}
}
public final void reset()
throws IOException
{
int h;
long z;
synchronized(lock)
{
checkOpenError();
h = handle;
z = 0L;
z = position - MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(z), 0x0014);
MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(z), 0x0014);
}
}
public final void mark(int readLimit)
{
int h;
long z;
synchronized(lock)
{
if((h = handle) != 0)
{
z = 0L;
position = MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(z), 0x0014);
}
}
}
public final boolean markSupported()
{
return handle != 0;
}
public final int read()
throws IOException
{
int result;
synchronized(lock)
{
checkOpenError();
result = 0;
descriptor.setDataInfo(MalikSystem.getLocalVariableAddress(result), 1);
if(readFile() != 1)
{
result = -1;
}
}
return result;
}
public final int read(byte[] dst)
throws IOException
{
int result;
int length;
if(dst == null)
{
throw new NullPointerException("FileInputStream.read: " +
"параметр dst равен нулевой ссылке.");
}
synchronized(lock)
{
checkOpenError();
label0:
{
if((length = dst.length) <= 0)
{
result = 0;
break label0;
}
descriptor.setDataInfo(dst, 0, length);
result = readFile();
}
}
return result;
}
public final int read(byte[] dst, int offset, int length)
throws IOException
{
int result;
int lim;
int len;
if(dst == null)
{
throw new NullPointerException("FileInputStream.read: " +
"параметр dst равен нулевой ссылке.");
}
if((lim = offset + length) > (len = dst.length) ||
lim < offset || offset > len || offset < 0)
{
throw new ArrayIndexOutOfBoundsException("FileInputStream.read: " +
"индекс выходит из диапазона.");
}
synchronized(lock)
{
checkOpenError();
label0:
{
if(length <= 0)
{
result = 0;
break label0;
}
descriptor.setDataInfo(dst, offset, length);
result = readFile();
}
}
return result;
}
public final int available()
throws IOException
{
int result;
long z;
synchronized(lock)
{
checkOpenError();
z = 0L;
result = (int) Math.min((long) Integer.MAX_VALUE, size -
MalikSystem.syscall(handle, MalikSystem.getLocalVariableAddress(z), 0x0014));
}
return result;
}
public final long skip(long bytesCount)
throws IOException
{
int h;
long z;
long result;
synchronized(lock)
{
checkOpenError();
result = 0L;
if(bytesCount > 0L)
{
h = handle;
z = 0L;
result = -MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(z), 0x0014) +
MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(bytesCount),
0x0014);
}
}
return result;
}
public final long seek(long offset)
throws IOException
{
long result;
synchronized(lock)
{
checkOpenError();
result = MalikSystem.syscall(handle,
MalikSystem.getLocalVariableAddress(offset), 0x0014);
}
return result;
}
public final long getSize()
{
return size;
}
public final String getFileName()
{
return fileName;
}
protected void $finalize$()
{
int h;
if((h = handle) != 0)
{
MalikSystem.syscall((long) h, 0x0011);
handle = 0;
}
}
private int readFile()
throws InterruptedIOException
{
int remaining;
int readed;
int length;
int h = handle;
long z = 0L;
DataDescriptor d = descriptor;
remaining = (int) Math.min((long) Integer.MAX_VALUE,
size - MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(z), 0x0014));
readed = (int) MalikSystem.syscall(h, d.getDescriptorAddress(), 0x0012);
length = d.getLength();
if(readed != remaining && readed != length)
{
throw new InterruptedIOException("FileInputStream.read: " +
"процесс чтения данных из файла " + fileName +
" был прерван. Прочитано байт: " + readed +
" из " + Math.min(remaining, length) + ".", readed);
}
return remaining == 0 ? -1 : readed;
}
}