[TOC]
回顾上一篇文章《[leveldb] 初步探索 leveldb》的样例代码,是不是发现有个类比例简单:leveldb::Status
,你发现它有status.ok()
和status.ToString()
方法。那怎么找到Status
类的定义和成员方法的实现呢?
1、 第一步:把相关代码找出来
1-1 用grep 大法过滤内容
我们知道C++
的类一般是这样定义的:class Status {...}
,我们grep
在当前目前递归-r .
全词匹配-w
和半词匹配都搜不到,最后grep "Status {"
出来了,并显示代码所在行数-n
。
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "class Status" -rnw .
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "class Status" -rn .
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "Status{" -rn .
wu_being@UbuntuKylin1704:~/Github/leveldb$ grep "Status {" -rn .
./include/leveldb/status.h:22:class LEVELDB_EXPORT Status {
wu_being@UbuntuKylin1704:~/Github/leveldb$
这个就是Status类定义的头文件:
./include/leveldb/status.h:22:class LEVELDB_EXPORT Status {
1-2 用find 大法找到文件
我们发现上面grep大法连文件名都过滤出来,下面用find大法通过文件名匹配到相关文件,找到一个Status类方法实现的文件./util/status.cc
。
wu_being@UbuntuKylin1704:~/Github/leveldb$
wu_being@UbuntuKylin1704:~/Github/leveldb$ find . -name *status.*
./util/status.cc
./util/status.o
./out-static/util/status.o
./include/leveldb/status.h
./out-shared/util/status.o
wu_being@UbuntuKylin1704:~/Github/leveldb$
2、 第二步:RTFSC (Read the fucking source code )
wu_being@UbuntuKylin1704:~/Github/leveldb$
wu_being@UbuntuKylin1704:~/Github/leveldb$ gedit include/leveldb/status.h &
[2] 3936
wu_being@UbuntuKylin1704:~/Github/leveldb$ gedit util/status.cc
[2]+ 已完成 gedit include/leveldb/status.h
wu_being@UbuntuKylin1704:~/Github/leveldb$
2-1 include/leveldb/status.h
#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_
#define STORAGE_LEVELDB_INCLUDE_STATUS_H_
#include <string>
#include "leveldb/export.h"
#include "leveldb/slice.h"
namespace leveldb {
class LEVELDB_EXPORT Status {
public:
// Create a success status.
Status() : state_(NULL) { }
~Status() { delete[] state_; }
// Copy the specified status.
Status(const Status& s);
void operator=(const Status& s);
// Return a success status.
static Status OK() { return Status(); }
// Return error status of an appropriate type.
static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) {
return Status(kNotFound, msg, msg2);
}
...
// Returns true iff the status indicates success.
bool ok() const { return (state_ == NULL); }
// Returns true iff the status indicates a NotFound error.
bool IsNotFound() const { return code() == kNotFound; }
...
// Return a string representation of this status suitable for printing.
// Returns the string "OK" for success.
// status.cc
std::string ToString() const;
private:
// OK status has a NULL state_. Otherwise, state_ is a new[] array
// of the following form:
// state_[0..3] == length of message
// state_[4] == code
// state_[5..] == message
const char* state_;
enum Code {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5
};
Code code() const {
return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
}
// status.cc
Status(Code code, const Slice& msg, const Slice& msg2);
static const char* CopyState(const char* s);
};
inline Status::Status(const Status& s) {
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
inline void Status::operator=(const Status& s) {
// The following condition catches both aliasing (when this == &s),
// and the common case where both s and *this are ok.
if (state_ != s.state_) {
delete[] state_;
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
}
} // namespace leveldb
#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_
2-1-1 类Status公有成员变量和方法
构造函数
public:
// Create a success status.
Status() : state_(NULL) { }
// Copy the specified status.
Status(const Status& s);
void operator=(const Status& s);
inline Status::Status(const Status& s) {
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
inline void Status::operator=(const Status& s) {
// The following condition catches both aliasing (when this == &s),
// and the common case where both s and *this are ok.
if (state_ != s.state_) {
delete[] state_;
state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
}
}
析构函数
~Status() { delete[] state_; }
2-1-2 类Status私有成员变量和方法
私有成员变量
下面这个state_设计很不好调试,在后面的CopyState方法就是了,没有手工调试配制state_。
// OK status has a NULL state_. Otherwise, state_ is a new[] array
// of the following form:
// state_[0..3] == length of message
// state_[4] == code
// state_[5..] == message
const char* state_;
enum Code {
kOk = 0,
kNotFound = 1,
kCorruption = 2,
kNotSupported = 3,
kInvalidArgument = 4,
kIOError = 5
};
私有成员方法
Code code() const {
return (state_ == NULL) ? kOk : static_cast<Code>(state_[4]);
}
// status.cc
Status(Code code, const Slice& msg, const Slice& msg2);
static const char* CopyState(const char* s);
2-2 util/status.cc
#include <stdio.h>
#include "port/port.h"
#include "leveldb/status.h"
namespace leveldb {
const char* Status::CopyState(const char* state) {
uint32_t size;
memcpy(&size, state, sizeof(size));
char* result = new char[size + 5];
memcpy(result, state, size + 5);
return result;
}
Status::Status(Code code, const Slice& msg, const Slice& msg2) {
assert(code != kOk);
const uint32_t len1 = msg.size();
const uint32_t len2 = msg2.size();
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
char* result = new char[size + 5];
memcpy(result, &size, sizeof(size));
result[4] = static_cast<char>(code);
memcpy(result + 5, msg.data(), len1);
if (len2) {
result[5 + len1] = ':';
result[6 + len1] = ' ';
memcpy(result + 7 + len1, msg2.data(), len2);
}
state_ = result;
}
std::string Status::ToString() const {
if (state_ == NULL) {
return "OK.";
} else {
char tmp[30];
const char* type;
switch (code()) {
case kOk:
type = "OK...";
break;
case kNotFound:
type = "NotFound: ";
break;
...
default:
snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
static_cast<int>(code()));
type = tmp;
break;
}
std::string result(type);
uint32_t length;
memcpy(&length, state_, sizeof(length));
result.append(state_ + 5, length);
return result;
}
}
} // namespace leveldb
Status::CopyState
// OK status has a NULL state_. Otherwise, state_ is a new[] array
// of the following form:
// state_[0..3] == length of message
// state_[4] == code
// state_[5..] == message
const char* Status::CopyState(const char* state) {
uint32_t size; //sizeof(size)为4
memcpy(&size, state, sizeof(size));//把state前面4个length of message字符给size
char* result = new char[size + 5];
memcpy(result, state, size + 5);
return result;
}
Status::ToString() const
std::string Status::ToString() const {
if (state_ == NULL) {
return "OK.";
} else {
char tmp[30];
const char* type;
switch (code()) {
case kOk:
type = "OK...";
break;
case kNotFound:
type = "NotFound: ";
break;
...
default:
snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
static_cast<int>(code()));
type = tmp;
break;
}
std::string result(type);
uint32_t length;
memcpy(&length, state_, sizeof(length));
result.append(state_ + 5, length);
return result;
}
}
私有构造函数
Status::Status
Status::Status(Code code, const Slice& msg, const Slice& msg2) {
assert(code != kOk);
const uint32_t len1 = msg.size();
const uint32_t len2 = msg2.size();
const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
char* result = new char[size + 5];
memcpy(result, &size, sizeof(size));
result[4] = static_cast<char>(code);
memcpy(result + 5, msg.data(), len1);
if (len2) {
result[5 + len1] = ':';
result[6 + len1] = ' ';
memcpy(result + 7 + len1, msg2.data(), len2);
}
state_ = result;
}
Wu_Being博客声明:本人博客欢迎转载,请标明博客原文和原链接!谢谢!
《[leveldb] 学习leveldb第一个类Status》: https://yq.aliyun.com/articles/241407/
如果你看完这篇博文,觉得对你有帮助,并且愿意付赞助费,那么我会更有动力写下去。