filename.cc 2.71 KB
Newer Older
Eddie Kohler's avatar
Eddie Kohler committed
1
// -*- related-file-name: "../include/lcdf/filename.hh" -*-
Eddie Kohler's avatar
Eddie Kohler committed
2 3 4

/* filename.{cc,hh} -- filenames
 *
Eddie Kohler's avatar
Eddie Kohler committed
5
 * Copyright (c) 1999-2019 Eddie Kohler
Eddie Kohler's avatar
Eddie Kohler committed
6 7 8 9 10 11 12 13 14 15
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version. This program is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 */

16 17 18
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
Eddie Kohler's avatar
Eddie Kohler committed
19 20
#include <lcdf/filename.hh>
#include <lcdf/landmark.hh>
21 22 23
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
Eddie Kohler's avatar
Eddie Kohler committed
24
#include <sys/types.h>
25
#include <sys/stat.h>
26 27 28
#ifndef PATHNAME_SEPARATOR
# define PATHNAME_SEPARATOR '/'
#endif
29 30 31
#ifndef CURRENT_DIRECTORY
# define CURRENT_DIRECTORY "./"
#endif
Eddie Kohler's avatar
Eddie Kohler committed
32 33


34 35
Filename::Filename(const String &fn)
    : _path(fn), _actual(0)
Eddie Kohler's avatar
Eddie Kohler committed
36
{
37 38 39 40 41 42 43 44 45 46 47 48 49
    if (!fn)
	return;

    int last_slash = fn.find_right(PATHNAME_SEPARATOR);
    if (last_slash >= 0) {
	_dir = _path.substring(0, last_slash + 1);
	_name = _path.substring(last_slash + 1);
    } else {
	_dir = CURRENT_DIRECTORY;
	_name = fn;
    }

    assert(_dir.back() == PATHNAME_SEPARATOR);
Eddie Kohler's avatar
Eddie Kohler committed
50 51
}

52 53
Filename::Filename(const String &dir, const String &name)
    : _name(name), _actual(0)
Eddie Kohler's avatar
Eddie Kohler committed
54
{
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
    if (!name)
	return;

    if (_name[0] == PATHNAME_SEPARATOR)
	_dir = "";
    else if (dir) {
	_dir = dir;
	if (dir.back() != PATHNAME_SEPARATOR)
	    _dir += PATHNAME_SEPARATOR;
    } else
	_dir = CURRENT_DIRECTORY;

    int slash = name.find_right(PATHNAME_SEPARATOR);
    if (slash >= 0) {
	_dir += name.substring(0, slash + 1);
	_name = name.substring(slash + 1);
71
    }
72

73
    _path = _dir + _name;
Eddie Kohler's avatar
Eddie Kohler committed
74 75
}

76 77
Filename::Filename(FILE *actual, const String &name)
    : _name(name), _path(name), _actual(actual)
Eddie Kohler's avatar
Eddie Kohler committed
78 79 80 81
{
}


82
String
Eddie Kohler's avatar
Eddie Kohler committed
83 84
Filename::extension() const
{
85 86 87 88 89 90 91
    int dot = _name.find_right('.');
    while (dot > 0 && _name[dot - 1] == '.')
	dot--;
    if (dot > 0)
	return _name.substring(dot + 1);
    else
	return String();
Eddie Kohler's avatar
Eddie Kohler committed
92 93
}

94
String
Eddie Kohler's avatar
Eddie Kohler committed
95 96
Filename::base() const
{
97 98 99 100
    if (String ex = extension())
	return _name.substring(0, _name.length() - ex.length() - 1);
    else
	return _name;
Eddie Kohler's avatar
Eddie Kohler committed
101 102 103 104 105 106
}


FILE *
Filename::open_read(bool binary) const
{
107 108 109
    if (_actual || !_path)
	return _actual;
    else
110
	return fopen(_path.c_str(), binary ? "rb" : "r");
Eddie Kohler's avatar
Eddie Kohler committed
111 112 113 114 115
}

bool
Filename::readable() const
{
116 117 118
    struct stat s;
    if (!_path)
	return false;
119
    return _actual || (_path && (stat(_path.c_str(), &s) >= 0));
Eddie Kohler's avatar
Eddie Kohler committed
120 121 122 123 124 125
}


FILE *
Filename::open_write(bool binary) const
{
126 127 128
    if (_actual || !_path)
	return _actual;
    else
129
	return fopen(_path.c_str(), binary ? "wb" : "w");
Eddie Kohler's avatar
Eddie Kohler committed
130
}