/******************************************************************************
 * mod_uploader / BasicFileWriter.cpp
 ******************************************************************************
 * Copyright (C) 2005 Tetsuya Kimata <kimata@acapulco.dyndns.org>
 *
 * All rights reserved.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any
 * damages arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any
 * purpose, including commercial applications, and to alter it and
 * redistribute it freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must
 *    not claim that you wrote the original software. If you use this
 *    software in a product, an acknowledgment in the product
 *    documentation would be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must
 *    not be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 *    distribution.
 *
 * $Id: BasicFileWriter.cpp 676 2005-09-14 14:43:48Z svn $
 *****************************************************************************/

#include "BasicFileWriter.h"
#include "Misc.h"

#include "apr_mmap.h"

/******************************************************************************
 * public メソッド
 *****************************************************************************/
BasicFileWriter::BasicFileWriter(apr_pool_t *pool, apr_file_t *fd,
                                 apr_size_t offset)
    : FileWriter(pool, fd)
{
    apr_off_t pos = offset;

    // 例外投げます
    if ((apr_file_seek(fd, APR_SET, &pos) != APR_SUCCESS) ||
        (pos != static_cast<apr_off_t>(offset))) {
        throw "ファイルの seek に失敗しました．";
    }
}

void BasicFileWriter::write(const void *buf, apr_size_t size)
{
    apr_size_t write_size;

    if (UNLIKELY(apr_file_write_full(get_fd(), buf, size, &write_size) != APR_SUCCESS)) {
        throw "ファイルの write に失敗しました．";
    }
}


/******************************************************************************
 * テスト
 *****************************************************************************/
#ifdef DEBUG_BasicFileWriter
#include <iostream>

#include "apr_general.h"

#define BUFSIZE 1234

using namespace std;

void usage(const char *prog_name)
{
    cerr << "Usage: " << prog_name << " <SRC> <DST>" << endl;
}

int main(int argc, const char * const *argv)
{
    apr_pool_t *pool;
    apr_file_t *src;
    apr_file_t *dst;
    char buffer[BUFSIZE];
    apr_size_t size = sizeof(buffer);

    apr_app_initialize(&argc, &argv, NULL);
    apr_pool_create(&pool, NULL);

    try {
        if (argc != 3) {
            throw "コピー元とコピー先のファイルが指定されていません．";
        }

        if (apr_file_open(&src, argv[1], APR_READ|APR_BINARY,
                          APR_OS_DEFAULT, pool) != APR_SUCCESS) {
            throw "コピー元のファイルを開けませんでした．";
        }

        if (apr_file_open(&dst, argv[2],
                          APR_READ|APR_WRITE|APR_CREATE|APR_EXCL|APR_BINARY,
                          APR_OS_DEFAULT, pool) != APR_SUCCESS) {
            throw "コピー先のファイルを開けませんでした．";
        }

        BasicFileWriter writer(pool, dst);
        while (apr_file_read(src, buffer, &size) == APR_SUCCESS) {
            writer.write(buffer, size);
            size = sizeof(buffer);
        }

        apr_file_close(dst);
        apr_file_close(src);
    } catch(const char *message) {
        cerr << "Error: " << message << endl;
        usage(argv[0]);

        return EXIT_FAILURE;
    }

    apr_terminate();

    return EXIT_SUCCESS;
}
#endif

// Local Variables:
// mode: c++
// buffer-file-coding-system: euc-japan-dos
// End:
