Blame samples/iotest.cpp

Packit 01d647
// ***************************************************************** -*- C++ -*-
Packit 01d647
/*
Packit 01d647
 * This program is part of the Exiv2 distribution.
Packit 01d647
 *
Packit 01d647
 * This program is free software; you can redistribute it and/or
Packit 01d647
 * modify it under the terms of the GNU General Public License
Packit 01d647
 * as published by the Free Software Foundation; either version 2
Packit 01d647
 * of the License, or (at your option) any later version.
Packit 01d647
 *
Packit 01d647
 * This program is distributed in the hope that it will be useful,
Packit 01d647
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 01d647
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 01d647
 * GNU General Public License for more details.
Packit 01d647
 *
Packit 01d647
 * You should have received a copy of the GNU General Public License
Packit 01d647
 * along with this program; if not, write to the Free Software
Packit 01d647
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit 01d647
 */
Packit 01d647
/*
Packit 01d647
  Abstract : Tester application for BasicIo functions. Tests MemIo primarily
Packit 01d647
        since FileIo just sits atop of FILE* streams.
Packit 01d647
Packit 01d647
  File     : iotest.cpp
Packit 01d647
  Author(s): Brad Schick (brad) <brad@robotbattle.com>
Packit 01d647
  History  : 04-Dec-04, brad: created
Packit 01d647
 */
Packit 01d647
// *****************************************************************************
Packit 01d647
// included header files
Packit 01d647
#include <exiv2/exiv2.hpp>
Packit 01d647
Packit 01d647
#include <cstdio>                               // for EOF
Packit 01d647
#include <cstring>
Packit 01d647
#include <iostream>
Packit Service fb147c
#include <stdio.h>
Packit 01d647
Packit 01d647
using Exiv2::byte;
Packit 01d647
using Exiv2::BasicIo;
Packit 01d647
using Exiv2::MemIo;
Packit 01d647
using Exiv2::FileIo;
Packit 01d647
using Exiv2::IoCloser;
Packit 01d647
using Exiv2::Error;
Packit 01d647
using Exiv2::strError;
Packit 01d647
Packit 01d647
int WriteReadSeek(BasicIo &io);
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// Main
Packit 01d647
int main(int argc, char* const argv[])
Packit 01d647
{
Packit Service fb147c
    Exiv2::XmpParser::initialize();
Packit Service fb147c
    ::atexit(Exiv2::XmpParser::terminate);
Packit Service fb147c
Packit Service fb147c
    try {
Packit Service fb147c
        if (argc < 4 || argc > 6 ) {
Packit Service fb147c
            std::cout << "Usage: " << argv[0] << " filein fileout1 fileout2 [remote [blocksize]]\n"
Packit Service fb147c
                         "copy filein to fileout1 and copy filein to fileout2\n"
Packit Service fb147c
                         "fileout1 and fileout2 are overwritten and should match filein exactly\n"
Packit Service fb147c
                         "\n"
Packit Service fb147c
                         "You may optionally provide the URL of a remote file to be copied to filein\n"
Packit Service fb147c
                         "If you use `remote`, you may optionally provide a blocksize for the copy buffer (default 10k)\n"
Packit Service fb147c
            ;
Packit Service fb147c
            return 1;
Packit Service fb147c
        }
Packit Service fb147c
        const char* f0 = argv[1]; // fileIn
Packit Service fb147c
        const char* f1 = argv[2]; // fileOut1
Packit Service fb147c
        const char* f2 = argv[3]; // fileOut2
Packit Service fb147c
        const char* fr = argv[4]; // remote file
Packit Service fb147c
        const char* ba = argv[5]; // block argument
Packit Service fb147c
Packit Service fb147c
        if ( argc >= 5 ) {
Packit Service fb147c
            int blocksize = argc==6 ? atoi(ba) : 10000;
Packit Service fb147c
            // ensure blocksize is sane
Packit Service fb147c
            if (blocksize>1024*1024) blocksize=10000;
Packit Service fb147c
            Exiv2::byte* bytes = blocksize>0 ? new Exiv2::byte[blocksize]: NULL;
Packit Service fb147c
Packit Service fb147c
            // copy fileIn from a remote location.
Packit Service fb147c
            BasicIo::AutoPtr io = Exiv2::ImageFactory::createIo(fr);
Packit Service fb147c
            if ( io->open() != 0 ) {
Packit Service fb147c
                Error(Exiv2::kerFileOpenFailed, io->path(), "rb", strError());
Packit Service fb147c
            }
Packit Service fb147c
            FileIo output(f0);
Packit Service fb147c
            if ( !output.open("wb") ) {
Packit Service fb147c
                Error(Exiv2::kerFileOpenFailed, output.path() , "w+b", strError());
Packit Service fb147c
            }
Packit Service fb147c
            size_t    l = 0;
Packit Service fb147c
            if ( bytes ) {
Packit Service fb147c
                int r ;
Packit Service fb147c
                while ( (r=io->read(bytes,blocksize)) > 0  ) {
Packit Service fb147c
                    l += r;
Packit Service fb147c
                    output.write(bytes,r) ;
Packit Service fb147c
                }
Packit Service fb147c
            } else {
Packit Service fb147c
                // read/write byte-wise (#1029)
Packit Service fb147c
                while ( l++ < io->size() ) {
Packit Service fb147c
                    output.putb(io->getb()) ;
Packit Service fb147c
                }
Packit Service fb147c
            }
Packit Service fb147c
            if ( bytes ) delete [] bytes;
Packit Service fb147c
            output.close();
Packit Service fb147c
        }
Packit 01d647
Packit Service fb147c
        FileIo fileIn(f0);
Packit Service fb147c
        if (fileIn.open() != 0) {
Packit Service fb147c
            throw Error(Exiv2::kerDataSourceOpenFailed, fileIn.path(), strError());
Packit Service fb147c
        }
Packit 01d647
Packit Service fb147c
        FileIo fileOut1(f1);
Packit Service fb147c
        if (fileOut1.open("w+b") != 0) {
Packit Service fb147c
            throw Error(Exiv2::kerFileOpenFailed, f1, "w+b", strError());
Packit Service fb147c
        }
Packit 01d647
Packit Service fb147c
        MemIo memIo1;
Packit 01d647
Packit Service fb147c
        // Copy to output file through memIo
Packit Service fb147c
        memIo1.write(fileIn);
Packit Service fb147c
        memIo1.seek(0, BasicIo::beg);
Packit Service fb147c
        fileOut1.write(memIo1);
Packit 01d647
Packit Service fb147c
        // Make sure they are all the same size
Packit Service fb147c
        if(fileIn.size() != memIo1.size() || memIo1.size() != fileOut1.size()) {
Packit Service fb147c
            std::cerr << argv[0] <<
Packit Service fb147c
                ": Sizes do not match\n";
Packit Service fb147c
            return 1;
Packit Service fb147c
        }
Packit 01d647
Packit Service fb147c
        // Read writereadseek test on MemIo
Packit Service fb147c
        MemIo memIo2;
Packit Service fb147c
        int rc = WriteReadSeek(memIo2);
Packit Service fb147c
        if (rc != 0) return rc;
Packit 01d647
Packit Service fb147c
        // Read writereadseek test on FileIo
Packit Service fb147c
        // Create or overwrite the file, then close it
Packit Service fb147c
        FileIo fileTest("iotest.txt");
Packit Service fb147c
        if (fileTest.open("w+b") != 0) {
Packit Service fb147c
            throw Error(Exiv2::kerFileOpenFailed, "iotest.txt", "w+b", strError());
Packit Service fb147c
        }
Packit 01d647
Packit Service fb147c
        fileTest.close();
Packit Service fb147c
        rc = WriteReadSeek(fileTest);
Packit Service fb147c
        if (rc != 0) return rc;
Packit 01d647
Packit Service fb147c
        // Another test of reading and writing
Packit Service fb147c
        fileOut1.seek(0, BasicIo::beg);
Packit Service fb147c
        memIo2.seek(0, BasicIo::beg);
Packit Service fb147c
        FileIo fileOut2(f2);
Packit Service fb147c
        if (fileOut2.open("w+b") != 0) {
Packit Service fb147c
            throw Error(Exiv2::kerFileOpenFailed, f2, "w+b", strError());
Packit 01d647
        }
Packit Service fb147c
Packit Service fb147c
        long readCount = 0;
Packit Service fb147c
        byte buf[32];
Packit Service fb147c
        while ((readCount=fileOut1.read(buf, sizeof(buf)))) {
Packit Service fb147c
            if (memIo2.write(buf, readCount) != readCount) {
Packit Service fb147c
                std::cerr << argv[0] <<
Packit Service fb147c
                    ": MemIo bad write 2\n";
Packit Service fb147c
                return 13;
Packit Service fb147c
            }
Packit Service fb147c
            if (fileOut2.write(buf, readCount) != readCount) {
Packit Service fb147c
                std::cerr << argv[0] <<
Packit Service fb147c
                    ": FileIo bad write 2\n";
Packit Service fb147c
                return 14;
Packit Service fb147c
            }
Packit 01d647
        }
Packit 01d647
Packit Service fb147c
        return 0;
Packit Service fb147c
    } catch (Exiv2::AnyError& e) {
Packit Service fb147c
        std::cerr << "Caught Exiv2 exception '" << e << "'\n";
Packit Service fb147c
        return 20;
Packit Service fb147c
    }
Packit 01d647
}
Packit 01d647
Packit 01d647
Packit 01d647
int WriteReadSeek(BasicIo &io)
Packit 01d647
{
Packit 01d647
    byte buf[4096];
Packit 01d647
    const char   tester1[] = "this is a little test of MemIo";
Packit 01d647
    const char   tester2[] = "Appending this on the end";
Packit 01d647
    const char   expect[]  = "this is a little teAppending this on the end";
Packit 01d647
    const size_t insert = 19;
Packit 01d647
    const size_t size1  = std::strlen(tester1) + 1;
Packit 01d647
    const size_t size2  = std::strlen(tester2) + 1;
Packit 01d647
Packit 01d647
    if (io.open() != 0) {
Packit 01d647
        throw Error(Exiv2::kerDataSourceOpenFailed, io.path(), strError());
Packit 01d647
    }
Packit 01d647
    IoCloser closer(io);
Packit 01d647
    if ((size_t) io.write((byte*)tester1, (long)size1) != size1) {
Packit 01d647
        std::cerr << ": WRS initial write failed\n";
Packit 01d647
        return 2;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    if (io.size() != size1) {
Packit 01d647
        std::cerr << ": WRS size is not " << size1 << "\n";
Packit 01d647
        return 2;
Packit 01d647
    }
Packit 01d647
    long     backup = (long)size1;
Packit 01d647
    io.seek(-backup, BasicIo::cur);
Packit 01d647
Packit 01d647
    int c = EOF;
Packit 01d647
    std::memset(buf, -1, sizeof(buf));
Packit 01d647
    for (int i = 0; (c=io.getb()) != EOF; ++i) {
Packit 01d647
        buf[i] = (byte)c;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    // Make sure we got the null back
Packit 01d647
    if(buf[size1-1] != 0) {
Packit 01d647
        std::cerr << ": WRS missing null terminator 1\n";
Packit 01d647
        return 3;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    if (strcmp(tester1, (char*)buf) != 0 ) {
Packit 01d647
        std::cerr << ": WRS strings don't match 1\n";
Packit 01d647
        return 4;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    io.seek(-2, BasicIo::end);
Packit 01d647
    if (io.getb() != 'o') {
Packit 01d647
        std::cerr << ": WRS bad getb o\n";
Packit 01d647
        return 5;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    io.seek(-2, BasicIo::cur);
Packit 01d647
    if (io.getb() != 'I') {
Packit 01d647
        std::cerr << ": WRS bad getb I\n";
Packit 01d647
        return 6;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    if (io.putb('O') != 'O') {
Packit 01d647
        std::cerr << ": WRS bad putb\n";
Packit 01d647
        return 7;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    io.seek(-1, BasicIo::cur);
Packit 01d647
    if (io.getb() != 'O') {
Packit 01d647
        std::cerr << ": WRS bad getb O\n";
Packit 01d647
        return 8;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    io.seek(insert, BasicIo::beg);
Packit 01d647
    if((size_t)io.write((byte*)tester2, (long)size2) != size2) {
Packit 01d647
        std::cerr << ": WRS bad write 1\n";
Packit 01d647
        return 9;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    // open should seek to beginning
Packit 01d647
    if (io.open() != 0)  {
Packit 01d647
        throw Error(Exiv2::kerDataSourceOpenFailed, io.path(), strError());
Packit 01d647
    }
Packit 01d647
    std::memset(buf, -1, sizeof(buf));
Packit 01d647
    if ((size_t) io.read(buf, sizeof(buf)) != insert + size2) {
Packit 01d647
        std::cerr << ": WRS something went wrong\n";
Packit 01d647
        return 10;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    // Make sure we got the null back
Packit 01d647
    if(buf[insert + size2 - 1] != 0) {
Packit 01d647
        std::cerr << ": WRS missing null terminator 2\n";
Packit 01d647
        return 11;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    if (std::strcmp(expect, (char*)buf) != 0 ) {
Packit 01d647
        std::cerr << ": WRS strings don't match 2\n";
Packit 01d647
        return 12;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    return 0;
Packit 01d647
}