/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016–2017, 2019–2023 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package malik.emulator.io.cloud;
import java.io.*;
import malik.emulator.io.*;
import malik.emulator.io.vfs.*;
import malik.emulator.util.*;
public class FileIOStream extends IOStream
{
private static final int NO_ERROR = 0;
private static final int FILE_NOT_FOUND = 1;
private static final int FILE_NAME_NOT_SPECIFIED = 3;
private static HandleInputStream createInput(String fileName, DataDescriptor descriptor, int handle) {
return new HandleInputStream(fileName, descriptor, handle) {
public final long getFileSize() {
long result;
synchronized(descriptor)
{
int h;
result = (h = handle) == 0 ? -1L : MalikSystem.syscall((long) h, 0x0015);
}
return result;
}
};
}
private static HandleOutputStream createOutput(String fileName, DataDescriptor descriptor, int handle) {
return new HandleOutputStream(fileName, descriptor, handle) {
};
}
private final int openError;
private int handle;
private final String fileName;
private final HandleInputStream input;
private final HandleOutputStream output;
private final DataDescriptor descriptor;
public FileIOStream(String fileName) {
int h;
int e;
int len;
DataDescriptor descriptor;
if(fileName == null || (len = fileName.length()) <= 0)
{
h = 0;
e = FILE_NAME_NOT_SPECIFIED;
} else
{
char[] name;
fileName.getChars(0, len, name = new char[len + 1], 0);
if((h = (int) MalikSystem.syscall(Array.getFirstElementAddress(name), 3, 0x0010)) == 0)
{
e = FILE_NOT_FOUND;
} else
{
e = NO_ERROR;
}
}
if(h == 0)
{
this.openError = e;
this.fileName = fileName;
this.input = null;
this.output = null;
this.descriptor = null;
return;
}
descriptor = new DataDescriptor();
this.openError = NO_ERROR;
this.handle = h;
this.fileName = fileName;
this.input = createInput(fileName, descriptor, h);
this.output = createOutput(fileName, descriptor, h);
this.descriptor = descriptor;
}
FileIOStream(String fileName, int handle) {
DataDescriptor descriptor = new DataDescriptor();
this.openError = NO_ERROR;
this.handle = handle;
this.fileName = fileName;
this.input = createInput(fileName, descriptor, handle);
this.output = createOutput(fileName, descriptor, handle);
this.descriptor = descriptor;
}
public void close() throws IOException {
int error;
checkOpenError();
error = 0;
synchronized(descriptor)
{
int h;
if((h = handle) != 0)
{
int bufferPosition;
HandleInputStream in = input;
HandleOutputStream out = output;
if((bufferPosition = out.position) > 0)
{
out.position = 0;
if(!out.writeFile(bufferPosition)) error = 1;
}
handle = 0;
in.handle = 0;
out.handle = 0;
MalikSystem.syscall((long) h, 0x0011);
}
}
if(error == 1)
{
throw new IOException("FileIOStream.close: ошибка произошла при записи файла.");
}
}
public void resetInputStream() throws IOException {
int error;
checkOpenError();
error = 0;
synchronized(descriptor)
{
label0:
{
if(handle == 0)
{
error = 1;
break label0;
}
input.resetPosition();
}
}
if(error == 1)
{
throw new ClosedFileException("FileIOStream.resetInputStream: файловый поток закрыт.");
}
}
public void resetOutputStream() throws IOException {
int error;
checkOpenError();
error = 0;
synchronized(descriptor)
{
label0:
{
int h;
int bufferPosition;
long delta;
HandleOutputStream out;
if((h = handle) == 0)
{
error = 1;
break label0;
}
if((bufferPosition = (out = output).position) > 0)
{
out.position = 0;
if(!out.writeFile(bufferPosition))
{
error = 2;
break label0;
}
}
delta = 0L;
delta = -MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(delta), 0x0014);
MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(delta), 0x0014);
}
}
switch(error)
{
case 1:
throw new ClosedFileException("FileIOStream.resetOutputStream: файловый поток закрыт.");
case 2:
throw new IOException("FileIOStream.resetOutputStream: ошибка произошла при записи файла.");
}
}
public boolean truncateSupported() {
return true;
}
public boolean positionSupported() {
return true;
}
public long truncate() throws IOException {
int error;
long result;
checkOpenError();
error = 0;
synchronized(descriptor)
{
label0:
{
int h;
int bufferPosition;
HandleOutputStream out;
if((h = handle) == 0)
{
error = 1;
result = 0L;
break label0;
}
if((bufferPosition = (out = output).position) > 0)
{
out.position = 0;
if(!out.writeFile(bufferPosition))
{
error = 2;
result = 0L;
break label0;
}
}
result = MalikSystem.syscall((long) h, 0x0016);
}
}
switch(error)
{
case 1:
throw new ClosedFileException("FileIOStream.truncate: файловый поток закрыт.");
case 2:
throw new IOException("FileIOStream.truncate: ошибка произошла при записи файла.");
}
return result;
}
public long position(long delta) throws IOException {
int error;
long result;
checkOpenError();
error = 0;
synchronized(descriptor)
{
label0:
{
int h;
int bufferPosition;
HandleOutputStream out;
if((h = handle) == 0)
{
error = 1;
result = 0L;
break label0;
}
if((bufferPosition = (out = output).position) > 0)
{
out.position = 0;
if(!out.writeFile(bufferPosition))
{
error = 2;
result = 0L;
break label0;
}
}
result = MalikSystem.syscall(h, MalikSystem.getLocalVariableAddress(delta), 0x0014);
}
}
switch(error)
{
case 1:
throw new ClosedFileException("FileIOStream.position: файловый поток закрыт.");
case 2:
throw new IOException("FileIOStream.position: ошибка произошла при записи файла.");
}
return result;
}
public InputStream getInputStream() throws IOException {
checkOpenError();
return input;
}
public OutputStream getOutputStream() throws IOException {
checkOpenError();
return output;
}
public void checkOpenError() throws IOException {
String name = fileName;
switch(openError)
{
case FILE_NOT_FOUND:
throw new FileNotFoundException((new StringBuilder()).append("FileIOStream.checkOpenError: файл ").append(name).append(" не найден или занят.").toString(), name);
case FILE_NAME_NOT_SPECIFIED:
throw new IOException("FileIOStream.checkOpenError: имя файла не было задано при создании этого экземпляра CloudFileStream.");
}
}
public boolean hasOpenError() {
int e;
return (e = openError) > NO_ERROR && e <= FILE_NAME_NOT_SPECIFIED;
}
public final long getFileSize() {
HandleInputStream in;
return (in = input) == null ? -1L : in.getFileSize();
}
public final String getFileName() {
return fileName;
}
}