/**
 * Copyright 2003-2006 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "jstreamsconfig.h"
#include "fileinputstream.h"
#include <cerrno>
#include <cstring>
using namespace jstreams;

const int32_t FileInputStream::defaultBufferSize = 1048576;
FileInputStream::FileInputStream(const char *filepath, int32_t buffersize) {

    // try to open the file for reading
    file = fopen(filepath, "rb");
    this->filepath = filepath;
    if (file == 0) {
        // handle error
        error = "Could not read file '";
        error += filepath;
        error += "': ";
	error += strerror(errno);
        status = Error;
        return;
    }
    // determine file size. if the stream is not seekable, the size will be -1
    fseek(file, 0, SEEK_END);
    size = ftell(file);
    fseek(file, 0, SEEK_SET);

    // if the file has size 0, make sure that it's really empty
    // this is useful for filesystems like /proc that report files as size 0
    // for files that do contain content
    if (size == 0) {
        char dummy[1];
        size_t n = fread(dummy, 1, 1, file);
        if (n == 1) {
            size = -1;
            fseek(file, 0, SEEK_SET);
        } else {
            fclose(file);
            file = 0;
            return;
        }
    }

    // allocate memory in the buffer
    mark(buffersize);
}
FileInputStream::~FileInputStream() {
    if (file) {
        if (fclose(file)) {
            // handle error
            error = "Could not close file '" + filepath + "'.";
        }
    }
}
int32_t
FileInputStream::fillBuffer(char* start, int32_t space) {
    if (file == 0) return -1;
    // read into the buffer
    int32_t nwritten = fread(start, 1, space, file);
    // check the file stream status
    if (ferror(file)) {
        error = "Could not read from file '" + filepath + "'.";
        fclose(file);
        file = 0;
        status = Error;
        return -1;
    }
    if (feof(file)) {
        fclose(file);
        file = 0;
    }
    return nwritten;
}
