mirror of
https://github.com/ceph/ceph
synced 2024-12-24 12:24:19 +00:00
07ac5d3e74
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1068 29311d96-e01e-0410-9327-a35deaab8ce9
207 lines
3.9 KiB
C++
207 lines
3.9 KiB
C++
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
|
/*
|
|
* Ceph - scalable distributed file system
|
|
*
|
|
* Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
|
|
*
|
|
* This is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software
|
|
* Foundation. See file COPYING.
|
|
*
|
|
*/
|
|
|
|
|
|
#ifndef __FILEPATH_H
|
|
#define __FILEPATH_H
|
|
|
|
|
|
/*
|
|
* BUG: /a/b/c is equivalent to a/b/c in dentry-breakdown, but not string.
|
|
* -> should it be different? how? should this[0] be "", with depth 4?
|
|
*
|
|
*/
|
|
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
using namespace std;
|
|
|
|
#include <ext/rope>
|
|
using namespace __gnu_cxx;
|
|
|
|
#include "buffer.h"
|
|
|
|
|
|
class filepath {
|
|
string path;
|
|
vector<string> bits;
|
|
|
|
void rebuild() {
|
|
if (absolute())
|
|
path = "/";
|
|
else
|
|
path.clear();
|
|
for (unsigned i=0; i<bits.size(); i++) {
|
|
if (i) path += "/";
|
|
path += bits[i];
|
|
}
|
|
}
|
|
void parse() {
|
|
bits.clear();
|
|
int off = 0;
|
|
while (off < (int)path.length()) {
|
|
// skip trailing/duplicate slash(es)
|
|
int nextslash = path.find('/', off);
|
|
if (nextslash == off) {
|
|
off++;
|
|
continue;
|
|
}
|
|
if (nextslash < 0)
|
|
nextslash = path.length(); // no more slashes
|
|
|
|
bits.push_back( path.substr(off,nextslash-off) );
|
|
off = nextslash+1;
|
|
}
|
|
}
|
|
|
|
public:
|
|
filepath() {}
|
|
filepath(const string& s) {
|
|
set_path(s);
|
|
}
|
|
filepath(const char* s) {
|
|
set_path(s);
|
|
}
|
|
|
|
bool absolute() { return path[0] == '/'; }
|
|
bool relative() { return !absolute(); }
|
|
|
|
void set_path(const string& s) {
|
|
path = s;
|
|
parse();
|
|
}
|
|
void set_path(const char *s) {
|
|
path = s;
|
|
parse();
|
|
}
|
|
|
|
string& get_path() {
|
|
return path;
|
|
}
|
|
int length() const {
|
|
return path.length();
|
|
}
|
|
|
|
const char *c_str() const {
|
|
return path.c_str();
|
|
}
|
|
|
|
|
|
filepath prefixpath(int s) const {
|
|
filepath t;
|
|
for (int i=0; i<s; i++)
|
|
t.add_dentry(bits[i]);
|
|
return t;
|
|
}
|
|
filepath postfixpath(int s) const {
|
|
filepath t;
|
|
for (unsigned i=s; i<bits.size(); i++)
|
|
t.add_dentry(bits[i]);
|
|
return t;
|
|
}
|
|
void add_dentry(const string& s) {
|
|
bits.push_back(s);
|
|
if (path.length())
|
|
path += "/";
|
|
path += s;
|
|
}
|
|
void append(const filepath& a) {
|
|
for (unsigned i=0; i<a.depth(); i++)
|
|
add_dentry(a[i]);
|
|
}
|
|
|
|
void pop_dentry() {
|
|
bits.pop_back();
|
|
rebuild();
|
|
}
|
|
|
|
|
|
|
|
void clear() {
|
|
path = "";
|
|
bits.clear();
|
|
}
|
|
|
|
const string& operator[](int i) const {
|
|
return bits[i];
|
|
}
|
|
|
|
const string& last_bit() const {
|
|
return bits[ bits.size()-1 ];
|
|
}
|
|
|
|
unsigned depth() const {
|
|
return bits.size();
|
|
}
|
|
bool empty() {
|
|
return bits.size() == 0;
|
|
}
|
|
|
|
|
|
void _rope(crope& r) {
|
|
char n = bits.size();
|
|
r.append((char*)&n, sizeof(char));
|
|
for (vector<string>::iterator it = bits.begin();
|
|
it != bits.end();
|
|
it++) {
|
|
r.append((*it).c_str(), (*it).length()+1);
|
|
}
|
|
}
|
|
|
|
void _unrope(crope& r, int& off) {
|
|
clear();
|
|
|
|
char n;
|
|
r.copy(off, sizeof(char), (char*)&n);
|
|
off += sizeof(char);
|
|
for (int i=0; i<n; i++) {
|
|
string s = r.c_str() + off;
|
|
off += s.length() + 1;
|
|
add_dentry(s);
|
|
}
|
|
}
|
|
|
|
void _encode(bufferlist& bl) {
|
|
char n = bits.size();
|
|
bl.append((char*)&n, sizeof(char));
|
|
for (vector<string>::iterator it = bits.begin();
|
|
it != bits.end();
|
|
it++) {
|
|
bl.append((*it).c_str(), (*it).length()+1);
|
|
}
|
|
}
|
|
|
|
void _decode(bufferlist& bl, int& off) {
|
|
clear();
|
|
|
|
char n;
|
|
bl.copy(off, sizeof(char), (char*)&n);
|
|
off += sizeof(char);
|
|
for (int i=0; i<n; i++) {
|
|
string s = bl.c_str() + off;
|
|
off += s.length() + 1;
|
|
add_dentry(s);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
inline ostream& operator<<(ostream& out, filepath& path)
|
|
{
|
|
return out << path.get_path();
|
|
}
|
|
|
|
#endif
|